~ubuntu-branches/ubuntu/utopic/python-traitsui/utopic

« back to all changes in this revision

Viewing changes to traitsui/ui_traits.py

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2011-07-09 13:57:39 UTC
  • Revision ID: james.westby@ubuntu.com-20110709135739-x5u20q86huissmn1
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 enthought/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/14/2004
 
15
#
 
16
#------------------------------------------------------------------------------
 
17
 
 
18
""" Defines common traits used within the traits.ui package.
 
19
"""
 
20
 
 
21
#-------------------------------------------------------------------------------
 
22
#  Imports:
 
23
#-------------------------------------------------------------------------------
 
24
 
 
25
from __future__ import absolute_import
 
26
 
 
27
from traits.api import (Any, Delegate, Enum, Expression, Float, HasStrictTraits,
 
28
    Instance, List, Range, Str, Trait, TraitError, TraitPrefixList, TraitType)
 
29
 
 
30
from traits.trait_base import get_resource_path
 
31
 
 
32
#-------------------------------------------------------------------------------
 
33
#  Trait definitions:
 
34
#-------------------------------------------------------------------------------
 
35
 
 
36
# Orientation trait:
 
37
Orientation = Trait( 'vertical',
 
38
                     TraitPrefixList( 'vertical', 'horizontal' ) )
 
39
 
 
40
# Styles for user interface elements:
 
41
EditorStyle = style_trait = Trait( 'simple',
 
42
                     TraitPrefixList( 'simple', 'custom', 'text', 'readonly' ),
 
43
                     cols = 4 )
 
44
 
 
45
# Group layout trait:
 
46
Layout = Trait( 'normal',
 
47
                TraitPrefixList( 'normal', 'split', 'tabbed', 'flow', 'fold' ) )
 
48
 
 
49
# Trait for the default object being edited:
 
50
AnObject = Expression( 'object' )
 
51
 
 
52
# The default dock style to use:
 
53
DockStyle = dock_style_trait = Enum( 'fixed', 'horizontal', 'vertical', 'tab',
 
54
                                     desc = "the default docking style to use" )
 
55
 
 
56
# The category of elements dragged out of the view:
 
57
ExportType = Str( desc = 'the category of elements dragged out of the view' )
 
58
 
 
59
# Delegate a trait value to the object's **container** trait:
 
60
ContainerDelegate = container_delegate = Delegate( 'container',
 
61
                                                   listenable = False )
 
62
 
 
63
# An identifier for the external help context:
 
64
HelpId = help_id_trait = Str( desc = "the external help context identifier" )
 
65
 
 
66
# A button to add to a view:
 
67
AButton = Trait( '', Str, Instance( 'traitsui.menu.Action' ) )
 
68
 
 
69
# The set of buttons to add to the view:
 
70
Buttons = List( AButton,
 
71
                desc = 'the action buttons to add to the bottom of the view' )
 
72
 
 
73
# View trait specified by name or instance:
 
74
AView = Trait( '', Str, Instance( 'traitsui.view.View' ) )
 
75
 
 
76
#-------------------------------------------------------------------------------
 
77
#  'StatusItem' class:
 
78
#-------------------------------------------------------------------------------
 
79
 
 
80
class StatusItem ( HasStrictTraits ):
 
81
 
 
82
    # The name of the trait the status information will be synched with:
 
83
    name = Str( 'status' )
 
84
 
 
85
    # The width of the status field. The possible values are:
 
86
    #
 
87
    #   - abs( width )  > 1.0: Width of the field in pixels = abs( width )
 
88
    #   - abs( width ) <= 1.0: Relative width of the field when compared to
 
89
    #                          the other relative width fields.
 
90
    width = Float( 0.5 )
 
91
 
 
92
    def __init__ ( self, value = None, **traits ):
 
93
        """ Initializes the item object.
 
94
        """
 
95
        super( StatusItem, self ).__init__( **traits )
 
96
 
 
97
        if value is not None:
 
98
            self.name = value
 
99
 
 
100
#-------------------------------------------------------------------------------
 
101
#  'ViewStatus' trait:
 
102
#-------------------------------------------------------------------------------
 
103
 
 
104
class ViewStatus ( TraitType ):
 
105
    """ Defines a trait whose value must be a single StatusItem instance or a
 
106
        list of StatusItem instances.
 
107
    """
 
