@@ -2722,7 +2722,7 @@ def __init__(self, canvas):
2722
2722
self ._init_toolbar ()
2723
2723
self ._id_drag = self .canvas .mpl_connect (
2724
2724
'motion_notify_event' , self .mouse_move )
2725
- self ._id_zoom = None
2725
+ self ._zoom_info = None
2726
2726
2727
2727
self ._button_pressed = None # determined by button pressed at start
2728
2728
@@ -2932,37 +2932,24 @@ def press_pan(self, event):
2932
2932
2933
2933
def press_zoom (self , event ):
2934
2934
"""Callback for mouse button press in zoom to rect mode."""
2935
- # If we're already in the middle of a zoom, pressing another
2936
- # button works to "cancel"
2937
- if self ._id_zoom is not None :
2938
- self .canvas .mpl_disconnect (self ._id_zoom )
2939
- self .release (event )
2940
- self .draw ()
2941
- self ._xypress = None
2942
- self ._button_pressed = None
2943
- self ._id_zoom = None
2935
+ if event .button not in [1 , 3 ]:
2944
2936
return
2945
-
2946
- if event . button in [ 1 , 3 ]:
2947
- self . _button_pressed = event . button
2948
- else :
2949
- self . _button_pressed = None
2937
+ if event . x is None or event . y is None :
2938
+ return
2939
+ axes = [ a for a in self . canvas . figure . get_axes ()
2940
+ if a . in_axes ( event ) and a . get_navigate () and a . can_zoom ()]
2941
+ if not axes :
2950
2942
return
2951
-
2952
2943
if self ._nav_stack () is None :
2953
- # set the home button to this view
2954
- self .push_current ()
2955
-
2956
- x , y = event .x , event .y
2957
- self ._xypress = []
2958
- for a in self .canvas .figure .get_axes ():
2959
- if (x is not None and y is not None and a .in_axes (event ) and
2960
- a .get_navigate () and a .can_zoom ()):
2961
- self ._xypress .append ((x , y , a ))
2962
-
2963
- self ._id_zoom = self .canvas .mpl_connect (
2964
- 'motion_notify_event' , self .drag_zoom )
2965
-
2944
+ self .push_current () # set the home button to this view
2945
+ id_zoom = self .canvas .mpl_connect (
2946
+ "motion_notify_event" , self .drag_zoom )
2947
+ self ._zoom_info = {
2948
+ "direction" : "in" if event .button == 1 else "out" ,
2949
+ "start_xy" : (event .x , event .y ),
2950
+ "axes" : axes ,
2951
+ "cid" : id_zoom ,
2952
+ }
2966
2953
self .press (event )
2967
2954
2968
2955
def push_current (self ):
@@ -3007,65 +2994,53 @@ def drag_pan(self, event):
3007
2994
3008
2995
def drag_zoom (self , event ):
3009
2996
"""Callback for dragging in zoom mode."""
3010
- if self ._xypress :
3011
- x , y = event .x , event .y
3012
- lastx , lasty , a = self ._xypress [0 ]
3013
- (x1 , y1 ), (x2 , y2 ) = np .clip (
3014
- [[lastx , lasty ], [x , y ]], a .bbox .min , a .bbox .max )
3015
- if event .key == "x" :
3016
- y1 , y2 = a .bbox .intervaly
3017
- elif event .key == "y" :
3018
- x1 , x2 = a .bbox .intervalx
3019
- self .draw_rubberband (event , x1 , y1 , x2 , y2 )
2997
+ start_xy = self ._zoom_info ["start_xy" ]
2998
+ ax = self ._zoom_info ["axes" ][0 ]
2999
+ (x1 , y1 ), (x2 , y2 ) = np .clip (
3000
+ [start_xy , [event .x , event .y ]], ax .bbox .min , ax .bbox .max )
3001
+ if event .key == "x" :
3002
+ y1 , y2 = ax .bbox .intervaly
3003
+ elif event .key == "y" :
3004
+ x1 , x2 = ax .bbox .intervalx
3005
+ self .draw_rubberband (event , x1 , y1 , x2 , y2 )
3020
3006
3021
3007
def release_zoom (self , event ):
3022
3008
"""Callback for mouse button release in zoom to rect mode."""
3023
- if self ._id_zoom is not None :
3024
- self .canvas .mpl_disconnect (self ._id_zoom )
3025
- self ._id_zoom = None
3009
+ if self ._zoom_info is None :
3010
+ return
3026
3011
3012
+ # We don't check the event button here, so that zooms can be cancelled
3013
+ # by (pressing and) releasing another mouse button.
3014
+ self .canvas .mpl_disconnect (self ._zoom_info ["cid" ])
3027
3015
self .remove_rubberband ()
3028
3016
3029
- if not self ._xypress :
3030
- return
3031
-
3032
- last_a = []
3017
+ start_x , start_y = self ._zoom_info ["start_xy" ]
3033
3018
3034
- for lastx , lasty , a in self ._xypress :
3019
+ for i , ax in enumerate ( self ._zoom_info [ "axes" ]) :
3035
3020
x , y = event .x , event .y
3036
3021
# ignore singular clicks - 5 pixels is a threshold
3037
3022
# allows the user to "cancel" a zoom action
3038
3023
# by zooming by less than 5 pixels
3039
- if ((abs (x - lastx ) < 5 and event .key != "y" ) or
3040
- (abs (y - lasty ) < 5 and event .key != "x" )):
3024
+ if ((abs (x - start_x ) < 5 and event .key != "y" ) or
3025
+ (abs (y - start_y ) < 5 and event .key != "x" )):
3041
3026
self ._xypress = None
3042
3027
self .release (event )
3043
3028
self .draw ()
3044
3029
return
3045
3030
3046
- # detect twinx, twiny axes and avoid double zooming
3047
- twinx , twiny = False , False
3048
- if last_a :
3049
- for la in last_a :
3050
- if a .get_shared_x_axes ().joined (a , la ):
3051
- twinx = True
3052
- if a .get_shared_y_axes ().joined (a , la ):
3053
- twiny = True
3054
- last_a .append (a )
3055
-
3056
- if self ._button_pressed == 1 :
3057
- direction = 'in'
3058
- elif self ._button_pressed == 3 :
3059
- direction = 'out'
3060
- else :
3061
- continue
3031
+ # Detect whether this axes is twinned with an earlier axes in the
3032
+ # list of zoomed axes, to avoid double zooming.
3033
+ twinx = any (ax .get_shared_x_axes ().joined (ax , prev )
3034
+ for prev in self ._zoom_info ["axes" ][:i ])
3035
+ twiny = any (ax .get_shared_y_axes ().joined (ax , prev )
3036
+ for prev in self ._zoom_info ["axes" ][:i ])
3062
3037
3063
- a ._set_view_from_bbox ((lastx , lasty , x , y ), direction ,
3064
- event .key , twinx , twiny )
3038
+ ax ._set_view_from_bbox (
3039
+ (start_x , start_y , x , y ), self ._zoom_info ["direction" ],
3040
+ event .key , twinx , twiny )
3065
3041
3066
3042
self .draw ()
3067
- self ._xypress = None
3068
- self ._button_pressed = None
3043
+ self ._zoom_info = None
3069
3044
3070
3045
self .push_current ()
3071
3046
self .release (event )
0 commit comments