1 | # Copyright (c) 2007, Enthought, Inc. |
---|
2 | # License: BSD Style. |
---|
3 | |
---|
4 | """ |
---|
5 | dynamic_form_using_instances.py |
---|
6 | ================================= |
---|
7 | |
---|
8 | Demo of the dynamic restructuring of an interface using InstanceEditor |
---|
9 | |
---|
10 | This code sample shows a simple implementation of the dynamic |
---|
11 | restructuring of a View on the basis of some trait attribute's |
---|
12 | assigned value. |
---|
13 | |
---|
14 | The demo class "Person" has attributes that apply to all instances |
---|
15 | ('first_name', 'last_name', 'age') and a single attribute 'misc' |
---|
16 | referring to another object whose traits are specific to age |
---|
17 | group (AdultSpec for adults 18 and over, ChildSpec for children |
---|
18 | under 18). The 'misc' attribute is re-assigned to a new instance |
---|
19 | of the appropriate type when a change to 'age' crosses the range |
---|
20 | boundary. |
---|
21 | |
---|
22 | The multi-attribute instance assigned to 'misc' is edited by means |
---|
23 | of a single InstanceEditor, which is displayed in the 'custom' style |
---|
24 | so that the dynamic portion of the interface is displayed in a panel |
---|
25 | rather than a separate window. |
---|
26 | """ |
---|
27 | |
---|
28 | from traits.api \ |
---|
29 | import HasTraits, Str, Range, Enum, Bool, Instance |
---|
30 | |
---|
31 | from traitsui.api \ |
---|
32 | import Item, Group, View, Handler |
---|
33 | |
---|
34 | |
---|
35 | class Spec ( HasTraits ): |
---|
36 | """ An empty class from which all age-specific trait list classes are |
---|
37 | derived. |
---|
38 | """ |
---|
39 | pass |
---|
40 | |
---|
41 | |
---|
42 | class ChildSpec ( Spec ): |
---|
43 | """ Trait list for children (assigned to 'misc' for a Person when age < 18). |
---|
44 | """ |
---|
45 | legal_guardian = Str |
---|
46 | school = Str |
---|
47 | grade = Range( 1, 12 ) |
---|
48 | |
---|
49 | traits_view = View( 'legal_guardian', |
---|
50 | 'school', |
---|
51 | 'grade' ) |
---|
52 | |
---|
53 | |
---|
54 | class AdultSpec ( Spec ): |
---|
55 | """ Trait list for adults (assigned to 'misc' for a Person when age >= 18). |
---|
56 | """ |
---|
57 | |
---|
58 | marital_status = Enum( 'single', 'married', 'divorced', 'widowed' ) |
---|
59 | registered_voter = Bool |
---|
60 | military_service = Bool |
---|
61 | |
---|
62 | traits_view = View( 'marital_status', |
---|
63 | 'registered_voter', |
---|
64 | 'military_service' ) |
---|
65 | |
---|
66 | |
---|
67 | class ViewHandler ( Handler ): |
---|
68 | """ Handler class to perform restructuring action when conditions are met. |
---|
69 | """ |
---|
70 | |
---|
71 | def object_age_changed ( self, info ): |
---|
72 | # TODO: cached values of AdultSpec and ChildSpec if toggling between |
---|
73 | if ((info.object.age >= 18) and |
---|
74 | (not isinstance( info.object.misc, AdultSpec ))): |
---|
75 | info.object.misc = AdultSpec() |
---|
76 | elif ((info.object.age < 18) and |
---|
77 | (not isinstance( info.object.misc, ChildSpec ))): |
---|
78 | info.object.misc = ChildSpec() |
---|
79 | |
---|
80 | |
---|
81 | class Person ( HasTraits ): |
---|
82 | """ Demo class for demonstrating dynamic interface restructuring. |
---|
83 | """ |
---|
84 | first_name = Str |
---|
85 | last_name = Str |
---|
86 | age = Range( 0, 120 ) |
---|
87 | misc = Instance( Spec ) |
---|
88 | |
---|
89 | # Interface for attributes that are always visible in interface: |
---|
90 | gen_group = Group( |
---|
91 | Item( name = 'first_name' ), |
---|
92 | Item( name = 'last_name' ), |
---|
93 | Item( name = 'age'), |
---|
94 | label = 'General Info', |
---|
95 | show_border = True |
---|
96 | ) |
---|
97 | |
---|
98 | # Interface for attributes that depend on the value of 'age': |
---|
99 | spec_group = Group( |
---|
100 | Group( |
---|
101 | Item( name = 'misc', style = 'custom' ), |
---|
102 | show_labels = False |
---|
103 | ), |
---|
104 | label = 'Additional Info', |
---|
105 | show_border = True |
---|
106 | ) |
---|
107 | |
---|
108 | # A simple View is enough as long as the right handler is specified: |
---|
109 | view = View( |
---|
110 | Group( gen_group, spec_group ), |
---|
111 | title = 'Personal Information', |
---|
112 | buttons = [ 'OK' ], |
---|
113 | resizable = True, |
---|
114 | handler = ViewHandler() |
---|
115 | ) |
---|
116 | |
---|
117 | |
---|
118 | # Create the demo: |
---|
119 | demo = Person( first_name = "Samuel", |
---|
120 | last_name = "Johnson", |
---|
121 | age = 18, |
---|
122 | misc = AdultSpec() ) |
---|
123 | |
---|
124 | # Run the demo (if invoked from the command line): |
---|
125 | if __name__ == '__main__': |
---|
126 | demo.configure_traits() |
---|
127 | |
---|