Logo Search packages:      
Sourcecode: mayavi2 version File versions  Download package

project_view.py

#-----------------------------------------------------------------------------
#
#  Copyright (c) 2005, 2006 by Enthought, Inc.
#  All rights reserved.
#
#-----------------------------------------------------------------------------

"""
The single project plugin's project view

"""

# Standard library imports.
import logging
from string import rfind

# Enthought library imports
from enthought.envisage import get_application
from enthought.envisage.resource.ui import ResourceTree, \
    ResourceTreeActionController
from enthought.envisage.workbench import View
from enthought.naming.api import Binding
from enthought.traits.api import Instance, Str

# Application specific imports.
from enthought.envisage.single_project.services import IPROJECT_MODEL, \
    IPROJECT_UI


# Setup a logger for this module.
logger=logging.getLogger(__name__)


00034 class ProjectView(View):
    """
    The single project plugin's project view

    """

    ##########################################################################
    # Traits
    ##########################################################################

    #### public 'ProjectView' interface ######################################

    # The suffix currently applied to our name
    name_suffix = Str('')

    # The suffix applied to titles when the current project is dirty.
    title_suffix = Str('*')


    ##########################################################################
    # 'View' interface.
    ##########################################################################

    #### public 'View' interface #############################################

00059     def create_control(self, parent):
        """
        Creates the toolkit-specific control that represents the view.

        'parent' is the toolkit-specific control that is the view's parent.

        """

        # Make sure our view stays in sync with the current project
        model_service = self._get_model_service()
        model_service.on_trait_change(self._on_project_changed, 'project')
        model_service.on_trait_change(self._on_project_selection_changed,
            'selection')

        # Create the contents of this view in a manner that allows derived
        # classes to customize the control without having to rewrite this
        # view.
        self._project_control = self._create_project_control(parent)

        # Let the UI service know about the tree.
        #
        # FIXME: This seems hacky!
        ui_service = self._get_ui_service()
        ui_service.project_control = self._project_control

        # Make sure our control is initialized to the current project
        self._switch_projects(None, model_service.project)

        return self._project_control.control


    ##########################################################################
    # 'ProjectView' interface.
    ##########################################################################

    #### protected 'ProjectView' interface #################################

00096     def _are_list_contents_different(self, list1, list2):
        """
        Convenience method to determine if two lists contain different
        items.  Returns True if the lists are different and False
        otherwise.

        """

        from sets import Set
        set1 = Set(list1)
        set2 = Set(list2)
        return set1 != set2


00110     def _clear_state(self):
        """
        Clears out all indications of any project state from this view.

        """

        self._update_project_control(None)
        self.name_suffix = ''

        return


00122     def _create_project_control(self, parent):
        """
        Create the UI control used to visualize the contents of a project.

        This implementation creates a ResourceTree control so that projects
        can be naming contexts with node visualization controlled by
        registering resource types.

        Derived class can override this to use a different control.

        """

        model_service = self._get_model_service()
        project_control = ResourceTree(
            parent,
            _name = 'Single_Project Plugin.Project Tree',
            resource_manager = model_service.resource_manager,
            lines_mode = 'on',
            controller = ResourceTreeActionController(
                application=get_application(), window=self.window)
            )

        # Listen to events on the control to keep our project in sync.
        project_control.on_trait_change(self._on_selection_changed,
            'selection')
        project_control.on_trait_change(self._on_node_activated_changed,
            'node_activated')
        project_control.on_trait_change(self._on_key_pressed_changed,
            'key_pressed')
        project_control.on_trait_change(self._on_control_right_clicked,
            'control_right_clicked')

        return project_control


00157     def _get_model_service(self):
        """
        Return a reference to the single project plugin's model service.

        """

        return self.window.application.get_service(IPROJECT_MODEL)


00166     def _get_ui_service(self):
        """
        Return a reference to the single project plugin's UI service.

        """

        return self.window.application.get_service(IPROJECT_UI)


00175     def _switch_projects(self, old, new):
        """
        Switches this view to the specified new project from the old project.

        Either value may be None.

        """

        # Remove listeners on the old project, if any.
        if old is not None:
            self._update_project_listeners(old, remove=True)

        # Update our state according to what the new project is, making sure
        # to add listeners to any new project.
        if new is not None:
            logger.debug("Changing ProjectView to Project [%s]", new.name)
            self._sync_state_to_project(new)
            self._update_project_listeners(new)
        else:
            logger.debug("Changing ProjectView to no project")
            self._clear_state()

        return


