enthought / traitsui
1
# -----------------------------------------------------------------------------
2
#
3
#  Copyright (c) 2006, Enthought, Inc.
4
#  All rights reserved.
5
#
6
#  This software is provided without warranty under the terms of the BSD
7
#  license included in LICENSE.txt and may be redistributed only
8
#  under the conditions described in the aforementioned license.  The license
9
#  is also available online at http://www.enthought.com/licenses/BSD.txt
10
#
11
#  Thanks for using Enthought open source!
12
#
13
#  Author: Dave Peterson <dpeterson@enthought.com>
14
#
15
# -----------------------------------------------------------------------------
16

17 0
"""
18
A handler that delegates the handling of events to a set of sub-handlers.
19

20
This is typically used as the handler for dynamic views.  See the
21
**traits.has_dynamic_view** module.
22
"""
23

24
# Enthought library imports
25 0
from traits.api import HasTraits, List
26 0
from .ui import Dispatcher
27

28
# Local imports.
29 0
from .handler import Handler
30

31
# Set up a logger:
32 0
import logging
33

34 0
logger = logging.getLogger(__name__)
35

36

37 0
class DelegatingHandler(Handler):
38
    """ A handler that delegates the handling of events to a set of
39
        sub-handlers.
40
    """
41

42
    # -- Public 'DelegatingHandler' Interface ---------------------------------
43

44
    #: The list of sub-handlers this object delegates to:
45 0
    sub_handlers = List(HasTraits)
46

47
    # -- Protected 'DelegatingHandler' Interface ------------------------------
48

49
    #: A list of dispatchable handler methods:
50 0
    _dispatchers = List()
51

52
    # -------------------------------------------------------------------------
53
    #  'Handler' interface:
54
    # -------------------------------------------------------------------------
55

56
    # -- Public Methods -------------------------------------------------------
57

58 0
    def closed(self, info, is_ok):
59
        """ Handles the user interface being closed by the user.
60

61
            This method is overridden here to unregister any dispatchers that
62
            were set up in the *init()* method.
63
        """
64 4
        for d in self._dispatchers:
65 0
            d.remove()
66

67 0
    def init(self, info):
68
        """ Initializes the controls of a user interface.
69

70
        This method is called after all user interface elements have been
71
        created, but before the user interface is displayed. Use this method to
72
        further customize the user interface before it is displayed.
73

74
        This method is overridden here to delegate to sub-handlers.
75

76
        Parameters
77
        ----------
78
        info : *UIInfo* object
79
            The UIInfo object associated with the view
80

81
        Returns
82
        -------
83
        initialized : bool
84
            A boolean, indicating whether the user interface was successfully
85
            initialized. A True value indicates that the UI can be displayed;
86
            a False value indicates that the display operation should be
87
            cancelled.
88
        """
89

90
        # Iterate through our sub-handlers, and for each method whose name is
91
        # of the form 'object_name_changed', where 'object' is the name of an
92
        # object in the UI's context, create a trait notification handler that
93
        # will call the method whenever object's 'name' trait changes.
94 0
        logger.debug("Initializing delegation in DelegatingHandler [%s]", self)
95 0
        context = info.ui.context
96 4
        for h in self.sub_handlers:
97
            # fixme: I don't know why this wasn't here before... I'm not
98
            # sure this is right!
99 0
            h.init(info)
100

101 4
            for name in self._each_trait_method(h):
102 4
                if name[-8:] == "_changed":
103 0
                    prefix = name[:-8]
104 0
                    col = prefix.find("_", 1)
105 4
                    if col >= 0:
106 0
                        object = context.get(prefix[:col])
107 4
                        if object is not None:
108 0
                            logger.debug(
109
                                "\tto method [%s] on handler[%s]", name, h
110
                            )
111 0
                            method = getattr(h, name)
112 0
                            trait_name = prefix[col + 1:]
113 0
                            self._dispatchers.append(
114
                                Dispatcher(method, info, object, trait_name)
115
                            )
116

117
                            # Also invoke the method immediately so initial
118
                            # user interface state can be correctly set.
119 4
                            if object.base_trait(trait_name).type != "event":
120 0
                                method(info)
121

122
                # fixme: These are explicit workarounds for problems with:-
123
                #
124
                # 'GeometryHierarchyViewHandler'
125
                #
126
                # which is used in the :-
127
                #
128
                # 'GeometryHierarchyTreeEditor'
129
                #
130
                # which are in the 'encode.cad.ui.geometry' package.
131
                #
132
                # The tree editor has dynamic views, and hence the handler gets
133
                # wrapped by a 'DelegatingHandler'. Unfortunately the handler
134
                # has a couple of methods that aren't picked up by the usual
135
                # wrapping strategy:-
136
                #
137
                # 1) 'tree_item_selected'
138
                #
139
                # - which is obviously called when a tree item is selected.
140
                #
141
                # 2) 'inspect_object'
142
                #
143
                # - which is called directly as as action from the context menu
144
                #   defined in the tree editor.
145
                #
146 4
                elif name in ["tree_item_selected", "inspect_object"]:
147 0
                    self.__dict__[name] = self._create_delegate(h, name)
148

149 0
        return True
150

151 0
    def _create_delegate(self, h, name):
152
        """ Quick fix for handler methods that are currently left out!
153
        """
154

155 0
        def delegate(*args, **kw):
156 0
            method = getattr(h, name)
157 0
            return method(*args, **kw)
158

159 0
        return delegate

Read our documentation on viewing source code .

Loading