@@ -2191,7 +2191,8 @@ def __init__(self, ax, onselect, drawtype='box',
2191
2191
minspanx = 0 , minspany = 0 , useblit = False ,
2192
2192
lineprops = None , rectprops = None , spancoords = 'data' ,
2193
2193
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 ):
2195
2196
r"""
2196
2197
Parameters
2197
2198
----------
@@ -2263,13 +2264,18 @@ def onselect(eclick: MouseEvent, erelease: MouseEvent)
2263
2264
default: "ctrl".
2264
2265
2265
2266
"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.
2266
2271
"""
2267
2272
super ().__init__ (ax , onselect , useblit = useblit , button = button ,
2268
2273
state_modifier_keys = state_modifier_keys )
2269
2274
2270
2275
self .to_draw = None
2271
2276
self .visible = True
2272
2277
self .interactive = interactive
2278
+ self .drag_from_anywhere = drag_from_anywhere
2273
2279
2274
2280
if drawtype == 'none' : # draw a line but make it invisible
2275
2281
_api .warn_deprecated (
@@ -2419,8 +2425,9 @@ def _onmove(self, event):
2419
2425
y1 = event .ydata
2420
2426
2421
2427
# 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 ):
2424
2431
x0 , x1 , y0 , y1 = self ._extents_on_press
2425
2432
dx = event .xdata - self .eventpress .xdata
2426
2433
dy = event .ydata - self .eventpress .ydata
@@ -2551,16 +2558,24 @@ def _set_active_handle(self, event):
2551
2558
if 'move' in self .state :
2552
2559
self .active_handle = 'C'
2553
2560
self ._extents_on_press = self .extents
2554
-
2555
2561
# Set active handle as closest handle, if mouse click is close enough.
2556
2562
elif m_dist < self .maxdist * 2 :
2563
+ # Prioritise center handle over other handles
2557
2564
self .active_handle = 'C'
2558
2565
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
2561
2574
elif c_dist < e_dist :
2575
+ # Closest to a corner handle
2562
2576
self .active_handle = self ._corner_order [c_idx ]
2563
2577
else :
2578
+ # Closest to an edge handle
2564
2579
self .active_handle = self ._edge_order [e_idx ]
2565
2580
2566
2581
# Save coordinates of rectangle at the start of handle movement.
@@ -2572,6 +2587,10 @@ def _set_active_handle(self, event):
2572
2587
y0 , y1 = y1 , event .ydata
2573
2588
self ._extents_on_press = x0 , x1 , y0 , y1
2574
2589
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
+
2575
2594
@property
2576
2595
def geometry (self ):
2577
2596
"""
0 commit comments