Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 99cb3dd

Browse files
authored
Merge pull request #10851 from DietmarSchwertberger/wxtoolmanager
ENH: Wx Toolbar for ToolManager
2 parents 1209037 + 71043a6 commit 99cb3dd

File tree

3 files changed

+149
-10
lines changed

3 files changed

+149
-10
lines changed

doc/sphinxext/mock_gui_toolkits.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ class ToolBar(object):
118118
class Frame(object):
119119
pass
120120

121+
class StatusBar(object):
122+
pass
123+
121124

122125
def setup(app):
123126
sys.modules.update(

examples/user_interfaces/toolmanager_sgskip.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
matplotlib.use('GTK3Cairo')
2020
# matplotlib.use('TkAgg')
2121
# matplotlib.use('QT5Agg')
22+
# matplotlib.use('WxAgg')
2223
matplotlib.rcParams['toolbar'] = 'toolmanager'
2324
import matplotlib.pyplot as plt
2425
from matplotlib.backend_tools import ToolBase, ToolToggleBase

lib/matplotlib/backends/backend_wx.py

Lines changed: 145 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
import matplotlib
1717
from matplotlib.backend_bases import (
1818
_Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase,
19-
NavigationToolbar2, RendererBase, TimerBase, cursors)
19+
NavigationToolbar2, RendererBase, TimerBase, cursors, ToolContainerBase,
20+
StatusbarBase)
2021
from matplotlib.backend_bases import _has_pil
2122

2223
from matplotlib._pylab_helpers import Gcf
@@ -25,6 +26,7 @@
2526
from matplotlib.path import Path
2627
from matplotlib.transforms import Affine2D
2728
from matplotlib.widgets import SubplotTool
29+
from matplotlib.backend_managers import ToolManager
2830
from matplotlib import cbook, rcParams, backend_tools
2931

3032
import wx
@@ -1156,9 +1158,8 @@ def __init__(self, num, fig):
11561158
# Frame will be sized later by the Fit method
11571159
DEBUG_MSG("__init__()", 1, self)
11581160
self.num = num
1161+
_set_frame_icon(self)
11591162

1160-
statbar = StatusBarWx(self)
1161-
self.SetStatusBar(statbar)
11621163
self.canvas = self.get_canvas(fig)
11631164
self.canvas.SetInitialSize(wx.Size(fig.bbox.width, fig.bbox.height))
11641165
self.canvas.SetFocus()
@@ -1167,7 +1168,18 @@ def __init__(self, num, fig):
11671168
# By adding toolbar in sizer, we are able to put it at the bottom
11681169
# of the frame - so appearance is closer to GTK version
11691170

1170-
self.toolbar = self._get_toolbar(statbar)
1171+
self.toolmanager = self._get_toolmanager()
1172+
if self.toolmanager:
1173+
self.statusbar = StatusbarWx(self, self.toolmanager)
1174+
else:
1175+
self.statusbar = StatusBarWx(self)
1176+
self.SetStatusBar(self.statusbar)
1177+
self.toolbar = self._get_toolbar(self.statusbar)
1178+
1179+
if self.toolmanager:
1180+
backend_tools.add_tools_to_manager(self.toolmanager)
1181+
if self.toolbar:
1182+
backend_tools.add_tools_to_container(self.toolbar)
11711183

11721184
if self.toolbar is not None:
11731185
self.toolbar.Realize()
@@ -1201,10 +1213,19 @@ def _get_toolbar(self, statbar):
12011213
if rcParams['toolbar'] == 'toolbar2':
12021214
toolbar = NavigationToolbar2Wx(self.canvas)
12031215
toolbar.set_status_bar(statbar)
1216+
elif matplotlib.rcParams['toolbar'] == 'toolmanager':
1217+
toolbar = ToolbarWx(self.toolmanager, self)
12041218
else:
12051219
toolbar = None
12061220
return toolbar
12071221

1222+
def _get_toolmanager(self):
1223+
if matplotlib.rcParams['toolbar'] == 'toolmanager':
1224+
toolmanager = ToolManager(self.canvas.figure)
1225+
else:
1226+
toolmanager = None
1227+
return toolmanager
1228+
12081229
def get_canvas(self, fig):
12091230
return FigureCanvasWx(self, -1, fig)
12101231

@@ -1261,8 +1282,8 @@ def __init__(self, canvas, num, frame):
12611282
self.frame = frame
12621283
self.window = frame
12631284

1264-
self.tb = frame.GetToolBar()
1265-
self.toolbar = self.tb # consistent with other backends
1285+
self.toolmanager = getattr(frame, "toolmanager", None)
1286+
self.toolbar = frame.GetToolBar()
12661287

12671288
def show(self):
12681289
self.frame.Show()
@@ -1326,6 +1347,20 @@ def _load_bitmap(filename):
13261347
return bmp
13271348

13281349

1350+
def _set_frame_icon(frame):
1351+
# set frame icon
1352+
bundle = wx.IconBundle()
1353+
for image in ('matplotlib.png', 'matplotlib_large.png'):
1354+
image = os.path.join(matplotlib.rcParams['datapath'], 'images', image)
1355+
if not os.path.exists(image):
1356+
continue
1357+
icon = wx.Icon(_load_bitmap(image))
1358+
if not icon.IsOk():
1359+
return
1360+
bundle.AddIcon(icon)
1361+
frame.SetIcons(bundle)
1362+
1363+
13291364
class MenuButtonWx(wx.Button):
13301365
"""
13311366
wxPython does not permit a menu to be incorporated directly into a toolbar.
@@ -1513,6 +1548,7 @@ def pan(self, *args):
15131548
def configure_subplots(self, evt):
15141549
global FigureManager # placates pyflakes: created by @_Backend.export
15151550
frame = wx.Frame(None, -1, "Configure subplots")
1551+
_set_frame_icon(frame)
15161552

15171553
toolfig = Figure((6, 3))
15181554
canvas = self.get_canvas(frame, toolfig)
@@ -1673,7 +1709,7 @@ class StatusBarWx(wx.StatusBar):
16731709
convenience.
16741710
"""
16751711

