1
# ------------------------------------------------------------------------------
2
#
3
#  Copyright (c) 2008, 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/21/2004
15
#
16
# ------------------------------------------------------------------------------
17 11
""" Defines the range editor factory for all traits user interface toolkits.
18
"""
19

20

21

22 11
from types import CodeType
23

24

25

26 11
from traits.api import (
27
    CTrait,
28
    Property,
29
    Range,
30
    Enum,
31
    Str,
32
    Int,
33
    Any,
34
    Str,
35
    Bool,
36
    Undefined,
37
)
38

39
# CIRCULAR IMPORT FIXME: Importing from the source rather than traits.ui.api
40
# to avoid circular imports, as this EditorFactory will be part of
41
# traits.ui.api as well.
42 11
from ..view import View
43

44 11
from ..editor_factory import EditorFactory
45

46 11
from ..toolkit import toolkit_object
47

48
# -------------------------------------------------------------------------
49
#  'ToolkitEditorFactory' class:
50
# -------------------------------------------------------------------------
51

52

53 11
class ToolkitEditorFactory(EditorFactory):
54
    """ Editor factory for range editors.
55
    """
56

57
    # -------------------------------------------------------------------------
58
    #  Trait definitions:
59
    # -------------------------------------------------------------------------
60

61
    #: Number of columns when displayed as an enumeration
62 11
    cols = Range(1, 20)
63

64
    #: Is user input set on every keystroke?
65 11
    auto_set = Bool(True)
66

67
    #: Is user input set when the Enter key is pressed?
68 11
    enter_set = Bool(False)
69

70
    #: Label for the low end of the range
71 11
    low_label = Str()
72

73
    #: Label for the high end of the range
74 11
    high_label = Str()
75

76
    #: FIXME: This is supported only in the wx backend so far.
77
    #: The width of the low and high labels
78 11
    label_width = Int()
79

80
    #: The name of an [object.]trait that defines the low value for the range
81 11
    low_name = Str()
82

83
    #: The name of an [object.]trait that defines the high value for the range
84 11
    high_name = Str()
85

86
    #: Formatting string used to format value and labels
87 11
    format = Str("%s")
88

89
    #: Is the range for floating pointer numbers (vs. integers)?
90 11
    is_float = Bool(Undefined)
91

92
    #: Function to evaluate floats/ints when they are assigned to an object
93
    #: trait
94 11
    evaluate = Any()
95

96
    #: The object trait containing the function used to evaluate floats/ints
97 11
    evaluate_name = Str()
98

99
    #: Low end of range
100 11
    low = Property()
101

102
    #: High end of range
103 11
    high = Property()
104

105
    #: Display mode to use
106 11
    mode = Enum(
107
        "auto", "slider", "xslider", "spinner", "enum", "text", "logslider"
108
    )
109

110
    # -------------------------------------------------------------------------
111
    #  Traits view definition:
112
    # -------------------------------------------------------------------------
113

114 11
    traits_view = View(
115
        [
116
            ["low", "high", "|[Range]"],
117
            ["low_label{Low}", "high_label{High}", "|[Range Labels]"],
118
            [
119
                "auto_set{Set automatically}",
120
                "enter_set{Set on enter key pressed}",
121
                "is_float{Is floating point range}",
122
                "-[Options]>",
123
            ],
124
            ["cols", "|[Number of columns for integer custom style]<>"],
125
        ]
126
    )
127

128 11
    def init(self, handler=None):
129
        """ Performs any initialization needed after all constructor traits
130
            have been set.
131
        """
132 11
        if handler is not None:
133 11
            if isinstance(handler, CTrait):
134 0
                handler = handler.handler
135

136 11
            if self.low_name == "":
137 11
                if isinstance(handler._low, CodeType):
138 0
                    self.low = eval(handler._low)
139
                else:
140 0
                    self.low = handler._low
141

142 11
            if self.high_name == "":
143 11
                if isinstance(handler._low, CodeType):
144 0
                    self.high = eval(handler._high)
145
                else:
146 0
                    self.high = handler._high
147
        else:
148 11
            if (self.low is None) and (self.low_name == ""):
149 0
                self.low = 0.0
150

151 11
            if (self.high is None) and (self.high_name == ""):
152 0
                self.high = 1.0
153

154 11
    def _get_low(self):
155 11
        return self._low
156

157 11
    def _set_low(self, low):
158 11
        old_low = self._low
159 11
        self._low = low = self._cast(low)
160 11
        if self.is_float is Undefined:
161 11
            self.is_float = isinstance(low, float)
162

163 11
        if (self.low_label == "") or (
164
            self.low_label == str(old_low)
165
        ):
166 11
            self.low_label = str(low)
167

168 11
    def _get_high(self):
169 11
        return self._high
170

171 11
    def _set_high(self, high):
172 11
        old_high = self._high
173 11
        self._high = high = self._cast(high)
174 11
        if self.is_float is Undefined:
175 0
            self.is_float = isinstance(high, float)
176

