-
Notifications
You must be signed in to change notification settings - Fork 1
Enabling tool positions #7
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
Changes from all commits
6238ceb
c9e55de
c286849
c643e53
9e70c13
a756229
043d32f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,11 @@ | |
import warnings | ||
import time | ||
import io | ||
try: | ||
from collections import OrderedDict | ||
except: | ||
# simple python 2.6 implementation, core-features only | ||
from matplotlib.cbook import OrderedDict | ||
|
||
import numpy as np | ||
import matplotlib.cbook as cbook | ||
|
@@ -3397,7 +3402,7 @@ def add_tools(self, tools): | |
for position, tool in enumerate(grouptools): | ||
self.add_tool(tool[1], tool[0], group, position) | ||
|
||
def add_tool(self, name, tool, group=None, position=None): | ||
def add_tool(self, name, tool, group=None, position=-1): | ||
"""Add tool to `NavigationBase` | ||
|
||
Add a tool to the tools controlled by Navigation | ||
|
@@ -3414,8 +3419,8 @@ def add_tool(self, name, tool, group=None, position=None): | |
Reference to find the class of the Tool to be added | ||
group: String | ||
Group to position the tool in | ||
position : int or None (default) | ||
Position within its group in the toolbar, if None, it goes at the end | ||
position : int | ||
Position within its group in the toolbar, if -1, it goes at the end | ||
""" | ||
|
||
tool_cls = self._get_cls_to_instantiate(tool) | ||
|
@@ -3582,6 +3587,7 @@ class ToolbarBase(object): | |
|
||
def __init__(self, navigation): | ||
self.navigation = navigation | ||
self._groups = OrderedDict() | ||
|
||
self.navigation.nav_connect('tool_message_event', self._message_cbk) | ||
self.navigation.nav_connect('tool_added_event', self._add_tool_cbk) | ||
|
@@ -3604,21 +3610,28 @@ def _tool_triggered_cbk(self, event): | |
|
||
def _add_tool_cbk(self, event): | ||
"""Captures 'tool_added_event' and adds the tool to the toolbar""" | ||
image = self._get_image_filename(event.tool.image) | ||
tool, group, position = event.tool, event.data['group'], \ | ||
event.data['position'] | ||
if group is None: | ||
return | ||
image = self._get_image_filename(tool.image) | ||
toggle = getattr(event.tool, 'toggled', None) is not None | ||
self.add_toolitem(event.tool.name, | ||
event.data['group'], | ||
event.data['position'], | ||
image, | ||
event.tool.description, | ||
8000 toggle) | ||
|
||
position, insert_index = self.get_positions(tool.name, group, position) | ||
self.add_toolitem(tool.name, group, insert_index, image, | ||
tool.description, toggle) | ||
self.add_tool_to_group(tool, group, position) | ||
|
||
if toggle: | ||
self.navigation.nav_connect('tool_trigger_%s' % event.tool.name, | ||
self.navigation.nav_connect('tool_trigger_%s' % tool.name, | ||
self._tool_triggered_cbk) | ||
|
||
def _remove_tool_cbk(self, event): | ||
"""Captures the 'tool_removed_event' signal and removes the tool""" | ||
self.remove_toolitem(event.tool.name) | ||
for group in self._groups: | ||
if event.tool.name in self._groups[group]: | ||
self._groups[group].remove(event.tool.name) | ||
|
||
def _get_image_filename(self, image): | ||
"""Find the image based on its name""" | ||
|
@@ -3642,6 +3655,74 @@ def trigger_tool(self, name): | |
""" | ||
self.navigation.tool_trigger_event(name, sender=self) | ||
|
||
def get_group_count(self, name): | ||
"""Gets useful indicies for a group. | ||
|
||
Parameters | ||
---------- | ||
name : string | ||
The name of the group. | ||
|
||
Returns | ||
------- | ||
(start_index, group_pos) : where: | ||
- `start_index, the index at the first item in the toolbar. | ||
- `group_pos`, the index of this group within the toolbar. | ||
""" | ||
index = 0 | ||
group_count = 0 | ||
for group in self._groups: | ||
if group == name: | ||
break | ||
index += len(self._groups[group]) | ||
group_count += 1 | ||
return index, group_count | ||
|
||
def get_positions(self, name, group, position=-1): | ||
"""Adds the tool to the group | ||
|
||
Parameters | ||
---------- | ||
name : string | ||
The name of the tool. | ||
group : string | ||
The name of the group. | ||
position : int | ||
The position within the group, if -1, it goes at the end. | ||
|
||
Returns | ||
------- | ||
(position, insert_index) : where: | ||
|
||
- `position` a validated version of the input argument, i.e. > 0. | ||
- `insert index` the position used to insert into the toolbar. | ||
""" | ||
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. Note to self, need to add some more documentation here, i.e. say it returns the position that this should get inserted into the toolbar. |
||
|
||
if position < 0: | ||
position += len(self._groups.get(group, [])) + 1 | ||
if position < 0: | ||
position = 0 | ||
|
||
return position, self.get_group_count(group)[0] + position | ||
|
||
def add_tool_to_group(self, tool, group, position=-1): | ||
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. I don't like this, you are forcing the toolbar and toolitems to be created at different stages, it might not be possible for some strage framework. 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. I did it like this so that one can either add a tool by overall position if the backend doesn't support a way to implement groups, thus the backend can add the tool in I don't think a framework exists where this would not work for. I imagine you refer to one that does do groups, but doesn't return a toolitem, in which case the backend could just save the raw information from I guess I try and implement here a default for the most basic case, i.e. the no-toolbar-groups situation, so that we don't have to duplicate this code. 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. The problem with the overall position, is that you have to decide if you include or not the |
||
""" Adds the tool to the group | ||
|
||
Parameters | ||
---------- | ||
tool : ToolBase | ||
The tool. | ||
group : string | ||
The name of the group. | ||
position: int | ||
The position of the tool within the group. | ||
""" | ||
|
||
if not group in self._groups: | ||
self._groups[group] = [] | ||
|
||
self._groups[group].insert(position, tool) | ||
|
||
def add_toolitem(self, name, group, position, image, description, toggle): | ||
"""Add a toolitem to the 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.
This should be done by backend, maybe you want to create a separate menu with all the tools which group is
None
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.
yes you are right, I did change the
in_toolbar
attribute for this and make sense. But again, the toolbar should be informed of all tools and it can decide what to include or not. Thegroup=None
is just a suggestion (implemented in the default backends)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 agree with what you want to achieve, but I really disagree with implementing it like this. My next PR, the one that I have been talking about, will, in my opinion give a better implementation of this.
Perhaps I should push ahead and just release my next PR as a w-i-p so that you can see for yourself.