Skip to content

Commit a3ee438

Browse files
authored
Merge pull request #11184 from jklymak/v2.2.x
Manual backport #11035
2 parents e870499 + d6f8782 commit a3ee438

File tree

3 files changed

+59
-14
lines changed

3 files changed

+59
-14
lines changed

lib/matplotlib/_constrained_layout.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
244244
ax._poslayoutbox.constrain_left_margin(0, strength='weak')
245245

246246
# do layout for suptitle.
247-
if fig._suptitle is not None:
247+
if fig._suptitle is not None and fig._suptitle._layoutbox is not None:
248248
sup = fig._suptitle
249249
bbox = invTransFig(sup.get_window_extent(renderer=renderer))
250250
height = bbox.y1 - bbox.y0

lib/matplotlib/figure.py

+18-13
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,8 @@ def suptitle(self, t, **kwargs):
718718
719719
fig.suptitle('this is the figure title', fontsize=12)
720720
"""
721+
manual_position = ('x' in kwargs or 'y' in kwargs)
722+
721723
x = kwargs.pop('x', 0.5)
722724
y = kwargs.pop('y', 0.98)
723725

@@ -740,19 +742,22 @@ def suptitle(self, t, **kwargs):
740742
sup.remove()
741743
else:
742744
self._suptitle = sup
743-
if self._layoutbox is not None:
744-
# assign a layout box to the suptitle...
745-
figlb = self._layoutbox
746-
self._suptitle._layoutbox = layoutbox.LayoutBox(
747-
parent=figlb,
748-
name=figlb.name+'.suptitle')
749-
for child in figlb.children:
750-
if not (child == self._suptitle._layoutbox):
751-
w_pad, h_pad, wspace, hspace = \
752-
self.get_constrained_layout_pads(
753-
relative=True)
754-
layoutbox.vstack([self._suptitle._layoutbox, child],
755-
padding=h_pad*2., strength='required')
745+
self._suptitle._layoutbox = None
746+
if self._layoutbox is not None and not manual_position:
747+
w_pad, h_pad, wspace, hspace = \
748+
self.get_constrained_layout_pads(relative=True)
749+
figlb = self._layoutbox
750+
self._suptitle._layoutbox = layoutbox.LayoutBox(
751+
parent=figlb, artist=self._suptitle,
752+
name=figlb.name+'.suptitle')
753+
# stack the suptitle on top of all the children.
754+
# Some day this should be on top of all the children in the
755+
# gridspec only.
756+
for child in figlb.children:
757+
if child is not self._suptitle._layoutbox:
758+
layoutbox.vstack([self._suptitle._layoutbox,
759+
child],
760+
padding=h_pad*2., strength='required')
756761
self.stale = True
757762
return self._suptitle
758763

lib/matplotlib/tests/test_constrainedlayout.py

+40
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,43 @@ def test_constrained_layout20():
388388
ax = fig.add_axes([0, 0, 1, 1])
389389
mesh = ax.pcolormesh(gx, gx, img)
390390
fig.colorbar(mesh)
391+
392+
393+
def test_constrained_layout21():
394+
'#11035: repeated calls to suptitle should not alter the layout'
395+
fig, ax = plt.subplots(constrained_layout=True)
396+
397+
fig.suptitle("Suptitle0")
398+
fig.canvas.draw()
399+
extents0 = np.copy(ax.get_position().extents)
400+
401+
fig.suptitle("Suptitle1")
402+
fig.canvas.draw()
403+
extents1 = np.copy(ax.get_position().extents)
404+
405+
np.testing.assert_allclose(extents0, extents1)
406+
407+
408+
def test_constrained_layout22():
409+
'#11035: suptitle should not be include in CL if manually positioned'
410+
fig, ax = plt.subplots(constrained_layout=True)
411+
412+
fig.canvas.draw()
413+
extents0 = np.copy(ax.get_position().extents)
414+
415+
fig.suptitle("Suptitle", y=0.5)
416+
fig.canvas.draw()
417+
extents1 = np.copy(ax.get_position().extents)
418+
419+
np.testing.assert_allclose(extents0, extents1)
420+
421+
422+
def test_constrained_layout23():
423+
'''
424+
Comment in #11035: suptitle used to cause an exception when
425+
reusing a figure w/ CL with ``clear=True``.
426+
'''
427+
428+
for i in range(2):
429+
fig, ax = plt.subplots(num="123", constrained_layout=True, clear=True)
430+
fig.suptitle("Suptitle{}".format(i))

0 commit comments

Comments
 (0)