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

Skip to content

Commit 1859c81

Browse files
authored
Merge pull request matplotlib#17135 from anntzer/panzoomhandler
Simplify pan/zoom toggling.
2 parents 32326fd + 2d41a72 commit 1859c81

File tree

4 files changed

+48
-64
lines changed

4 files changed

+48
-64
lines changed

lib/matplotlib/backend_bases.py

Lines 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
@@ -2652,6 +2652,15 @@ def set_window_title(self, title):
26522652
cursors = tools.cursors
26532653

26542654

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

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

2731-
self.mode = '' # a mode string for the status bar
2741+
self.mode = _Mode.NONE # a mode string for the status bar
27322742
self.set_history_buttons()
27332743

27342744
def set_message(self, s):
@@ -2806,17 +2816,17 @@ def _update_cursor(self, event):
28062816
"""
28072817
Update the cursor after a mouse move event or a tool (de)activation.
28082818
"""
2809-
if not event.inaxes or not self._active:
2819+
if not event.inaxes or not self.mode:
28102820
if self._lastCursor != cursors.POINTER:
28112821
self.set_cursor(cursors.POINTER)
28122822
self._lastCursor = cursors.POINTER
28132823
else:
2814-
if (self._active == 'ZOOM'
2824+
if (self.mode == _Mode.ZOOM
28152825
and self._lastCursor != cursors.SELECT_REGION):
28162826
self.set_cursor(cursors.SELECT_REGION)
28172827
self._lastCursor = cursors.SELECT_REGION
2818-
elif (self._active == 'PAN' and
2819-
self._lastCursor != cursors.MOVE):
2828+
elif (self.mode == _Mode.PAN
2829+
and self._lastCursor != cursors.MOVE):
28202830
self.set_cursor(cursors.MOVE)
28212831
self._lastCursor = cursors.MOVE
28222832

@@ -2871,40 +2881,32 @@ def mouse_move(self, event):
28712881
else:
28722882
self.set_message(self.mode)
28732883

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

29102912
def press(self, event):
@@ -3108,33 +3110,15 @@ def update(self):
31083110
self.set_history_buttons()
31093111

31103112
def zoom(self, *args):
3111-
"""Activate zoom to rect mode."""
3112-
if self._active == 'ZOOM':
3113-
self._active = None
3113+
"""Toggle zoom to rect mode."""
3114+
if self.mode == _Mode.ZOOM:
3115+
self.mode = _Mode.NONE
3116+
self.canvas.widgetlock.release(self)
31143117
else:
3115-
self._active = 'ZOOM'
3116-
3117-
if self._idPress is not None:
3118-
self._idPress = self.canvas.mpl_disconnect(self._idPress)
3119-
self.mode = ''
3120-
3121-
if self._idRelease is not None:
3122-
self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
3123-
self.mode = ''
3124-
3125-
if self._active:
3126-
self._idPress = self.canvas.mpl_connect('button_press_event',
3127-
self.press_zoom)
3128-
self._idRelease = self.canvas.mpl_connect('button_release_event',
3129-
self.release_zoom)
3130-
self.mode = 'zoom rect'
3118+
self.mode = _Mode.ZOOM
31313119
self.canvas.widgetlock(self)
3132-
else:
3133-
self.canvas.widgetlock.release(self)
3134-
31353120
for a in self.canvas.figure.get_axes():
3136-
a.set_navigate_mode(self._active)
3137-
3121+
a.set_navigate_mode(self.mode)
31383122
self.set_message(self.mode)
31393123

31403124
def set_history_buttons(self):

lib/matplotlib/backends/backend_gtk3.py

Lines 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

Lines 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

Lines 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)