class ResourceReference(HasTraits): """ Abstract base class for resource references. Resource references are returned from calls to 'locate_reference' on the resource manager. """ # The resource factory that will be used to load the resource. resource_factory = Instance(ResourceFactory) # ReadOnly ########################################################################### # 'ResourceReference' interface. ########################################################################### def load(self): """ Loads the resource. """ raise NotImplementedError
class TreeNode ( HasPrivateTraits ): #--------------------------------------------------------------------------- # Trait definitions: #--------------------------------------------------------------------------- children = Str # Name of trait containing children ('' = Leaf) label = Str # Name of trait containing label ('=label' = constant) name = Str # Name to use when a new instance is being created rename = true # Can the object's children be renamed? copy = true # Can the object's children be copied? delete = true # Can the object's children be deleted? insert = true # Can children be inserted (or just appended)? auto_open = false # Automatically open ( i.e. expand) tree nodes? auto_close = false # Automatically close sibling tree nodes? add = List( Any ) # List of object classes than can be added/copied move = List( Any ) # List of object classes that can be moved node_for = List( Any ) # List of object classes the node applies to formatter = Callable # Function for formatting label on_select = Callable # Function for handling selecting an object on_dclick = Callable # Function for handling double_clicking an object view = Instance( View ) # View to use for editing object menu = Any # Right click context menu icon_item = Str( '<item>' ) # Name of leaf item icon icon_group = Str( '<group>' ) # Name of group item icon icon_open = Str( '<open>' ) # Name of opened group item icon icon_path = Str # Resource path used to locate node icon # fixme: The 'menu' trait should really be defined as: # Instance( 'enthought.traits.ui.menu.MenuBar' ), but it doesn't work # right currently. #--------------------------------------------------------------------------- # Initializes the object: #--------------------------------------------------------------------------- def __init__ ( self, **traits ): super( TreeNode, self ).__init__( **traits ) if self.icon_path == '': self.icon_path = resource_path() #---- Overridable methods: ----------------------------------------------------- #--------------------------------------------------------------------------- # Returns whether chidren of this object are allowed or not: #--------------------------------------------------------------------------- def allows_children ( self, object ): """ Returns whether chidren of this object are allowed or not. """ return (self.children != '') #--------------------------------------------------------------------------- # Returns whether or not the object has children: #--------------------------------------------------------------------------- def has_children ( self, object ): """ Returns whether or not the object has children. """ return (len( self.get_children( object ) ) > 0) #--------------------------------------------------------------------------- # Gets the object's children: #--------------------------------------------------------------------------- def get_children ( self, object ): """ Gets the object's children. """ return getattr( object, self.children ) #--------------------------------------------------------------------------- # Appends a child to the object's children: #--------------------------------------------------------------------------- def append_child ( self, object, child ): """ Appends a child to the object's children. """ getattr( object, self.children ).append( child ) #--------------------------------------------------------------------------- # Inserts a child into the object's children: #--------------------------------------------------------------------------- def insert_child ( self, object, index, child ): """ Inserts a child into the object's children. """ getattr( object, self.children )[ index: index ] = [ child ] #--------------------------------------------------------------------------- # Deletes a child at a specified index from the object's children: #--------------------------------------------------------------------------- def delete_child ( self, object, index ): """ Deletes a child at a specified index from the object's children. """ del getattr( object, self.children )[ index ] #--------------------------------------------------------------------------- # Sets up/Tears down a listener for 'children replaced' on a specified # object: #--------------------------------------------------------------------------- def when_children_replaced ( self, object, listener, remove ): """ Sets up/Tears down a listener for 'children replaced' on a specified object. """ object.on_trait_change( listener, self.children, remove = remove ) #--------------------------------------------------------------------------- # Sets up/Tears down a listener for 'children changed' on a specified # object: #--------------------------------------------------------------------------- def when_children_changed ( self, object, listener, remove ): """ Sets up/Tears down a listener for 'children changed' on a specified object. """ object.on_trait_change( listener, self.children + '_items', remove = remove ) #--------------------------------------------------------------------------- # Gets the label to display for a specified object: #--------------------------------------------------------------------------- def get_label ( self, object ): """ Gets the label to display for a specified object. """ label = self.label if label[:1] == '=': return label[1:] label = getattr( object, label ) if self.formatter is None: return label return self.formatter( object, label ) #--------------------------------------------------------------------------- # Sets the label for a specified object: #--------------------------------------------------------------------------- def set_label ( self, object, label ): """ Sets the label for a specified object. """ label_name = self.label if label_name[:1] != '=': setattr( object, label_name, label ) #--------------------------------------------------------------------------- # Sets up/Tears down a listener for 'label changed' on a specified object: #--------------------------------------------------------------------------- def when_label_changed ( self, object, listener, remove ): """ Sets up/Tears down a listener for 'label changed' on a specified object. """ label = self.label if label[:1] != '=': object.on_trait_change( listener, label, remove = remove ) #--------------------------------------------------------------------------- # Returns the icon for a specified object: #--------------------------------------------------------------------------- def get_icon ( self, object, is_expanded ): """ Returns the icon for a specified object. """ if not self.allows_children( object ): return self.icon_item if is_expanded: return self.icon_open return self.icon_group #--------------------------------------------------------------------------- # Returns the path used to locate an object's icon: #--------------------------------------------------------------------------- def get_icon_path ( self, object ): """ Returns the path used to locate an object's icon. """ return self.icon_path #--------------------------------------------------------------------------- # Returns the name to use when adding a new object instance (displayed in # the 'New' submenu): #--------------------------------------------------------------------------- def get_name ( self, object ): """ Returns the name to use when adding a new object instance (displayed in the 'New' submenu). """ return self.name #--------------------------------------------------------------------------- # Gets the View to use when editing an object: #--------------------------------------------------------------------------- def get_view ( self, object ): """ Gets the View to use when editing an object. """ return self.view #--------------------------------------------------------------------------- # Returns the right-click context menu for an object: #--------------------------------------------------------------------------- def get_menu ( self, object ): """ Returns the right-click context menu for an object. """ return self.menu #--------------------------------------------------------------------------- # Returns whether or not the object's children can be renamed: #--------------------------------------------------------------------------- def can_rename ( self, object ): """ Returns whether or not the object's children can be renamed. """ return self.rename #--------------------------------------------------------------------------- # Returns whether or not the object's children can be copied: #--------------------------------------------------------------------------- def can_copy ( self, object ): """ Returns whether or not the object's children can be copied. """ return self.copy #--------------------------------------------------------------------------- # Returns whether or not the object's children can be deleted: #--------------------------------------------------------------------------- def can_delete ( self, object ): """ Returns whether or not the object's children can be deleted. """ return self.delete #--------------------------------------------------------------------------- # Returns whether or not the object's children can be inserted (or just # appended): #--------------------------------------------------------------------------- def can_insert ( self, object ): """ Returns whether or not the object's children can be inserted (or just appended). """ return self.insert #--------------------------------------------------------------------------- # Returns whether or not the object's children should be auto-opened: #--------------------------------------------------------------------------- def can_auto_open ( self, object ): """ Returns whether or not the object's children should be auto-opened. """ return self.auto_open #--------------------------------------------------------------------------- # Returns whether or not the object's children should be auto-closed: #--------------------------------------------------------------------------- def can_auto_close ( self, object ): """ Returns whether or not the object's children should be auto-closed. """ return self.auto_close #--------------------------------------------------------------------------- # Returns whether or not this is the node that should handle a specified # object: #--------------------------------------------------------------------------- def is_node_for ( self, object ): """ Returns whether or not this is the node that should handle a specified object. """ return isinstance( object, tuple( self.node_for ) ) #--------------------------------------------------------------------------- # Returns whether a given 'add_object' can be added to an object: #--------------------------------------------------------------------------- def can_add ( self, object, add_object ): """ Returns whether a given object is droppable on the node. """ if isinstance( add_object, tuple( self.add ) ): return True for item in self.move: if type( item ) in SequenceTypes: item = item[0] if isinstance( add_object, item ): return True return False #--------------------------------------------------------------------------- # Returns the list of classes that can be added to the object: #--------------------------------------------------------------------------- def get_add ( self, object ): """ Returns the list of classes that can be added to the object. """ return self.add #--------------------------------------------------------------------------- # Returns a droppable version of a specified object: #--------------------------------------------------------------------------- def drop_object ( self, object, dropped_object ): """ Returns a droppable version of a specified object. """ if isinstance( dropped_object, tuple( self.add ) ): return dropped_object for item in self.move: if type( item ) in SequenceTypes: if isinstance( dropped_object, item[0] ): return item[1]( object, dropped_object ) else: if isinstance( dropped_object, item ): return dropped_object #--------------------------------------------------------------------------- # Handles an object being selected: #--------------------------------------------------------------------------- def select ( self, object ): """ Handles an object being selected. """ if self.on_select is not None: self.on_select( object ) return None return True #--------------------------------------------------------------------------- # Handles an object being double-clicked: #--------------------------------------------------------------------------- def dclick ( self, object ): """ Handles an object being double-clicked. """ if self.on_dclick is not None: self.on_dclick( object ) return None return True #----- Private methods: -------------------------------------------------------- #--------------------------------------------------------------------------- # Returns whether an object has any children: #--------------------------------------------------------------------------- def _has_children ( self, object ): """ Returns whether an object has any children. """ return (self.allows_children( object ) and self.has_children( object )) #--------------------------------------------------------------------------- # Returns whether a given object is droppable on the node: #--------------------------------------------------------------------------- def _is_droppable ( self, object, add_object, for_insert ): """ Returns whether a given object is droppable on the node. """ if for_insert and (not self.can_insert( object )): return False return self.can_add( object, add_object ) #--------------------------------------------------------------------------- # Returns a droppable version of a specified object: #--------------------------------------------------------------------------- def _drop_object ( self, object, dropped_object, make_copy = True ): new_object = self.drop_object( object, dropped_object ) if (new_object is not dropped_object) or (not make_copy): return new_object return copy.deepcopy( new_object )
from ui_traits import container_delegate from editor_factory import EditorFactory #------------------------------------------------------------------------------- # Constants: #------------------------------------------------------------------------------- # Pattern of all digits: all_digits = re.compile( r'\d+' ) #------------------------------------------------------------------------------- # Trait definitions: #------------------------------------------------------------------------------- # EditorFactory reference trait: ItemEditor = Instance( EditorFactory ) # Amount of padding to add around item: Padding = Range( -15, 15, 0, desc = 'amount of padding to add around item' ) #------------------------------------------------------------------------------- # 'Item' class: #------------------------------------------------------------------------------- class Item ( ViewSubElement ): #--------------------------------------------------------------------------- # Trait definitions: #--------------------------------------------------------------------------- id = Str # Name of the item
class ResourceManager(HasTraits): """ The default resource manager. A resource manager locates and loads application resources such as images and sounds etc. """ # Allowed extensions for image resources. IMAGE_EXTENSIONS = ['.png', '.jpg', '.bmp', '.gif', '.ico'] # The resource factory is responsible for actually creating resources. # This is used so that (for example) different GUI toolkits can create # a images in the format that they require. resource_factory = Instance(ResourceFactory) ########################################################################### # 'ResourceManager' interface. ########################################################################### def locate_image(self, image_name, path): """ Locates an image. """ if not operator.isSequenceType(path): path = [path] resource_path = [] for item in path: if type(item) is str: resource_path.append(item) else: resource_path.extend(self._get_resource_path(item)) return self._locate_image(image_name, resource_path) def load_image(self, image_name, path): """ Loads an image. """ reference = self.locate_image(image_name, path) if reference is not None: image = reference.load() else: image = None return image ########################################################################### # Private interface. ########################################################################### def _locate_image(self, image_name, resource_path): """ Attempts to locate an image resource. If the image is found, an image resource reference is returned. If the image is NOT found None is returned. """ # If the image name contains a file extension (eg. '.jpg') then we will # only accept an an EXACT filename match. basename, extension = os.path.splitext(image_name) if len(extension) > 0: extensions = [extension] pattern = image_name # Otherwise, we will search for common image suffixes. else: extensions = self.IMAGE_EXTENSIONS pattern = image_name + '.*' for dirname in resource_path: # Try the 'images' sub-directory first (since that is commonly # where we put them!). If the image is not found there then look # in the directory itself. for path in ['images', '']: # Is there anything resembling the image name in the directory? filenames = glob.glob(join(dirname, path, pattern)) for filename in filenames: not_used, extension = os.path.splitext(filename) if extension in extensions: reference = ImageReference(self.resource_factory, filename=filename) return reference # Is there an 'images' zip file in the directory? zip_filename = join(dirname, 'images.zip') if os.path.isfile(zip_filename): zip_file = ZipFile(zip_filename, 'r') # Try the image name itself, and then the image name with # common images suffixes. for extension in extensions: try: image_data = zip_file.read(basename + extension) reference = ImageReference(self.resource_factory, data=image_data) return reference except: pass return None def _get_resource_path(self, object): """ Returns the resource path for an object. """ if hasattr(object, 'resource_path'): resource_path = object.resource_path else: resource_path = self._get_default_resource_path(object) return resource_path def _get_default_resource_path(self, object): """ Returns the default resource path for an object. """ resource_path = [] for klass in inspect.getmro(object.__class__): try: resource_path.append(get_path(klass)) # We get an attribute error when we get to a C extension type (in # our case it will most likley be 'CHasTraits'. We simply ignore # everything after this point! except AttributeError: break return resource_path