Skip to content

Commit 0ff5997

Browse files
committed
adding radio_group for toggle tools
1 parent 6cc040b commit 0ff5997

File tree

3 files changed

+94
-49
lines changed

3 files changed

+94
-49
lines changed

examples/user_interfaces/navigation.py

+14-9
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,25 @@ class ListTools(ToolBase):
1313
description = 'List Tools'
1414

1515
def trigger(self, *args, **kwargs):
16-
print ('_' * 80)
17-
print ("{0:12} {1:45} {2}".format('Name (id)',
18-
'Tool description',
19-
'Keymap'))
20-
print ('-' * 80)
16+
print('_' * 80)
17+
print("{0:12} {1:45} {2}".format('Name (id)',
18+
'Tool description',
19+
'Keymap'))
20+
print('-' * 80)
2121
tools = self.navigation.tools
2222
for name in sorted(tools.keys()):
2323
if not tools[name].description:
2424
continue
2525
keys = ', '.join(sorted(self.navigation.get_tool_keymap(name)))
26-
print ("{0:12} {1:45} {2}".format(name,
27-
tools[name].description,
28-
keys))
29-
print ('_' * 80)
26+
print("{0:12} {1:45} {2}".format(name,
27+
tools[name].description,
28+
keys))
29+
print('_' * 80)
30+
print("Active Toggle tools")
31+
print("{0:12} {1:45}").format("Group", "Active")
32+
print('-' * 80)
33+
for group, active in self.navigation.active_toggle.items():
34+
print("{0:12} {1:45}").format(group, active)
3035

3136

3237
# A simple example of copy canvas

lib/matplotlib/backend_bases.py

+36-7
Original file line numberDiff line numberDiff line change
@@ -3280,7 +3280,7 @@ def __init__(self, manager):
32803280

32813281
self._tools = {}
32823282
self._keys = {}
3283-
self._toggled = None
3283+
self._toggled = {}
32843284
self._callbacks = cbook.CallbackRegistry()
32853285

32863286
# to process keypress event
@@ -3333,7 +3333,7 @@ def message_event(self, message, sender=None):
33333333
def active_toggle(self):
33343334
"""Toggled Tool
33353335
3336-
**string** : Currently toggled tool, or None
3336+
**dict** : Currently toggled tools
33373337
"""
33383338

33393339
return self._toggled
@@ -3393,7 +3393,8 @@ def remove_tool(self, name):
33933393
tool = self._tools[name]
33943394
tool.destroy()
33953395

3396-
if self._toggled == name:
3396+
# If is a toggle tool and toggled, untoggle
3397+
if getattr(tool, 'toggled', False):
33973398
self.tool_trigger_event(tool, 'navigation')
33983399

33993400
self._remove_keys(name)
@@ -3456,6 +3457,15 @@ def add_tool(self, name, tool, group=None, position=None):
34563457
if tool_cls.keymap is not None:
34573458
self.set_tool_keymap(name, tool_cls.keymap)
34583459

3460+
# For toggle tools init the radio_grop in self._toggled
3461+
if getattr(tool_cls, 'toggled', False) is not False:
3462+
# None group is not mutually exclusive, a set is used to keep track
3463+
# of all toggled tools in this group
3464+
if tool_cls.radio_group is None:
3465+
self._toggled.setdefault(None, set())
3466+
else:
3467+
self._toggled.setdefault(tool_cls.radio_group, None)
3468+
34593469
self._tool_added_event(self._tools[name], group, position)
34603470

34613471
def _tool_added_event(self, tool, group, position):
@@ -3470,16 +3480,35 @@ def _handle_toggle(self, tool, sender, canvasevent, data):
34703480
# Toggle tools, need to be untoggled before other Toggle tool is used
34713481
# This is called from tool_trigger_event
34723482

3473-
if self._toggled == tool.name:
3483+
radio_group = tool.radio_group
3484+
# radio_group None is not mutually exclusive
3485+
# just keep track of toggled tools in this group
3486+
if radio_group is None:
3487+
if tool.toggled:
3488+
self._toggled[None].remove(tool.name)
3489+
else:
3490+
self._toggled[None].add(tool.name)
3491+
return
3492+
3493+
# If it is the same tool that is toggled in the radio_group
3494+
# untoggle it
3495+
if self._toggled[radio_group] == tool.name:
34743496
toggled = None
3475-
elif self._toggled is None:
3497+
# If no tool was toggled in the radio_group
3498+
# toggle it
3499+
elif self._toggled.get(radio_group, None) is None:
34763500
toggled = tool.name
3501+
# Other tool in the radio_group is toggled
34773502
else:
34783503
# Untoggle previously toggled tool
3479-
self.tool_trigger_event(self._toggled, self, canvasevent, data)
3504+
self.tool_trigger_event(self._toggled[radio_group],
3505+
self,
3506+
canvasevent,
3507+
data)
34803508
toggled = tool.name
34813509

3482-
self._toggled = toggled
3510+
# Keep track of the toggled tool in the radio_group
3511+
self._toggled[radio_group] = toggled
34833512
# for a in self.canvas.figure.get_axes():
34843513
# a.set_navigate_mode(self._toggled)
34853514

