Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5d73e9f

Browse files
author
Federico Ariza
committed
ToolManager and Tools can be initialized without tools
1 parent 5ae231a commit 5d73e9f

File tree

4 files changed

+117
-45
lines changed

4 files changed

+117
-45
lines changed

lib/matplotlib/backend_managers.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,12 @@ class ToolManager(object):
5656
`LockDraw` object to know if the message is available to write
5757
"""
5858

59-
def __init__(self, canvas):
59+
def __init__(self, figure=None):
6060
warnings.warn('Treat the new Tool classes introduced in v1.5 as ' +
6161
'experimental for now, the API will likely change in ' +
6262
'version 2.1 and perhaps the rcParam as well')
63-
self.canvas = canvas
6463

65-
self._key_press_handler_id = self.canvas.mpl_connect(
66-
'key_press_event', self._key_press)
64+
self._key_press_handler_id = None
6765

6866
self._tools = {}
6967
self._keys = {}
@@ -74,6 +72,45 @@ def __init__(self, canvas):
7472
self.keypresslock = widgets.LockDraw()
7573
self.messagelock = widgets.LockDraw()
7674

75+
self._figure = None
76+
self.set_figure(figure)
77+
78+
@property
79+
def canvas(self):
80+
"""Canvas managed by FigureManager"""
81+
if not self._figure:
82+
return None
83+
return self._figure.canvas
84+
85+
@property
86+
def figure(self):
87+
"""Figure that holds the canvas"""
88+
return self._figure
89+
90+
@figure.setter
91+
def figure(self, figure):
92+
self.set_figure(figure)
93+
94+
def set_figure(self, figure, update_tools=True):
95+
"""
96+
Sets the figure to interact with the tools
97+
98+
Parameters
99+
==========
100+
figure: `Figure`
101+
update_tools: bool
102+
Force tools to update figure
103+
"""
104+
if self._key_press_handler_id:
105+
self.canvas.mpl_disconnect(self._key_press_handler_id)
106+
self._figure = figure
107+
if figure:
108+
self._key_press_handler_id = self.canvas.mpl_connect(
109+
'key_press_event', self._key_press)
110+
if update_tools:
111+
for tool in self._tools.values():
112+
tool.figure = figure
113+
77114
def toolmanager_connect(self, s, func):
78115
"""
79116
Connect event with string *s* to *func*.
@@ -245,6 +282,7 @@ def add_tool(self, name, tool, *args, **kwargs):
245282
else:
246283
self._toggled.setdefault(tool_obj.radio_group, None)
247284

285+
tool_obj.set_figure(self.figure)
248286
self._tool_added_event(tool_obj)
249287
return tool_obj
250288

lib/matplotlib/backend_tools.py

Lines changed: 73 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,37 @@ def __init__(self, toolmanager, name):
7777
'experimental for now, the API will likely change in ' +
7878
'version 2.1, and some tools might change name')
7979
self._name = name
80+
self._toolmanager = toolmanager
8081
self._figure = None
81-
self.toolmanager = toolmanager
82-
self.figure = toolmanager.canvas.figure
8382

8483
@property
8584
def figure(self):
8685
return self._figure
8786

87+
@figure.setter
88+
def figure(self, figure):
89+
self.set_figure(figure)
90+
91+
@property
92+
def canvas(self):
93+
if not self._figure:
94+
return None
95+
return self._figure.canvas
96+
97+
@property
98+
def toolmanager(self):
99+
return self._toolmanager
100+
101+
def set_figure(self, figure):
102+
"""
103+
Assign a figure to the tool
104+
105+
Parameters
106+
----------
107+
figure: `Figure`
108+
"""
109+
self._figure = figure
110+
88111
def trigger(self, sender, event, data=None):
89112
"""
90113
Called when this tool gets used
@@ -104,20 +127,6 @@ def trigger(self, sender, event, data=None):
104127

105128
pass
106129

107-
@figure.setter
108-
def figure(self, figure):
109-
"""
110-
Set the figure
111-
112-
Set the figure to be affected by this tool
113-
114-
Parameters
115-
----------
116-
figure: `Figure`
117-
"""
118-
119-
self._figure = figure
120-
121130
@property
122131
def name(self):
123132
"""Tool Id"""
@@ -193,6 +202,14 @@ def toggled(self):
193202

194203
return self._toggled
195204

205+
def set_figure(self, figure):
206+
toggled = self.toggled
207+
if toggled:
208+
self.trigger(self, None)
209+
ToolBase.set_figure(self, figure)
210+
if figure and toggled:
211+
self.trigger(self, None)
212+
196213

197214
class SetCursorBase(ToolBase):
198215
"""
@@ -203,8 +220,7 @@ class SetCursorBase(ToolBase):
203220
"""
204221
def __init__(self, *args, **kwargs):
205222
ToolBase.__init__(self, *args, **kwargs)
206-
self._idDrag = self.figure.canvas.mpl_connect(
207-
'motion_notify_event', self._set_cursor_cbk)
223+
self._idDrag = None
208224
self._cursor = None
209225
self._default_cursor = cursors.POINTER
210226
self._last_cursor = self._default_cursor
@@ -215,6 +231,14 @@ def __init__(self, *args, **kwargs):
215231
for tool in self.toolmanager.tools.values():
216232
self._add_tool(tool)
217233

234+
def set_figure(self, figure):
235+
if self._idDrag:
236+
self.canvas.mpl_disconnect(self._idDrag)
237+
ToolBase.set_figure(self, figure)
238+
if figure:
239+
self._idDrag = self.canvas.mpl_connect(
240+
'motion_notify_event', self._set_cursor_cbk)
241+
218242
def _tool_trigger_cbk(self, event):
219243
if event.tool.toggled:
220244
self._cursor = event.tool.cursor
@@ -266,9 +290,16 @@ class ToolCursorPosition(ToolBase):
266290
This tool runs in the background reporting the position of the cursor
267291
"""
268292
def __init__(self, *args, **kwargs):
293+
self._idDrag = None
269294
ToolBase.__init__(self, *args, **kwargs)
270-
self._idDrag = self.figure.canvas.mpl_connect(
271-
'motion_notify_event', self.send_message)
295+
296+
def set_figure(self, figure):
297+
if self._idDrag:
298+
self.canvas.mpl_disconnect(self._idDrag)
299+
ToolBase.set_figure(self, figure)
300+
if figure:
301+
self._idDrag = self.canvas.mpl_connect(
302+
'motion_notify_event', self.send_message)
272303

