@@ -2189,7 +2189,8 @@ def __init__(self, ax, onselect, drawtype='box',
21892189 minspanx = 0 , minspany = 0 , useblit = False ,
21902190 lineprops = None , rectprops = None , spancoords = 'data' ,
21912191 button = None , maxdist = 10 , marker_props = None ,
2192- interactive = False , state_modifier_keys = None ):
2192+ interactive = False , state_modifier_keys = None ,
2193+ drag_from_anywhere = False ):
21932194 r"""
21942195 Parameters
21952196 ----------
@@ -2261,13 +2262,18 @@ def onselect(eclick: MouseEvent, erelease: MouseEvent)
22612262 default: "ctrl".
22622263
22632264 "square" and "center" can be combined.
2265+
2266+ drag_from_anywhere : bool, optional
2267+ If `True`, the widget can be moved by clicking anywhere within
2268+ its bounds.
22642269 """
22652270 super ().__init__ (ax , onselect , useblit = useblit , button = button ,
22662271 state_modifier_keys = state_modifier_keys )
22672272
22682273 self .to_draw = None
22692274 self .visible = True
22702275 self .interactive = interactive
2276+ self .drag_from_anywhere = drag_from_anywhere
22712277
22722278 if drawtype == 'none' : # draw a line but make it invisible
22732279 drawtype = 'line'
@@ -2407,8 +2413,9 @@ def _onmove(self, event):
24072413 y1 = event .ydata
24082414
24092415 # move existing shape
2410- elif (('move' in self .state or self .active_handle == 'C' )
2411- and self ._extents_on_press is not None ):
2416+ elif (('move' in self .state or self .active_handle == 'C' or
2417+ (self .drag_from_anywhere and self ._contains (event ))) and
2418+ self ._extents_on_press is not None ):
24122419 x0 , x1 , y0 , y1 = self ._extents_on_press
24132420 dx = event .xdata - self .eventpress .xdata
24142421 dy = event .ydata - self .eventpress .ydata
@@ -2539,16 +2546,24 @@ def _set_active_handle(self, event):
25392546 if 'move' in self .state :
25402547 self .active_handle = 'C'
25412548 self ._extents_on_press = self .extents
2542-
25432549 # Set active handle as closest handle, if mouse click is close enough.
25442550 elif m_dist < self .maxdist * 2 :
2551+ # Prioritise center handle over other handles
25452552 self .active_handle = 'C'
25462553 elif c_dist > self .maxdist and e_dist > self .maxdist :
2547- self .active_handle = None
2548- return
2554+ # Not close to any handles
2555+ if self .drag_from_anywhere and self ._contains (event ):
2556+ # Check if we've clicked inside the region
2557+ self .active_handle = 'C'
2558+ self ._extents_on_press = self .extents
2559+ else :
2560+ self .active_handle = None
2561+ return
25492562 elif c_dist < e_dist :
2563+ # Closest to a corner handle
25502564 self .active_handle = self ._corner_order [c_idx ]
25512565 else :
2566+ # Closest to an edge handle
25522567 self .active_handle = self ._edge_order [e_idx ]
25532568
25542569 # Save coordinates of rectangle at the start of handle movement.
@@ -2560,6 +2575,10 @@ def _set_active_handle(self, event):
25602575 y0 , y1 = y1 , event .ydata
25612576 self ._extents_on_press = x0 , x1 , y0 , y1
25622577
2578+ def _contains (self , event ):
2579+ """Return True if event is within the patch."""
2580+ return self .to_draw .contains (event , radius = 0 )[0 ]
2581+
25632582 @property
25642583 def geometry (self ):
25652584 """
0 commit comments