Skip to content

Commit f6a2f19

Browse files
committed
reducing number of locks
1 parent 6065daa commit f6a2f19

File tree

3 files changed

+92
-136
lines changed

3 files changed

+92
-136
lines changed

lib/matplotlib/backend_bases.py

+34-57
Original file line numberDiff line numberDiff line change
@@ -3232,11 +3232,9 @@ class NavigationBase(object):
32323232
----------
32333233
canvas : `FigureCanvas` instance
32343234
toolbar : `Toolbar` instance that is controlled by this `Navigation`
3235-
keypresslock : `LockDraw` to direct the `canvas` key_press_event
3236-
movelock : `LockDraw` to direct the `canvas` motion_notify_event
3237-
presslock : `LockDraw` to direct the `canvas` button_press_event
3238-
releaselock : `LockDraw` to direct the `canvas` button_release_event
3239-
canvaslock : shortcut to `canvas.widgetlock`
3235+
keypresslock : `LockDraw` to know if the `canvas` key_press_event is
3236+
locked
3237+
messagelock : `LockDraw` to know if the message is available to write
32403238
"""
32413239
_default_cursor = cursors.POINTER
32423240
_default_tools = [tools.ToolToggleGrid,
@@ -3266,11 +3264,6 @@ def __init__(self, canvas, toolbar=None):
32663264
self._idDrag = self.canvas.mpl_connect('motion_notify_event',
32673265
self._mouse_move)
32683266

3269-
self._idPress = self.canvas.mpl_connect('button_press_event',
3270-
self._press)
3271-
self._idRelease = self.canvas.mpl_connect('button_release_event',
3272-
self._release)
3273-
32743267
# a dict from axes index to a list of view limits
32753268
self.views = cbook.Stack()
32763269
self.positions = cbook.Stack() # stack of subplot positions
@@ -3282,11 +3275,7 @@ def __init__(self, canvas, toolbar=None):
32823275

32833276
#to communicate with tools and redirect events
32843277
self.keypresslock = widgets.LockDraw()
3285-
self.movelock = widgets.LockDraw()
3286-
self.presslock = widgets.LockDraw()
3287-
self.releaselock = widgets.LockDraw()
3288-
#just to group all the locks in one place
3289-
self.canvaslock = self.canvas.widgetlock
3278+
self.messagelock = widgets.LockDraw()
32903279

32913280
for tool in self._default_tools:
32923281
if tool is None:
@@ -3479,16 +3468,9 @@ def _trigger_tool(self, name, event, from_toolbar):
34793468
tool(self.canvas.figure, event)
34803469

34813470
def _key_press(self, event):
3482-
if event.key is None:
3471+
if event.key is None or self.keypresslock.locked():
34833472
return
34843473

3485-
#some tools may need to capture keypress, but they need to be toggle
3486-
if self._toggled:
3487-
instance = self._get_instance(self._toggled)
3488-
if self.keypresslock.isowner(instance):
3489-
instance.key_press(event)
3490-
return
3491-
34923474
name = self._keys.get(event.key, None)
34933475
self._trigger_tool(name, event, False)
34943476

@@ -3559,12 +3541,6 @@ def update(self):
35593541
# self.set_history_buttons()
35603542

35613543
def _mouse_move(self, event):
3562-
if self._toggled:
3563-
instance = self._instances[self._toggled]
3564-
if self.movelock.isowner(instance):
3565-
instance.mouse_move(event)
3566-
return
3567-
35683544
if not event.inaxes or not self._toggled:
35693545
if self._last_cursor != self._default_cursor:
35703546
self.set_cursor(self._default_cursor)
@@ -3576,7 +3552,7 @@ def _mouse_move(self, event):
35763552
self.set_cursor(cursor)
35773553
self._last_cursor = cursor
35783554

3579-
if self.toolbar is None:
3555+
if self.toolbar is None or self.messagelock.locked():
35803556
return
35813557

35823558
if event.inaxes and event.inaxes.get_navigate():
@@ -3593,30 +3569,6 @@ def _mouse_move(self, event):
35933569
else:
35943570
self.toolbar.set_message('')
35953571

3596-
def _release(self, event):
3597-
if self._toggled:
3598-
instance = self._instances[self._toggled]
3599-
if self.releaselock.isowner(instance):
3600-
instance.release(event)
3601-
return
3602-
self.release(event)
3603-
3604-
def release(self, event):
3605-
pass
3606-
3607-
def _press(self, event):
3608-
"""Called whenver a mouse button is pressed."""
3609-
if self._toggled:
3610-
instance = self._instances[self._toggled]
3611-
if self.presslock.isowner(instance):
3612-
instance.press(event)
3613-
return
3614-
self.press(event)
3615-
3616-
def press(self, event):
3617-
"""Called whenver a mouse button is pressed."""
3618-
pass
3619-
36203572
def draw(self):
36213573
"""Redraw the canvases, update the locators"""
36223574
for a in self.canvas.figure.get_axes():
@@ -3681,9 +3633,34 @@ def push_current(self):
36813633
self.positions.push(pos)
36823634
# self.set_history_buttons()
36833635

3684-
def draw_rubberband(self, event, x0, y0, x1, y1):
3685-
"""Draw a rectangle rubberband to indicate zoom limits"""
3686-
pass
3636+
def draw_rubberband(self, event, caller, x0, y0, x1, y1):
3637+
"""Draw a rectangle rubberband to indicate zoom limits
3638+
3639+
Draw a rectanlge in the canvas, if
3640+
`self.canvas.widgetlock` is available to **caller**
3641+
3642+
Parameters
3643+
----------
3644+
event : `FigureCanvas` event
3645+
caller : instance trying to draw the rubberband
3646+
x0, y0, x1, y1 : coordinates
3647+
"""
3648+
if not self.canvas.widgetlock.available(caller):
3649+
warnings.warn("%s doesn't own the canvas widgetlock" % caller)
3650+
3651+
def remove_rubberband(self, event, caller):
3652+
"""Remove the rubberband
3653+
3654+
Remove the rubberband if the `self.canvas.widgetlock` is
3655+
available to **caller**
3656+
3657+
Parameters
3658+
----------
3659+
event : `FigureCanvas` event
3660+
caller : instance trying to remove the rubberband
3661+
"""
3662+
if not self.canvas.widgetlock.available(caller):
3663+
warnings.warn("%s doesn't own the canvas widgetlock" % caller)
36873664

36883665

36893666
class ToolbarBase(object):

lib/matplotlib/backend_tools.py

+54-74
Original file line numberDiff line numberDiff line change
@@ -141,37 +141,13 @@ def unregister(self, *args):
141141
class ToolToggleBase(ToolPersistentBase):
142142
"""Toggleable tool
143143
144-
This tool is a Persistent Tool, that has the ability to capture
145-
the keypress, press and release events, preventing other tools
146-
to use the same events at the same time
144+
This tool is a Persistent Tool that has a toggled state.
145+
Every time it is triggered, it switches between enable and disable
146+
147147
"""
148148
toggle = True
149149
_toggled = False
150150

151-
def mouse_move(self, event):
152-
"""Mouse move event
153-
154-
Called when a motion_notify_event is emited by the `FigureCanvas` if
155-
`navigation.movelock(self)` was setted
156-
"""
157-
pass
158-
159-
def press(self, event):
160-
"""Mouse press event
161-
162-
Called when a button_press_event is emited by the `FigureCanvas` if
163-
`navigation.presslock(self)` was setted
164-
"""
165-
pass
166-
167-
def release(self, event):
168-
"""Mouse release event
169-
170-
Called when a button_release_event is emited by the `FigureCanvas` if
171-
`navigation.releaselock(self)` was setted
172-
"""
173-
pass
174-
175151
def trigger(self, event):
176152
if self._toggled:
177153
self.disable(event)
@@ -182,26 +158,23 @@ def trigger(self, event):
182158
def enable(self, event=None):
183159
"""Enable the toggle tool
184160
185-
This method is called when the tool is triggered and not active
161+
This method is called when the tool is triggered and not toggled
186162
"""
187163
pass
188164

189165
def disable(self, event=None):
190166
"""Disable the toggle tool
191167
192-
This method is called when the tool is triggered and active.
193-
* Second click on the toolbar button
168+
This method is called when the tool is triggered and toggled.
169+
* Second click on the toolbar tool button
194170
* Another toogle tool is triggered (from the same `navigation`)
195171
"""
196172
pass
197173

198-
def key_press(self, event):
199-
"""Key press event
200-
201-
Called when a key_press_event is emited by the `FigureCanvas` if
202-
`navigation.keypresslock(self)` was setted
203-
"""
204-
pass
174+
@property
175+
def toggled(self):
176+
"""State of the toggled tool"""
177+
return self._toggled
205178

206179

207180
class ToolQuit(ToolBase):
@@ -391,26 +364,29 @@ def __init__(self, *args):
391364
self._ids_zoom = []
392365
self._button_pressed = None
393366
self._xypress = None
367+
self._idPress = None
368+
self._idRelease = None
394369

395370
def enable(self, event):
396-
self.navigation.canvaslock(self)
397-
self.navigation.presslock(self)
398-
self.navigation.releaselock(self)
371+
self.figure.canvas.widgetlock(self)
372+
self._idPress = self.figure.canvas.mpl_connect(
373+
'button_press_event', self._press)
374+
self._idRelease = self.figure.canvas.mpl_connect(
375+
'button_release_event', self._release)
399376

400377
def disable(self, event):
401-
self.navigation.canvaslock.release(self)
402-
self.navigation.presslock.release(self)
403-
self.navigation.releaselock.release(self)
378+
self.figure.canvas.widgetlock.release(self)
379+
self.figure.canvas.mpl_disconnect(self._idPress)
380+
self.figure.canvas.mpl_disconnect(self._idRelease)
404381

405-
def press(self, event):
406-
"""the press mouse button in zoom to rect mode callback"""
382+
def _press(self, event):
383+
"""the _press mouse button in zoom to rect mode callback"""
407384
# If we're already in the middle of a zoom, pressing another
408385
# button works to "cancel"
409386
if self._ids_zoom != []:
410-
self.navigation.movelock.release(self)
411387
for zoom_id in self._ids_zoom:
412388
self.figure.canvas.mpl_disconnect(zoom_id)
413-
self.navigation.release(event)
389+
self.navigation.remove_rubberband(event, self)
414390
self.navigation.draw()
415391
self._xypress = None
416392
self._button_pressed = None
@@ -439,26 +415,25 @@ def press(self, event):
439415
self._xypress.append((x, y, a, i, a.viewLim.frozen(),
440416
a.transData.frozen()))
441417

442-
self.navigation.movelock(self)
418+
id1 = self.figure.canvas.mpl_connect(
419+
'motion_notify_event', self._mouse_move)
443420
id2 = self.figure.canvas.mpl_connect('key_press_event',
444421
self._switch_on_zoom_mode)
445422
id3 = self.figure.canvas.mpl_connect('key_release_event',
446423
self._switch_off_zoom_mode)
447424

448-
self._ids_zoom = id2, id3
425+
self._ids_zoom = id1, id2, id3
449426
self._zoom_mode = event.key
450427

451-
self.navigation.press(event)
452-
453428
def _switch_on_zoom_mode(self, event):
454429
self._zoom_mode = event.key
455-
self.mouse_move(event)
430+
self._mouse_move(event)
456431

457432
def _switch_off_zoom_mode(self, event):
458433
self._zoom_mode = None
459-
self.mouse_move(event)
434+
self._mouse_move(event)
460435

461-
def mouse_move(self, event):
436+
def _mouse_move(self, event):
462437
"""the drag callback in zoom mode"""
463438
if self._xypress:
464439
x, y = event.x, event.y
@@ -476,11 +451,10 @@ def mouse_move(self, event):
476451
x1, y1, x2, y2 = a.bbox.extents
477452
x, lastx = x1, x2
478453

479-
self.navigation.draw_rubberband(event, x, y, lastx, lasty)
454+
self.navigation.draw_rubberband(event, self, x, y, lastx, lasty)
480455

481-
def release(self, event):
456+
def _release(self, event):
482457
"""the release mouse button callback in zoom to rect mode"""
483-
self.navigation.movelock.release(self)
484458
for zoom_id in self._ids_zoom:
485459
self.figure.canvas.mpl_disconnect(zoom_id)
486460
self._ids_zoom = []
@@ -496,7 +470,7 @@ def release(self, event):
496470
# ignore singular clicks - 5 pixels is a threshold
497471
if abs(x - lastx) < 5 or abs(y - lasty) < 5:
498472
self._xypress = None
499-
self.navigation.release(event)
473+
self.navigation.remove_rubberband(event, self)
500474
self.navigation.draw()
501475
return
502476

@@ -604,7 +578,7 @@ def release(self, event):
604578
self._zoom_mode = None
605579

606580
self.navigation.push_current()
607-
self.navigation.release(event)
581+
self.navigation.remove_rubberband(event, self)
608582

609583

610584
class ToolPan(ToolToggleBase):
@@ -620,18 +594,23 @@ def __init__(self, *args):
620594
ToolToggleBase.__init__(self, *args)
621595
self._button_pressed = None
622596
self._xypress = None
597+
self._idPress = None
598+
self._idRelease = None
599+
self._idDrag = None
623600

624601
def enable(self, event):
625-
self.navigation.canvaslock(self)
626-
self.navigation.presslock(self)
627-
self.navigation.releaselock(self)
602+
self.figure.canvas.widgetlock(self)
603+
self._idPress = self.figure.canvas.mpl_connect(
604+
'button_press_event', self._press)
605+
self._idRelease = self.figure.canvas.mpl_connect(
606+
'button_release_event', self._release)
628607

629608
def disable(self, event):
630-
self.navigation.canvaslock.release(self)
631-
self.navigation.presslock.release(self)
632-
self.navigation.releaselock.release(self)
609+
self.figure.canvas.widgetlock.release(self)
610+
self.figure.canvas.mpl_disconnect(self._idPress)
611+
self.figure.canvas.mpl_disconnect(self._idRelease)
633612

634-
def press(self, event):
613+
def _press(self, event):
635614
if event.button == 1:
636615
self._button_pressed = 1
637616
elif event.button == 3:
@@ -653,14 +632,16 @@ def press(self, event):
653632
a.get_navigate() and a.can_pan()):
654633
a.start_pan(x, y, event.button)
655634
self._xypress.append((a, i))
656-
self.navigation.movelock(self)
657-
self.navigation.press(event)
635+
self.navigation.messagelock(self)
636+
self._idDrag = self.figure.canvas.mpl_connect(
637+
'motion_notify_event', self._mouse_move)
658638

659-
def release(self, event):
639+
def _release(self, event):
660640
if self._button_pressed is None:
661641
return
662642

663-
self.navigation.movelock.release(self)
643+
self.figure.canvas.mpl_disconnect(self._idDrag)
644+
self.navigation.messagelock.release(self)
664645

665646
for a, _ind in self._xypress:
666647
a.end_pan()
@@ -669,12 +650,11 @@ def release(self, event):
669650
self._xypress = []
670651
self._button_pressed = None
671652
self.navigation.push_current()
672-
self.navigation.release(event)
673653
self.navigation.draw()
674654

675-
def mouse_move(self, event):
655+
def _mouse_move(self, event):
676656
for a, _ind in self._xypress:
677-
#safer to use the recorded button at the press than current button:
678-
#multiple button can get pressed during motion...
657+
#safer to use the recorded button at the _press than current
658+
#button: #multiple button can get pressed during motion...
679659
a.drag_pan(self._button_pressed, event.key, event.x, event.y)
680660
self.navigation.dynamic_update()

0 commit comments

Comments
 (0)