@@ -2189,7 +2189,8 @@ def __init__(self, ax, onselect, drawtype='box',
21892189minspanx = 0 ,minspany = 0 ,useblit = False ,
21902190lineprops = None ,rectprops = None ,spancoords = 'data' ,
21912191button = 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 ):
21932194r"""
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 """
22652270super ().__init__ (ax ,onselect ,useblit = useblit ,button = button ,
22662271state_modifier_keys = state_modifier_keys )
22672272
22682273self .to_draw = None
22692274self .visible = True
22702275self .interactive = interactive
2276+ self .drag_from_anywhere = drag_from_anywhere
22712277
22722278if drawtype == 'none' :# draw a line but make it invisible
22732279drawtype = 'line'
@@ -2407,8 +2413,9 @@ def _onmove(self, event):
24072413y1 = 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 ):
24122419x0 ,x1 ,y0 ,y1 = self ._extents_on_press
24132420dx = event .xdata - self .eventpress .xdata
24142421dy = event .ydata - self .eventpress .ydata
@@ -2536,19 +2543,28 @@ def _set_active_handle(self, event):
25362543e_idx ,e_dist = self ._edge_handles .closest (event .x ,event .y )
25372544m_idx ,m_dist = self ._center_handle .closest (event .x ,event .y )
25382545
2546+ contains = self ._contains (event )
25392547if 'move' in self .state :
25402548self .active_handle = 'C'
25412549self ._extents_on_press = self .extents
2542-
25432550# Set active handle as closest handle, if mouse click is close enough.
25442551elif m_dist < self .maxdist * 2 :
2552+ # Prioritise center handle over other handles
25452553self .active_handle = 'C'
2546- elif c_dist > self .maxdist and e_dist > self .maxdist :
2547- self .active_handle = None
2548- return
2554+ elif (c_dist > self .maxdist and e_dist > self .maxdist ):
2555+ # Not close to any handles
2556+ if self .drag_from_anywhere and contains :
2557+ # Check if we've clicked inside the region
2558+ self .active_handle = 'C'
2559+ self ._extents_on_press = self .extents
2560+ else :
2561+ self .active_handle = None
2562+ return
25492563elif c_dist < e_dist :
2564+ # Closest to a corner handle
25502565self .active_handle = self ._corner_order [c_idx ]
25512566else :
2567+ # Closest to an edge handle
25522568self .active_handle = self ._edge_order [e_idx ]
25532569
25542570# Save coordinates of rectangle at the start of handle movement.
@@ -2560,6 +2576,10 @@ def _set_active_handle(self, event):
25602576y0 ,y1 = y1 ,event .ydata
25612577self ._extents_on_press = x0 ,x1 ,y0 ,y1
25622578
2579+ def _contains (self ,event ):
2580+ """Return True if event is within the patch."""
2581+ return self .to_draw .contains (event ,radius = 0 )[0 ]
2582+
25632583@property
25642584def geometry (self ):
25652585"""