@@ -2699,7 +2699,7 @@ def __init__(self, canvas):
2699
2699
self ._init_toolbar ()
2700
2700
self ._id_drag = self .canvas .mpl_connect (
2701
2701
'motion_notify_event' , self .mouse_move )
2702
- self ._id_zoom = None
2702
+ self ._zoom_info = None
2703
2703
2704
2704
self ._button_pressed = None # determined by button pressed at start
2705
2705
@@ -2909,37 +2909,24 @@ def press_pan(self, event):
2909
2909
2910
2910
def press_zoom (self , event ):
2911
2911
"""Callback for mouse button press in zoom to rect mode."""
2912
- # If we're already in the middle of a zoom, pressing another
2913
- # button works to "cancel"
2914
- if self ._id_zoom is not None :
2915
- self .canvas .mpl_disconnect (self ._id_zoom )
2916
- self .release (event )
2917
- self .draw ()
2918
- self ._xypress = None
2919
- self ._button_pressed = None
2920
- self ._id_zoom = None
2912
+ if event .button not in [1 , 3 ]:
2921
2913
return
2922
-
2923
- if event . button in [ 1 , 3 ]:
2924
- self . _button_pressed = event . button
2925
- else :
2926
- self . _button_pressed = None
2914
+ if event . x is None or event . y is None :
2915
+ return
2916
+ axes = [ a for a in self . canvas . figure . get_axes ()
2917
+ if a . in_axes ( event ) and a . get_navigate () and a . can_zoom ()]
2918
+ if not axes :
2927
2919
return
2928
-
2929
2920
if self ._nav_stack () is None :
2930
- # set the home button to this view
2931
- self .push_current ()
2932
-
2933
- x , y = event .x , event .y
2934
- self ._xypress = []
2935
- for a in self .canvas .figure .get_axes ():
2936
- if (x is not None and y is not None and a .in_axes (event ) and
2937
- a .get_navigate () and a .can_zoom ()):
2938
- self ._xypress .append ((x , y , a ))
2939
-
2940
- self ._id_zoom = self .canvas .mpl_connect (
2941
- 'motion_notify_event' , self .drag_zoom )
2942
-
2921
+ self .push_current () # set the home button to this view
2922
+ id_zoom = self .canvas .mpl_connect (
2923
+ "motion_notify_event" , self .drag_zoom )
2924
+ self ._zoom_info = {
2925
+ "direction" : "in" if event .button == 1 else "out" ,
2926
+ "start_xy" : (event .x , event .y ),
2927
+ "axes" : axes ,
2928
+ "cid" : id_zoom ,
2929
+ }
2943
2930
self .press (event )
2944
2931
2945
2932
def push_current (self ):
@@ -2984,65 +2971,53 @@ def drag_pan(self, event):
2984
2971
2985
2972
def drag_zoom (self , event ):
2986
2973
"""Callback for dragging in zoom mode."""
2987
- if self ._xypress :
2988
- x , y = event .x , event .y
2989
- lastx , lasty , a = self ._xypress [0 ]
2990
- (x1 , y1 ), (x2 , y2 ) = np .clip (
2991
- [[lastx , lasty ], [x , y ]], a .bbox .min , a .bbox .max )
2992
- if event .key == "x" :
2993
- y1 , y2 = a .bbox .intervaly
2994
- elif event .key == "y" :
2995
- x1 , x2 = a .bbox .intervalx
2996
- self .draw_rubberband (event , x1 , y1 , x2 , y2 )
2974
+ start_xy = self ._zoom_info ["start_xy" ]
2975
+ ax = self ._zoom_info ["axes" ][0 ]
2976
+ (x1 , y1 ), (x2 , y2 ) = np .clip (
2977
+ [start_xy , [event .x , event .y ]], ax .bbox .min , ax .bbox .max )
2978
+ if event .key == "x" :
2979
+ y1 , y2 = ax .bbox .intervaly
2980
+ elif event .key == "y" :
2981
+ x1 , x2 = ax .bbox .intervalx
2982
+ self .draw_rubberband (event , x1 , y1 , x2 , y2 )
2997
2983
2998
2984
def release_zoom (self , event ):
2999
2985
"""Callback for mouse button release in zoom to rect mode."""
3000
- if self ._id_zoom is not None :
3001
- self .canvas .mpl_disconnect (self ._id_zoom )
3002
- self ._id_zoom = None
2986
+ if self ._zoom_info is None :
2987
+ return
3003
2988
2989
+ # We don't check the event button here, so that zooms can be cancelled
2990
+ # by (pressing and) releasing another mouse button.
2991
+ self .canvas .mpl_disconnect (self ._zoom_info ["cid" ])
3004
2992
self .remove_rubberband ()
3005
2993
3006
- if not self ._xypress :
3007
- return
3008
-
3009
- last_a = []
2994
+ start_x , start_y = self ._zoom_info ["start_xy" ]
3010
2995
3011
- for lastx , lasty , a in self ._xypress :
2996
+ for i , ax in enumerate ( self ._zoom_info [ "axes" ]) :
3012
2997
x , y = event .x , event .y
3013
2998
# ignore singular clicks - 5 pixels is a threshold
3014
2999
# allows the user to "cancel" a zoom action
3015
3000
# by zooming by less than 5 pixels
3016
- if ((abs (x - lastx ) < 5 and event .key != "y" ) or
3017
- (abs (y - lasty ) < 5 and event .key != "x" )):
3001
+ if ((abs (x - start_x ) < 5 and event .key != "y" ) or
3002
+ (abs (y - start_y ) < 5 and event .key != "x" )):
3018
3003
self ._xypress = None
3019
3004
self .release (event )
3020
3005
self .draw ()
3021
3006
return
3022
3007
3023
- # detect twinx, twiny axes and avoid double zooming
3024
- twinx , twiny = False , False
3025
- if last_a :
3026
- for la in last_a :
3027
- if a .get_shared_x_axes ().joined (a , la ):
3028
- twinx = True
3029
- if a .get_shared_y_axes ().joined (a , la ):
3030
- twiny = True
3031
- last_a .append (a )
3032
-
3033
- if self ._button_pressed == 1 :
3034
- direction = 'in'
3035
- elif self ._button_pressed == 3 :
3036
- direction = 'out'
3037
- else :
3038
- continue
3008
+ # Detect whether this axes is twinned with an earlier axes in the
3009
+ # list of zoomed axes, to avoid double zooming.
3010
+ twinx = any (ax .get_shared_x_axes ().joined (ax , prev )
3011
+ for prev in self ._zoom_info ["axes" ][:i ])
3012
+ twiny = any (ax .get_shared_y_axes ().joined (ax , prev )
3013
+ for prev in self ._zoom_info ["axes" ][:i ])
3039
3014
3040
- a ._set_view_from_bbox ((lastx , lasty , x , y ), direction ,
3041
- event .key , twinx , twiny )
3015
+ ax ._set_view_from_bbox (
3016
+ (start_x , start_y , x , y ), self ._zoom_info ["direction" ],
3017
+ event .key , twinx , twiny )
3042
3018
3043
3019
self .draw ()
3044
- self ._xypress = None
3045
- self ._button_pressed = None
3020
+ self ._zoom_info = None
3046
3021
3047
3022
self .push_current ()
3048
3023
self .release (event )
0 commit comments