1
#------------------------------------------------------------------------------
3
# Copyright (c) 2005, Enthought, Inc.
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
11
# Thanks for using Enthought open source!
13
# Author: David C. Morrill
16
#------------------------------------------------------------------------------
18
""" Defines common traits used within the traits.ui package.
21
#-------------------------------------------------------------------------------
23
#-------------------------------------------------------------------------------
25
from __future__ import absolute_import
27
from traits.api import (Any, Delegate, Enum, Expression, Float, HasStrictTraits,
28
Instance, List, Range, Str, Trait, TraitError, TraitPrefixList, TraitType)
30
from traits.trait_base import get_resource_path
32
#-------------------------------------------------------------------------------
34
#-------------------------------------------------------------------------------
37
Orientation = Trait( 'vertical',
38
TraitPrefixList( 'vertical', 'horizontal' ) )
40
# Styles for user interface elements:
41
EditorStyle = style_trait = Trait( 'simple',
42
TraitPrefixList( 'simple', 'custom', 'text', 'readonly' ),
46
Layout = Trait( 'normal',
47
TraitPrefixList( 'normal', 'split', 'tabbed', 'flow', 'fold' ) )
49
# Trait for the default object being edited:
50
AnObject = Expression( 'object' )
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" )
56
# The category of elements dragged out of the view:
57
ExportType = Str( desc = 'the category of elements dragged out of the view' )
59
# Delegate a trait value to the object's **container** trait:
60
ContainerDelegate = container_delegate = Delegate( 'container',
63
# An identifier for the external help context:
64
HelpId = help_id_trait = Str( desc = "the external help context identifier" )
66
# A button to add to a view:
67
AButton = Trait( '', Str, Instance( 'traitsui.menu.Action' ) )
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' )
73
# View trait specified by name or instance:
74
AView = Trait( '', Str, Instance( 'traitsui.view.View' ) )
76
#-------------------------------------------------------------------------------
78
#-------------------------------------------------------------------------------
80
class StatusItem ( HasStrictTraits ):
82
# The name of the trait the status information will be synched with:
83
name = Str( 'status' )
85
# The width of the status field. The possible values are:
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.
92
def __init__ ( self, value = None, **traits ):
93
""" Initializes the item object.
95
super( StatusItem, self ).__init__( **traits )
100
#-------------------------------------------------------------------------------
101
# 'ViewStatus' trait:
102
#-------------------------------------------------------------------------------
104
class ViewStatus ( TraitType ):
105
""" Defines a trait whose value must be a single StatusItem instance or a
106
list of StatusItem instances.
109
# Define the default value for the trait:
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')
116
def validate ( self, object, name, value ):
117
""" Validates that a specified value is valid for this trait.
119
if isinstance( value, basestring ):
120
return [ StatusItem( name = value ) ]
122
if isinstance( value, StatusItem ):
129
if isinstance( value, SequenceTypes ):
131
if isinstance( item, basestring ):
132
result.append( StatusItem( name = item ) )
133
elif isinstance( item, StatusItem ):
134
result.append( item )
140
self.error( object, name, value )
142
#-------------------------------------------------------------------------------
144
#-------------------------------------------------------------------------------
146
image_resource_cache = {}
147
image_bitmap_cache = {}
149
def convert_image ( value, level = 3 ):
150
""" Converts a specified value to an ImageResource if possible.
152
global image_resource_cache
154
if not isinstance( value, basestring ):
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 )
163
result = image_resource_cache.get( key )
167
from .image.image import ImageLibrary
169
result = ImageLibrary.image_resource( value )
173
from pyface.image_resource import ImageResource
174
result = ImageResource( value, search_path = [ search_path ] )
176
image_resource_cache[ key ] = result
180
def convert_bitmap ( image_resource ):
181
""" Converts an ImageResource to a bitmap using a cache.
183
global image_bitmap_cache
185
bitmap = image_bitmap_cache.get( image_resource )
186
if (bitmap is None) and (image_resource is not None):
188
image_bitmap_cache[ image_resource ] = bitmap = \
189
image_resource.create_bitmap()
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.
200
# Define the default value for the trait:
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'
206
def __init__ ( self, value = None, **metadata ):
207
""" Creates an Image trait.
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.
215
super( Image, self ).__init__( convert_image( value ), **metadata )
217
def validate ( self, object, name, value ):
218
""" Validates that a specified value is valid for this trait.
220
from pyface.image_resource import ImageResource
225
new_value = convert_image( value, 4 )
226
if isinstance( new_value, ImageResource ):
229
self.error( object, name, value )
231
def create_editor ( self ):
232
""" Returns the default UI editor for the trait.
234
from .editors.api import ImageEditor
237
#-------------------------------------------------------------------------------
239
#-------------------------------------------------------------------------------
241
def convert_theme ( value, level = 3 ):
242
""" Converts a specified value to a Theme if possible.
244
if not isinstance( value, basestring ):
247
if (value[:1] == '@') and (value.find( ':' ) >= 2):
249
from .image.image import ImageLibrary
251
info = ImageLibrary.image_info( value )
258
from .theme import Theme
259
return Theme( image = convert_image( value, level + 1 ) )
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.
266
# Define the default value for the trait:
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'
272
def __init__ ( self, value = None, **metadata ):
273
""" Creates an ATheme trait.
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.
281
super( ATheme, self ).__init__( convert_theme( value ), **metadata )
283
def validate ( self, object, name, value ):
284
""" Validates that a specified value is valid for this trait.
286
from .theme import Theme
291
new_value = convert_theme( value, 4 )
292
if isinstance( new_value, Theme ):
295
self.error( object, name, value )
297
#-------------------------------------------------------------------------------
299
#-------------------------------------------------------------------------------
301
class BaseMB ( HasStrictTraits ):
303
def __init__ ( self, *args, **traits ):
304
""" Initializes the object.
309
left = right = top = bottom = args[0]
311
left = right = args[0]
312
top = bottom = args[1]
314
left, right, top, bottom = args
316
raise TraitError( '0, 1, 2 or 4 arguments expected, but %d '
318
self.set( left = left, right = right, top = top, bottom = bottom )
320
super( BaseMB, self ).__init__( **traits )
322
#-------------------------------------------------------------------------------
324
#-------------------------------------------------------------------------------
326
class Margin ( BaseMB ):
328
# The amount of padding/margin at the top:
329
top = Range( -32, 32, 0 )
331
# The amount of padding/margin at the bottom:
332
bottom = Range( -32, 32, 0 )
334
# The amount of padding/margin on the left:
335
left = Range( -32, 32, 0 )
337
# The amount of padding/margin on the right:
338
right = Range( -32, 32, 0 )
340
#-------------------------------------------------------------------------------
342
#-------------------------------------------------------------------------------
344
class Border ( BaseMB ):
346
# The amount of border at the top:
347
top = Range( 0, 32, 0 )
349
# The amount of border at the bottom:
350
bottom = Range( 0, 32, 0 )
352
# The amount of border on the left:
353
left = Range( 0, 32, 0 )
355
# The amount of border on the right:
356
right = Range( 0, 32, 0 )
358
#-------------------------------------------------------------------------------
360
#-------------------------------------------------------------------------------
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.
367
# The desired value class:
370
# Define the default value for the trait:
371
default_value = Margin( 0 )
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')
378
def validate ( self, object, name, value ):
379
""" Validates that a specified value is valid for this trait.
381
if isinstance( value, int ):
383
value = self.klass( value )
385
self.error( object, name, value )
386
elif isinstance( value, tuple ):
388
value = self.klass( *value )
390
self.error( object, name, value )
392
if isinstance( value, self.klass ):
395
self.error( object, name, value )
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.
401
dv = self.default_value
402
dvt = self.default_value_type
404
if isinstance( dv, int ):
405
dv = self.klass( dv )
406
elif isinstance( dv, tuple ):
407
dv = self.klass( *dv )
409
if not isinstance( dv, self.klass ):
410
return super( HasMargin, self ).get_default_value()
412
self.default_value_type = dvt = 7
413
dv = ( self.klass, (), dv.get() )
417
#-------------------------------------------------------------------------------
419
#-------------------------------------------------------------------------------
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.
426
# The desired value class:
429
# Define the default value for the trait:
430
default_value = Border( 0 )
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')
437
#-------------------------------------------------------------------------------
438
# Other trait definitions:
439
#-------------------------------------------------------------------------------
441
# The position of an image relative to its associated text:
442
Position = Enum( 'left', 'right', 'above', 'below' )
444
# The alignment of text within a control:
445
Alignment = Enum( 'default', 'left', 'center', 'right' )
447
# The spacing between two items:
448
Spacing = Range( -32, 32, 3 )
450
#-------------------------------------------------------------------------------
452
#-------------------------------------------------------------------------------
454
# Types that represent sequences:
455
SequenceTypes = ( tuple, list )