273304
def send_message(self, event):
274305
"""Call `matplotlib.backend_managers.ToolManager.message_event`"""
@@ -458,16 +489,17 @@ def __init__(self, *args, **kwargs):
458489
self.home_views = WeakKeyDictionary()
459490
ToolBase.__init__(self, *args, **kwargs)
460491

461-
def add_figure(self):
492+
def add_figure(self, figure):
462493
"""Add the current figure to the stack of views and positions"""
463-
if self.figure not in self.views:
464-
self.views[self.figure] = cbook.Stack()
465-
self.positions[self.figure] = cbook.Stack()
466-
self.home_views[self.figure] = WeakKeyDictionary()
494+
495+
if figure not in self.views:
496+
self.views[figure] = cbook.Stack()
497+
self.positions[figure] = cbook.Stack()
498+
self.home_views[figure] = WeakKeyDictionary()
467499
# Define Home
468-
self.push_current()
500+
self.push_current(figure)
469501
# Make sure we add a home view for new axes as they're added
470-
self.figure.add_axobserver(lambda fig: self.update_home_views())
502+
figure.add_axobserver(lambda fig: self.update_home_views(fig))
471503

472504
def clear(self, figure):
473505
"""Reset the axes stack"""
@@ -508,18 +540,19 @@ def update_view(self):
508540

509541
self.figure.canvas.draw_idle()
510542

511-
def push_current(self):
543+
def push_current(self, figure=None):
512544
"""
513545
Push the current view limits and position onto their respective stacks
514546
"""
515-
547+
if not figure:
548+
figure = self.figure
516549
views = WeakKeyDictionary()
517550
pos = WeakKeyDictionary()
518-
for a in self.figure.get_axes():
551+
for a in figure.get_axes():
519552
views[a] = a._get_view()
520553
pos[a] = self._axes_pos(a)
521-
self.views[self.figure].push(views)
522-
self.positions[self.figure].push(pos)
554+
self.views[figure].push(views)
555+
self.positions[figure].push(pos)
523556

524557
def _axes_pos(self, ax):
525558
"""
@@ -539,15 +572,17 @@ def _axes_pos(self, ax):
539572
return (ax.get_position(True).frozen(),
540573
ax.get_position().frozen())
541574

542-
def update_home_views(self):
575+
def update_home_views(self, figure=None):
543576
"""
544577
Make sure that self.home_views has an entry for all axes present in the
545578
figure
546579
"""
547580

548-
for a in self.figure.get_axes():
549-
if a not in self.home_views[self.figure]:
550-
self.home_views[self.figure][a] = a._get_view()
581+
if not figure:
582+
figure = self.figure
583+
for a in figure.get_axes():
584+
if a not in self.home_views[figure]:
585+
self.home_views[figure][a] = a._get_view()
551586

552587
def refresh_locators(self):
553588
"""Redraw the canvases, update the locators"""
@@ -592,7 +627,7 @@ class ViewsPositionsBase(ToolBase):
592627
_on_trigger = None
593628

594629
def trigger(self, sender, event, data=None):
595-
self.toolmanager.get_tool(_views_positions).add_figure()
630+
self.toolmanager.get_tool(_views_positions).add_figure(self.figure)
596631
getattr(self.toolmanager.get_tool(_views_positions),
597632
self._on_trigger)()
598633
self.toolmanager.get_tool(_views_positions).update_view()
@@ -672,7 +707,7 @@ def disable(self, event):
672707
self.figure.canvas.mpl_disconnect(self._idScroll)
673708

674709
def trigger(self, sender, event, data=None):
675-
self.toolmanager.get_tool(_views_positions).add_figure()
710+
self.toolmanager.get_tool(_views_positions).add_figure(self.figure)
676711
ToolToggleBase.trigger(self, sender, event, data)
677712

678713
def scroll_zoom(self, event):

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,6 @@ def full_screen_toggle (self):
482482
self.window.unfullscreen()
483483
_full_screen_flag = False
484484

485-
486485
def _get_toolbar(self):
487486
# must be inited after the window, drawingArea and figure
488487
# attrs are set
@@ -497,7 +496,7 @@ def _get_toolbar(self):
497496
def _get_toolmanager(self):
498497
# must be initialised after toolbar has been setted
499498
if rcParams['toolbar'] != 'toolbar2':
500-
toolmanager = ToolManager(self.canvas)
499+
toolmanager = ToolManager(self.canvas.figure)
501500
else:
502501
toolmanager = None
503502
return toolmanager

lib/matplotlib/backends/backend_tkagg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ def _get_toolbar(self):
570570

571571
def _get_toolmanager(self):
572572
if rcParams['toolbar'] != 'toolbar2':
573-
toolmanager = ToolManager(self.canvas)
573+
toolmanager = ToolManager(self.canvas.figure)
574574
else:
575575
toolmanager = None
576576
return toolmanager

0 commit comments

Comments
 (0)