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

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
8cceed4
navigation and toolbar coexistence
fariza Jan 23, 2014
3118a5a
mod keypress in figuremanager
fariza Jan 23, 2014
b4d5fcf
helper methods in toolbar and navigation
fariza Jan 24, 2014
1e8af47
Adding doc to base methods
fariza Jan 24, 2014
622cb95
property for active_toggle
fariza Jan 26, 2014
d1a9de4
simulate click
fariza Jan 27, 2014
3f89d52
activate renamed to trigger
fariza Jan 28, 2014
4f3c10b
toggle tools using enable/disable from its trigger method
fariza Jan 29, 2014
6065daa
simplifying _handle_toggle
fariza Jan 29, 2014
f6a2f19
reducing number of locks
fariza Jan 29, 2014
05db3b6
changing toggle and persistent attributes for issubclass
fariza Feb 4, 2014
c08fe56
bug in combined key press
fariza Feb 4, 2014
b207a72
untoggle zoom and pan from keypress while toggled
fariza Feb 4, 2014
9266447
classmethods for default tools modification
fariza Feb 6, 2014
a53419a
adding zaxis and some pep8
fariza May 1, 2014
704c717
removing legacy method dynamic update
fariza May 6, 2014
5056729
tk backend
fariza May 6, 2014
e6a4e1e
example working with Tk
fariza May 6, 2014
8942c47
duplicate code in keymap tool initialization
fariza Jul 24, 2014
022de6f
grammar corrections
fariza Jul 24, 2014
2c9a195
moving views and positions to tools
fariza Jul 24, 2014
cafe668
The views positions mixin automatically adds the clear as axobserver
fariza Jul 25, 2014
224f745
bug when navigation was not defined
fariza Jul 25, 2014
94c711e
Small refactor so that we first initiate the Navigation (ToolManager)…
OceanWolf Jul 28, 2014
67257e7
Moved default_tool initilisation to FigureManagerBase and cleaned.
OceanWolf Jul 29, 2014
ffa65d6
Temporary fix to backends
OceanWolf Jul 29, 2014
6739ee0
removing persistent tools
fariza Sep 3, 2014
d18206f
removing unregister
fariza Sep 4, 2014
34a52c8
change cursor inmediately after toggle
fariza Sep 5, 2014
c2da483
removing intoolbar
fariza Oct 15, 2014
44a9b0e
events working
fariza Oct 16, 2014
a2ed47f
using pydispatch
fariza Oct 17, 2014
0665890
using navigation as signal handler
fariza Oct 20, 2014
411e6e2
removing view positions singleton
fariza Oct 20, 2014
d484ebd
moving set_cursor completely out of navigation
fariza Oct 27, 2014
75bf97b
removing unused event class
fariza Nov 10, 2014
6cc040b
underscore in tool_trigger-xxx
fariza Nov 10, 2014
0ff5997
adding radio_group for toggle tools
fariza Nov 14, 2014
af6734f
scroll to zoom in zoom/pan tools
fariza Nov 28, 2014
78513d2
remove ToolAddedEvent incorporating the functionality into toolevent
fariza Dec 5, 2014
377ff54
eliminating repeated loop
fariza Jan 5, 2015
7dbbf58
replace draw by draw_idle in tools
fariza Jan 21, 2015
dd66b57
rename mpl_connect
fariza Jan 21, 2015
67a414f
cleaning navigation and toolbar dependencies
fariza Feb 4, 2015
e415d8d
Made NavigationBase.get_tool() more useful.
OceanWolf Feb 11, 2015
1213086
Refactored Toolbar out of NavigationBase
OceanWolf Feb 12, 2015
ba61dec
Some short cuts for adding tools
OceanWolf Feb 16, 2015
9f2ee2b
Lots of fixes
OceanWolf Feb 18, 2015
9da2b13
Rename ToolbarBase -> ToolContainerBase
OceanWolf Feb 18, 2015
110253f
Statusbar
OceanWolf Feb 20, 2015
e2804ea
tool group position
fariza Feb 26, 2015
9a64b7e
docstrings and small corrections by WeatherGod
fariza Mar 23, 2015
64f947f
tkbackend updated
fariza Mar 31, 2015
e8cd5d5
tacaswell comments aprl 1
fariza Apr 1, 2015
4bbcf4e
renaming tool_trigger_event
fariza Apr 1, 2015
73a2661
add_tools moved out of base classes
fariza Apr 1, 2015
1b83628
figure.setter in tools
fariza Apr 1, 2015
e4edd23
rename tools to default_tools to avoid confusion
fariza Apr 1, 2015
d4ac2fb
docstring helper add_tools methods
fariza Apr 1, 2015
a7640ef
rename navigation to toolmanager
fariza Apr 2, 2015
48a6971
tkagg updated for toolmanager and tool groups
fariza Apr 2, 2015
8dafe09
doc and minor code organization
fariza Apr 2, 2015
a0695d0
whats new
fariza Apr 3, 2015
328b169
missing object from class declaration
fariza Apr 3, 2015
aac4744
remove comments and docstrings
fariza Apr 3, 2015
f09b9ef
import with original name backend_tools
fariza Apr 3, 2015
def3a52
rename 2 -> to, example without gtk only code
fariza Apr 7, 2015
9ee7e25
zoom pan buttons order
fariza Apr 7, 2015
5eae4e1
matplotlib.rcParams['toolbar'] == 'None' starts toolmanager but not t…
fariza Apr 7, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
example working with Tk
  • Loading branch information
