File: range_editor.py

package info (click to toggle)
python-traitsui 4.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 13,292 kB
  • sloc: python: 39,867; makefile: 120; sh: 5
file content (286 lines) | stat: -rw-r--r-- 10,535 bytes parent folder | download | duplicates (3)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#------------------------------------------------------------------------------
#
#  Copyright (c) 2008, Enthought, Inc.
#  All rights reserved.
#
#  This software is provided without warranty under the terms of the BSD
#  license included in enthought/LICENSE.txt and may be redistributed only
#  under the conditions described in the aforementioned license.  The license
#  is also available online at http://www.enthought.com/licenses/BSD.txt
#
#  Thanks for using Enthought open source!
#
#  Author: David C. Morrill
#  Date:   10/21/2004
#
#------------------------------------------------------------------------------
""" Defines the range editor factory for all traits user interface toolkits.
"""

#-------------------------------------------------------------------------------
#  Imports:
#-------------------------------------------------------------------------------

from __future__ import absolute_import

from traits.api import (CTrait, Property, Range, Enum, Str, Int, Any, Unicode,
        Bool, Undefined)

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

from ..editor_factory import EditorFactory

from ..toolkit import toolkit_object

#-------------------------------------------------------------------------------
#  'ToolkitEditorFactory' class:
#-------------------------------------------------------------------------------

class ToolkitEditorFactory ( EditorFactory ):
    """ Editor factory for range editors.
    """
    #---------------------------------------------------------------------------
    #  Trait definitions:
    #---------------------------------------------------------------------------

    # Number of columns when displayed as an enumeration
    cols = Range( 1, 20 )

    # Is user input set on every keystroke?
    auto_set = Bool(True)

    # Is user input set when the Enter key is pressed?
    enter_set = Bool(False)

    # Label for the low end of the range
    low_label = Unicode

    # Label for the high end of the range
    high_label = Unicode

    # FIXME: This is supported only in the wx backend so far.
    # The width of the low and high labels
    label_width = Int

    # The name of an [object.]trait that defines the low value for the range
    low_name = Str

    # The name of an [object.]trait that defines the high value for the range
    high_name = Str

    # Formatting string used to format value and labels
    format = Unicode( '%s' )

    # Is the range for floating pointer numbers (vs. integers)?
    is_float = Bool( Undefined )

    # Function to evaluate floats/ints when they are assigned to an object trait
    evaluate = Any

    # The object trait containing the function used to evaluate floats/ints
    evaluate_name = Str

    # Low end of range
    low = Property

    # High end of range
    high = Property

    # Display mode to use
    mode = Enum( 'auto', 'slider', 'xslider', 'spinner', 'enum', 'text', 'logslider' )

    #---------------------------------------------------------------------------
    #  Traits view definition:
    #---------------------------------------------------------------------------

    traits_view = View( [ [ 'low', 'high',
                            '|[Range]' ],
                          [ 'low_label{Low}', 'high_label{High}',
                            '|[Range Labels]' ],
                          [ 'auto_set{Set automatically}',
                            'enter_set{Set on enter key pressed}',
                            'is_float{Is floating point range}',
                            '-[Options]>' ],
                          [ 'cols',
                            '|[Number of columns for integer custom style]<>' ]
                        ] )

    #---------------------------------------------------------------------------
    #  Performs any initialization needed after all constructor traits have
    #  been set:
    #---------------------------------------------------------------------------

    def init ( self, handler = None ):
        """ Performs any initialization needed after all constructor traits
            have been set.
        """
        if handler is not None:
            if isinstance( handler, CTrait ):
                handler = handler.handler

            if self.low_name == '':
                self.low  = handler._low

            if self.high_name == '':
                self.high = handler._high
        else:
            if (self.low is None) and (self.low_name == ''):
                self.low  = 0.0

            if (self.high is None) and (self.high_name == ''):
                self.high = 1.0

    #---------------------------------------------------------------------------
    #  Define the 'low' and 'high' traits:
    #---------------------------------------------------------------------------

    def _get_low ( self ):
        return self._low

    def _set_low ( self, low ):
        old_low         = self._low
        self._low = low = self._cast( low )
        if self.is_float is Undefined:
            self.is_float = isinstance( low, float )

        if (self.low_label == '') or (self.low_label == unicode(old_low)):
            self.low_label = unicode(low)

    def _get_high ( self ):
        return self._high

    def _set_high ( self, high ):
        old_high          = self._high
        self._high = high = self._cast( high )
        if self.is_float is Undefined:
            self.is_float = isinstance( high, float )

        if (self.high_label == '') or (self.high_label == unicode(old_high)):
            self.high_label = unicode(high)

    def _cast ( self, value ):
        if not isinstance( value, basestring ):
            return value

        try:
            return int( value )
        except ValueError:
            return float( value )

    #-- Private Methods --------------------------------------------------------

    def _get_low_high ( self, ui ):
        """ Returns the low and high values used to determine the initial range.
        """
        low, high = self.low, self.high

        if (low is None) and (self.low_name != ''):
            low = self.named_value( self.low_name, ui )
            if self.is_float is Undefined:
                self.is_float = isinstance( low, float )

        if (high is None) and (self.high_name != ''):
            high = self.named_value( self.high_name, ui )
            if self.is_float is Undefined:
                self.is_float = isinstance( high, float )

        if self.is_float is Undefined:
            self.is_float = True

        return ( low, high, self.is_float )

    #---------------------------------------------------------------------------
    #  Property getters.
    #---------------------------------------------------------------------------
    def _get_simple_editor_class( self ):
        """ Returns the editor class to use for a simple style.

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

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

        if (low is None) or (high is None):
            return toolkit_object('range_editor:RangeTextEditor')

        if (not is_float) and (abs(high - low) > 1000000000L):
            return toolkit_object('range_editor:RangeTextEditor')

        if self.mode != 'auto':
            return toolkit_object('range_editor:SimpleEditorMap')[ self.mode ]

        if is_float and (abs(high - low) > 100):
            return toolkit_object('range_editor:LargeRangeSliderEditor')

        if is_float or (abs(high - low) <= 100):
            return toolkit_object('range_editor:SimpleSliderEditor')

        return toolkit_object('range_editor:SimpleSpinEditor')

    def _get_custom_editor_class ( self ):
        """ Creates a custom style of range editor

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

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

        """
        low, high, is_float = self._low_value, self._high_value, self.is_float
        if (low is None) or (high is None):
            return toolkit_object('range_editor:RangeTextEditor')

        if self.mode != 'auto':
            return toolkit_object('range_editor:CustomEditorMap')[ self.mode ]

        if is_float or (abs(high - low) > 15):
           return self.simple_editor_class

        return toolkit_object('range_editor:CustomEnumEditor')

    def _get_text_editor_class( self ):
        """Returns the editor class to use for a text style.
        """
        return toolkit_object('range_editor:RangeTextEditor')

    #---------------------------------------------------------------------------
    #  'Editor' factory methods:
    #---------------------------------------------------------------------------

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

        """
        self._low_value, self._high_value, self.is_float = self._get_low_high(ui)
        return super(RangeEditor, self).simple_editor(ui, object, name, description, parent)

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

        """
        self._low_value, self._high_value, self.is_float = self._get_low_high(ui)
        return super(RangeEditor, self).custom_editor(ui, object, name, description, parent)


# Define the RangeEditor class
RangeEditor = ToolkitEditorFactory

### EOF ---------------------------------------------------------------------