@@ -2995,6 +2995,63 @@ def _zoom_pan_handler(self, event):
29952995 elif event .name == "button_release_event" :
29962996 self .release_zoom (event )
29972997
2998+ def _start_event_axes_pan (self , event , method = "zoom" ):
2999+ # call "ax.start_pan(..)" on all relevant axes of an event
3000+
3001+ def _ax_filter (ax ):
3002+ return (ax .in_axes (event ) and
3003+ ax .get_navigate () and
3004+ getattr (ax , f"can_{ method } " )()
3005+ )
3006+
3007+ def _capture_events (ax ):
3008+ f = ax .get_forward_navigation_events ()
3009+ if f == "auto" : # (capture = patch visibility)
3010+ f = not ax .patch .get_visible ()
3011+ return not f
3012+
3013+ # get all relevant axes for the event
3014+ axes = list (filter (_ax_filter , self .canvas .figure .get_axes ()))
3015+
3016+ if len (axes ) == 0 :
3017+ return
3018+
3019+ if self ._nav_stack () is None :
3020+ self .push_current () # Set the home button to this view.
3021+
3022+ # group axes by zorder (reverse to trigger later axes first)
3023+ grps = dict ()
3024+ for ax in reversed (axes ):
3025+ grps .setdefault (ax .get_zorder (), []).append (ax )
3026+
3027+ pan_axes = []
3028+ # go through zorders in reverse until we hit a capturing axes
3029+ for zorder in sorted (grps , reverse = True ):
3030+ for ax in grps [zorder ]:
3031+ pan_axes .append (ax )
3032+ # NOTE: shared axes are automatically triggered, but twin-axes not!
3033+ pan_axes .extend (ax ._twinned_axes .get_siblings (ax ))
3034+
3035+ if _capture_events (ax ):
3036+ break # break if we hit a capturing axes
3037+ else :
3038+ # If the inner loop finished without an explicit break,
3039+ # (e.g. no capturing axes was found) continue the
3040+ # outer loop to the next zorder.
3041+ continue
3042+
3043+ # If the inner loop was terminated with an explicit break,
3044+ # terminate the outer loop as well.
3045+ break
3046+
3047+ # avoid duplicated triggers (but keep order of list)
3048+ pan_axes = list (dict .fromkeys (pan_axes ))
3049+
3050+ for ax in pan_axes :
3051+ ax .start_pan (event .x , event .y , event .button )
3052+
3053+ return pan_axes
3054+
29983055 def pan (self , * args ):
29993056 """
30003057 Toggle the pan/zoom tool.
@@ -3020,16 +3077,14 @@ def press_pan(self, event):
30203077 if (event .button not in [MouseButton .LEFT , MouseButton .RIGHT ]
30213078 or event .x is None or event .y is None ):
30223079 return
3023- axes = [ a for a in self . canvas . figure . get_axes ()
3024- if a . in_axes (event ) and a . get_navigate () and a . can_pan ()]
3080+
3081+ axes = self . _start_event_axes_pan (event , method = "pan" )
30253082 if not axes :
30263083 return
3027- if self ._nav_stack () is None :
3028- self .push_current () # set the home button to this view
3029- for ax in axes :
3030- ax .start_pan (event .x , event .y , event .button )
3084+
30313085 self .canvas .mpl_disconnect (self ._id_drag )
30323086 id_drag = self .canvas .mpl_connect ("motion_notify_event" , self .drag_pan )
3087+
30333088 self ._pan_info = self ._PanInfo (
30343089 button = event .button , axes = axes , cid = id_drag )
30353090
@@ -3075,21 +3130,23 @@ def press_zoom(self, event):
30753130 if (event .button not in [MouseButton .LEFT , MouseButton .RIGHT ]
30763131 or event .x is None or event .y is None ):
30773132 return
3078- axes = [ a for a in self . canvas . figure . get_axes ()
3079- if a . in_axes (event ) and a . get_navigate () and a . can_zoom ()]
3133+
3134+ axes = self . _start_event_axes_pan (event , method = "zoom" )
30803135 if not axes :
30813136 return
3082- if self ._nav_stack () is None :
3083- self .push_current () # set the home button to this view
3137+
30843138 id_zoom = self .canvas .mpl_connect (
30853139 "motion_notify_event" , self .drag_zoom )
3140+
30863141 # A colorbar is one-dimensional, so we extend the zoom rectangle out
30873142 # to the edge of the Axes bbox in the other dimension. To do that we
30883143 # store the orientation of the colorbar for later.
3089- if hasattr (axes [0 ], "_colorbar" ):
3090- cbar = axes [0 ]._colorbar .orientation
3144+ parent_ax = axes [0 ]
3145+ if hasattr (parent_ax , "_colorbar" ):
3146+ cbar = parent_ax ._colorbar .orientation
30913147 else :
30923148 cbar = None
3149+
30933150 self ._zoom_info = self ._ZoomInfo (
30943151 direction = "in" if event .button == 1 else "out" ,
30953152 start_xy = (event .x , event .y ), axes = axes , cid = id_zoom , cbar = cbar )
0 commit comments