fariza committed Apr 7, 2015
commit e6a4e1e282a1f36dd44769fc29f5520ea73282fa
54 changes: 30 additions & 24 deletions examples/user_interfaces/navigation.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
import matplotlib
# matplotlib.use('GTK3Cairo')
matplotlib.use('TkAGG')
matplotlib.use('GTK3Cairo')
# matplotlib.use('TkAGG')
matplotlib.rcParams['toolbar'] = 'navigation'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are examples, I would suggest getting rid of extraneous commented out code, and also highlight important lines of code such as this one. For example, is it important that it gets called before importing pyplot? What is it for? Perhaps a short docstring at the top of this example would help explain its purpose/goal that it is demonstrating?

import matplotlib.pyplot as plt
from matplotlib.backend_tools import ToolBase


#Create a simple tool to list all the tools
# Create a simple tool to list all the tools
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if these comments be class docstrings docstrings instead

class ListTools(ToolBase):
#keyboard shortcut
# keyboard shortcut
keymap = 'm'
#Name used as id, must be unique between tools of the same navigation
name = 'List'
description = 'List Tools'
#Where to put it in the toolbar, -1 = at the end, None = Not in toolbar
position = -1

def trigger(self, event):
#The most important attributes are navigation and figure
self.navigation.list_tools()


#A simple example of copy canvas
#ref: at https://github.com/matplotlib/matplotlib/issues/1987
class CopyTool(ToolBase):
tools = self.navigation.get_tools()

print ('_' * 80)
print ("{0:12} {1:45} {2}".format('Name (id)',
'Tool description',
'Keymap'))
print ('_' * 80)
for name in sorted(tools.keys()):
keys = ', '.join(sorted(tools[name]['keymap']))
print ("{0:12} {1:45} {2}".format(name,
tools[name]['description'],
keys))
print ('_' * 80)


# A simple example of copy canvas
# ref: at https://github.com/matplotlib/matplotlib/issues/1987
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, should be a class docstring

class CopyToolGTK3(ToolBase):
keymap = 'ctrl+c'
name = 'Copy'
description = 'Copy canvas'
position = -1
# It is not added to the toolbar as a button
intoolbar = False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this need to get removed now?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks


def trigger(self, event):
from gi.repository import Gtk, Gdk
Expand All @@ -41,13 +48,12 @@ def trigger(self, event):
fig = plt.figure()
plt.plot([1, 2, 3])

#If we are in the old toolbar, don't try to modify it
if matplotlib.rcParams['toolbar'] in ('navigation', 'None'):
##Add the custom tools that we created
fig.canvas.manager.navigation.add_tool(ListTools)
fig.canvas.manager.navigation.add_tool(CopyTool)
# Add the custom tools that we created
fig.canvas.manager.navigation.add_tool('List', ListTools)
if matplotlib.rcParams['backend'] == 'GTK3Cairo':
fig.canvas.manager.navigation.add_tool('copy', CopyToolGTK3)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine with making this a GTK3Cairo-only example. Makes it a little bit simpler


