MEP22: Toolbar rewrite#
Status#
Progress
Branches and Pull requests#
Previous work:
Pull Requests:
Removing the NavigationToolbar classesmatplotlib/matplotlib#2740CLOSED
Keeping the NavigationToolbar classesmatplotlib/matplotlib#2759CLOSED
Navigation by events:matplotlib/matplotlib#3652
Abstract#
The main goal of this MEP is to make it easier to modify (add, change,remove) the way the user interacts with the figures.
The user interaction with the figure is deeply integrated within theCanvas and Toolbar. Making extremely difficult to do any modification.
This MEP proposes the separation of this interaction into Toolbar,Navigation and Tools to provide independent access andreconfiguration.
This approach will make easier to create and share tools amongusers. In the far future, we can even foresee a kind of MarketplaceforTool
s where the most popular can be added into the maindistribution.
Detailed description#
The reconfiguration of the Toolbar is complex, most of the time itrequires a custom backend.
The creation of custom Tools sometimes interferes with the Toolbar, asexample seematplotlib/matplotlib#2694 alsothe shortcuts are hardcoded and again not easily modifiablematplotlib/matplotlib#2699
The proposed solution is to take the actions out of theToolbar
and theshortcuts out of theCanvas
. The actions and shortcuts will be in the formofTool
s.
A new classNavigation
will be the bridge between the events from theCanvas
andToolbar
and redirect them to the appropriateTool
.
At the end the user interaction will be divided into three classes:
NavigationBase: This class is instantiated for each FigureManagerand connect the all user interactions with the Tools
ToolbarBase: This existing class is relegated only as a GUI accessto Tools.
ToolBase: Is the basic definition of Tools.
Implementation#
ToolBase(object)#
Tools can have a graphical representation as theSubplotTool
or not even bepresent in the Toolbar asQuit
.
TheToolBase
has the following class attributes for configuration at definition time
keymap = None: Key(s) to be used to trigger the tool
description = '': Small description of the tool
image = None: Image that is used in the toolbar
The following instance attributes are set at instantiation:
name
navigation
Methods#
trigger(self,event)
: This is the main method of the Tool, it is calledwhen the Tool is triggered by:Toolbar button click
keypress associated with the Tool Keymap
Call to navigation.trigger_tool(name)
set_figure(self,figure)
: Set the figure and navigation attributesdestroy(self,*args)
: Destroy theTool
graphical interface (ifexists)
Available Tools#
ToolQuit
ToolEnableAllNavigation
ToolEnableNavigation
ToolToggleGrid
ToolToggleFullScreen
ToolToggleYScale
ToolToggleXScale
ToolHome
ToolBack
ToolForward
SaveFigureBase
ConfigureSubplotsBase
ToolToggleBase(ToolBase)#
TheToolToggleBase
has the following class attributes forconfiguration at definition time
radio_group = None: Attribute to group 'radio' like tools (mutuallyexclusive)
cursor = None: Cursor to use when the tool is active
TheToggleable Tools, can capture keypress, mouse moves, and mousebutton press
Methods#
enable(self,event)
: Called byToolToggleBase.trigger
methoddisable(self,event)
: Called when the tool is untoggledtoggled
:Property True or False
Available Tools#
ToolZoom
ToolPan
NavigationBase#
Defines the following attributes:
canvas:
keypresslock: Lock to know if the
canvas
key_press_event
isavailable and process itmessagelock: Lock to know if the message is available to write
Methods (intended for the end user)#
nav_connect(self,s,func)
: Connect to navigation for eventsnav_disconnect(self,cid)
: Disconnect from navigation eventmessage_event(self,message,sender=None)
: Emit atool_message_event eventactive_toggle(self)
:Property The currently toggled tools orNoneget_tool_keymap(self,name)
: Return a list of keys that areassociated with the toolset_tool_keymap(self,name,``*keys
)``: Set the keys for the given toolremove_tool(self,name)
: Removes tool from the navigation control.add_tools(self,tools)
: Add multiple tools toNavigation
add_tool(self,name,tool,group=None,position=None)
: Add a toolto theNavigation
tool_trigger_event(self,name,sender=None,canvasevent=None,data=None)
: Trigger a tool and fire the eventtools
:Property A dict with available tools withcorresponding keymaps, descriptions and objectsget_tool(self,name)
: Return the tool object
ToolbarBase#
Methods (for backend implementation)#
add_toolitem(self,name,group,position,image,description,toggle)
:Add a toolitem to the toolbar. This method is a callback fromtool_added_event
(emitted by navigation)set_message(self,s)
: Display a message on toolbar or in status bartoggle_toolitem(self,name)
: Toggle the toolitem without firing event.remove_toolitem(self,name)
: Remove a toolitem from theToolbar
Backward compatibility#
For backward compatibility added 'navigation' to the list of valuessupported byrcParams["toolbar"]
(default:'toolbar2'
), that is used forNavigation
classesinstantiation instead of the NavigationToolbar classes
With this parameter, it makes it transparent to anyone using theexisting backends.
[@pelson comment: This also gives us an opportunity to avoid needingto implement all of this in the same PR - some backends canpotentially exist without the new functionality for a short while (butit must be done at some point).]