177 11
        if (self.high_label == "") or (
178
            self.high_label == str(old_high)
179
        ):
180 11
            self.high_label = str(high)
181

182 11
    def _cast(self, value):
183 11
        if not isinstance(value, str):
184 11
            return value
185

186 0
        try:
187 0
            return int(value)
188 0
        except ValueError:
189 0
            return float(value)
190

191
    # -- Private Methods ------------------------------------------------------
192

193 11
    def _get_low_high(self, ui):
194
        """ Returns the low and high values used to determine the initial range.
195
        """
196 8
        low, high = self.low, self.high
197

198 11
        if (low is None) and (self.low_name != ""):
199 0
            low = self.named_value(self.low_name, ui)
200 11
            if self.is_float is Undefined:
201 0
                self.is_float = isinstance(low, float)
202

203 11
        if (high is None) and (self.high_name != ""):
204 0
            high = self.named_value(self.high_name, ui)
205 11
            if self.is_float is Undefined:
206 0
                self.is_float = isinstance(high, float)
207

208 11
        if self.is_float is Undefined:
209 0
            self.is_float = True
210

211 8
        return (low, high, self.is_float)
212

213
    # -------------------------------------------------------------------------
214
    #  Property getters.
215
    # -------------------------------------------------------------------------
216 11
    def _get_simple_editor_class(self):
217
        """ Returns the editor class to use for a simple style.
218

219
        The type of editor depends on the type and extent of the range being
220
        edited:
221

222
        * One end of range is unspecified: RangeTextEditor
223
        * **mode** is specified and not 'auto': editor corresponding to **mode**
224
        * Floating point range with extent > 100: LargeRangeSliderEditor
225
        * Integer range or floating point range with extent <= 100:
226
          SimpleSliderEditor
227
        * All other cases: SimpleSpinEditor
228
        """
229 8
        low, high, is_float = self._low_value, self._high_value, self.is_float
230

231 11
        if (low is None) or (high is None):
232 0
            return toolkit_object("range_editor:RangeTextEditor")
233

234 11
        if (not is_float) and (abs(high - low) > 1000000000):
235 0
            return toolkit_object("range_editor:RangeTextEditor")
236

237 11
        if self.mode != "auto":
238 8
            return toolkit_object("range_editor:SimpleEditorMap")[self.mode]
239

240 11
        if is_float and (abs(high - low) > 100):
241 0
            return toolkit_object("range_editor:LargeRangeSliderEditor")
242

243 11
        if is_float or (abs(high - low) <= 100):
244 0
            return toolkit_object("range_editor:SimpleSliderEditor")
245

246 0
        return toolkit_object("range_editor:SimpleSpinEditor")
247

248 11
    def _get_custom_editor_class(self):
249
        """ Creates a custom style of range editor
250

251
        The type of editor depends on the type and extent of the range being
252
        edited:
253

254
        * One end of range is unspecified: RangeTextEditor
255
        * **mode** is specified and not 'auto': editor corresponding to **mode**
256
        * Floating point range: Same as "simple" style
257
        * Integer range with extent > 15: Same as "simple" style
258
        * Integer range with extent <= 15: CustomEnumEditor
259

260
        """
261 8
        low, high, is_float = self._low_value, self._high_value, self.is_float
262 11
        if (low is None) or (high is None):
263 0
            return toolkit_object("range_editor:RangeTextEditor")
264

265 11
        if self.mode != "auto":
266 8
            return toolkit_object("range_editor:CustomEditorMap")[self.mode]
267

268 11
        if is_float or (abs(high - low) > 15):
269 0
            return self.simple_editor_class
270

271 0
        return toolkit_object("range_editor:CustomEnumEditor")
272

273 11
    def _get_text_editor_class(self):
274
        """Returns the editor class to use for a text style.
275
        """
276 0
        return toolkit_object("range_editor:RangeTextEditor")
277

278
    # -------------------------------------------------------------------------
279
    #  'Editor' factory methods:
280
    # -------------------------------------------------------------------------
281

282 11
    def simple_editor(self, ui, object, name, description, parent):
283
        """ Generates an editor using the "simple" style.
284
        Overridden to set the values of the _low_value, _high_value and
285
        is_float traits.
286

287
        """
288 8
        self._low_value, self._high_value, self.is_float = self._get_low_high(
289
            ui
290
        )
291 8
        return super(RangeEditor, self).simple_editor(
292
            ui, object, name, description, parent
293
        )
294

295 11
    def custom_editor(self, ui, object, name, description, parent):
296
        """ Generates an editor using the "custom" style.
297
        Overridden to set the values of the _low_value, _high_value and
298
        is_float traits.
299

300
        """
301 8
        self._low_value, self._high_value, self.is_float = self._get_low_high(
302
            ui
303
        )
304 8
        return super(RangeEditor, self).custom_editor(
305
            ui, object, name, description, parent
306
        )
307

308

309
# Define the RangeEditor class
310 11
RangeEditor = ToolkitEditorFactory

Read our documentation on viewing source code .

Loading