##Just for fun, lets remove the back button
fig.canvas.manager.navigation.remove_tool('Back')
# Just for fun, lets remove the back button
fig.canvas.manager.navigation.remove_tool('Back')

plt.show()
110 changes: 35 additions & 75 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -3230,41 +3230,27 @@ class NavigationBase(object):

Attributes
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't lined up with the underscores below

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

----------
canvas : `FigureCanvas` instance
manager : `FigureManager` instance
toolbar : `Toolbar` instance that is controlled by this `Navigation`
keypresslock : `LockDraw` to know if the `canvas` key_press_event is
locked
messagelock : `LockDraw` to know if the message is available to write
"""

_default_cursor = cursors.POINTER
_default_tools = [tools.ToolToggleGrid,
tools.ToolToggleFullScreen,
tools.ToolQuit,
tools.ToolEnableAllNavigation,
tools.ToolEnableNavigation,
tools.ToolToggleXScale,
tools.ToolToggleYScale,
tools.ToolHome, tools.ToolBack,
tools.ToolForward,
None,
tools.ToolZoom,
tools.ToolPan,
None,
'ConfigureSubplots',
'SaveFigure']

def __init__(self, canvas, toolbar=None):

def __init__(self, manager):
""".. automethod:: _toolbar_callback"""

self.canvas = canvas
self.toolbar = self._get_toolbar(toolbar, canvas)
self.manager = manager
self.canvas = manager.canvas
self.toolbar = manager.toolbar

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

self._idDrag = self.canvas.mpl_connect('motion_notify_event',
self._mouse_move)
self._idDrag = self.canvas.mpl_connect(
'motion_notify_event', self._mouse_move)

# a dict from axes index to a list of view limits
self.views = cbook.Stack()
Expand All @@ -3280,36 +3266,15 @@ def __init__(self, canvas, toolbar=None):
# to write into toolbar message
self.messagelock = widgets.LockDraw()

for tool in self._default_tools:
for name, tool in tools.tools:
if tool is None:
if self.toolbar is not None:
self.toolbar.add_separator(-1)
else:
self.add_tool(tool)
self.add_tool(name, tool, None)

self._last_cursor = self._default_cursor

@classmethod
def get_default_tools(cls):
"""Get the default tools"""

return cls._default_tools

@classmethod
def set_default_tools(cls, tools):
"""Set default tools"""

cls._default_tools = tools

def _get_toolbar(self, toolbar, canvas):
# must be inited after the window, drawingArea and figure
# attrs are set
if rcParams['toolbar'] == 'navigation' and toolbar is not None:
toolbar = toolbar(canvas.manager)
else:
toolbar = None
return toolbar

@property
def active_toggle(self):
"""Toggled Tool
Expand Down Expand Up @@ -3381,8 +3346,7 @@ def unregister(self, name):
This method is used by `PersistentTools` to remove the reference kept
by `Navigation`.

It is usually called by the `deactivate` method or during
destroy if it is a graphical Tool.
It is usually called by the `unregister` method

If called, next time the `Tool` is used it will be reinstantiated
instead of using the existing instance.
Expand Down Expand Up @@ -3411,29 +3375,27 @@ def remove_tool(self, name):
if self.toolbar:
self.toolbar._remove_toolitem(name)

def add_tool(self, tool):
def add_tool(self, name, tool, position=None):
"""Add tool to `Navigation`

Parameters
----------
name : string
Name of the tool, treated as the ID, has to be unique
tool : string or `Tool` class
Reference to find the class of the Tool to be added
position : int or None (default)
Position in the toolbar, if None, is positioned at the end
"""

tool_cls = self._get_cls_to_instantiate(tool)
if tool_cls is False:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably should do a # noqa here to keep pep8 from complaining. Might also need a comment explaining why to keep future devs from "fixing" this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't see the pep8 error here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be if not tool_cls ?

Wouldn't be simpler to just have self._get_cls_to_instantiate raise if it fails? If you want to do something else in that case then just try...execpt and if you want to die (which I am assuming is the default case) you don't have to do anything.

