File: application_browser.py

package info (click to toggle)
python-envisageplugins 3.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 1,616 kB
  • ctags: 1,970
  • sloc: python: 7,047; makefile: 11; sh: 11; lisp: 1
file content (145 lines) | stat: -rw-r--r-- 4,290 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
""" A view showing a summary of the running application. """


# Standard library imports.
import inspect

# Enthought library imports.
from enthought.envisage.api import IApplication, IPlugin
from enthought.envisage.developer.code_browser.api import CodeBrowser
from enthought.io.api import File
from enthought.traits.api import Any, HasTraits, Instance
from enthought.traits.ui.api import Item, TreeEditor, View

# fixme: non-api import.
from enthought.plugins.text_editor.editor.text_editor import TextEditor

# Local imports.
from application_browser_tree import application_browser_tree_nodes


application_browser_view = View(
    Item(
        name       = 'application',
        show_label = False,
        editor     = TreeEditor(
            nodes       = application_browser_tree_nodes,
            editable    = False,
            orientation = 'vertical',
            hide_root   = True,
            show_icons  = True,
            selected    = 'selection',
            on_dclick   = 'object.dclick'
        )
    ),

    resizable = True,
    style     = 'custom',
    title     = 'Application',

    width     = .1,
    height    = .1
)


class ApplicationBrowser(HasTraits):
    """ An application browser.

    Actually, this class exists just because to use a trait editor we have
    to have a trait to edit!

    """

    # The application that we are browsing.
    application = Instance(IApplication)

    # The code browser that we use to parse plugin source code.
    code_browser = Instance(CodeBrowser)

    # The workbench service.
    workbench = Instance('enthought.envisage.ui.workbench.api.Workbench')
    
    # The object that is currently selected in the tree.
    selection = Any
    
    # The default traits UI view.
    traits_view = application_browser_view

    ###########################################################################
    # 'ApplicationBrowser' interface.
    ###########################################################################

    #### Trait initializers ###################################################

    def _code_browser_default(self):
        """ Trait initializer. """

        return self.application.get_service(CodeBrowser)

    def _workbench_default(self):
        """ Trait initializer. """

        from enthought.envisage.ui.workbench.api import Workbench
        
        return self.application.get_service(Workbench)
    
    #### Trait change handlers ################################################

    def _selection_changed(self, trait_name, old, new):
        """ Static trait change handler. """

        #print 'Selection changed', trait_name, old, new

        return

    #### Methods ##############################################################
    
    def dclick(self, obj):
        """ Called when an object in the tree is double-clicked. """

        if IPlugin(obj, None) is not None:
            # Parse the plugin source code.
            module = self._parse_plugin(obj)

            # Get the plugin klass.
            klass = self._get_plugin_klass(module, obj)

            # Edit the plugin.
            editor = self.workbench.edit(
                self._get_file_object(obj), kind=TextEditor
            )

            # Move to the class definition.
            editor.select_line(klass.lineno)
            
        return

    ###########################################################################
    # Private interface.
    ###########################################################################

    def _get_file_object(self, obj):
        """ Return a 'File' object for an object's source file. """
        
        return File(path=inspect.getsourcefile(type(obj)))

    def _get_plugin_klass(self, module, plugin):
        """ Get the klass that defines the plugin. """
        
        for name, klass in module.klasses.items():
            if name == type(plugin).__name__:
                break

        else:
            klass = None
            
        return klass

    def _parse_plugin(self, plugin):
        """ Parse the plugin source code. """

        filename = self._get_file_object(plugin).path

        return self.code_browser.read_file(filename)
    
#### EOF ######################################################################