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 2d41a72

Browse filesBrowse files
committed
Simplify pan/zoom toggling.
- Store current active tool just in the .mode attribute, rather than both in .mode and ._active; use a "StrEnum" (like an IntEnum, but for strs...) for backcompat. - Connect a single handler which will dispatch to the correct sub-handler depending on the active tool, rather than having to disconnect and reconnect handlers every time a tool is changed.
1 parent f6b8891 commit 2d41a72
Copy full SHA for 2d41a72

File tree

Expand file treeCollapse file tree

4 files changed

+48
-64
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+48
-64
lines changed

‎lib/matplotlib/backend_bases.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_bases.py
+43-59Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"""
3030

3131
from contextlib import contextmanager
32-
from enum import IntEnum
32+
from enum import Enum, IntEnum
3333
import functools
3434
import importlib
3535
import io
@@ -2651,6 +2651,15 @@ def set_window_title(self, title):
26512651
cursors = tools.cursors
26522652

26532653

2654+
class _Mode(str, Enum):
2655+
NONE = ""
2656+
PAN = "pan/zoom"
2657+
ZOOM = "zoom rect"
2658+
2659+
def __str__(self):
2660+
return self.value
2661+
2662+
26542663
class NavigationToolbar2:
26552664
"""
26562665
Base class for the navigation cursor, version 2
@@ -2715,19 +2724,20 @@ def __init__(self, canvas):
27152724
canvas.toolbar = self
27162725
self._nav_stack = cbook.Stack()
27172726
self._xypress = None # location and axis info at the time of the press
2718-
self._idPress = None
2719-
self._idRelease = None
2720-
self._active = None
27212727
# This cursor will be set after the initial draw.
27222728
self._lastCursor = cursors.POINTER
27232729
self._init_toolbar()
2730+
self._id_press = self.canvas.mpl_connect(
2731+
'button_press_event', self._zoom_pan_handler)
2732+
self._id_release = self.canvas.mpl_connect(
2733+
'button_release_event', self._zoom_pan_handler)
27242734
self._id_drag = self.canvas.mpl_connect(
27252735
'motion_notify_event', self.mouse_move)
27262736
self._zoom_info = None
27272737

27282738
self._button_pressed = None # determined by button pressed at start
27292739

2730-
self.mode = '' # a mode string for the status bar
2740+
self.mode = _Mode.NONE # a mode string for the status bar
27312741
self.set_history_buttons()
27322742

