-
-
Notifications
You must be signed in to change notification settings - Fork 7.8k
MEP22: Navigation by events #3652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
69 commits
Select commit
Hold shift + click to select a range
8cceed4
navigation and toolbar coexistence
fariza 3118a5a
mod keypress in figuremanager
fariza b4d5fcf
helper methods in toolbar and navigation
fariza 1e8af47
Adding doc to base methods
fariza 622cb95
property for active_toggle
fariza d1a9de4
simulate click
fariza 3f89d52
activate renamed to trigger
fariza 4f3c10b
toggle tools using enable/disable from its trigger method
fariza 6065daa
simplifying _handle_toggle
fariza f6a2f19
reducing number of locks
fariza 05db3b6
changing toggle and persistent attributes for issubclass
fariza c08fe56
bug in combined key press
fariza b207a72
untoggle zoom and pan from keypress while toggled
fariza 9266447
classmethods for default tools modification
fariza a53419a
adding zaxis and some pep8
fariza 704c717
removing legacy method dynamic update
fariza 5056729
tk backend
fariza e6a4e1e
example working with Tk
fariza 8942c47
duplicate code in keymap tool initialization
fariza 022de6f
grammar corrections
fariza 2c9a195
moving views and positions to tools
fariza cafe668
The views positions mixin automatically adds the clear as axobserver
fariza 224f745
bug when navigation was not defined
fariza 94c711e
Small refactor so that we first initiate the Navigation (ToolManager)…
OceanWolf 67257e7
Moved default_tool initilisation to FigureManagerBase and cleaned.
OceanWolf ffa65d6
Temporary fix to backends
OceanWolf 6739ee0
removing persistent tools
fariza d18206f
removing unregister
fariza 34a52c8
change cursor inmediately after toggle
fariza c2da483
removing intoolbar
fariza 44a9b0e
events working
fariza a2ed47f
using pydispatch
fariza 0665890
using navigation as signal handler
fariza 411e6e2
removing view positions singleton
fariza d484ebd
moving set_cursor completely out of navigation
fariza 75bf97b
removing unused event class
fariza 6cc040b
underscore in tool_trigger-xxx
fariza 0ff5997
adding radio_group for toggle tools
fariza af6734f
scroll to zoom in zoom/pan tools
fariza 78513d2
remove ToolAddedEvent incorporating the functionality into toolevent
fariza 377ff54
eliminating repeated loop
fariza 7dbbf58
replace draw by draw_idle in tools
fariza dd66b57
rename mpl_connect
fariza 67a414f
cleaning navigation and toolbar dependencies
fariza e415d8d
Made NavigationBase.get_tool() more useful.
OceanWolf 1213086
Refactored Toolbar out of NavigationBase
OceanWolf ba61dec
Some short cuts for adding tools
OceanWolf 9f2ee2b
Lots of fixes
OceanWolf 9da2b13
Rename ToolbarBase -> ToolContainerBase
OceanWolf 110253f
Statusbar
OceanWolf e2804ea
tool group position
fariza 9a64b7e
docstrings and small corrections by WeatherGod
fariza 64f947f
tkbackend updated
fariza e8cd5d5
tacaswell comments aprl 1
fariza 4bbcf4e
renaming tool_trigger_event
fariza 73a2661
add_tools moved out of base classes
fariza 1b83628
figure.setter in tools
fariza e4edd23
rename tools to default_tools to avoid confusion
fariza d4ac2fb
docstring helper add_tools methods
fariza a7640ef
rename navigation to toolmanager
fariza 48a6971
tkagg updated for toolmanager and tool groups
fariza 8dafe09
doc and minor code organization
fariza a0695d0
whats new
fariza 328b169
missing object from class declaration
fariza aac4744
remove comments and docstrings
fariza f09b9ef
import with original name backend_tools
fariza def3a52
rename 2 -> to, example without gtk only code
fariza 9ee7e25
zoom pan buttons order
fariza 5eae4e1
matplotlib.rcParams['toolbar'] == 'None' starts toolmanager but not t…
fariza File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
:mod:`matplotlib.backend_managers` | ||
=================================== | ||
|
||
.. automodule:: matplotlib.backend_managers | ||
:members: | ||
:undoc-members: | ||
:show-inheritance: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
:mod:`matplotlib.backend_tools` | ||
================================ | ||
|
||
.. automodule:: matplotlib.backend_tools | ||
:members: | ||
:undoc-members: | ||
:show-inheritance: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
ToolManager | ||
----------- | ||
|
||
Federico Ariza wrote the new `matplotlib.backend_managers.ToolManager` that comes as replacement for `NavigationToolbar2` | ||
|
||
`ToolManager` offers a new way of looking at the user interactions with the figures. | ||
Before we had the `NavigationToolbar2` with its own tools like `zoom/pan/home/save/...` and also we had the shortcuts like | ||
`yscale/grid/quit/....` | ||
`Toolmanager` relocate all those actions as `Tools` (located in `matplotlib.backend_tools`), and defines a way to `access/trigger/reconfigure` them. | ||
|
||
The `Toolbars` are replaced for `ToolContainers` that are just GUI interfaces to `trigger` the tools. But don't worry the default backends include a `ToolContainer` called `toolbar` | ||
|
||
|
||
.. note:: | ||
For the moment the `ToolManager` is working only with `GTK3` and `Tk` backends. | ||
Make sure you are using one of those. | ||
Port for the rest of the backends is comming soon. | ||
|
||
To activate the `ToolManager` include the following at the top of your file: | ||
|
||
>>> matplotlib.rcParams['toolbar'] = 'toolmanager' | ||
|
||
|
||
Interact with the ToolContainer | ||
``````````````````````````````` | ||
|
||
The most important feature is the ability to easily reconfigure the ToolContainer (aka toolbar). | ||
For example, if we want to remove the "forward" button we would just do. | ||
|
||
>>> fig.canvas.manager.toolmanager.remove_tool('forward') | ||
|
||
Now if you want to programmatically trigger the "home" button | ||
|
||
>>> fig.canvas.manager.toolmanager.trigger_tool('home') | ||
|
||
|
||
New Tools | ||
````````` | ||
|
||
It is possible to add new tools to the ToolManager | ||
|
||
A very simple tool that prints "You're awesome" would be:: | ||
|
||
from matplotlib.backend_tools import ToolBase | ||
class AwesomeTool(ToolBase): | ||
def trigger(self, *args, **kwargs): | ||
print("You're awesome") | ||
|
||
|
||
To add this tool to `ToolManager` | ||
|
||
>>> fig.canvas.manager.toolmanager.add_tool('Awesome', AwesomeTool) | ||
|
||
If we want to add a shortcut ("d") for the tool | ||
|
||
>>> fig.canvas.manager.toolmanager.update_keymap('Awesome', 'd') | ||
|
||
|
||
To add it to the toolbar inside the group 'foo' | ||
|
||
>>> fig.canvas.manager.toolbar.add_tool('Awesome', 'foo') | ||
|
||
|
||
There is a second class of tools, "Toggleable Tools", this are almost the same as our basic tools, just that belong to a group, and are mutually exclusive inside that group. | ||
For tools derived from `ToolToggleBase` there are two basic methods `enable` and `disable` that are called automatically whenever it is toggled. | ||
|
||
|
||
A full example is located in :ref:`user_interfaces-toolmanager` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't have a section for a "Full Example" if it is just a link to an actual example. Just link it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
'''This example demonstrates how to: | ||
* Modify the Toolbar | ||
* Create tools | ||
* Add tools | ||
* Remove tools | ||
Using `matplotlib.backend_managers.ToolManager` | ||
''' | ||
|
||
|
||
from __future__ import print_function | ||
import matplotlib | ||
matplotlib.use('GTK3Cairo') | ||
matplotlib.rcParams['toolbar'] = 'toolmanager' | ||
import matplotlib.pyplot as plt | ||
from matplotlib.backend_tools import ToolBase, ToolToggleBase | ||
from gi.repository import Gtk, Gdk | ||
|
||
|
||
class ListTools(ToolBase): | ||
'''List all the tools controlled by the `ToolManager`''' | ||
# keyboard shortcut | ||
default_keymap = 'm' | ||
description = 'List Tools' | ||
|
||
def trigger(self, *args, **kwargs): | ||
print('_' * 80) | ||
print("{0:12} {1:45} {2}".format('Name (id)', | ||
'Tool description', | ||
'Keymap')) | ||
print('-' * 80) | ||
tools = self.toolmanager.tools | ||
for name in sorted(tools.keys()): | ||
if not tools[name].description: | ||
continue | ||
keys = ', '.join(sorted(self.toolmanager.get_tool_keymap(name))) | ||
print("{0:12} {1:45} {2}".format(name, | ||
tools[name].description, | ||
keys)) | ||
print('_' * 80) | ||
print("Active Toggle tools") | ||
print("{0:12} {1:45}".format("Group", "Active")) | ||
print('-' * 80) | ||
for group, active in self.toolmanager.active_toggle.items(): | ||
print("{0:12} {1:45}".format(group, active)) | ||
|
||
|
||
class GroupHideTool(ToolToggleBase): | ||
'''Hide lines with a given gid''' | ||
default_keymap = 'G' | ||
description = 'Hide by gid' | ||
|
||
def __init__(self, *args, **kwargs): | ||
self.gid = kwargs.pop('gid') | ||
ToolToggleBase.__init__(self, *args, **kwargs) | ||
|
||
def enable(self, *args): | ||
self.set_lines_visibility(False) | ||
|
||
def disable(self, *args): | ||
self.set_lines_visibility(True) | ||
|
||
def set_lines_visibility(self, state): | ||
gr_lines = [] | ||
for ax in self.figure.get_axes(): | ||
for line in ax.get_lines(): | ||
if line.get_gid() == self.gid: | ||
line.set_visible(state) | ||
self.figure.canvas.draw() | ||
|
||
|
||
fig = plt.figure() | ||
plt.plot([1, 2, 3], gid='mygroup') | ||
plt.plot([2, 3, 4], gid='unknown') | ||
plt.plot([3, 2, 1], gid='mygroup') | ||
|
||
# Add the custom tools that we created | ||
fig.canvas.manager.toolmanager.add_tool('List', ListTools) | ||
fig.canvas.manager.toolmanager.add_tool('Hide', GroupHideTool, gid='mygroup') | ||
|
||
|
||
# Add an existing tool to new group `foo`. | ||
# It can be added as many times as we want | ||
fig.canvas.manager.toolbar.add_tool('zoom', 'foo') | ||
|
||
# Remove the forward button | ||
fig.canvas.manager.toolmanager.remove_tool('forward') | ||
|
||
# To add a custom tool to the toolbar at specific location inside | ||
# the navigation group | ||
fig.canvas.manager.toolbar.add_tool('Hide', 'navigation', 1) | ||
|
||
plt.show() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get a little bit confused here. Why does the user have to interact with the toolmanager? Now that I see these examples, I wonder if the user should ever call methods upon toolmanager. I understand the functional importance of the toolmanager, but from the user's perspective, adding a tool involves interacting with two separate objects that appear (to them) to have very little to do with each other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some tools don't need to have visual representation and others do (button for a toolbar).
But at the end, is up to the user to determine what he wants in his toolbar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right... good point. Might make sense in the future to add some convenience methods to make things easier for users, but I agree now that the user-facing distinction is necessary.