| Home | Trees | Indices | Help |
|
|---|
|
|
1 #-------------------------------------------------------------------------------
2 #
3 # Define the set of abstract classes needed to define the notion of a
4 # graphical 'trait sheet' for use with the 'traits' module.
5 #
6 # Note: This module provides abstract definitions only. Concrete implementaions
7 # are GUI toolkit specific and are provided by the following modules:
8 #
9 # - wxtrait_sheet.py: wxPython
10 # - tktrait_sheet.py: Tkinter
11 #
12 # Written by: David C. Morrill
13 #
14 # Date: 10/07/2002
15 #
16 # (c) Copyright 2002 by Enthought, Inc.
17 #
18 #-------------------------------------------------------------------------------
19
20 #-------------------------------------------------------------------------------
21 # Imports:
22 #-------------------------------------------------------------------------------
23 from __future__ import division # confidence high
24
25 from types import StringType, ListType, TupleType
26 from trait_base import SequenceTypes
27 from trait_handlers import TraitPrefixList
28 from traits import Trait, HasTraits, ReadOnly
29 from string import lowercase, uppercase
30
31 #-------------------------------------------------------------------------------
32 # Trait definitions:
33 #-------------------------------------------------------------------------------
34
35 none_or_string = Trait( None, None, StringType )
36
37 true_trait = Trait( 'true', {
38 'true': 1, 't': 1, 'yes': 1, 'y': 1, 'on': 1, 1: 1,
39 'false': 0, 'f': 0, 'no': 0, 'n': 0, 'off': 0, 0: 0
40 } )
41
42 style_trait = Trait( None, None,
43 TraitPrefixList( 'simple', 'custom', 'text', 'readonly' ) )
44
45 object_trait = Trait( None, None, HasTraits )
46
47 basic_sequence_types = [ ListType, TupleType ]
48
49 #-------------------------------------------------------------------------------
50 # 'TraitSheetHandler' class:
51 #-------------------------------------------------------------------------------
52
54
55 #----------------------------------------------------------------------------
56 # Set the initial position of a trait sheet:
57 #----------------------------------------------------------------------------
58
61
62 #----------------------------------------------------------------------------
63 # Notification that a trait sheet is being closed:
64 #----------------------------------------------------------------------------
65
68
69 #----------------------------------------------------------------------------
70 # Notification that a trait sheet has modified a trait of its
71 # associated object:
72 #----------------------------------------------------------------------------
73
76
77 #----------------------------------------------------------------------------
78 # Create extra content to add to the trait sheet:
79 #----------------------------------------------------------------------------
80
83
84 # Create a default TraitSheetHandler:
85 default_trait_sheet_handler = TraitSheetHandler()
86
87 #-------------------------------------------------------------------------------
88 # 'TraitEditor' class:
89 #-------------------------------------------------------------------------------
90
92
93 #----------------------------------------------------------------------------
94 # Interactively edit the 'trait_name' trait of 'object' in a
95 # self-contained dialog:
96 #----------------------------------------------------------------------------
97
98 # def popup_editor ( self, object, trait_name, description, handler,
99 # parent = None ):
100 # return 0
101
102 #----------------------------------------------------------------------------
103 # Create a simple, imbeddable text view of the current value of the
104 # 'trait_name' trait of 'object':
105 #----------------------------------------------------------------------------
106
110
111 #----------------------------------------------------------------------------
112 # Create a simple, imbeddable view of the current value of the
113 # 'trait_name' trait of 'object':
114 #----------------------------------------------------------------------------
115
119
120 #----------------------------------------------------------------------------
121 # Create a custom, imbeddable view of the current value of the
122 # 'trait_name' trait of 'object':
123 #----------------------------------------------------------------------------
124
129
130 #----------------------------------------------------------------------------
131 # Set a specified object trait value:
132 #----------------------------------------------------------------------------
133
135 original_value = getattr( object, trait_name )
136 setattr( object, trait_name, value )
137 handler.changed( object, trait_name, value, original_value, True )
138
139 #----------------------------------------------------------------------------
140 # Return the text representation of the 'trait' trait of 'object':
141 #----------------------------------------------------------------------------
142
145
146 #----------------------------------------------------------------------------
147 # Return the text representation of a specified object trait value:
148 #----------------------------------------------------------------------------
149
151 return str( value )
152
153 #-------------------------------------------------------------------------------
154 # 'TraitMonitor' class:
155 #-------------------------------------------------------------------------------
156
158
159 #----------------------------------------------------------------------------
160 # Initialize the object:
161 #----------------------------------------------------------------------------
162
164 self.control = control
165 self.on_trait_change_handler = on_trait_change_handler
166 object.on_trait_change( self.on_trait_change, trait_name )
167
168 #----------------------------------------------------------------------------
169 # Handle an object trait being changed:
170 #----------------------------------------------------------------------------
171
173 try:
174 self.on_trait_change_handler( self.control, new )
175 except:
176 # NOTE: This code handles the case where a trait editor window has
177 # been destroyed, but we don't know about it. Attempting to update the
178 # now non-existent control generates an exception. We catch it here,
179 # then disconnect the handler so it doesn't happen again:
180 object.on_trait_change( self.on_trait_change, trait_name,
181 remove = True )
182
183 #-------------------------------------------------------------------------------
184 # 'TraitGroupItem' class:
185 #-------------------------------------------------------------------------------
186
188
189 __traits__ = {
190 'name': none_or_string,
191 'label': none_or_string,
192 'style': style_trait,
193 'editor': Trait( None, None, TraitEditor ),
194 'object': object_trait
195 }
196
197 #----------------------------------------------------------------------------
198 # Initialize the object:
199 #----------------------------------------------------------------------------
200
202 HasTraits.__init__( self, **traits )
203 if (len( value ) == 1) and (type( value[0] ) in SequenceTypes):
204 value = value[0]
205 for data in value:
206 if type( data ) is StringType:
207 if self.name is None:
208 self.name = data
209 elif self.label is None:
210 self.label = data
211 else:
212 self.style = data
213 elif isinstance( data, TraitEditor ):
214 self.editor = data
215 else:
216 self.object = data
217
218 #---------------------------------------------------------------------------
219 # Create a clone of the object:
220 #---------------------------------------------------------------------------
221
226
227 #----------------------------------------------------------------------------
228 # Return the user interface label for a specified object's trait:
229 #----------------------------------------------------------------------------
230
232 return ( self.label or
233 (self.object or object)._base_trait( self.name ).label or
234 self.user_name_for( self.name ) )
235
236 #----------------------------------------------------------------------------
237 # Return a 'user-friendly' name for a specified trait:
238 #----------------------------------------------------------------------------
239
241 name = name.replace( '_', ' ' ).capitalize()
242 result = ''
243 last_lower = 0
244 for c in name:
245 if (c in uppercase) and last_lower:
246 result += ' '
247 last_lower = (c in lowercase)
248 result += c
249 return result
250
251 #----------------------------------------------------------------------------
252 # Return the TraitEditor object for a specified object's trait:
253 #----------------------------------------------------------------------------
254
258
259 #-------------------------------------------------------------------------------
260 # 'TraitGroup' class:
261 #-------------------------------------------------------------------------------
262
264
265 __traits__ = {
266 'values': ReadOnly,
267 'label': none_or_string,
268 'style': style_trait,
269 'orientation': Trait( 'vertical',
270 TraitPrefixList( 'vertical', 'horizontal' ) ),
271 'show_border': true_trait,
272 'show_labels': true_trait,
273 'object': object_trait
274 }
275
276 #----------------------------------------------------------------------------
277 # Initialize the object:
278 #----------------------------------------------------------------------------
279
281 HasTraits.__init__( self, **traits )
282 _values = []
283 for value in values:
284 if (isinstance( value, TraitGroup ) or
285 isinstance( value, TraitGroupItem )):
286 _values.append( value )
287 else:
288 _values.append( TraitGroupItem( value ) )
289 self.values = _values
290
291 #---------------------------------------------------------------------------
292 # Create a clone of the object:
293 #---------------------------------------------------------------------------
294
296 clone = self.__class__()
297 clone.clone_traits( self,
298 [ 'label', 'style', 'orientation', 'show_border', 'show_labels' ] )
299 clone_values_append = clone.values.append
300 for value in self.values:
301 clone_values_append( value.clone() )
302 return clone
303
304 #---------------------------------------------------------------------------
305 # Handle merging a TraitGroup with other editable traitsL
306 #---------------------------------------------------------------------------
307
309 return merge_trait_groups( self, other )
310
311 #-------------------------------------------------------------------------------
312 # 'TraitGroupList' class:
313 #-------------------------------------------------------------------------------
314
316
317 #---------------------------------------------------------------------------
318 # Handle merging a TraitGroup with other editable traitsL
319 #---------------------------------------------------------------------------
320
322 return merge_trait_groups( self, other )
323
324 #-------------------------------------------------------------------------------
325 # 'MergeTraitGroups' class:
326 #-------------------------------------------------------------------------------
327
329
330 #---------------------------------------------------------------------------
331 # Merge two trait groups:
332 #---------------------------------------------------------------------------
333
335 return getattr( self, '%s_%s' % (
336 self._kind( group1 ), self._kind( group2 ) ) )(
337 group1, group2 )
338
339 #---------------------------------------------------------------------------
340 # Return a string describing the kind of group specified:
341 #---------------------------------------------------------------------------
342
344 if isinstance( group, TraitGroup ):
345 return 'tg'
346 if (isinstance( group, TraitGroupList ) or
347 (type( group ) in basic_sequence_types)):
348 if (len( group ) == 0) or (type( group[0] ) is StringType):
349 return 'strl'
350 return 'tgl'
351 return 'str'
352
353 #---------------------------------------------------------------------------
354 # Merge one TraitGroup into another:
355 #---------------------------------------------------------------------------
356
358 values = dest_group.values
359 n = len( values )
360 for value in src_group.values:
361 if isinstance( value, TraitGroupItem ) or (value.label is None):
362 values.append( value )
363 else:
364 label = value.label
365 for i in range( n ):
366 merge_item = values[i]
367 if (isinstance( merge_item, TraitGroup ) and
368 (label == merge_item.label)):
369 self._merge( merge_item, value )
370 break
371 else:
372 values.append( value )
373
374 #---------------------------------------------------------------------------
375 # Handle the various combinations of arguments:
376 #---------------------------------------------------------------------------
377
379 return TraitGroupList( [ group1, group2 ] )
380
382 return TraitGroupList( [ group1 ] + group2 )
383
387
391
393 return TraitGroupList( group1 + [ group2 ] )
394
396 return TraitGroupList( group1 + group2 )
397
401
405
409
413
415 return self.tgl_tgl( [ group1 ], [ group2 ] )
416
418 return self.tgl_tgl( [ group1 ], group2 )
419
423
427
429 return self.tgl_tgl( group1, [ group2 ] )
430
432 result = TraitGroupList()
433 page = 0
434 for group in group1:
435 group = group.clone()
436 if group.label is None:
437 page += 1
438 group.label = 'Page %d' % page
439 result.append( group )
440 for group in group2:
441 label = group.label
442 if label is None:
443 page += 1
444 group.label = 'Page %d' % page
445 result.append( group )
446 else:
447 for merge_group in result:
448 if label == merge_group.label:
449 self._merge( merge_group, group )
450 break
451 else:
452 result.append( group )
453 return result
454
455 # Create a singleton instance which can be used to merge trait groups:
456 merge_trait_groups = MergeTraitGroups()
457
458 """
459 A trait_element is:
460 - A string (specifying a trait name)
461 - A tuple containing 1 to 3 elements:
462 - 1 string: trait name
463 - 2 strings: trait name and UI label
464 - 1 string and 1 TraitEditor: trait name and editor
465 - 2 strings and 1 TraitEditor: trait name, UI label and editor
466
467 A Trait Sheet description can be:
468 - A string (edit the single trait whose name is specified by the string)
469 - A list of trait_elements: (simple non-tabbed trait sheet, vertically
470 oriented, two-column using UI labels and simple editor)
471 - A TraitGroup (simple non-tabbed trait sheet using layout specified by
472 the TraitGroup contents)
473 - A list of TraitGroup's (Each TraitGroup defines a notebook tab, the
474 contents of which are defined by the TraitGroup's contents)
475
476 Each element passed to a TraitGroup constructor can be:
477 - A trait_element (defines a single trait to be editor)
478 - A TraitGroup (defines a nested group of traits to be edited)
479
480 Examples of Trait Sheet descriptions:
481
482 [ 'foo', 'bar', 'baz' ]
483
484 [ TraitGroup( 'foo', 'bar', 'baz', label = 'Main' ),
485 TraitGroup( 'color', 'style', 'weight', label = 'Border' )
486 ]
487
488 [ TraitGroup( ( 'foo', 'Enter Foo' ),
489 ( 'bar', 'Enter Bar', TraitEditBar() ),
490 'baz', label = 'Main' ),
491 TraitGroup( 'color', 'style', 'weight', label = 'Border' )
492 ]
493
494 [ TraitGroup(
495 TraitGroup( 'foo', 'bar', 'baz',
496 label = 'Group 1' ),
497 TraitGroup( 'color', 'style', 'weight',
498 label = 'Line',
499 border = 'no',
500 orientation = 'horizontal',
501 show_labels = 'no',
502 style = 'custom' ),
503 label = 'Main' ),
504 """
505
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu Jan 13 11:20:30 2011 | http://epydoc.sourceforge.net |