I suspect @WeatherGod also has a pyflake/pylint turned on.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, I am reading and commenting top-down. Sorry if some of these seem dumb in light of code I have not read yet.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done @tacaswell change, but still not see the pep8 error

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different versions of pep8? I find myself curious to learn about this as Travis doesn't complain.

warnings.warn('Impossible to find class for %s' % str(tool))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this raise an exception? The function failed to achieve its goal and no new tool was added.

return
name = tool_cls.name

if name is None:
warnings.warn('tool_clss need a name to be added, it is used '
'as ID')
return
if name in self._tools:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be done first in this function? Do we want to check to make sure that they are the same type? Again, why warn rather than raise?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used warn because i don't think that adding twice the same tool represents a major fault and your program will keep working as expected (you already have the tool)

warnings.warn('A tool_cls with the same name already exist, '
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a user won't know what tool_cls is because that name is only relevant inside this function. Say "Tool class".

Also, "exist" --> "exists".

'not added')

return

self._tools[name] = tool_cls
Expand All @@ -3444,7 +3406,7 @@ def add_tool(self, tool):
(k, self._keys[k], name))
self._keys[k] = name

if self.toolbar and tool_cls.position is not None:
if self.toolbar and tool_cls.intoolbar:
# TODO: better search for images, they are not always in the
# datapath
basedir = os.path.join(rcParams['datapath'], 'images')
Expand All @@ -3453,10 +3415,11 @@ def add_tool(self, tool):
else:
fname = None
toggle = issubclass(tool_cls, tools.ToolToggleBase)
self.toolbar._add_toolitem(name, tool_cls.description,
fname,
tool_cls.position,
toggle)
self.toolbar._add_toolitem(name,
tool_cls.description,
fname,
position,
toggle)

def _get_cls_to_instantiate(self, callback_class):
if isinstance(callback_class, six.string_types):
Expand Down Expand Up @@ -3505,7 +3468,7 @@ def _key_press(self, event):

def _get_instance(self, name):
if name not in self._instances:
instance = self._tools[name](self.canvas.figure)
instance = self._tools[name](self.canvas.figure, name)
# register instance
self._instances[name] = instance

Expand Down Expand Up @@ -3551,26 +3514,23 @@ def _handle_toggle(self, name, event=None, from_toolbar=False):
for a in self.canvas.figure.get_axes():
a.set_navigate_mode(self._toggled)

def list_tools(self):
"""Print the list the tools controlled by `Navigation`"""
def get_tools(self):
"""Return the tools controlled by `Navigation`"""

print ('_' * 80)
print ("{0:20} {1:50} {2}".format('Name (id)', 'Tool description',
'Keymap'))
print ('_' * 80)
d = {}
for name in sorted(self._tools.keys()):
tool = self._tools[name]
keys = [k for k, i in six.iteritems(self._keys) if i == name]
print ("{0:20} {1:50} {2}".format(tool.name, tool.description,
', '.join(keys)))
print ('_' * 80, '\n')
d[name] = {'cls': tool,
'description': tool.description,
'keymap': keys}
return d

def update(self):
"""Reset the axes stack"""

self.views.clear()
self.positions.clear()
# self.set_history_buttons()

def _mouse_move(self, event):
if not event.inaxes or not self._toggled:
Expand Down Expand Up @@ -3667,7 +3627,6 @@ def push_current(self):
a.get_position().frozen()))
self.views.push(lims)
self.positions.push(pos)
# self.set_history_buttons()

def draw_rubberband(self, event, caller, x0, y0, x1, y1):
"""Draw a rectangle rubberband to indicate zoom limits
Expand Down Expand Up @@ -3719,7 +3678,7 @@ def __init__(self, manager):
self.manager = manager

def _add_toolitem(self, name, description, image_file, position,
toggle):
toggle):
"""Add a toolitem to the toolbar

The callback associated with the button click event,
Expand Down Expand Up @@ -3776,7 +3735,8 @@ def _toggle(self, name, callback=False):

"""

# carefull, callback means to perform or not the callback while toggling
# carefull, callback means to perform or not the callback while
# toggling
raise NotImplementedError

def _remove_toolitem(self, name):
Expand Down
Loading