enthought / traitsui
1
# ------------------------------------------------------------------------------
2
#
3
#  Copyright (c) 2005, 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: David C. Morrill
14
#  Date:   10/07/2004
15
#
16
# ------------------------------------------------------------------------------
17

18 4
""" Defines the abstract EditorFactory class, which represents a factory for
19
    creating the Editor objects used in a Traits-based user interface.
20
"""
21

22 4
import logging
23

24 4
from traits.api import (
25
    HasPrivateTraits,
26
    Callable,
27
    Str,
28
    Bool,
29
    Event,
30
    Any,
31
    Property,
32
)
33

34 4
from .helper import enum_values_changed
35 4
from .toolkit import toolkit_object
36

37

38 4
logger = logging.getLogger(__name__)
39

40
# -------------------------------------------------------------------------
41
#  'EditorFactory' abstract base class:
42
# -------------------------------------------------------------------------
43

44

45 4
class EditorFactory(HasPrivateTraits):
46
    """ Represents a factory for creating the Editor objects in a Traits-based
47
        user interface.
48
    """
49

50
    # -------------------------------------------------------------------------
51
    #  Trait definitions:
52
    # -------------------------------------------------------------------------
53

54
    #: Function to use for string formatting
55 4
    format_func = Callable()
56

57
    #: Format string to use for formatting (used if **format_func** is not set).
58 4
    format_str = Str()
59

60
    #: Is the editor being used to create table grid cells?
61 4
    is_grid_cell = Bool(False)
62

63
    #: Are created editors initially enabled?
64 4
    enabled = Bool(True)
65

66
    #: The extended trait name of the trait containing editor invalid state
67
    #: status:
68 4
    invalid = Str()
69

70
    #: Text aligment to use in most readonly editors
71
    #: Possible values: left, right, top, bottom, just, vcenter, hcenter, center
72
    #: Example: left,vcenter
73 4
    text_alignment = Str()
74

75
    #: The editor class to use for 'simple' style views.
76 4
    simple_editor_class = Property()
77

78
    #: The editor class to use for 'custom' style views.
79 4
    custom_editor_class = Property()
80

81
    #: The editor class to use for 'text' style views.
82 4
    text_editor_class = Property()
83

84
    #: The editor class to use for 'readonly' style views.
85 4
    readonly_editor_class = Property()
86

87 4
    def __init__(self, *args, **traits):
88
        """ Initializes the factory object.
89
        """
90 4
        HasPrivateTraits.__init__(self, **traits)
91 4
        self.init(*args)
92

93 4
    def init(self):
94
        """ Performs any initialization needed after all constructor traits
95
            have been set.
96
        """
97 4
        pass
98

99 4
    def named_value(self, name, ui):
100
        """ Returns the value of a specified extended name of the form: name or
101
            context_object_name.name[.name...]:
102
        """
103 0
        names = name.split(".")
104

105 4
        if len(names) == 1:
106
            # fixme: This will produce incorrect values if the actual Item the
107
            # factory is being used with does not use the default object='name'
108
            # value, and the specified 'name' does not contain a '.'. The
109
            # solution will probably involve providing the Item as an argument,
110
            # but it is currently not available at the time this method needs to
111
            # be called...
112 0
            names.insert(0, "object")
113

114 0
        value = ui.context[names[0]]
115 4
        for name in names[1:]:
116 0
            value = getattr(value, name)
117

118 0
        return value
119

120
    # -------------------------------------------------------------------------
121
    #  Methods that generate backend toolkit-specific editors.
122
    # -------------------------------------------------------------------------
123

124 4
    def simple_editor(self, ui, object, name, description, parent):
125
        """ Generates an editor using the "simple" style.
126
        """
127 4
        return self.simple_editor_class(
128
            parent,
129
            factory=self,
130
            ui=ui,
131
            object=object,
132
            name=name,
133
            description=description,
134
        )
135

136 4
    def custom_editor(self, ui, object, name, description, parent):
137
        """ Generates an editor using the "custom" style.
138
        """
139 4
        return self.custom_editor_class(
140
            parent,
141
            factory=self,
142
            ui=ui,
143
            object=object,
144
            name=name,
145
            description=description,
146
        )
147

148 4
    def text_editor(self, ui, object, name, description, parent):
149
        """ Generates an editor using the "text" style.
150
        """
151 4
        return self.text_editor_class(
152
            parent,
153
            factory=self,
154
            ui=ui,
155
            object=object,
156
            name=name,
157
            description=description,
158
        )
159

160 4
    def readonly_editor(self, ui, object, name, description, parent):
161
        """ Generates an "editor" that is read-only.
162
        """
163 4
        return self.readonly_editor_class(
164
            parent,
165
            factory=self,
166
            ui=ui,
167
            object=object,
168
            name=name,
169
            description=description,
170
        )
171

172
    # -------------------------------------------------------------------------
173
    #  Private methods
174
    # -------------------------------------------------------------------------
175

176 4
    @classmethod
177
    def _get_toolkit_editor(cls, class_name):
178
        """
179
        Returns the editor by name class_name in the backend package.
180
        """