00200     def _sync_state_to_project(self, project):
        """
        Sync the state of this view to the specified project's state.

        """

        logger.debug('Syncing ProjectView [%s] to project state [%s]', self,
            project)

        # Update the project control to display the specified project
        self._update_project_control(project)

        # Update our name suffix based on the dirty state of the project.
        self.name_suffix = (project.dirty and self.title_suffix) or ''

        return


00218     def _update_project_control(self, project):
        """
        Update the the project control to the specified project.

        Derived classes should override this if they overrode
        _create_project_control().

        """

        if project is None:
            self._project_control.root = None
        else:
            self._project_control.root = Binding(name=project.name, obj=project)


00233     def _update_project_listeners(self, project, remove=False):
        """
        Update listeners on the specified project instance.

        If remove is False then listeners are added, else listeners
        are removed.

        """

        project.on_trait_change(self._on_project_name_changed, 'name', remove)
        project.on_trait_change(self._on_project_dirty_changed, 'dirty',
            remove)

        return


    #### trait handlers ######################################################

00251     def _name_suffix_changed(self, old, new):
        """
        Handle changes to our name suffix.

        """

        logger.debug('Detected change in name suffix to [%s] within ' + \
            'ProjectView [%s]', new, self)

        # Update our own name by removing the old suffix, if any, and adding
        # on the new suffix, if any.
        name = self.name
        if old is not None and len(old) > 0:
            index = rfind(name, " " + old)
            if index > -1:
                name = name[0:index]
        if new is not None and len(new) > 0:
            name = name + ' ' + new
        self.name = name

        # Update the containing window's suffix as well
        self.window.title_suffix = new

        return


00277     def _on_control_right_clicked (self, event):
        """
        Handle events when the tree control itself is right-clicked.

        """

        logger.debug('ProjectView control right-clicked')
        self._get_ui_service().display_default_context_menu(self.control, event)

        return


00289     def _on_key_pressed_changed(self, event):
        """
        Handle key presses while our control has focus.

        """

        logger.debug("ProjectView key pressed [%s]", event)

        # If the delete key was pressed, then delete the current selected
        # object.
        if event.key_code == 127:
            self._get_ui_service().delete_selection()

        return


00305     def _on_node_activated_changed(self, node):
        """
        Handle nodes being activated (i.e. double-clicked.)

        """

        logger.debug("ProjectView node activated [%s]", node)

        return


00316     def _on_project_changed(self, obj, trait_name, old, new):
        """
        Handle when the current project changes.

        """

        logger.debug('\n\n ***************** \n\n')
        logger.debug('Detected project changed from [%s] to [%s] in '
            'ProjectView [%s]', old, new, self)

        self._switch_projects(old, new)

        return


00331     def _on_project_dirty_changed(self, obj, trait_name, old, new):
        """
        Handle the open project's dirty flag changing.

        """

        logger.debug('Detected change in project dirty to [%s] within ' + \
            'ProjectView [%s]', new, self)

        suffix = (new and self.title_suffix) or ''
        self.name_suffix = suffix

        return


00346     def _on_project_name_changed(self, obj, trait_name, old, new):
        """
        Handle the open project's name changing.

        """

        self._project_control.root.name = new

        return


00357     def _on_project_selection_changed(self, obj, trait_name, old, new):
        """
        Handle the current project's selection changing.

        """

        logger.debug('Detected project selection changed from [%s] ' + \
            'to [%s] within ProjectView [%s]', old, new, self)

        # Ensure that the Tree control's selection matches the selection in
        # the project.
        control_selection = self._project_control.selection
        if self._are_list_contents_different(new, control_selection):
            logger.debug('  Updating selection on tree control for ' + \
                'ProjectView [%s]', self)
            self._project_control.set_selection(new)

        # Ensure that this view's selection contains whatever was selected
        # within the project.
        if self._are_list_contents_different(new, self.selection):
            logger.debug('  Updating selection on ProjectView [%s]', self)
            self.selection = new

        return


00383     def _on_selection_changed(self, obj, trait_name, old, new):
        """
        Handle selection changes in our tree control.

        """

        logger.debug('Detected tree control selection change from [%s] ' + \
            'to [%s] within ProjectView [%s]', old, new, self)

        # Ensure that the project model service's record of selection contains
        # the same elements as the tree control.
        model_service = self._get_model_service()
        if self._are_list_contents_different(new, model_service.selection):
            logger.debug('  Updating selection on project model service')
            model_service.selection = new

        # Note that we don't have to update this view's selection record as
        # we do that through our listener on the project selection.

        return


00405     def _on_closing_changed(self, old, new):
        """
        Handle when this view closes.

        """

        logger.debug("ProjectView [%s] closing!", self)

        return


#### EOF #####################################################################

Generated by  Doxygen 1.6.0   Back to index