1676-
def __init__(self, parent):
1712+
def __init__(self, parent, *args, **kwargs):
16771713
wx.StatusBar.__init__(self, parent, -1)
16781714
self.SetFieldsCount(2)
16791715
self.SetStatusText("None", 1)
@@ -1688,9 +1724,107 @@ def set_function(self, string):
16881724

16891725

16901726
# tools for matplotlib.backend_managers.ToolManager:
1691-
# for now only SaveFigure, SetCursor and Rubberband are implemented
1692-
# once a ToolbarWx is implemented, also FigureManagerWx needs to be
1693-
# modified, similar to pull request #9934
1727+
1728+
class ToolbarWx(ToolContainerBase, wx.ToolBar):
1729+
def __init__(self, toolmanager, parent, style=wx.TB_HORIZONTAL):
1730+
ToolContainerBase.__init__(self, toolmanager)
1731+
wx.ToolBar.__init__(self, parent, -1, style=style)
1732+
self._toolitems = {}
1733+
self._groups = {}
1734+
self._last = None
1735+
1736+
def add_toolitem(
1737+
self, name, group, position, image_file, description, toggle):
1738+
1739+
before, group = self._add_to_group(group, name, position)
1740+
idx = self.GetToolPos(before.Id)
1741+
if image_file:
1742+
bmp = _load_bitmap(image_file)
1743+
kind = wx.ITEM_NORMAL if not toggle else wx.ITEM_CHECK
1744+
tool = self.InsertTool(idx, -1, name, bmp, wx.NullBitmap, kind,
1745+
description or "")
1746+
else:
1747+
size = (self.GetTextExtent(name)[0]+10, -1)
1748+
if toggle:
1749+
control = wx.ToggleButton(self, -1, name, size=size)
1750+
else:
1751+
control = wx.Button(self, -1, name, size=size)
1752+
tool = self.InsertControl(idx, control, label=name)
1753+
self.Realize()
1754+
1755+
def handler(event):
1756+
self.trigger_tool(name)
1757+
1758+
if image_file:
1759+
self.Bind(wx.EVT_TOOL, handler, tool)
1760+
else:
1761+
control.Bind(wx.EVT_LEFT_DOWN, handler)
1762+
1763+
self._last = tool
1764+
self._toolitems.setdefault(name, [])
1765+
group.insert(position, tool)
1766+
self._toolitems[name].append((tool, handler))
1767+
1768+
def _add_to_group(self, group, name, position):
1769+
gr = self._groups.get(group, [])
1770+
if not gr:
1771+
sep = self.AddSeparator()
1772+
gr.append(sep)
1773+
before = gr[position]
1774+
self._groups[group] = gr
1775+
return before, gr
1776+
1777+
def toggle_toolitem(self, name, toggled):
1778+
if name not in self._toolitems:
1779+
return
1780+
for tool, handler in self._toolitems[name]:
1781+
if not tool.IsControl():
1782+
self.ToggleTool(tool.Id, toggled)
1783+
else:
1784+
tool.GetControl().SetValue(toggled)
1785+
self.Refresh()
1786+
1787+
def remove_toolitem(self, name):
1788+
for tool, handler in self._toolitems[name]:
1789+
self.DeleteTool(tool.Id)
1790+
del self._toolitems[name]
1791+
1792+
1793+
class StatusbarWx(StatusbarBase, wx.StatusBar):
1794+
"""for use with ToolManager"""
1795+
def __init__(self, parent, *args, **kwargs):
1796+
StatusbarBase.__init__(self, *args, **kwargs)
1797+
wx.StatusBar.__init__(self, parent, -1)
1798+
self.SetFieldsCount(1)
1799+
self.SetStatusText("")
1800+
1801+
def set_message(self, s):
1802+
self.SetStatusText(s)
1803+
1804+
1805+
class ConfigureSubplotsWx(backend_tools.ConfigureSubplotsBase):
1806+
def trigger(self, *args):
1807+
self.configure_subplots()
1808+
1809+
def configure_subplots(self):
1810+
frame = wx.Frame(None, -1, "Configure subplots")
1811+
_set_frame_icon(frame)
1812+
1813+
toolfig = Figure((6, 3))
1814+
canvas = self.get_canvas(frame, toolfig)
1815+
1816+
# Now put all into a sizer
1817+
sizer = wx.BoxSizer(wx.VERTICAL)
1818+
# This way of adding to sizer allows resizing
1819+
sizer.Add(canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
1820+
frame.SetSizer(sizer)
1821+
frame.Fit()
1822+
tool = SubplotTool(self.canvas.figure, toolfig)
1823+
frame.Show()
1824+
1825+
def get_canvas(self, frame, fig):
1826+
return type(self.canvas)(frame, -1, fig)
1827+
16941828

16951829
class SaveFigureWx(backend_tools.SaveFigureBase):
16961830
def trigger(self, *args):
@@ -1837,6 +1971,7 @@ def trigger(self, *args, **kwargs):
18371971

18381972

18391973
backend_tools.ToolSaveFigure = SaveFigureWx
1974+
backend_tools.ToolConfigureSubplots = ConfigureSubplotsWx
18401975
backend_tools.ToolSetCursor = SetCursorWx
18411976
backend_tools.ToolRubberband = RubberbandWx
18421977
backend_tools.ToolCopyToClipboard = ToolCopyToClipboardWx

0 commit comments

Comments
 (0)