lib/matplotlib/backend_tools.py

+44-33
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ class ToolToggleBase(ToolBase):
119119
"""
120120

121121
radio_group = None
122-
"""Attribute to group 'radio' like tools"""
122+
"""Attribute to group 'radio' like tools (mutually exclusive)
123+
124+
**String** that identifies the group or **None** if not belonging to a
125+
group
126+
"""
123127

124128
cursor = None
125129
"""Cursor to use when the tool is active"""
@@ -328,7 +332,7 @@ def trigger(self, sender, event, data=None):
328332
a.set_navigate(i == n)
329333

330334

331-
class ToolGrid(ToolBase):
335+
class ToolGrid(ToolToggleBase):
332336
"""Tool to toggle the grid of the figure"""
333337

334338
description = 'Toogle Grid'
@@ -337,60 +341,65 @@ class ToolGrid(ToolBase):
337341
def trigger(self, sender, event, data=None):
338342
if event.inaxes is None:
339343
return
340-
event.inaxes.grid()
344+
ToolToggleBase.trigger(self, sender, event, data)
345+
346+
def enable(self, event):
347+
event.inaxes.grid(True)
348+
self.figure.canvas.draw()
349+
350+
def disable(self, event):
351+
event.inaxes.grid(False)
341352
self.figure.canvas.draw()
342353

343354

344-
class ToolFullScreen(ToolBase):
355+
class ToolFullScreen(ToolToggleBase):
345356
"""Tool to toggle full screen"""
346357

347358
description = 'Toogle Fullscreen mode'
348359
keymap = rcParams['keymap.fullscreen']
349360

350-
def trigger(self, sender, event):
361+
def enable(self, event):
351362
self.figure.canvas.manager.full_screen_toggle()
352363

364+
def disable(self, event):
365+
self.figure.canvas.manager.full_screen_toggle()
353366

354-
class ToolYScale(ToolBase):
355-
"""Tool to toggle between linear and logarithmic the Y axis"""
356367

357-
description = 'Toogle Scale Y axis'
358-
keymap = rcParams['keymap.yscale']
368+
class AxisScaleBase(ToolToggleBase):
369+
"""Base Tool to toggle between linear and logarithmic"""
359370

360371
def trigger(self, sender, event, data=None):
361-
"""Toggle axis scale"""
362-
ax = event.inaxes
363-
if ax is None:
372+
if event.inaxes is None:
364373
return
374+
ToolToggleBase.trigger(self, sender, event, data)
375+
376+
def enable(self, event):
377+
self.set_scale(event.inaxes, 'log')
378+
self.figure.canvas.draw()
379+
380+
def disable(self, event):
381+
self.set_scale(event.inaxes, 'linear')
382+
self.figure.canvas.draw()
365383

366-
scale = ax.get_yscale()
367-
if scale == 'log':
368-
ax.set_yscale('linear')
369-
ax.figure.canvas.draw()
370-
elif scale == 'linear':
371-
ax.set_yscale('log')
372-
ax.figure.canvas.draw()
373384

385+
class ToolYScale(AxisScaleBase):
386+
"""Tool to toggle between linear and logarithmic the Y axis"""
374387

375-
class ToolXScale(ToolBase):
388+
description = 'Toogle Scale Y axis'
389+
keymap = rcParams['keymap.yscale']
390+
391+
def set_scale(self, ax, scale):
392+
ax.set_yscale(scale)
393+
394+
395+
class ToolXScale(AxisScaleBase):
376396
"""Tool to toggle between linear and logarithmic the X axis"""
377397

378398
description = 'Toogle Scale X axis'
379399
keymap = rcParams['keymap.xscale']
380400

381-
def trigger(self, sender, event, data=None):
382-
"""Toggle axis scale"""
383-
ax = event.inaxes
384-
if ax is None:
385-
return
386-
387-
scalex = ax.get_xscale()
388-
if scalex == 'log':
389-
ax.set_xscale('linear')
390-
ax.figure.canvas.draw()
391-
elif scalex == 'linear':
392-
ax.set_xscale('log')
393-
ax.figure.canvas.draw()
401+
def set_scale(self, ax, scale):
402+
ax.set_xscale(scale)
394403

395404

396405
class ToolViewsPositions(ToolBase):
@@ -591,6 +600,7 @@ class ToolZoom(ZoomPanBase):
591600
image = 'zoom_to_rect.png'
592601
keymap = rcParams['keymap.zoom']
593602
cursor = cursors.SELECT_REGION
603+
radio_group = 'default'
594604

595605
def __init__(self, *args):
596606
ZoomPanBase.__init__(self, *args)
@@ -802,6 +812,7 @@ class ToolPan(ZoomPanBase):
802812
description = 'Pan axes with left mouse, zoom with right'
803813
image = 'move.png'
804814
cursor = cursors.MOVE
815+
radio_group = 'default'
805816

806817
def __init__(self, *args):
807818
ZoomPanBase.__init__(self, *args)

0 commit comments

Comments
 (0)