Browse files

Merge pull request #68 from enthought/fix-dock-pane-toggle-group

Dock pane toggle group reacts to changes in dock panes.
  • Loading branch information...
2 parents 1430a9d + 4dcf242 commit 615d00343027ef1f16325b0cb8a59b026eda0789 @pberkes pberkes committed Nov 26, 2012
Showing with 156 additions and 11 deletions.
  1. +47 −11 pyface/tasks/action/dock_pane_toggle_group.py
  2. +109 −0 pyface/tasks/tests/test_dock_pane_toggle_group.py
View
58 pyface/tasks/action/dock_pane_toggle_group.py
@@ -1,6 +1,10 @@
+""" A Group for toggling the visibility of a task's dock panes. """
+
+
# Enthought library imports.
from pyface.action.api import Action, ActionItem, Group
-from traits.api import Instance, List, Property, Unicode, on_trait_change
+from traits.api import cached_property, Instance, List, on_trait_change, \
+ Property, Unicode
# Local imports.
from pyface.tasks.i_dock_pane import IDockPane
@@ -58,7 +62,6 @@ def _update_visible(self):
if self.dock_pane:
self.visible = self.dock_pane.closable
-
class DockPaneToggleGroup(Group):
""" A Group for toggling the visibility of a task's dock panes.
"""
@@ -69,21 +72,54 @@ class DockPaneToggleGroup(Group):
items = List
- ###########################################################################
- # Protected interface.
- ###########################################################################
+ #### 'DockPaneToggleGroup' interface ######################################
- def _items_default(self):
- """ Create a DockPaneToggleAction for each dock pane.
- """
+ task = Property(depends_on='parent.controller')
+
+ @cached_property
+ def _get_task(self):
+ manager = self.get_manager()
+
+ if manager is None or manager.controller is None:
+ return None
+
+ return manager.controller.task
+
+ dock_panes = Property(depends_on='task.window._states.dock_panes')
+
+ @cached_property
+ def _get_dock_panes(self):
+ if self.task is None or self.task.window is None:
+ return []
+
+ task_state = self.task.window._get_state(self.task)
+ return task_state.dock_panes
+
+ def get_manager(self):
+ # FIXME: Is there no better way to get a reference to the menu manager?
manager = self
while isinstance(manager, Group):
manager = manager.parent
- task = manager.controller.task
+ return manager
+
+ #### Private interface ####################################################
+
+ @on_trait_change('dock_panes[]')
+ def _dock_panes_updated(self):
+ """Recreate the group items when dock panes have been added/removed.
+ """
+
+ # Remove the previous group items.
+ self.destroy()
items = []
- for dock_pane in task.window.get_dock_panes(task):
+ for dock_pane in self.dock_panes:
action = DockPaneToggleAction(dock_pane=dock_pane)
items.append(ActionItem(action=action))
+
items.sort(key=lambda item: item.action.name)
- return items
+ self.items = items
+
+ # Inform the parent menu manager.
+ manager = self.get_manager()
+ manager.changed = True
View
109 pyface/tasks/tests/test_dock_pane_toggle_group.py
@@ -0,0 +1,109 @@
+# Standard library imports.
+import unittest
+
+# Enthought library imports.
+from pyface.tasks.action.api import SMenu, SMenuBar, SGroup, \
+ DockPaneToggleGroup
+from pyface.tasks.api import DockPane, Task, TaskPane, TaskWindow
+from traits.api import List
+
+
+class BogusTask(Task):
+
+ id = 'tests.bogus_task'
+ name = 'Bogus Task'
+
+ dock_panes = List
+
+ def create_central_pane(self):
+ return TaskPane(id='tests.bogus_task.central_pane')
+
+ def create_dock_panes(self):
+ self.dock_panes = dock_panes = [
+ DockPane(id='tests.bogus_task.dock_pane_2', name='Dock Pane 2'),
+ DockPane(id='tests.bogus_task.dock_pane_1', name='Dock Pane 1'),
+ ]
+
+ return dock_panes
+
+ def _menu_bar_default(self):
+ menu_bar = SMenuBar(
+ SMenu(
+ SGroup(
+ group_factory=DockPaneToggleGroup,
+ id='tests.bogus_task.DockPaneToggleGroup'
+ ),
+ id= 'View', name='&View'
+ )
+ )
+
+ return menu_bar
+
+
+class DockPaneToggleGroupTestCase(unittest.TestCase):
+
+ def setUp(self):
+ # Set up the bogus task with its window.
+ self.task = BogusTask()
+
+ window = TaskWindow()
+ window.add_task(self.task)
+
+ self.task_state = window._get_state(self.task)
+
+ # Fish the dock pane toggle group from the menu bar manager.
+ dock_pane_toggle_group = []
+ def find_doc_pane_toggle(item):
+ if item.id == 'tests.bogus_task.DockPaneToggleGroup':
+ dock_pane_toggle_group.append(item)
+
+ self.task_state.menu_bar_manager.walk(find_doc_pane_toggle)
+
+ self.dock_pane_toggle_group = dock_pane_toggle_group[0]
+
+ def get_dock_pane_toggle_action_names(self):
+ names = [
+ action_item.action.name
+ for action_item in self.dock_pane_toggle_group.items
+ ]
+
+ return names
+
+ #### Tests ################################################################
+
+ def test_group_content_at_startup(self):
+ # Check that there are 2 dock panes in the group at the beginning.
+ self.assertEqual(2, len(self.dock_pane_toggle_group.items))
+
+ # Names are sorted by the group.
+ names = self.get_dock_pane_toggle_action_names()
+ expected_names = ['Dock Pane 1', 'Dock Pane 2']
+ self.assertItemsEqual(expected_names, names)
+
+ def test_react_to_dock_pane_added(self):
+ # Add a dock pane to the task.
+ self.task_state.dock_panes.append(
+ DockPane(id='tests.bogus_task.dock_pane_0', name='Dock Pane 0')
+ )
+
+ # Check that there are 3 dock panes in the group.
+ self.assertEqual(3, len(self.dock_pane_toggle_group.items))
+
+ # Names are sorted by the group.
+ names = self.get_dock_pane_toggle_action_names()
+ expected_names = ['Dock Pane 0', 'Dock Pane 1', 'Dock Pane 2']
+ self.assertItemsEqual(expected_names, names)
+
+ def test_react_to_dock_pane_removed(self):
+ # Remove a dock pane from the task.
+ self.task_state.dock_panes.remove(self.task.dock_panes[0])
+
+ # Check that there is only 1 dock pane left in the group.
+ self.assertEqual(1, len(self.dock_pane_toggle_group.items))
+
+ names = self.get_dock_pane_toggle_action_names()
+ expected_names = ['Dock Pane 1']
+ self.assertItemsEqual(expected_names, names)
+
+if __name__ == '__main__':
+ unittest.main()

0 comments on commit 615d003

Please sign in to comment.