From d6f87829954eec68289080727a052d1763195e24 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 7 May 2018 09:43:03 -0700 Subject: [PATCH] Fixed backport --- lib/matplotlib/_constrained_layout.py | 2 +- lib/matplotlib/figure.py | 31 ++++++++------ .../tests/test_constrainedlayout.py | 40 +++++++++++++++++++ 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/_constrained_layout.py b/lib/matplotlib/_constrained_layout.py index 6fe3d7d03b95..e3a874650e96 100644 --- a/lib/matplotlib/_constrained_layout.py +++ b/lib/matplotlib/_constrained_layout.py @@ -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 diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 398f065c6736..dd24a060d666 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -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) @@ -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 diff --git a/lib/matplotlib/tests/test_constrainedlayout.py b/lib/matplotlib/tests/test_constrainedlayout.py index 9c36fb2476ee..2f536b9b4c91 100644 --- a/lib/matplotlib/tests/test_constrainedlayout.py +++ b/lib/matplotlib/tests/test_constrainedlayout.py @@ -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))