Skip to content

Manual backport #11035 #11184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/matplotlib/_constrained_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
ax._poslayoutbox.constrain_left_margin(0, strength='weak')

# do layout for suptitle.
if fig._suptitle is not None:
if fig._suptitle is not None and fig._suptitle._layoutbox is not None:
sup = fig._suptitle
bbox = invTransFig(sup.get_window_extent(renderer=renderer))
height = bbox.y1 - bbox.y0
Expand Down
31 changes: 18 additions & 13 deletions lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,8 @@ def suptitle(self, t, **kwargs):

fig.suptitle('this is the figure title', fontsize=12)
"""
manual_position = ('x' in kwargs or 'y' in kwargs)

x = kwargs.pop('x', 0.5)
y = kwargs.pop('y', 0.98)

Expand All @@ -740,19 +742,22 @@ def suptitle(self, t, **kwargs):
sup.remove()
else:
self._suptitle = sup
if self._layoutbox is not None:
# assign a layout box to the suptitle...
figlb = self._layoutbox
self._suptitle._layoutbox = layoutbox.LayoutBox(
parent=figlb,
name=figlb.name+'.suptitle')
for child in figlb.children:
if not (child == self._suptitle._layoutbox):
w_pad, h_pad, wspace, hspace = \
self.get_constrained_layout_pads(
relative=True)
layoutbox.vstack([self._suptitle._layoutbox, child],
padding=h_pad*2., strength='required')
self._suptitle._layoutbox = None
if self._layoutbox is not None and not manual_position:
w_pad, h_pad, wspace, hspace = \
self.get_constrained_layout_pads(relative=True)
figlb = self._layoutbox
self._suptitle._layoutbox = layoutbox.LayoutBox(
parent=figlb, artist=self._suptitle,
name=figlb.name+'.suptitle')
# stack the suptitle on top of all the children.
# Some day this should be on top of all the children in the
# gridspec only.
for child in figlb.children:
if child is not self._suptitle._layoutbox:
layoutbox.vstack([self._suptitle._layoutbox,
child],
padding=h_pad*2., strength='required')
self.stale = True
return self._suptitle

Expand Down
40 changes: 40 additions & 0 deletions lib/matplotlib/tests/test_constrainedlayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,43 @@ def test_constrained_layout20():
ax = fig.add_axes([0, 0, 1, 1])
mesh = ax.pcolormesh(gx, gx, img)
fig.colorbar(mesh)


def test_constrained_layout21():
'#11035: repeated calls to suptitle should not alter the layout'
fig, ax = plt.subplots(constrained_layout=True)

fig.suptitle("Suptitle0")
fig.canvas.draw()
extents0 = np.copy(ax.get_position().extents)

fig.suptitle("Suptitle1")
fig.canvas.draw()
extents1 = np.copy(ax.get_position().extents)

np.testing.assert_allclose(extents0, extents1)


def test_constrained_layout22():
'#11035: suptitle should not be include in CL if manually positioned'
fig, ax = plt.subplots(constrained_layout=True)

fig.canvas.draw()
extents0 = np.copy(ax.get_position().extents)

fig.suptitle("Suptitle", y=0.5)
fig.canvas.draw()
extents1 = np.copy(ax.get_position().extents)

np.testing.assert_allclose(extents0, extents1)


def test_constrained_layout23():
'''
Comment in #11035: suptitle used to cause an exception when
reusing a figure w/ CL with ``clear=True``.
'''

for i in range(2):
fig, ax = plt.subplots(num="123", constrained_layout=True, clear=True)
fig.suptitle("Suptitle{}".format(i))