Skip to content

Unify toolbar init across backends. #22250

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
Jan 26, 2022
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
17 changes: 16 additions & 1 deletion lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,9 @@ class FigureManagerBase:
figure.canvas.manager.button_press_handler_id)
"""

_toolbar2_class = None
_toolmanager_toolbar_class = None

def __init__(self, canvas, num):
self.canvas = canvas
canvas.manager = self # store a pointer to parent
Expand All @@ -2734,7 +2737,19 @@ def __init__(self, canvas, num):
self.toolmanager = (ToolManager(canvas.figure)
if mpl.rcParams['toolbar'] == 'toolmanager'
else None)
self.toolbar = None
if (mpl.rcParams["toolbar"] == "toolbar2"
and self._toolbar2_class):
self.toolbar = self._toolbar2_class(self.canvas)
elif (mpl.rcParams["toolbar"] == "toolmanager"
and self._toolmanager_toolbar_class):
self.toolbar = self._toolmanager_toolbar_class(self.toolmanager)
else:
self.toolbar = None

if self.toolmanager:
tools.add_tools_to_manager(self.toolmanager)
if self.toolbar:
tools.add_tools_to_container(self.toolbar)

@self.canvas.figure.add_axobserver
def notify_axes_change(fig):
Expand Down
17 changes: 2 additions & 15 deletions lib/matplotlib/backends/_backend_tk.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,8 @@ def __init__(self, canvas, num, window):
self.window.withdraw()
# packing toolbar first, because if space is getting low, last packed
# widget is getting shrunk first (-> the canvas)
self.toolbar = self._get_toolbar()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

if self.toolmanager:
backend_tools.add_tools_to_manager(self.toolmanager)
if self.toolbar:
backend_tools.add_tools_to_container(self.toolbar)

# If the window has per-monitor DPI awareness, then setup a Tk variable
# to store the DPI, which will be updated by the C code, and the trace
# will handle it on the Python side.
Expand All @@ -430,15 +424,6 @@ def __init__(self, canvas, num, window):

self._shown = False

def _get_toolbar(self):
if mpl.rcParams['toolbar'] == 'toolbar2':
toolbar = NavigationToolbar2Tk(self.canvas)
elif mpl.rcParams['toolbar'] == 'toolmanager':
toolbar = ToolbarTk(self.toolmanager)
else:
toolbar = None
return toolbar

def _update_window_dpi(self, *args):
newdpi = self._window_dpi.get()
self.window.call('tk', 'scaling', newdpi / 72)
Expand Down Expand Up @@ -898,6 +883,8 @@ def trigger(self, *args):


Toolbar = ToolbarTk
FigureManagerTk._toolbar2_class = NavigationToolbar2Tk
FigureManagerTk._toolmanager_toolbar_class = ToolbarTk


@_Backend.export
Expand Down
9 changes: 2 additions & 7 deletions lib/matplotlib/backends/backend_gtk3.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,6 @@ def __init__(self, canvas, num):
# calculate size for window
w, h = self.canvas.get_width_height()

self.toolbar = self._get_toolbar()

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.show()
self.vbox.pack_end(self.toolbar, False, False, 0)
Expand Down Expand Up @@ -737,6 +730,8 @@ def error_msg_gtk(msg, parent=None):
FigureCanvasGTK3, _backend_gtk.ConfigureSubplotsGTK)
backend_tools._register_tool_class(
FigureCanvasGTK3, _backend_gtk.RubberbandGTK)
FigureManagerGTK3._toolbar2_class = NavigationToolbar2GTK3
FigureManagerGTK3._toolmanager_toolbar_class = ToolbarGTK3


@_BackendGTK.export
Expand Down
20 changes: 2 additions & 18 deletions lib/matplotlib/backends/backend_gtk4.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,13 +279,6 @@ def __init__(self, canvas, num):
# calculate size for window
w, h = self.canvas.get_width_height()

self.toolbar = self._get_toolbar()

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:
sw = Gtk.ScrolledWindow(vscrollbar_policy=Gtk.PolicyType.NEVER)
sw.set_child(self.toolbar)
Expand Down Expand Up @@ -335,17 +328,6 @@ def full_screen_toggle(self):
else:
self.window.unfullscreen()

def _get_toolbar(self):
# must be inited after the window, drawingArea and figure
# attrs are set
if mpl.rcParams['toolbar'] == 'toolbar2':
toolbar = NavigationToolbar2GTK4(self.canvas)
elif mpl.rcParams['toolbar'] == 'toolmanager':
toolbar = ToolbarGTK4(self.toolmanager)
else:
toolbar = None
return toolbar

def get_window_title(self):
return self.window.get_title()

Expand Down Expand Up @@ -673,6 +655,8 @@ def trigger(self, *args, **kwargs):
backend_tools._register_tool_class(
FigureCanvasGTK4, _backend_gtk.RubberbandGTK)
Toolbar = ToolbarGTK4
FigureManagerGTK4._toolbar2_class = NavigationToolbar2GTK4
FigureManagerGTK4._toolmanager_toolbar_class = ToolbarGTK4


@_BackendGTK.export
Expand Down
42 changes: 18 additions & 24 deletions lib/matplotlib/backends/backend_macosx.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,30 +62,6 @@ def resize(self, width, height):
self.draw_idle()


class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
"""
Wrap everything up into a window for the pylab interface
"""
def __init__(self, canvas, num):
_macosx.FigureManager.__init__(self, canvas)
icon_path = str(cbook._get_data_path('images/matplotlib.pdf'))
_macosx.FigureManager.set_icon(icon_path)
FigureManagerBase.__init__(self, canvas, num)
if mpl.rcParams['toolbar'] == 'toolbar2':
self.toolbar = NavigationToolbar2Mac(canvas)
else:
self.toolbar = None
if self.toolbar is not None:
self.toolbar.update()

if mpl.is_interactive():
self.show()
self.canvas.draw_idle()

def close(self):
Gcf.destroy(self)


class NavigationToolbar2Mac(_macosx.NavigationToolbar2, NavigationToolbar2):

def __init__(self, canvas):
Expand Down Expand Up @@ -123,6 +99,24 @@ def set_message(self, message):
_macosx.NavigationToolbar2.set_message(self, message.encode('utf-8'))


class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
_toolbar2_class = NavigationToolbar2Mac

def __init__(self, canvas, num):
_macosx.FigureManager.__init__(self, canvas)
icon_path = str(cbook._get_data_path('images/matplotlib.pdf'))
_macosx.FigureManager.set_icon(icon_path)
FigureManagerBase.__init__(self, canvas, num)
if self.toolbar is not None:
self.toolbar.update()
if mpl.is_interactive():
self.show()
self.canvas.draw_idle()

def close(self):
Gcf.destroy(self)


@_Backend.export
class _BackendMac(_Backend):
FigureCanvas = FigureCanvasMac
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_nbagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class NavigationIPy(NavigationToolbar2WebAgg):


class FigureManagerNbAgg(FigureManagerWebAgg):
ToolbarCls = NavigationIPy
_toolbar2_class = ToolbarCls = NavigationIPy

def __init__(self, canvas, num):
self._shown = False
Expand Down
22 changes: 4 additions & 18 deletions lib/matplotlib/backends/backend_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,13 +529,6 @@ def __init__(self, canvas, num):

self.window._destroying = False

self.toolbar = self._get_toolbar(self.canvas, self.window)

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:
self.window.addToolBar(self.toolbar)
tbs_height = self.toolbar.sizeHint().height()
Expand Down Expand Up @@ -582,17 +575,6 @@ def _widgetclosed(self):
# Gcf can get destroyed before the Gcf.destroy
# line is run, leading to a useless AttributeError.

def _get_toolbar(self, canvas, parent):
# must be inited after the window, drawingArea and figure
# attrs are set
if mpl.rcParams['toolbar'] == 'toolbar2':
toolbar = NavigationToolbar2QT(canvas)
elif mpl.rcParams['toolbar'] == 'toolmanager':
toolbar = ToolbarQt(self.toolmanager)
else:
toolbar = None
return toolbar

def resize(self, width, height):
# The Qt methods return sizes in 'virtual' pixels so we do need to
# rescale from physical to logical pixels.
Expand Down Expand Up @@ -1021,6 +1003,10 @@ def trigger(self, *args, **kwargs):
qApp.clipboard().setPixmap(pixmap)


FigureManagerQT._toolbar2_class = NavigationToolbar2QT
FigureManagerQT._toolmanager_toolbar_class = ToolbarQt


@_Backend.export
class _BackendQT(_Backend):
FigureCanvas = FigureCanvasQT
Expand Down
7 changes: 1 addition & 6 deletions lib/matplotlib/backends/backend_webagg_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,20 +453,15 @@ def set_history_buttons(self):


class FigureManagerWebAgg(backend_bases.FigureManagerBase):
ToolbarCls = NavigationToolbar2WebAgg
_toolbar2_class = ToolbarCls = NavigationToolbar2WebAgg

def __init__(self, canvas, num):
self.web_sockets = set()
super().__init__(canvas, num)
self.toolbar = self._get_toolbar(canvas)

def show(self):
pass

def _get_toolbar(self, canvas):
toolbar = self.ToolbarCls(canvas)
return toolbar

def resize(self, w, h, forward=True):
self._send_event(
'resize',
Expand Down
47 changes: 12 additions & 35 deletions lib/matplotlib/backends/backend_wx.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,13 +901,9 @@ def __init__(self, num, fig, *, canvas_class=None):

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.SetToolBar(self.toolbar)
toolbar = self.canvas.manager.toolbar
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that not?

Suggested change
toolbar = self.canvas.manager.toolbar
toolbar = self.figmgr.toolbar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I have some later plans to get rid of the (non-standard) figmgr as well...

if toolbar is not None:
self.SetToolBar(toolbar)

# On Windows, canvas sizing must occur after toolbar addition;
# otherwise the toolbar further resizes the canvas.
Expand All @@ -920,18 +916,8 @@ def __init__(self, num, fig, *, canvas_class=None):

self.Bind(wx.EVT_CLOSE, self._on_close)

@property
def toolmanager(self):
return self.figmgr.toolmanager

def _get_toolbar(self):
if mpl.rcParams['toolbar'] == 'toolbar2':
toolbar = NavigationToolbar2Wx(self.canvas)
elif mpl.rcParams['toolbar'] == 'toolmanager':
toolbar = ToolbarWx(self.toolmanager)
else:
toolbar = None
return toolbar
toolmanager = property(lambda self: self.figmgr.toolmanager)
toolbar = property(lambda self: self.GetToolBar()) # backcompat

@_api.deprecated(
"3.6", alternative="the canvas_class constructor parameter")
Expand All @@ -956,7 +942,7 @@ def _on_close(self, event):

def Destroy(self, *args, **kwargs):
try:
self.canvas.mpl_disconnect(self.toolbar._id_drag)
self.canvas.mpl_disconnect(self.canvas.manager.toolbar._id_drag)
# Rationale for line above: see issue 2941338.
except AttributeError:
pass # classic toolbar lacks the attribute
Expand All @@ -965,8 +951,8 @@ def Destroy(self, *args, **kwargs):
# MPLBACKEND=wxagg python -c 'from pylab import *; plot()'.
if self and not self.IsBeingDeleted():
super().Destroy(*args, **kwargs)
# self.toolbar.Destroy() should not be necessary if the close event
# is allowed to propagate.
# toolbar.Destroy() should not be necessary if the close event is
# allowed to propagate.
return True


Expand All @@ -988,20 +974,7 @@ class FigureManagerWx(FigureManagerBase):
def __init__(self, canvas, num, frame):
_log.debug("%s - __init__()", type(self))
self.frame = self.window = frame
self._initializing = True
super().__init__(canvas, num)
self._initializing = False

@property
def toolbar(self):
return self.frame.GetToolBar()

@toolbar.setter
def toolbar(self, value):
# Never allow this, except that base class inits this to None before
# the frame is set up.
if not self._initializing:
raise AttributeError("can't set attribute")

def show(self):
# docstring inherited
Expand Down Expand Up @@ -1373,6 +1346,10 @@ def trigger(self, *args, **kwargs):
wx.TheClipboard.Close()


FigureManagerWx._toolbar2_class = NavigationToolbar2Wx
FigureManagerWx._toolmanager_toolbar_class = ToolbarWx


@_Backend.export
class _BackendWx(_Backend):
FigureCanvas = FigureCanvasWx
Expand Down
10 changes: 0 additions & 10 deletions lib/matplotlib/tests/test_backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
from matplotlib.backend_bases import (
FigureCanvasBase, LocationEvent, MouseButton, MouseEvent,
NavigationToolbar2, RendererBase)
from matplotlib.backend_tools import (ToolZoom, ToolPan, RubberbandBase,
ToolViewsPositions, _views_positions)
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
Expand Down Expand Up @@ -250,14 +248,6 @@ def test_toolbar_zoompan():
plt.rcParams['toolbar'] = 'toolmanager'
ax = plt.gca()
assert ax.get_navigate_mode() is None
ax.figure.canvas.manager.toolmanager.add_tool(name="zoom",
tool=ToolZoom)
ax.figure.canvas.manager.toolmanager.add_tool(name="pan",
tool=ToolPan)
ax.figure.canvas.manager.toolmanager.add_tool(name=_views_positions,
tool=ToolViewsPositions)
ax.figure.canvas.manager.toolmanager.add_tool(name='rubberband',
tool=RubberbandBase)
ax.figure.canvas.manager.toolmanager.trigger_tool('zoom')
assert ax.get_navigate_mode() == "ZOOM"
ax.figure.canvas.manager.toolmanager.trigger_tool('pan')
Expand Down