Repository URL to install this package:
Version:
6.1.1 ▾
|
traitsui
/
view_elements.py
|
---|
#------------------------------------------------------------------------------
#
# Copyright (c) 2005, Enthought, Inc.
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in enthought/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!
#
# Author: David C. Morrill
# Date: 10/18/2004
#
#------------------------------------------------------------------------------
""" Define the ViewElements class, which is used to define a (typically
class-based) hierarchical name space of related ViewElement objects.
Normally there is a ViewElements object associated with each Traits-based
class, which contains all of the ViewElement objects associated with the
class. The ViewElements object is also linked to the ViewElements objects
of its associated class's parent classes.
"""
#-------------------------------------------------------------------------
# Imports:
#-------------------------------------------------------------------------
from __future__ import absolute_import
from traits.api import HasStrictTraits, List, Dict, Str, Int, Any, TraitError
from .view_element import ViewElement
#-------------------------------------------------------------------------
# Trait definitions:
#-------------------------------------------------------------------------
# Trait for contents of a ViewElements object
content_trait = Dict(str, ViewElement)
#-------------------------------------------------------------------------
# 'ViewElements' class:
#-------------------------------------------------------------------------
class ViewElements(HasStrictTraits):
""" Defines a hierarchical name space of related ViewElement objects.
"""
#-------------------------------------------------------------------------
# Trait definitions:
#-------------------------------------------------------------------------
# Dictionary containing the named ViewElement items
content = content_trait
#-------------------------------------------------------------------------
# Finds a specified ViewElement within the specified (optional) search
# context:
#-------------------------------------------------------------------------
def find(self, name, stack=None):
""" Finds a specified ViewElement within the specified (optional) search
context.
"""
# Assume search starts from the beginning the of the search order:
i = 0
# If a stack was specified, see if there is a matching entry in the
# stack already:
if stack is not None:
for ssi in stack:
if name == ssi.id:
# Match found, resume search at next ViewElements object
# in the search order:
i = ssi.context + 1
break
# Search for a matching name starting at the specified ViewElements
# object in the search order:
for j, ves in enumerate(self._get_search_order()[i:]):
result = ves.content.get(name)
if result is not None:
# Match found. If there is a stack, push matching name and
# ViewElements context onto it:
if stack is not None:
stack[0:0] = [SearchStackItem(id=name,
context=i + j)]
# Return the ViewElement object that matched the name:
return result
# Indicate no match was found:
return None
#-------------------------------------------------------------------------
# Returns a sorted list of all names accessible from the ViewElements
# object that are of a specified (ViewElement) type:
#-------------------------------------------------------------------------
def filter_by(self, klass=None):
""" Returns a sorted list of all names accessible from the ViewElements
object that are of a specified (ViewElement) type.
"""
if klass is None:
from . import view
klass = view.View
result = []
# Add each item in the search order which is of the right class and
# which is not already in the result list:
for ves in self._get_search_order():
for name, ve in ves.content.items():
if isinstance(ve, klass) and (name not in result):
result.append(name)
# Sort the resulting list of names:
result.sort()
# Return the result:
return result
#-------------------------------------------------------------------------
# Handles the 'parents' list being updated:
#-------------------------------------------------------------------------
def _parents__changed(self):
self._search_order = None
def _parents_items_changed(self):
self._search_order = None
#-------------------------------------------------------------------------
# Returns the current search order (computing it if necessary):
#-------------------------------------------------------------------------
def _get_search_order(self):
if self._search_order is None:
self._search_order = self._mro()
return self._search_order
#-------------------------------------------------------------------------
# Compute the Python 'C3' algorithm used to determine a class's 'mro'
# and apply it to the 'parents' of the ViewElements to determine the
# correct search order:
#-------------------------------------------------------------------------
def _mro(self):
return self._merge(
[[self]] +
[parent._get_search_order()[:] for parent in self.parents] +
[self.parents[:]])
def _merge(self, seqs):
result = []
while True:
# Remove any empty sequences from the list:
seqs = [seq for seq in seqs if len(seq) > 0]
if len(seqs) == 0:
return result
# Find merge candidates among the sequence heads:
for seq in seqs:
candidate = seq[0]
if len([s for s in seqs if candidate in s[1:]]) == 0:
break
else:
raise TraitError("Inconsistent ViewElements hierarchy")
# Add the candidate to the result:
result.append(candidate)
# Then remove the candidate:
for seq in seqs:
if seq[0] == candidate:
del seq[0]
#-------------------------------------------------------------------------
# Returns a 'pretty print' version of the ViewElements object:
#-------------------------------------------------------------------------
def __repr__(self):
""" Returns a "pretty print" version of the ViewElements object.
"""
return self.content.__repr__()
#-------------------------------------------------------------------------
# Define forward reference traits:
#-------------------------------------------------------------------------
ViewElements.add_class_trait('parents', List(ViewElements))
ViewElements.add_class_trait('_search_order', Any)
#-------------------------------------------------------------------------
# 'SearchStackItem' class:
#-------------------------------------------------------------------------
class SearchStackItem(HasStrictTraits):
#-------------------------------------------------------------------------
# Trait definitions:
#-------------------------------------------------------------------------
# Name that was looked up
id = Str
# Index into the 'mro' list of ViewElements that the ID was found in
context = Int