Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dce6631

Browse filesBrowse files
committed
Fix toolmanager x/y scale "togglers".
ToolXScale and ToolYScale actually *cannot* be implemented using ToolToggleBase because a single "toggle" flag cannot store the log/linear state of *multiple* axes at once (i.e. the behavior of pressing "l" becomes wrong as soon as there are multiple axes in a given figure). Instead these must be plain tools that inspect the actual scale on the axes before deciding what to do. In practice, the easiest is to again reuse the classic toolbar implementation, as is already done for ToolGrid and ToolMinorGrid. Factor out that "forward-to-classic-toolbar" implementation into a _ToolForwardingToClassicToolbar base class and use that whereever possible.
1 parent 07002c2 commit dce6631
Copy full SHA for dce6631

File tree

2 files changed

+44
-86
lines changed
Filter options

2 files changed

+44
-86
lines changed

‎lib/matplotlib/backend_tools.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_tools.py
+34-71Lines changed: 34 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
Abstract base classes define the primitives for Tools.
33
These tools are used by `matplotlib.backend_managers.ToolManager`
44
5-
:class:`ToolBase`
6-
Simple stateless tool
5+
`ToolBase`
6+
Simple stateless tool.
77
8-
:class:`ToolToggleBase`
9-
Tool that has two states, only one Toggle tool can be
10-
active at any given time for the same
11-
`matplotlib.backend_managers.ToolManager`
8+
`ToolToggleBase`
9+
Tool that has two states, only one Toggle tool can be active at any given time for
10+
the same `matplotlib.backend_managers.ToolManager`.
1211
"""
1312

1413
import enum
@@ -22,7 +21,6 @@
2221
import numpy as np
2322

2423
import matplotlib as mpl
25-
from matplotlib._pylab_helpers import Gcf
2624
from matplotlib import _api, cbook
2725

2826

@@ -352,101 +350,66 @@ def remove_rubberband(self):
352350
pass
353351

354352

355-
class ToolQuit(ToolBase):
353+
class _ToolForwardingToClassicToolbar(ToolBase):
354+
_rc_entry = '' # Must be set by subclass.
355+
default_keymap = property(lambda self: mpl.rcParams[self._rc_entry])
356+
357+
def trigger(self, sender, event, data=None):
358+
sentinel = str(uuid.uuid4())
359+
# Trigger classic key press event handling by temporarily setting the keymap to
360+
# a unique key and sending an event with that key.
361+
with (cbook._setattr_cm(event, key=sentinel),
362+
mpl.rc_context({self._rc_entry: sentinel})):
363+
mpl.backend_bases.key_press_handler(event, self.figure.canvas)
364+
365+
366+
class ToolQuit(_ToolForwardingToClassicToolbar):
356367
"""Tool to call the figure manager destroy method."""
357368

358369
description = 'Quit the figure'
359-
default_keymap = property(lambda self: mpl.rcParams['keymap.quit'])
360-
361-
def trigger(self, sender, event, data=None):
362-
Gcf.destroy_fig(self.figure)
370+
_rc_entry = 'keymap.quit'
363371

364372

365-
class ToolQuitAll(ToolBase):
373+
class ToolQuitAll(_ToolForwardingToClassicToolbar):
366374
"""Tool to call the figure manager destroy method."""
367375

368376
description = 'Quit all figures'
369-
default_keymap = property(lambda self: mpl.rcParams['keymap.quit_all'])
370-
371-
def trigger(self, sender, event, data=None):
372-
Gcf.destroy_all()
377+
_rc_entry = 'keymap.quit_all'
373378

374379

375-
class ToolGrid(ToolBase):
380+
class ToolGrid(_ToolForwardingToClassicToolbar):
376381
"""Tool to toggle the major grids of the figure."""
377382

378383
description = 'Toggle major grids'
379-
default_keymap = property(lambda self: mpl.rcParams['keymap.grid'])
380-
381-
def trigger(self, sender, event, data=None):
382-
sentinel = str(uuid.uuid4())
383-
# Trigger grid switching by temporarily setting :rc:`keymap.grid`
384-
# to a unique key and sending an appropriate event.
385-
with (cbook._setattr_cm(event, key=sentinel),
386-
mpl.rc_context({'keymap.grid': sentinel})):
387-
mpl.backend_bases.key_press_handler(event, self.figure.canvas)
384+
_rc_entry = 'keymap.grid'
388385

389386

390-
class ToolMinorGrid(ToolBase):
387+
class ToolMinorGrid(_ToolForwardingToClassicToolbar):
391388
"""Tool to toggle the major and minor grids of the figure."""
392389

393390
description = 'Toggle major and minor grids'
394-
default_keymap = property(lambda self: mpl.rcParams['keymap.grid_minor'])
395-
396-
def trigger(self, sender, event, data=None):
397-
sentinel = str(uuid.uuid4())
398-
# Trigger grid switching by temporarily setting :rc:`keymap.grid_minor`
399-
# to a unique key and sending an appropriate event.
400-
with (cbook._setattr_cm(event, key=sentinel),
401-
mpl.rc_context({'keymap.grid_minor': sentinel})):
402-
mpl.backend_bases.key_press_handler(event, self.figure.canvas)
391+
_rc_entry = 'keymap.grid_minor'
403392

404393

405-
class ToolFullScreen(ToolBase):
394+
class ToolFullScreen(_ToolForwardingToClassicToolbar):
406395
"""Tool to toggle full screen."""
407396

408397
description = 'Toggle fullscreen mode'
409-
default_keymap = property(lambda self: mpl.rcParams['keymap.fullscreen'])
398+
_rc_entry = 'keymap.fullscreen'
410399

411-
def trigger(self, sender, event, data=None):
412-
self.figure.canvas.manager.full_screen_toggle()
413-
414-
415-
class AxisScaleBase(ToolToggleBase):
416-
"""Base Tool to toggle between linear and logarithmic."""
417400

418-
def trigger(self, sender, event, data=None):
419-
if event.inaxes is None:
420-
return
421-
super().trigger(sender, event, data)
422-
423-
def enable(self, event=None):
424-
self.set_scale(event.inaxes, 'log')
425-
self.figure.canvas.draw_idle()
401+
class ToolXScale(_ToolForwardingToClassicToolbar):
402+
"""Tool to toggle between linear and logarithmic scales on the X axis."""
426403

427-
def disable(self, event=None):
428-
self.set_scale(event.inaxes, 'linear')
429-
self.figure.canvas.draw_idle()
404+
description = 'Toggle scale X axis'
405+
_rc_entry = 'keymap.xscale'
430406

431407

432-
class ToolYScale(AxisScaleBase):
408+
class ToolYScale(_ToolForwardingToClassicToolbar):
433409
"""Tool to toggle between linear and logarithmic scales on the Y axis."""
434410

435411
description = 'Toggle scale Y axis'
436-
default_keymap = property(lambda self: mpl.rcParams['keymap.yscale'])
437-
438-
def set_scale(self, ax, scale):
439-
ax.set_yscale(scale)
440-
441-
442-
class ToolXScale(AxisScaleBase):
443-
"""Tool to toggle between linear and logarithmic scales on the X axis."""
444-
445-
description = 'Toggle scale X axis'
446-
default_keymap = property(lambda self: mpl.rcParams['keymap.xscale'])
447-
448-
def set_scale(self, ax, scale):
449-
ax.set_xscale(scale)
412+
_rc_entry = 'keymap.yscale'
450413

451414

452415
class ToolViewsPositions(ToolBase):

‎lib/matplotlib/backend_tools.pyi

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_tools.pyi
+10-15Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,16 @@ class RubberbandBase(ToolBase):
5858
def draw_rubberband(self, *data) -> None: ...
5959
def remove_rubberband(self) -> None: ...
6060

61-
class ToolQuit(ToolBase): ...
62-
class ToolQuitAll(ToolBase): ...
63-
class ToolGrid(ToolBase): ...
64-
class ToolMinorGrid(ToolBase): ...
65-
class ToolFullScreen(ToolBase): ...
66-
67-
class AxisScaleBase(ToolToggleBase):
68-
def enable(self, event: ToolEvent | None = ...) -> None: ...
69-
def disable(self, event: ToolEvent | None = ...) -> None: ...
70-
71-
class ToolYScale(AxisScaleBase):
72-
def set_scale(self, ax: Axes, scale: str | ScaleBase) -> None: ...
73-
74-
class ToolXScale(AxisScaleBase):
75-
def set_scale(self, ax, scale: str | ScaleBase) -> None: ...
61+
class _ToolForwardingToClassicToolbar(ToolBase):
62+
_rc_entry: str
63+
64+
class ToolQuit(_ToolForwardingToClassicToolbar): ...
65+
class ToolQuitAll(_ToolForwardingToClassicToolbar): ...
66+
class ToolGrid(_ToolForwardingToClassicToolbar): ...
67+
class ToolMinorGrid(_ToolForwardingToClassicToolbar): ...
68+
class ToolFullScreen(_ToolForwardingToClassicToolbar): ...
69+
class ToolXScale(_ToolForwardingToClassicToolbar): ...
70+
class ToolYScale(_ToolForwardingToClassicToolbar): ...
7671

7772
class ToolViewsPositions(ToolBase):
7873
views: dict[Figure | Axes, cbook._Stack]

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.