27332743
def set_message(self, s):
@@ -2805,17 +2815,17 @@ def _update_cursor(self, event):
28052815
"""
28062816
Update the cursor after a mouse move event or a tool (de)activation.
28072817
"""
2808-
if not event.inaxes or not self._active:
2818+
if not event.inaxes or not self.mode:
28092819
if self._lastCursor != cursors.POINTER:
28102820
self.set_cursor(cursors.POINTER)
28112821
self._lastCursor = cursors.POINTER
28122822
else:
2813-
if (self._active == 'ZOOM'
2823+
if (self.mode == _Mode.ZOOM
28142824
and self._lastCursor != cursors.SELECT_REGION):
28152825
self.set_cursor(cursors.SELECT_REGION)
28162826
self._lastCursor = cursors.SELECT_REGION
2817-
elif (self._active == 'PAN' and
2818-
self._lastCursor != cursors.MOVE):
2827+
elif (self.mode == _Mode.PAN
2828+
and self._lastCursor != cursors.MOVE):
28192829
self.set_cursor(cursors.MOVE)
28202830
self._lastCursor = cursors.MOVE
28212831

@@ -2870,40 +2880,32 @@ def mouse_move(self, event):
28702880
else:
28712881
self.set_message(self.mode)
28722882

2883+
def _zoom_pan_handler(self, event):
2884+
if self.mode == _Mode.PAN:
2885+
if event.name == "button_press_event":
2886+
self.press_pan(event)
2887+
elif event.name == "button_release_event":
2888+
self.release_pan(event)
2889+
if self.mode == _Mode.ZOOM:
2890+
if event.name == "button_press_event":
2891+
self.press_zoom(event)
2892+
elif event.name == "button_release_event":
2893+
self.release_zoom(event)
2894+
28732895
def pan(self, *args):
28742896
"""
2875-
Activate the pan/zoom tool.
2897+
Toggle the pan/zoom tool.
28762898
28772899
Pan with left button, zoom with right.
28782900
"""
2879-
# set the pointer icon and button press funcs to the
2880-
# appropriate callbacks
2881-
2882-
if self._active == 'PAN':
2883-
self._active = None
2901+
if self.mode == _Mode.PAN:
2902+
self.mode = _Mode.NONE
2903+
self.canvas.widgetlock.release(self)
28842904
else:
2885-
self._active = 'PAN'
2886-
if self._idPress is not None:
2887-
self._idPress = self.canvas.mpl_disconnect(self._idPress)
2888-
self.mode = ''
2889-
2890-
if self._idRelease is not None:
2891-
self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
2892-
self.mode = ''
2893-
2894-
if self._active:
2895-
self._idPress = self.canvas.mpl_connect(
2896-
'button_press_event', self.press_pan)
2897-
self._idRelease = self.canvas.mpl_connect(
2898-
'button_release_event', self.release_pan)
2899-
self.mode = 'pan/zoom'
2905+
self.mode = _Mode.PAN
29002906
self.canvas.widgetlock(self)
2901-
else:
2902-
self.canvas.widgetlock.release(self)
2903-
29042907
for a in self.canvas.figure.get_axes():
2905-
a.set_navigate_mode(self._active)
2906-
2908+
a.set_navigate_mode(self.mode)
29072909
self.set_message(self.mode)
29082910

29092911
def press(self, event):
@@ -3101,33 +3103,15 @@ def update(self):
31013103
self.set_history_buttons()
31023104

31033105
def zoom(self, *args):
3104-
"""Activate zoom to rect mode."""
3105-
if self._active == 'ZOOM':
3106-
self._active = None
3106+
"""Toggle zoom to rect mode."""
3107+
if self.mode == _Mode.ZOOM:
3108+
self.mode = _Mode.NONE
3109+
self.canvas.widgetlock.release(self)
31073110
else:
3108-
self._active = 'ZOOM'
3109-
3110-
if self._idPress is not None:
3111-
self._idPress = self.canvas.mpl_disconnect(self._idPress)
3112-
self.mode = ''
3113-
3114-
if self._idRelease is not None:
3115-
self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
3116-
self.mode = ''
3117-
3118-
if self._active:
3119-
self._idPress = self.canvas.mpl_connect('button_press_event',
3120-
self.press_zoom)
3121-
self._idRelease = self.canvas.mpl_connect('button_release_event',
3122-
self.release_zoom)
3123-
self.mode = 'zoom rect'
3111+
self.mode = _Mode.ZOOM
31243112
self.canvas.widgetlock(self)
3125-
else:
3126-
self.canvas.widgetlock.release(self)
3127-
31283113
for a in self.canvas.figure.get_axes():
3129-
a.set_navigate_mode(self._active)
3130-
3114+
a.set_navigate_mode(self.mode)
31313115
self.set_message(self.mode)
31323116

31333117
def set_history_buttons(self):

‎lib/matplotlib/backends/backend_gtk3.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_gtk3.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ def _update_buttons_checked(self):
528528
button = self._gtk_ids.get(name)
529529
if button:
530530
with button.handler_block(button._signal_handler):
531-
button.set_active(self._active == active)
531+
button.set_active(self.mode.name == active)
532532

533533
def pan(self, *args):
534534
super().pan(*args)

‎lib/matplotlib/backends/backend_qt5.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_qt5.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,9 +745,9 @@ def edit_parameters(self):
745745
def _update_buttons_checked(self):
746746
# sync button checkstates to match active mode
747747
if 'pan' in self._actions:
748-
self._actions['pan'].setChecked(self._active == 'PAN')
748+
self._actions['pan'].setChecked(self.mode.name == 'PAN')
749749
if 'zoom' in self._actions:
750-
self._actions['zoom'].setChecked(self._active == 'ZOOM')
750+
self._actions['zoom'].setChecked(self.mode.name == 'ZOOM')
751751

752752
def pan(self, *args):
753753
super().pan(*args)

‎lib/matplotlib/backends/backend_wx.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_wx.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ def set_cursor(self, cursor):
12091209
self.canvas.Update()
12101210

12111211
def press(self, event):
1212-
if self._active == 'ZOOM':
1212+
if self.mode.name == 'ZOOM':
12131213
if not self.retinaFix:
12141214
self.wxoverlay = wx.Overlay()
12151215
else:
@@ -1221,7 +1221,7 @@ def press(self, event):
12211221
self.zoomAxes = event.inaxes
12221222

12231223
def release(self, event):
1224-
if self._active == 'ZOOM':
1224+
if self.mode.name == 'ZOOM':
12251225
# When the mouse is released we reset the overlay and it
12261226
# restores the former content to the window.
12271227
if not self.retinaFix:

0 commit comments

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