108
 
 
109
    # Define the default value for the trait:
 
110
    default_value = None
 
111
 
 
112
    # A description of the type of value this trait accepts:
 
113
    info_text = ('None, a string, a single StatusItem instance, or a list or '
 
114
                 'tuple of strings and/or StatusItem instances')
 
115
 
 
116
    def validate ( self, object, name, value ):
 
117
        """ Validates that a specified value is valid for this trait.
 
118
        """
 
119
        if isinstance( value, basestring ):
 
120
            return [ StatusItem( name = value ) ]
 
121
 
 
122
        if isinstance( value, StatusItem ):
 
123
            return [ value ]
 
124
 
 
125
        if value is None:
 
126
            return value
 
127
 
 
128
        result = []
 
129
        if isinstance( value, SequenceTypes ):
 
130
            for item in value:
 
131
                if isinstance( item, basestring ):
 
132
                    result.append( StatusItem( name = item ) )
 
133
                elif isinstance( item, StatusItem ):
 
134
                    result.append( item )
 
135
                else:
 
136
                    break
 
137
            else:
 
138
                return result
 
139
 
 
140
        self.error( object, name, value )
 
141
 
 
142
#-------------------------------------------------------------------------------
 
143
#  'Image' trait:
 
144
#-------------------------------------------------------------------------------
 
145
 
 
146
image_resource_cache = {}
 
147
image_bitmap_cache   = {}
 
148
 
 
149
def convert_image ( value, level = 3 ):
 
150
    """ Converts a specified value to an ImageResource if possible.
 
151
    """
 
152
    global image_resource_cache
 
153
 
 
154
    if not isinstance( value, basestring ):
 
155
        return value
 
156
 
 
157
    key             = value
 
158
    is_traits_image = (value[:1] == '@')
 
159
    if not is_traits_image:
 
160
        search_path = get_resource_path( level )
 
161
        key         = '%s[%s]' % ( value, search_path )
 
162
 
 
163
    result = image_resource_cache.get( key )
 
164
    if result is None:
 
165
        if is_traits_image:
 
166
            try:
 
167
                from .image.image import ImageLibrary
 
168
 
 
169
                result = ImageLibrary.image_resource( value )
 
170
            except:
 
171
                result = None
 
172
        else:
 
173
            from pyface.image_resource import ImageResource
 
174
            result = ImageResource( value, search_path = [ search_path ] )
 
175
 
 
176
        image_resource_cache[ key ] = result
 
177
 
 
178
    return result
 
179
 
 
180
def convert_bitmap ( image_resource ):
 
181
    """ Converts an ImageResource to a bitmap using a cache.
 
182
    """
 
183
    global image_bitmap_cache
 
184
 
 
185
    bitmap = image_bitmap_cache.get( image_resource )
 
186
    if (bitmap is None) and (image_resource is not None):
 
187
        #try:
 
188
        image_bitmap_cache[ image_resource ] = bitmap = \
 
189
            image_resource.create_bitmap()
 
190
        #except:
 
191
        #    pass
 
192
 
 
193
    return bitmap
 
194
 
 
195
class Image ( TraitType ):
 
196
    """ Defines a trait whose value must be a PyFace ImageResource or a string
 
197
        that can be converted to one.
 
198
    """
 
199
 
 
200
    # Define the default value for the trait:
 
201
    default_value = None
 
202
 
 
203
    # A description of the type of value this trait accepts:
 
204
    info_text = 'an ImageResource or string that can be used to define one'
 
205
 
 
206
    def __init__ ( self, value = None, **metadata ):
 
207
        """ Creates an Image trait.
 
208
 
 
209
        Parameters
 
210
        ----------
 
211
        value : string or ImageResource
 
212
            The default value for the Image, either an ImageResource object,
 
213
            or a string from which an ImageResource object can be derived.
 
214
        """
 
215
        super( Image, self ).__init__( convert_image( value ), **metadata )
 
216
 
 
217
    def validate ( self, object, name, value ):
 
218
        """ Validates that a specified value is valid for this trait.
 
219
        """
 
220
        from pyface.image_resource import ImageResource
 
221
 
 
222
        if value is None:
 
223
            return None
 
224
 
 
225
        new_value = convert_image( value, 4 )
 
226
        if isinstance( new_value, ImageResource ):
 
