From 30f8b77993b544f2f4433cb2fa8cbd9a4a6772aa Mon Sep 17 00:00:00 2001 From: DietmarSchwertberger Date: Wed, 21 Mar 2018 03:54:38 +0100 Subject: [PATCH 1/5] first implementation of Toolmanager for the Wx backends --- .../user_interfaces/toolmanager_sgskip.py | 1 + lib/matplotlib/backends/backend_wx.py | 156 ++++++++++++++++-- 2 files changed, 147 insertions(+), 10 deletions(-) diff --git a/examples/user_interfaces/toolmanager_sgskip.py b/examples/user_interfaces/toolmanager_sgskip.py index 6ae0fc3d88e9..9820e12744c5 100644 --- a/examples/user_interfaces/toolmanager_sgskip.py +++ b/examples/user_interfaces/toolmanager_sgskip.py @@ -19,6 +19,7 @@ matplotlib.use('GTK3Cairo') # matplotlib.use('TkAgg') # matplotlib.use('QT5Agg') +# matplotlib.use('WxAgg') matplotlib.rcParams['toolbar'] = 'toolmanager' import matplotlib.pyplot as plt from matplotlib.backend_tools import ToolBase, ToolToggleBase diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index dfbf23340492..2ee7eb9d1deb 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -18,7 +18,8 @@ import matplotlib from matplotlib.backend_bases import ( _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, - NavigationToolbar2, RendererBase, TimerBase, cursors) + NavigationToolbar2, RendererBase, TimerBase, cursors, ToolContainerBase, + StatusbarBase) from matplotlib.backend_bases import _has_pil from matplotlib._pylab_helpers import Gcf @@ -27,6 +28,7 @@ from matplotlib.path import Path from matplotlib.transforms import Affine2D from matplotlib.widgets import SubplotTool +from matplotlib.backend_managers import ToolManager from matplotlib import cbook, rcParams, backend_tools import wx @@ -1158,9 +1160,8 @@ def __init__(self, num, fig): # Frame will be sized later by the Fit method DEBUG_MSG("__init__()", 1, self) self.num = num + _set_frame_icon(self) - statbar = StatusBarWx(self) - self.SetStatusBar(statbar) self.canvas = self.get_canvas(fig) self.canvas.SetInitialSize(wx.Size(fig.bbox.width, fig.bbox.height)) self.canvas.SetFocus() @@ -1169,7 +1170,18 @@ def __init__(self, num, fig): # 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 = self._get_toolbar(statbar) + self.toolmanager = self._get_toolmanager() + if self.toolmanager: + self.statusbar = StatusbarWx(self, self.toolmanager) + else: + self.statusbar = StatusBarWx(self) + self.SetStatusBar(self.statusbar) + self.toolbar = self._get_toolbar(self.statusbar) + + if self.toolmanager: + backend_tools.add_tools_to_manager(self.toolmanager) + if self.toolbar: + backend_tools.add_tools_to_container(self.toolbar) if self.toolbar is not None: self.toolbar.Realize() @@ -1203,10 +1215,19 @@ def _get_toolbar(self, statbar): if rcParams['toolbar'] == 'toolbar2': toolbar = NavigationToolbar2Wx(self.canvas) toolbar.set_status_bar(statbar) + elif matplotlib.rcParams['toolbar'] == 'toolmanager': + toolbar = ToolbarWx(self.toolmanager, self) else: toolbar = None return toolbar + def _get_toolmanager(self): + if matplotlib.rcParams['toolbar'] == 'toolmanager': + toolmanager = ToolManager(self.canvas.figure) + else: + toolmanager = None + return toolmanager + def get_canvas(self, fig): return FigureCanvasWx(self, -1, fig) @@ -1263,8 +1284,8 @@ def __init__(self, canvas, num, frame): self.frame = frame self.window = frame - self.tb = frame.GetToolBar() - self.toolbar = self.tb # consistent with other backends + self.toolmanager = frame.toolmanager + self.toolbar = frame.GetToolBar() def show(self): self.frame.Show() @@ -1328,6 +1349,22 @@ def _load_bitmap(filename): return bmp +_FRAME_ICON = None +def _set_frame_icon(frame): + # set frame icon + global _FRAME_ICON + if not _FRAME_ICON: + _FRAME_ICON = bundle = wx.IconBundle() + for image in ('matplotlib.png', 'matplotlib_large.png'): + image = os.path.join(matplotlib.rcParams['datapath'], 'images', + image) + if not os.path.exists(image): continue + icon = wx.Icon(_load_bitmap(image)) + if not icon.IsOk(): return + bundle.AddIcon(icon) + frame.SetIcons(_FRAME_ICON) + + class MenuButtonWx(wx.Button): """ wxPython does not permit a menu to be incorporated directly into a toolbar. @@ -1675,7 +1712,7 @@ class StatusBarWx(wx.StatusBar): convenience. """ - def __init__(self, parent): + def __init__(self, parent, *args, **kwargs): wx.StatusBar.__init__(self, parent, -1) self.SetFieldsCount(2) self.SetStatusText("None", 1) @@ -1690,9 +1727,107 @@ def set_function(self, string): # tools for matplotlib.backend_managers.ToolManager: -# for now only SaveFigure, SetCursor and Rubberband are implemented -# once a ToolbarWx is implemented, also FigureManagerWx needs to be -# modified, similar to pull request #9934 + +class ToolbarWx(ToolContainerBase, wx.ToolBar): + def __init__(self, toolmanager, parent, style=wx.TB_HORIZONTAL): + ToolContainerBase.__init__(self, toolmanager) + wx.ToolBar.__init__(self, parent, -1, style=style) + self._toolitems = {} + self._groups = {} + self._last = None + + def add_toolitem( + self, name, group, position, image_file, description, toggle): + + before, group = self._add_to_group(group, name, position) + idx = self.GetToolPos(before.Id) + if image_file: + bmp = _load_bitmap(image_file) + kind = wx.ITEM_NORMAL if not toggle else wx.ITEM_CHECK + tool = self.InsertTool(idx, -1, name, bmp, wx.NullBitmap, kind, + description or "") + else: + size = (self.GetTextExtent(name)[0]+10,-1) + if toggle: + control = wx.ToggleButton(self, -1, name, size=size) + else: + control = wx.Button(self, -1, name, size=size) + tool = self.InsertControl(idx, control, label=name) + self.Realize() + + def handler(event): + self.trigger_tool(name) + + if image_file: + self.Bind(wx.EVT_TOOL, handler, tool) + else: + control.Bind(wx.EVT_LEFT_DOWN, handler) + + self._last = tool + self._toolitems.setdefault(name, []) + group.insert(position, tool) + self._toolitems[name].append((tool, handler)) + + def _add_to_group(self, group, name, position): + gr = self._groups.get(group, []) + if not gr: + sep = self.AddSeparator() + gr.append(sep) + before = gr[position] + self._groups[group] = gr + return before, gr + + def toggle_toolitem(self, name, toggled): + if name not in self._toolitems: + return + for tool, handler in self._toolitems[name]: + if not tool.IsControl(): + self.ToggleTool(tool.Id, toggled) + else: + tool.GetControl().SetValue(toggled) + self.Refresh() + def remove_toolitem(self, name): + for tool, handler in self._toolitems[name]: + self.DeleteTool(tool.Id) + del self._toolitems[name] + + +class StatusbarWx(StatusbarBase, wx.StatusBar): + """for use with ToolManager""" + def __init__(self, parent, *args, **kwargs): + StatusbarBase.__init__(self, *args, **kwargs) + wx.StatusBar.__init__(self, parent, -1) + self.SetFieldsCount(1) + self.SetStatusText("") + + def set_message(self, s): + self.SetStatusText(s) + + +class ConfigureSubplotsWx(backend_tools.ConfigureSubplotsBase): + def trigger(self, *args): + self.configure_subplots() + + def configure_subplots(self): + frame = wx.Frame(None, -1, "Configure subplots") + _set_frame_icon(frame) + frame.toolmanager = None + + toolfig = Figure((6, 3)) + canvas = self.get_canvas(frame, toolfig) + + # Now put all into a sizer + sizer = wx.BoxSizer(wx.VERTICAL) + # This way of adding to sizer allows resizing + sizer.Add(canvas, 1, wx.LEFT | wx.TOP | wx.GROW) + frame.SetSizer(sizer) + frame.Fit() + tool = SubplotTool(self.canvas.figure, toolfig) + frame.Show() + + def get_canvas(self, frame, fig): + return type(self.canvas)(frame, -1, fig) + class SaveFigureWx(backend_tools.SaveFigureBase): def trigger(self, *args): @@ -1827,6 +1962,7 @@ def remove_rubberband(self, dc=None): backend_tools.ToolSaveFigure = SaveFigureWx +backend_tools.ToolConfigureSubplots = ConfigureSubplotsWx backend_tools.ToolSetCursor = SetCursorWx backend_tools.ToolRubberband = RubberbandWx From 5bd1d761d08908e28d6dca33f5f7ee9e2c367cbd Mon Sep 17 00:00:00 2001 From: DietmarSchwertberger Date: Wed, 21 Mar 2018 04:08:00 +0100 Subject: [PATCH 2/5] fix for non-toolmanager use of Wx backends; set frame icon for subplot tool --- lib/matplotlib/backends/backend_wx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 2ee7eb9d1deb..e6e022092317 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1284,7 +1284,7 @@ def __init__(self, canvas, num, frame): self.frame = frame self.window = frame - self.toolmanager = frame.toolmanager + self.toolmanager = getattr(frame, "toolmanager", None) self.toolbar = frame.GetToolBar() def show(self): @@ -1552,6 +1552,7 @@ def pan(self, *args): def configure_subplots(self, evt): global FigureManager # placates pyflakes: created by @_Backend.export frame = wx.Frame(None, -1, "Configure subplots") + _set_frame_icon(frame) toolfig = Figure((6, 3)) canvas = self.get_canvas(frame, toolfig) @@ -1811,7 +1812,6 @@ def trigger(self, *args): def configure_subplots(self): frame = wx.Frame(None, -1, "Configure subplots") _set_frame_icon(frame) - frame.toolmanager = None toolfig = Figure((6, 3)) canvas = self.get_canvas(frame, toolfig) From 9844acc11e8a5dd6fe3f5f362aae55971128a3a3 Mon Sep 17 00:00:00 2001 From: DietmarSchwertberger Date: Wed, 21 Mar 2018 10:54:36 +0100 Subject: [PATCH 3/5] fix PEP8 warnings --- lib/matplotlib/backends/backend_wx.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index e6e022092317..68b4f66e8802 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1350,6 +1350,8 @@ def _load_bitmap(filename): _FRAME_ICON = None + + def _set_frame_icon(frame): # set frame icon global _FRAME_ICON @@ -1358,9 +1360,11 @@ def _set_frame_icon(frame): for image in ('matplotlib.png', 'matplotlib_large.png'): image = os.path.join(matplotlib.rcParams['datapath'], 'images', image) - if not os.path.exists(image): continue + if not os.path.exists(image): + continue icon = wx.Icon(_load_bitmap(image)) - if not icon.IsOk(): return + if not icon.IsOk(): + return bundle.AddIcon(icon) frame.SetIcons(_FRAME_ICON) @@ -1748,7 +1752,7 @@ def add_toolitem( tool = self.InsertTool(idx, -1, name, bmp, wx.NullBitmap, kind, description or "") else: - size = (self.GetTextExtent(name)[0]+10,-1) + size = (self.GetTextExtent(name)[0]+10, -1) if toggle: control = wx.ToggleButton(self, -1, name, size=size) else: @@ -1787,6 +1791,7 @@ def toggle_toolitem(self, name, toggled): else: tool.GetControl().SetValue(toggled) self.Refresh() + def remove_toolitem(self, name): for tool, handler in self._toolitems[name]: self.DeleteTool(tool.Id) From 01a83de610b5326474a3fa412efd3f4d8a04d9db Mon Sep 17 00:00:00 2001 From: DietmarSchwertberger Date: Mon, 26 Mar 2018 19:16:38 +0200 Subject: [PATCH 4/5] don't store icon as global; re-load instead --- lib/matplotlib/backends/backend_wx.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 68b4f66e8802..1cf6d05f33c9 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1349,24 +1349,18 @@ def _load_bitmap(filename): return bmp -_FRAME_ICON = None - - def _set_frame_icon(frame): # set frame icon - global _FRAME_ICON - if not _FRAME_ICON: - _FRAME_ICON = bundle = wx.IconBundle() - for image in ('matplotlib.png', 'matplotlib_large.png'): - image = os.path.join(matplotlib.rcParams['datapath'], 'images', - image) - if not os.path.exists(image): - continue - icon = wx.Icon(_load_bitmap(image)) - if not icon.IsOk(): - return - bundle.AddIcon(icon) - frame.SetIcons(_FRAME_ICON) + bundle = wx.IconBundle() + for image in ('matplotlib.png', 'matplotlib_large.png'): + image = os.path.join(matplotlib.rcParams['datapath'], 'images', image) + if not os.path.exists(image): + continue + icon = wx.Icon(_load_bitmap(image)) + if not icon.IsOk(): + return + bundle.AddIcon(icon) + frame.SetIcons(bundle) class MenuButtonWx(wx.Button): From 71043a6e8720e20ea11785e6fbc5b3ee195667f7 Mon Sep 17 00:00:00 2001 From: DietmarSchwertberger Date: Mon, 23 Apr 2018 20:22:38 +0200 Subject: [PATCH 5/5] add StatusBar to MyWx to avoid metaclass error message --- doc/sphinxext/mock_gui_toolkits.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/sphinxext/mock_gui_toolkits.py b/doc/sphinxext/mock_gui_toolkits.py index bb378e77382c..0cb9f93635b4 100644 --- a/doc/sphinxext/mock_gui_toolkits.py +++ b/doc/sphinxext/mock_gui_toolkits.py @@ -118,6 +118,9 @@ class ToolBar(object): class Frame(object): pass + class StatusBar(object): + pass + def setup(app): sys.modules.update( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy