Skip to content

Commit

Permalink
figure centered FigureManager and ToolManager
Browse files Browse the repository at this point in the history
  • Loading branch information
fariza committed May 8, 2015
1 parent 029829b commit ec5fa0d
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 55 deletions.
59 changes: 59 additions & 0 deletions examples/user_interfaces/multifigure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# from __future__ import print_function
import matplotlib
matplotlib.use('GTK3AGG')
# matplotlib.rcParams['backend.multifigure'] = False
matplotlib.rcParams['toolbar'] = 'toolmanager'
from matplotlib.backend_tools import ToolBase


from matplotlib.figure import Figure
from matplotlib.backend_managers import FigureManager


class t1(ToolBase):
description = "change canvas"
def __init__(self, *args, **kwargs):
self.mfigure = kwargs.pop('figure')
ToolBase.__init__(self, *args, **kwargs)

def trigger(self, *args, **kwargs):
self.toolmanager.manager.figure = self.mfigure


manager = FigureManager(None, 1)
backend = manager._backend

fig1 = Figure()
canvas1 = backend.FigureCanvas(fig1)
ax1 = fig1.add_subplot(111)
ax1.plot([1, 2, 3])

manager.figure = fig1

fig2 = Figure()
canvas2 = backend.FigureCanvas(fig2)
ax2 = fig2.add_subplot(111)
ax2.plot([3, 2, 1])

fig3 = Figure()
canvas3 = backend.FigureCanvas(fig3)
ax3 = fig3.add_subplot(111)
ax3.plot([1, 1, 1])

sidebar = manager._get_toolbar()
sidebar.set_flow('vertical')


manager.toolmanager.add_tool('f1', t1, figure=fig1)
manager.toolmanager.add_tool('f2', t1, figure=fig2)
manager.toolmanager.add_tool('f3', t1, figure=fig3)
sidebar.add_tool('f1', 'foo')
sidebar.add_tool('f2', 'foo')
sidebar.add_tool('f3', 'foo')
manager.window.add_element(sidebar, False, 'west')


manager.show()
manager.mpl_connect('window_destroy_event', manager.destroy)
manager._mainloop()

22 changes: 22 additions & 0 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2718,6 +2718,28 @@ def add_element(self, element, expand, place):
"""
pass

def replace_element(self, oldelement, newelement):
"""Replaces a gui widget for another
Parameters
----------
oldelement: A gui element.
The element to be replaced
newelement: A gui element.
The replacement element
"""
pass

def remove_element(self, element):
"""Removes a widget
Parameters
----------
element: A gui element
Element to be removed from the gui
"""
pass

def destroy_event(self, *args):
"""Fires this event when the window wants to destroy itself.
Expand Down
102 changes: 77 additions & 25 deletions lib/matplotlib/backend_managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,52 +75,83 @@ def __init__(self, figure, num):
cbook.EventEmitter.__init__(self)
self.num = num

self._h = 0
self._w = 0
self._figure = None
self.key_press_handler_id = None
self._backend = get_backend()
self._mainloop = self._backend.MainLoop()
self.toolmanager = self._get_toolmanager()

self.window = self._backend.Window('Figure %d' % num)
self.window.mpl_connect('window_destroy_event', self._destroy)

self.canvas = self._backend.FigureCanvas(figure, manager=self)

self.key_press_handler_id = self.canvas.mpl_connect('key_press_event',
self.key_press) if rcParams['toolbar'] != 'toolmanager' else None

w = int(self.canvas.figure.bbox.width)
h = int(self.canvas.figure.bbox.height)

self.window.add_element(self.canvas, True, 'center')

self.toolmanager = self._get_toolmanager()
self.figure = figure
self.toolbar = self._get_toolbar()

if self.toolmanager:
tools.add_tools_to_manager(self.toolmanager)
if self.toolbar:
tools.add_tools_to_container(self.toolbar)
self.statusbar = self._backend.Statusbar(self.toolmanager)
h += self.window.add_element(self.statusbar, False, 'south')
self._h += self.window.add_element(self.statusbar, False,
'south')

if self.toolbar is not None:
h += self.window.add_element(self.toolbar, False, 'south')
self._h += self.window.add_element(self.toolbar, False, 'south')

self.window.set_default_size(w, h)
self.window.set_default_size(self._w, self._h)
self._full_screen_flag = False

if is_interactive():
self.window.show()

@property
def figure(self):
return self._figure

@figure.setter
def figure(self, figure):
if not figure:
return

if self.key_press_handler_id:
self.figure.canvas.mpl_disconnect(self.key_press_handler_id)

if not figure.canvas:
self._backend.FigureCanvas(figure, manager=self)

if rcParams['toolbar'] != 'toolmanager':
self.key_press_handler_id = figure.canvas.mpl_connect(
'key_press_event', self.key_press)

if not self._figure:
self._add_figure_to_window(figure)
else:
self.window.replace_element(self._figure.canvas, figure.canvas)

self._figure = figure
self.toolmanager.figure = figure

def notify_axes_change(fig):
'this will be called whenever the current axes is changed'
if self.toolmanager is None and self.toolbar is not None:
self.toolbar.update()
self.canvas.figure.add_axobserver(notify_axes_change)
figure.add_axobserver(notify_axes_change)

def _add_figure_to_window(self, figure):
self._w += int(figure.bbox.width)
self._h += int(figure.bbox.height)
self.window.add_element(figure.canvas, True, 'center')
self.window.set_default_size(self._w, self._h)
figure.canvas.show()

def key_press(self, event):
"""
Implement the default mpl key bindings defined at
:ref:`key-event-handling`
"""
key_press_handler(event, self.canvas, self.canvas.toolbar)
key_press_handler(event, self.figure.canvas, self.toolbar)

def _destroy(self, event=None):
# Callback from the when the window wants to destroy itself
Expand All @@ -132,7 +163,8 @@ def destroy(self, *args):
"""Called to destroy this FigureManager, gets called by Gcf through
event magic.
"""
self.canvas.destroy()
if self.figure and self.figure.canvas:
self.figure.canvas.destroy()
if self.toolbar:
self.toolbar.destroy()
self.window.destroy()
Expand Down Expand Up @@ -173,15 +205,15 @@ def _get_toolbar(self):
if rcParams['toolbar'] == 'toolmanager':
toolbar = self._backend.Toolbar(self.toolmanager)
elif rcParams['toolbar'] == 'toolbar2':
toolbar = self._backend.Toolbar2(self.canvas, self.window)
toolbar = self._backend.Toolbar2(self.figure.canvas, self.window)
else:
toolbar = None
return toolbar

def _get_toolmanager(self):
# must be initialised after toolbar has been setted
if rcParams['toolbar'] != 'toolbar2':
toolmanager = ToolManager(self.canvas)
toolmanager = ToolManager(self)
else:
toolmanager = None
return toolmanager
Expand Down Expand Up @@ -234,21 +266,41 @@ class ToolManager(object):
`LockDraw` object to know if the message is available to write
"""

def __init__(self, canvas):
self.canvas = canvas

self._key_press_handler_id = self.canvas.mpl_connect(
'key_press_event', self._key_press)

def __init__(self, manager):
self._figure = None
self._tools = {}
self._keys = {}
self._toggled = {}
self._callbacks = cbook.CallbackRegistry()
self._key_press_handler_id = None

# to process keypress event
self.keypresslock = widgets.LockDraw()
self.messagelock = widgets.LockDraw()

self.manager = manager
self.figure = manager.figure

@property
def figure(self):
return self._figure

@figure.setter
def figure(self, figure):
if not figure:
return

if self._key_press_handler_id:
self.figure.canvas.mpl_disconnect(self._key_press_handler_id)

self._key_press_handler_id = figure.canvas.mpl_connect(
'key_press_event', self._key_press)

for tool in self._tools.values():
tool.figure = figure

self._figure = figure

def toolmanager_connect(self, s, func):
"""
Connect event with string *s* to *func*.
Expand Down
Loading

0 comments on commit ec5fa0d

Please sign in to comment.