Source code for pyface.workbench.action.view_chooser
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
""" A UI that allows the user to choose a view. """
from pyface.workbench.api import IView, WorkbenchWindow
from traits.api import Any, HasTraits, Instance, List, Str
from traits.api import TraitError, Undefined
from traitsui.api import Item, TreeEditor, TreeNode, View
from traitsui.menu import Action # fixme: Non-api import!
[docs]class Category(HasTraits):
""" A view category. """
# The name of the category.
name = Str()
# The views in the category.
views = List()
[docs]class WorkbenchWindowTreeNode(TreeNode):
""" A tree node for workbench windows that displays the window's views.
The views are grouped by their category.
"""
# 'TreeNode' interface -------------------------------------------------
# List of object classes that the node applies to.
node_for = [WorkbenchWindow]
# ------------------------------------------------------------------------
# 'TreeNode' interface.
# ------------------------------------------------------------------------
[docs] def get_children(self, object):
""" Get the object's children. """
# Collate the window's views into categories.
categories_by_name = self._get_categories_by_name(object)
categories = list(categories_by_name.values())
categories.sort(key=lambda category: category.name)
return categories
# ------------------------------------------------------------------------
# Private interface.
# ------------------------------------------------------------------------
def _get_categories_by_name(self, window):
""" Return a dictionary containing all categories keyed by name. """
categories_by_name = {}
for view in window.views:
category = categories_by_name.get(view.category)
if category is None:
category = Category(name=view.category)
categories_by_name[view.category] = category
category.views.append(view)
return categories_by_name
[docs]class IViewTreeNode(TreeNode):
""" A tree node for objects that implement the 'IView' interface.
This node does *not* recognise objects that can be *adapted* to the 'IView'
interface, only those that actually implement it. If we wanted to allow
for adaptation we would have to work out a way for the rest of the
'TreeNode' code to access the adapter, not the original object. We could,
of course override every method, but that seems a little, errr, tedious.
We could probably do with something like in the Pyface tree where there
is a method that returns the actual object that we want to manipulate.
"""
[docs] def is_node_for(self, obj):
""" Returns whether this is the node that handles a specified object.
"""
# By checking for 'is obj' here, we are *not* allowing adaptation (if
# we were allowing adaptation it would be 'is not None'). See the class
# doc string for details.
return IView(obj, Undefined) is obj
[docs] def get_icon(self, obj, is_expanded):
""" Returns the icon for a specified object. """
if obj.image is not None:
icon = obj.image
else:
# fixme: A bit of magic here! Is there a better way to say 'use
# the default leaf icon'?
icon = "<item>"
return icon
[docs]class ViewChooser(HasTraits):
""" Allow the user to choose a view.
This implementation shows views in a tree grouped by category.
"""
# The window that contains the views to choose from.
window = Instance("pyface.workbench.api.WorkbenchWindow")
# The currently selected tree item (at any point in time this might be
# either None, a view category, or a view).
selected = Any()
# The selected view (None if the selected item is not a view).
view = Instance(IView)
# Traits UI views -----------------------------------------------------#
traits_ui_view = View(
Item(
name="window",
editor=TreeEditor(
nodes=[
WorkbenchWindowTreeNode(
auto_open=True,
label="=Views",
rename=False,
copy=False,
delete=False,
insert=False,
menu=None,
),
TreeNode(
node_for=[Category],
auto_open=True,
children="views",
label="name",
rename=False,
copy=False,
delete=False,
insert=False,
menu=None,
),
IViewTreeNode(
auto_open=False,
label="name",
rename=False,
copy=False,
delete=False,
insert=False,
menu=None,
),
],
editable=False,
hide_root=True,
selected="selected",
show_icons=True,
),
show_label=False,
),
buttons=[Action(name="OK", enabled_when="view is not None"), "Cancel"],
resizable=True,
style="custom",
title="Show View",
width=0.2,
height=0.4,
)
# ------------------------------------------------------------------------
# 'ViewChooser' interface.
# ------------------------------------------------------------------------
def _selected_changed(self, old, new):
""" Static trait change handler. """
# If the assignment fails then the selected object does *not* implement
# the 'IView' interface.
try:
self.view = new
except TraitError:
self.view = None
return