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 f4223d9

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 a4dca24 commit f4223d9
Copy full SHA for f4223d9

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

@@ -358,101 +356,66 @@ def remove_rubberband(self):
358356
pass
359357

360358

361-
class ToolQuit(ToolBase):
359+
class _ToolForwardingToClassicToolbar(ToolBase):
360+
_rc_entry = '' # Must be set by subclass.
361+
default_keymap = property(lambda self: mpl.rcParams[self._rc_entry])
362+
363+
def trigger(self, sender, event, data=None):
364+
sentinel = str(uuid.uuid4())
365+
# Trigger classic toolbar implementation by temporarily setting the keymap to a
366+
# unique key and sending an appropriate event.
367+
with cbook._setattr_cm(event, key=sentinel), \
368+
mpl.rc_context({self._rc_entry: sentinel}):
369+
mpl.backend_bases.key_press_handler(event, self.figure.canvas)
370+
371+
372+
class ToolQuit(_ToolForwardingToClassicToolbar):
362373
"""Tool to call the figure manager destroy method."""
363374

364375
description = 'Quit the figure'
365-
default_keymap = property(lambda self: mpl.rcParams['keymap.quit'])
366-
367-
def trigger(self, sender, event, data=None):
368-
Gcf.destroy_fig(self.figure)
376+
_rc_entry = 'keymap.quit'
369377

370378

371-
class ToolQuitAll(ToolBase):
379+
class ToolQuitAll(_ToolForwardingToClassicToolbar):
372380
"""Tool to call the figure manager destroy method."""
373381

374382
description = 'Quit all figures'
375-
default_keymap = property(lambda self: mpl.rcParams['keymap.quit_all'])
376-
377-
def trigger(self, sender, event, data=None):
378-
Gcf.destroy_all()
383+
_rc_entry = 'keymap.quit_all'
379384

380385

381-
class ToolGrid(ToolBase):
386+
class ToolGrid(_ToolForwardingToClassicToolbar):
382387
"""Tool to toggle the major grids of the figure."""
383388

384389
description = 'Toggle major grids'
385-
default_keymap = property(lambda self: mpl.rcParams['keymap.grid'])
386-
387-
def trigger(self, sender, event, data=None):
388-
sentinel = str(uuid.uuid4())
389-
# Trigger grid switching by temporarily setting :rc:`keymap.grid`
390-
# to a unique key and sending an appropriate event.
391-
with cbook._setattr_cm(event, key=sentinel), \
392-
mpl.rc_context({'keymap.grid': sentinel}):
393-
mpl.backend_bases.key_press_handler(event, self.figure.canvas)
390+
_rc_entry = 'keymap.grid'
394391

395392

396-
class ToolMinorGrid(ToolBase):
393+
class ToolMinorGrid(_ToolForwardingToClassicToolbar):
397394
"""Tool to toggle the major and minor grids of the figure."""
398395

399396
description = 'Toggle major and minor grids'
400-
default_keymap = property(lambda self: mpl.rcParams['keymap.grid_minor'])
401-
402-
def trigger(self, sender, event, data=None):
403-
sentinel = str(uuid.uuid4())
404-
# Trigger grid switching by temporarily setting :rc:`keymap.grid_minor`
405-
# to a unique key and sending an appropriate event.
406-
with cbook._setattr_cm(event, key=sentinel), \
407-
mpl.rc_context({'keymap.grid_minor': sentinel}):
408-
mpl.backend_bases.key_press_handler(event, self.figure.canvas)
397+
_rc_entry = 'keymap.grid_minor'
409398

410399

411-
class ToolFullScreen(ToolBase):
400+
class ToolFullScreen(_ToolForwardingToClassicToolbar):
412401
"""Tool to toggle full screen."""
413402

414403
description = 'Toggle fullscreen mode'
415-
default_keymap = property(lambda self: mpl.rcParams['keymap.fullscreen'])
404+
_rc_entry = 'keymap.fullscreen'
416405

417-
def trigger(self, sender, event, data=None):
418-
self.figure.canvas.manager.full_screen_toggle()
419-
420-
421-
class AxisScaleBase(ToolToggleBase):
422-
"""Base Tool to toggle between linear and logarithmic."""
423406

424-
def trigger(self, sender, event, data=None):
425-
if event.inaxes is None:
426-
return
427-
super().trigger(sender, event, data)
428-
429-
def enable(self, event=None):
430-
self.set_scale(event.inaxes, 'log')
431-
self.figure.canvas.draw_idle()
407+
class ToolXScale(_ToolForwardingToClassicToolbar):
408+
"""Tool to toggle between linear and logarithmic scales on the X axis."""
432409

433-
def disable(self, event=None):
434-
self.set_scale(event.inaxes, 'linear')
435-
self.figure.canvas.draw_idle()
410+
description = 'Toggle scale X axis'
411+
_rc_entry = 'keymap.xscale'
436412

437413

438-
class ToolYScale(AxisScaleBase):
414+
class ToolYScale(_ToolForwardingToClassicToolbar):
439415
"""Tool to toggle between linear and logarithmic scales on the Y axis."""
440416

441417
description = 'Toggle scale Y axis'
442-
default_keymap = property(lambda self: mpl.rcParams['keymap.yscale'])
443-
444-
def set_scale(self, ax, scale):
445-
ax.set_yscale(scale)
446-
447-
448-
class ToolXScale(AxisScaleBase):
449-
"""Tool to toggle between linear and logarithmic scales on the X axis."""
450-
451-
description = 'Toggle scale X axis'
452-
default_keymap = property(lambda self: mpl.rcParams['keymap.xscale'])
453-
454-
def set_scale(self, ax, scale):
455-
ax.set_xscale(scale)
418+
_rc_entry = 'keymap.yscale'
456419

457420

458421
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.