@@ -2722,7 +2722,7 @@ def __init__(self, canvas):
27222722 self ._init_toolbar ()
27232723 self ._id_drag = self .canvas .mpl_connect (
27242724 'motion_notify_event' , self .mouse_move )
2725- self ._id_zoom = None
2725+ self ._zoom_info = None
27262726
27272727 self ._button_pressed = None # determined by button pressed at start
27282728
@@ -2932,37 +2932,24 @@ def press_pan(self, event):
29322932
29332933 def press_zoom (self , event ):
29342934 """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 ]:
29442936 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 :
29502942 return
2951-
29522943 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+ }
29662953 self .press (event )
29672954
29682955 def push_current (self ):
@@ -3007,65 +2994,53 @@ def drag_pan(self, event):
30072994
30082995 def drag_zoom (self , event ):
30092996 """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 )
30203006
30213007 def release_zoom (self , event ):
30223008 """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
30263011
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" ])
30273015 self .remove_rubberband ()
30283016
3029- if not self ._xypress :
3030- return
3031-
3032- last_a = []
3017+ start_x , start_y = self ._zoom_info ["start_xy" ]
30333018
3034- for lastx , lasty , a in self ._xypress :
3019+ for i , ax in enumerate ( self ._zoom_info [ "axes" ]) :
30353020 x , y = event .x , event .y
30363021 # ignore singular clicks - 5 pixels is a threshold
30373022 # allows the user to "cancel" a zoom action
30383023 # 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" )):
30413026 self ._xypress = None
30423027 self .release (event )
30433028 self .draw ()
30443029 return
30453030
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 ])
30623037
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 )
30653041
30663042 self .draw ()
3067- self ._xypress = None
3068- self ._button_pressed = None
3043+ self ._zoom_info = None
30693044
30703045 self .push_current ()
30713046 self .release (event )
0 commit comments