@@ -2191,7 +2191,8 @@ def __init__(self, ax, onselect, drawtype='box',
21912191 minspanx = 0 , minspany = 0 , useblit = False ,
21922192 lineprops = None , rectprops = None , spancoords = 'data' ,
21932193 button = None , maxdist = 10 , marker_props = None ,
2194- interactive = False , state_modifier_keys = None ):
2194+ interactive = False , state_modifier_keys = None ,
2195+ drag_from_anywhere = False ):
21952196 r"""
21962197 Parameters
21972198 ----------
@@ -2263,13 +2264,18 @@ def onselect(eclick: MouseEvent, erelease: MouseEvent)
22632264 default: "ctrl".
22642265
22652266 "square" and "center" can be combined.
2267+
2268+ drag_from_anywhere : bool, optional
2269+ If `True`, the widget can be moved by clicking anywhere within
2270+ its bounds.
22662271 """
22672272 super ().__init__ (ax , onselect , useblit = useblit , button = button ,
22682273 state_modifier_keys = state_modifier_keys )
22692274
22702275 self .to_draw = None
22712276 self .visible = True
22722277 self .interactive = interactive
2278+ self .drag_from_anywhere = drag_from_anywhere
22732279
22742280 if drawtype == 'none' : # draw a line but make it invisible
22752281 _api .warn_deprecated (
@@ -2419,8 +2425,9 @@ def _onmove(self, event):
24192425 y1 = event .ydata
24202426
24212427 # move existing shape
2422- elif (('move' in self .state or self .active_handle == 'C' )
2423- and self ._extents_on_press is not None ):
2428+ elif (('move' in self .state or self .active_handle == 'C' or
2429+ (self .drag_from_anywhere and self ._contains (event ))) and
2430+ self ._extents_on_press is not None ):
24242431 x0 , x1 , y0 , y1 = self ._extents_on_press
24252432 dx = event .xdata - self .eventpress .xdata
24262433 dy = event .ydata - self .eventpress .ydata
@@ -2551,16 +2558,24 @@ def _set_active_handle(self, event):
25512558 if 'move' in self .state :
25522559 self .active_handle = 'C'
25532560 self ._extents_on_press = self .extents
2554-
25552561 # Set active handle as closest handle, if mouse click is close enough.
25562562 elif m_dist < self .maxdist * 2 :
2563+ # Prioritise center handle over other handles
25572564 self .active_handle = 'C'
25582565 elif c_dist > self .maxdist and e_dist > self .maxdist :
2559- self .active_handle = None
2560- return
2566+ # Not close to any handles
2567+ if self .drag_from_anywhere and self ._contains (event ):
2568+ # Check if we've clicked inside the region
2569+ self .active_handle = 'C'
2570+ self ._extents_on_press = self .extents
2571+ else :
2572+ self .active_handle = None
2573+ return
25612574 elif c_dist < e_dist :
2575+ # Closest to a corner handle
25622576 self .active_handle = self ._corner_order [c_idx ]
25632577 else :
2578+ # Closest to an edge handle
25642579 self .active_handle = self ._edge_order [e_idx ]
25652580
25662581 # Save coordinates of rectangle at the start of handle movement.
@@ -2572,6 +2587,10 @@ def _set_active_handle(self, event):
25722587 y0 , y1 = y1 , event .ydata
25732588 self ._extents_on_press = x0 , x1 , y0 , y1
25742589
2590+ def _contains (self , event ):
2591+ """Return True if event is within the patch."""
2592+ return self .to_draw .contains (event , radius = 0 )[0 ]
2593+
25752594 @property
25762595 def geometry (self ):
25772596 """
0 commit comments