From 225317b81ace2b5d0474effc8e38fa6f82607a50 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sun, 19 Dec 2021 00:18:02 +0100 Subject: [PATCH] Use standard toolbar in wx. The previous approach manually positioned the toolbar to have it at the bottom of the window, but this can in fact be achieved just with style=wx.TB_BOTTOM. Removing manual sizing of the toolbar also fixes a bug previously present on Windows, whereby a `set_size_inches` reducing the size of the canvas would *not* reduce the window width, likely because it was forced to its max value by the toolbar's explicit size. --- .../next_api_changes/behavior/22013-AL.rst | 5 +++ lib/matplotlib/backends/backend_wx.py | 44 ++++++------------- 2 files changed, 19 insertions(+), 30 deletions(-) create mode 100644 doc/api/next_api_changes/behavior/22013-AL.rst diff --git a/doc/api/next_api_changes/behavior/22013-AL.rst b/doc/api/next_api_changes/behavior/22013-AL.rst new file mode 100644 index 000000000000..c46b9ab7e488 --- /dev/null +++ b/doc/api/next_api_changes/behavior/22013-AL.rst @@ -0,0 +1,5 @@ +``FigureFrameWx.sizer`` +~~~~~~~~~~~~~~~~~~~~~~~ +... has been removed. The frame layout is no longer based on a sizer, as the +canvas is now the sole child widget; the toolbar is now a regular toolbar +added using ``SetToolBar``. diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index a7f35368a0a5..581f67bd802c 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -898,37 +898,25 @@ def __init__(self, num, fig, *, canvas_class=None): "required after the deprecation period starting in Matplotlib " "%(since)s elapses.") self.canvas = self.get_canvas(fig) - w, h = map(math.ceil, fig.bbox.size) - self.canvas.SetInitialSize(wx.Size(w, h)) - self.canvas.SetFocus() - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) - # By adding toolbar in sizer, we are able to put it at the bottom - # of the frame - so appearance is closer to GTK version self.figmgr = FigureManagerWx(self.canvas, num, self) self.toolbar = self._get_toolbar() - if self.figmgr.toolmanager: backend_tools.add_tools_to_manager(self.figmgr.toolmanager) if self.toolbar: backend_tools.add_tools_to_container(self.toolbar) - if self.toolbar is not None: - self.toolbar.Realize() - # On Windows platform, default window size is incorrect, so set - # toolbar width to figure width. - tw, th = self.toolbar.GetSize() - fw, fh = self.canvas.GetSize() - # By adding toolbar in sizer, we are able to put it at the bottom - # of the frame - so appearance is closer to GTK version. - self.toolbar.SetSize(wx.Size(fw, th)) - self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) - self.SetSizer(self.sizer) - self.Fit() + self.SetToolBar(self.toolbar) + # On Windows, canvas sizing must occur after toolbar addition; + # otherwise the toolbar further resizes the canvas. + w, h = map(math.ceil, fig.bbox.size) + self.canvas.SetInitialSize(wx.Size(w, h)) self.canvas.SetMinSize((2, 2)) + self.canvas.SetFocus() + + self.Fit() self.Bind(wx.EVT_CLOSE, self._on_close) @@ -966,10 +954,6 @@ def _on_close(self, event): # Carry on with close event propagation, frame & children destruction event.Skip() - def GetToolBar(self): - """Override wxFrame::GetToolBar as we don't have managed toolbar""" - return self.toolbar - def Destroy(self, *args, **kwargs): try: self.canvas.mpl_disconnect(self.toolbar._id_drag) @@ -1049,9 +1033,9 @@ def set_window_title(self, title): def resize(self, width, height): # docstring inherited - self.canvas.SetInitialSize( - wx.Size(math.ceil(width), math.ceil(height))) - self.window.GetSizer().Fit(self.window) + # Directly using SetClientSize doesn't handle the toolbar on Windows. + self.window.SetSize(self.window.ClientToWindowSize(wx.Size( + math.ceil(width), math.ceil(height)))) def _load_bitmap(filename): @@ -1073,8 +1057,8 @@ def _set_frame_icon(frame): class NavigationToolbar2Wx(NavigationToolbar2, wx.ToolBar): - def __init__(self, canvas, coordinates=True): - wx.ToolBar.__init__(self, canvas.GetParent(), -1) + def __init__(self, canvas, coordinates=True, *, style=wx.TB_BOTTOM): + wx.ToolBar.__init__(self, canvas.GetParent(), -1, style=style) if 'wxMac' in wx.PlatformInfo: self.SetToolBitmapSize((24, 24)) @@ -1202,7 +1186,7 @@ def set_history_buttons(self): # tools for matplotlib.backend_managers.ToolManager: class ToolbarWx(ToolContainerBase, wx.ToolBar): - def __init__(self, toolmanager, parent, style=wx.TB_HORIZONTAL): + def __init__(self, toolmanager, parent, style=wx.TB_BOTTOM): ToolContainerBase.__init__(self, toolmanager) wx.ToolBar.__init__(self, parent, -1, style=style) self._space = self.AddStretchableSpace()