227
            return new_value
 
228
 
 
229
        self.error( object, name, value )
 
230
 
 
231
    def create_editor ( self ):
 
232
        """ Returns the default UI editor for the trait.
 
233
        """
 
234
        from .editors.api import ImageEditor
 
235
        return ImageEditor()
 
236
 
 
237
#-------------------------------------------------------------------------------
 
238
#  'ATheme' trait:
 
239
#-------------------------------------------------------------------------------
 
240
 
 
241
def convert_theme ( value, level = 3 ):
 
242
    """ Converts a specified value to a Theme if possible.
 
243
    """
 
244
    if not isinstance( value, basestring ):
 
245
        return value
 
246
 
 
247
    if (value[:1] == '@') and (value.find( ':' ) >= 2):
 
248
        try:
 
249
            from .image.image import ImageLibrary
 
250
 
 
251
            info = ImageLibrary.image_info( value )
 
252
        except:
 
253
            info = None
 
254
 
 
255
        if info is not None:
 
256
            return info.theme
 
257
 
 
258
    from .theme import Theme
 
259
    return Theme( image = convert_image( value, level + 1 ) )
 
260
 
 
261
class ATheme ( TraitType ):
 
262
    """ Defines a trait whose value must be a traits UI Theme or a string that
 
263
        can be converted to one.
 
264
    """
 
265
 
 
266
    # Define the default value for the trait:
 
267
    default_value = None
 
268
 
 
269
    # A description of the type of value this trait accepts:
 
270
    info_text = 'a Theme or string that can be used to define one'
 
271
 
 
272
    def __init__ ( self, value = None, **metadata ):
 
273
        """ Creates an ATheme trait.
 
274
 
 
275
        Parameters
 
276
        ----------
 
277
        value : string or Theme
 
278
            The default value for the ATheme, either a Theme object, or a
 
279
            string from which a Theme object can be derived.
 
280
        """
 
281
        super( ATheme, self ).__init__( convert_theme( value ), **metadata )
 
282
 
 
283
    def validate ( self, object, name, value ):
 
284
        """ Validates that a specified value is valid for this trait.
 
285
        """
 
286
        from .theme import Theme
 
287
 
 
288
        if value is None:
 
289
            return None
 
290
 
 
291
        new_value = convert_theme( value, 4 )
 
292
        if isinstance( new_value, Theme ):
 
293
            return new_value
 
294
 
 
295
        self.error( object, name, value )
 
296
 
 
297
#-------------------------------------------------------------------------------
 
298
#  'BasePMB' class:
 
299
#-------------------------------------------------------------------------------
 
300
 
 
301
class BaseMB ( HasStrictTraits ):
 
302
 
 
303
    def __init__ ( self, *args, **traits ):
 
304
        """ Initializes the object.
 
305
        """
 
306
        n = len( args )
 
307
        if n > 0:
 
308
            if n == 1:
 
309
                left = right = top = bottom = args[0]
 
310
            elif n == 2:
 
311
                left = right  = args[0]
 
312
                top  = bottom = args[1]
 
313
            elif n == 4:
 
314
                left, right, top, bottom = args
 
315
            else:
 
316
                raise TraitError( '0, 1, 2 or 4 arguments expected, but %d '
 
317
                                  'specified' % n )
 
318
            self.set( left = left, right = right, top = top, bottom = bottom )
 
319
 
 
320
        super( BaseMB, self ).__init__( **traits )
 
321
 
 
322
#-------------------------------------------------------------------------------
 
323
#  'Margin' class:
 
324
#-------------------------------------------------------------------------------
 
325
 
 
326
class Margin ( BaseMB ):
 
327
 
 
328
    # The amount of padding/margin at the top:
 
329
    top = Range( -32, 32, 0 )
 
330
 
 
331
    # The amount of padding/margin at the bottom:
 
332
    bottom = Range( -32, 32, 0 )
 
333
 
 
334
    # The amount of padding/margin on the left:
 
335
    left = Range( -32, 32, 0 )
 
336
 
 
337
    # The amount of padding/margin on the right:
 
338
    right = Range( -32, 32, 0 )
 
339
 
 
340
#-------------------------------------------------------------------------------
 
341
#  'Border' class:
 
342
#-------------------------------------------------------------------------------
 