181 4
        editor_factory_modules = [
182
            factory_class.__module__
183
            for factory_class in cls.mro()
184
            if issubclass(factory_class, EditorFactory)
185
        ]
186 4
        for index, editor_module in enumerate(editor_factory_modules):
187 4
            try:
188 4
                editor_module_name = editor_module.split(".")[-1]
189 4
                object_ref = ":".join([editor_module_name, class_name])
190 4
                return toolkit_object(object_ref, True)
191 4
            except RuntimeError as e:
192 4
                msg = "Can't import toolkit_object '{}': {}"
193 4
                logger.debug(msg.format(object_ref, e))
194 4
                if index == len(editor_factory_modules) - 1:
195 0
                    raise e
196 0
        return None
197

198 4
    def string_value(self, value, format_func=None):
199
        """ Returns the text representation of a specified object trait value.
200

201
        If the **format_func** attribute is set on the editor factory, then
202
        this method calls that function to do the formatting.  If the
203
        **format_str** attribute is set on the editor factory, then this
204
        method uses that string for formatting. If neither attribute is
205
        set, then this method just calls the appropriate text type to format.
206
        """
207 4
        if self.format_func is not None:
208 4
            return self.format_func(value)
209

210 4
        if self.format_str != "":
211 0
            return self.format_str % value
212

213 4
        if format_func is not None:
214 4
            return format_func(value)
215

216 4
        return str(value)
217

218
    # -------------------------------------------------------------------------
219
    #  Property getters
220
    # -------------------------------------------------------------------------
221

222 4
    def _get_simple_editor_class(self):
223
        """ Returns the editor class to use for "simple" style views.
224
        The default implementation tries to import the SimpleEditor class in the
225
        editor file in the backend package, and if such a class is not to found
226
        it returns the SimpleEditor class defined in editor_factory module in
227
        the backend package.
228

229
        """
230 4
        try:
231 4
            SimpleEditor = self._get_toolkit_editor("SimpleEditor")
232 0
        except Exception as e:
233 0
            msg = "Can't import SimpleEditor for {}: {}"
234 0
            logger.debug(msg.format(self.__class__, e))
235 0
            SimpleEditor = toolkit_object("editor_factory:SimpleEditor")
236 4
        return SimpleEditor
237

238 4
    def _get_custom_editor_class(self):
239
        """ Returns the editor class to use for "custom" style views.
240
        The default implementation tries to import the CustomEditor class in the
241
        editor file in the backend package, and if such a class is not to found
242
        it returns simple_editor_class.
243

244
        """
245 4
        try:
246 4
            CustomEditor = self._get_toolkit_editor("CustomEditor")
247 0
        except Exception as e:
248 0
            msg = "Can't import CustomEditor for {}: {}"
249 0
            logger.debug(msg.format(self.__class__, e))
250 0
            CustomEditor = self.simple_editor_class
251 4
        return CustomEditor
252

253 4
    def _get_text_editor_class(self):
254
        """ Returns the editor class to use for "text" style views.
255
        The default implementation tries to import the TextEditor class in the
256
        editor file in the backend package, and if such a class is not found
257
        it returns the TextEditor class declared in the editor_factory module in
258
        the backend package.
259

260
        """
261 4
        try:
262 4
            TextEditor = self._get_toolkit_editor("TextEditor")
263 0
        except Exception as e:
264 0
            msg = "Can't import TextEditor for {}: {}"
265 0
            logger.debug(msg.format(self.__class__, e))
266 0
            TextEditor = toolkit_object("editor_factory:TextEditor")
267 4
        return TextEditor
268

269 4
    def _get_readonly_editor_class(self):
270
        """ Returns the editor class to use for "readonly" style views.
271
        The default implementation tries to import the ReadonlyEditor class in
272
        the editor file in the backend package, and if such a class is not found
273
        it returns the ReadonlyEditor class declared in the editor_factory
274
        module in the backend package.
275

276
        """
277 4
        try:
278 4
            ReadonlyEditor = self._get_toolkit_editor("ReadonlyEditor")
279 0
        except Exception as e:
280 0
            msg = "Can't import ReadonlyEditor for {}: {}"
281 0
            logger.debug(msg.format(self.__class__, e))
282 0
            ReadonlyEditor = toolkit_object("editor_factory:ReadonlyEditor")
283 4
        return ReadonlyEditor
284

285

286
# -------------------------------------------------------------------------
287
#  'EditorWithListFactory' abstract base class:
288
# -------------------------------------------------------------------------
289

290

291 4
class EditorWithListFactory(EditorFactory):
292
    """ Base class for factories of editors for objects that contain lists.
293
    """
294

295
    # -------------------------------------------------------------------------
296
    #  Trait definitions:
297
    # -------------------------------------------------------------------------
298

299
    #: Values to enumerate (can be a list, tuple, dict, or a CTrait or
300
    #: TraitHandler that is "mapped"):
301 4
    values = Any()
302

303
    #: Extended name of the trait on **object** containing the enumeration data:
304 4
    object = Str("object")
305

306
    #: Name of the trait on 'object' containing the enumeration data
307 4
    name = Str()

Read our documentation on viewing source code .

Loading