343
 
 
344
class Border ( BaseMB ):
 
345
 
 
346
    # The amount of border at the top:
 
347
    top = Range( 0, 32, 0 )
 
348
 
 
349
    # The amount of border at the bottom:
 
350
    bottom = Range( 0, 32, 0 )
 
351
 
 
352
    # The amount of border on the left:
 
353
    left = Range( 0, 32, 0 )
 
354
 
 
355
    # The amount of border on the right:
 
356
    right = Range( 0, 32, 0 )
 
357
 
 
358
#-------------------------------------------------------------------------------
 
359
#  'HasMargin' trait:
 
360
#-------------------------------------------------------------------------------
 
361
 
 
362
class HasMargin ( TraitType ):
 
363
    """ Defines a trait whose value must be a Margin object or an integer or
 
364
        tuple value that can be converted to one.
 
365
    """
 
366
 
 
367
    # The desired value class:
 
368
    klass = Margin
 
369
 
 
370
    # Define the default value for the trait:
 
371
    default_value = Margin( 0 )
 
372
 
 
373
    # A description of the type of value this trait accepts:
 
374
    info_text = ('a Margin instance, or an integer in the range from -32 to 32 '
 
375
                 'or a tuple with 1, 2 or 4 integers in that range that can be '
 
376
                 'used to define one')
 
377
 
 
378
    def validate ( self, object, name, value ):
 
379
        """ Validates that a specified value is valid for this trait.
 
380
        """
 
381
        if isinstance( value, int ):
 
382
            try:
 
383
                value = self.klass( value )
 
384
            except:
 
385
                self.error( object, name, value )
 
386
        elif isinstance( value, tuple ):
 
387
            try:
 
388
                value = self.klass( *value )
 
389
            except:
 
390
                self.error( object, name, value )
 
391
 
 
392
        if isinstance( value, self.klass ):
 
393
            return value
 
394
 
 
395
        self.error( object, name, value )
 
396
 
 
397
    def get_default_value ( self ):
 
398
        """ Returns a tuple of the form: ( default_value_type, default_value )
 
399
            which describes the default value for this trait.
 
400
        """
 
401
        dv  = self.default_value
 
402
        dvt = self.default_value_type
 
403
        if dvt < 0:
 
404
            if isinstance( dv, int ):
 
405
                dv = self.klass( dv )
 
406
            elif isinstance( dv, tuple ):
 
407
                dv = self.klass( *dv )
 
408
 
 
409
            if not isinstance( dv, self.klass ):
 
410
                return super( HasMargin, self ).get_default_value()
 
411
 
 
412
            self.default_value_type = dvt = 7
 
413
            dv = ( self.klass, (), dv.get() )
 
414
 
 
415
        return ( dvt, dv )
 
416
 
 
417
#-------------------------------------------------------------------------------
 
418
#  'HasBorder' trait:
 
419
#-------------------------------------------------------------------------------
 
420
 
 
421
class HasBorder ( HasMargin ):
 
422
    """ Defines a trait whose value must be a Border object or an integer
 
423
        or tuple value that can be converted to one.
 
424
    """
 
425
 
 
426
    # The desired value class:
 
427
    klass = Border
 
428
 
 
429
    # Define the default value for the trait:
 
430
    default_value = Border( 0 )
 
431
 
 
432
    # A description of the type of value this trait accepts:
 
433
    info_text = ('a Border instance, or an integer in the range from 0 to 32 '
 
434
                 'or a tuple with 1, 2 or 4 integers in that range that can be '
 
435
                 'used to define one')
 
436
 
 
437
#-------------------------------------------------------------------------------
 
438
#  Other trait definitions:
 
439
#-------------------------------------------------------------------------------
 
440
 
 
441
# The position of an image relative to its associated text:
 
442
Position = Enum( 'left', 'right', 'above', 'below' )
 
443
 
 
444
# The alignment of text within a control:
 
445
Alignment = Enum( 'default', 'left', 'center', 'right' )
 
446
 
 
447
# The spacing between two items:
 
448
Spacing = Range( -32, 32, 3 )
 
449
 
 
450
#-------------------------------------------------------------------------------
 
451
#  Other definitions:
 
452
#-------------------------------------------------------------------------------
 
453
 
 
454
# Types that represent sequences:
 
455
SequenceTypes = ( tuple, list )
 
456