~ubuntu-branches/ubuntu/trusty/python-traitsui/trusty

« back to all changes in this revision

Viewing changes to docs/source/traitsui_user_manual/factory_intro.rst

  • 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
.. _introduction-to-trait-editor-factories:
 
2
 
 
3
======================================
 
4
Introduction to Trait Editor Factories
 
5
======================================
 
6
 
 
7
The preceding code samples in this User Manual have been surprisingly simple
 
8
considering the sophistication of the interfaces that they produce. In
 
9
particular, no code at all has been required to produce appropriate widgets for
 
10
the Traits to be viewed or edited in a given window. This is one of the
 
11
strengths of TraitsUI: usable interfaces can be produced simply and with a
 
12
relatively low level of UI programming expertise.
 
13
 
 
14
An even greater strength lies in the fact that this simplicity does not have to
 
15
be paid for in lack of flexibility. Where a novice TraitsUI programmer can
 
16
ignore the question of widgets altogether, a more advanced one can select from a
 
17
variety of predefined interface components for displaying any given Trait.
 
18
Furthermore, a programmer who is comfortable both with TraitsUI and with UI
 
19
programming in general can harness the full power and flexibility of the
 
20
underlying GUI toolkit from within TraitsUI.
 
21
 
 
22
The secret behind this combination of simplicity and flexibility is a TraitsUI
 
23
construct called a trait :term:`editor factory`. A trait editor factory
 
24
encapsulates a set of display instructions for a given :term:`trait type`,
 
25
hiding GUI-toolkit-specific code inside an abstraction with a relatively
 
26
straightforward interface. Furthermore, every :term:`predefined trait type` in
 
27
the Traits package has a predefined trait editor factory that is automatically
 
28
used whenever the trait is displayed, unless you specify otherwise.
 
29
 
 
30
Consider the following script and the window it creates:
 
31
 
 
32
.. _example-12-using-default-trait-editors:
 
33
 
 
34
.. rubric:: Example 12: Using default trait editors
 
35
 
 
36
::
 
37
 
 
38
    # default_trait_editors.py -- Example of using default 
 
39
    #                             trait editors
 
40
    
 
41
    from traits.api import HasTraits, Str, Range, Bool
 
42
    from traitsui.api import View, Item
 
43
    
 
44
    class Adult(HasTraits):
 
45
        first_name = Str
 
46
        last_name = Str
 
47
        age = Range(21,99)
 
48
        registered_voter = Bool
 
49
    
 
50
    
 
51
        traits_view = View(Item(name='first_name'),
 
52
                           Item(name='last_name'),
 
53
                           Item(name='age'),
 
54
                           Item(name='registered_voter'))
 
55
    
 
56
    alice = Adult(first_name='Alice', 
 
57
                  last_name='Smith',
 
58
                  age=42, 
 
59
                  registered_voter=True)
 
60
    
 
61
    alice.configure_traits()
 
62
 
 
63
.. figure::  images/ui_for_ex12.jpg
 
64
   :alt: UI showing text boxes for names, slider for Age, and checkbox for voter
 
65
   
 
66
   Figure 12: User interface for Example 12
 
67
 
 
68
Notice that each trait is displayed in an appropriate widget, even though the
 
69
code does not explicitly specify any widgets at all. The two Str traits appear
 
70
in text boxes, the Range is displayed using a combination of a text box and a
 
71
slider, and the Bool is represented by a checkbox. Each implementation is
 
72
generated by the default trait editor factory (TextEditor, RangeEditor and
 
73
BooleanEditor respectively) associated with the trait type.
 
74
 
 
75
TraitsUI is by no means limited to these defaults. There are two ways to
 
76
override the default representation of a :term:`trait attribute` in a TraitsUI
 
77
window:
 
78
 
 
79
- Explicitly specifying an alternate trait editor factory
 
80
- Specifying an alternate style for the editor generated by the factory
 
81
 
 
82
The remainder of this chapter examines these alternatives more closely.
 
83
 
 
84
.. _specifying-an-alternate-trait-editor-factory:
 
85
 
 
86
Specifying an Alternate Trait Editor Factory
 
87
--------------------------------------------
 
88
 
 
89
As of this writing the TraitsUI package includes a wide variety of predefined
 
90
trait editor factories, which are described in
 
91
:ref:`basic-trait-editor-factories` and :ref:`advanced-trait-editors`. Some
 
92
additional editor factories are specific to the wxWidgets toolkit and are
 
93
defined in one of the following packages:
 
94
 
 
95
- traitsui.wx
 
96
- traitsui.wx.extra
 
97
- traitsui.wx.extra.windows (specific to Microsoft Windows)
 
98
 
 
99
These editor factories are described in :ref:`extra-trait-editor-factories`.
 
100
 
 
101
For a current complete list of editor factories, refer to the *Traits API
 
102
Reference*. 
 
103
 
 
104
Other packages can define their own editor factories for their own traits. For
 
105
example, enthought.kiva.api.KivaFont uses a KivaFontEditor() and
 
106
enthought.enable2.traits.api.RGBAColor uses an RGBAColorEditor().
 
107
 
 
108
For most :term:`predefined trait type`\ s (see `Traits User Manual <http://github.enthought.com/traits/index.html>`_), there is
 
109
exactly one predefined trait editor factory suitable for displaying it: the
 
110
editor factory that is assigned as its default. [15]_ There are exceptions,
 
111
however; for example, a Str trait defaults to using a TextEditor, but can also
 
112
use a CodeEditor or an HTMLEditor. A List trait can be edited by means of
 
113
ListEditor, TableEditor (if the List elements are HasTraits objects),
 
114
CheckListEditor or SetEditor. Furthermore, the TraitsUI package includes tools
 
115
for building additional trait editors and factories for them as needed.
 
116
 
 
117
To use an alternate editor factory for a trait in a TraitsUI window, you must
 
118
specify it in the View for that window. This is done at the Item level, using
 
119
the *editor* keyword parameter. The syntax of the specification is 
 
120
:samp:`editor = {editor_factory}()`. (Use the same syntax for specifying that
 
121
the default editor should be used, but with certain keyword parameters 
 
122
explicitly specified; see :ref:`initializing-editors`).
 
123
 
 
124
For example, to display a Str trait called **my_string** using the default
 
125
editor factory (TextEditor()), the View might contain the following Item::
 
126
 
 
127
    Item(name='my_string')
 
128
 
 
129
The resulting widget would have the following appearance:
 
130
 
 
131
.. figure:: images/default_text_editor.gif
 
132
   :alt: Text field showing text that contains HTML markup
 
133
   
 
134
   Figure 13: Default editor for a Str trait
 
135
 
 
136
To use the HTMLEditor factory instead, add the appropriate specification to the
 
137
Item::
 
138
 
 
139
    Item( name='my_string', editor=HTMLEditor() )
 
140
 
 
141
The resulting widget appears as in Figure 14:
 
142
 
 
143
.. figure:: images/HTML_editor.gif
 
144
   :alt: Same text as Figure 13, styled as HTML
 
145
   
 
146
   Figure 14: Editor generated by HTMLEditor()
 
147
 
 
148
.. NOTE:: TraitsUI does not check editors for appropriateness.
 
149
 
 
150
   TraitsUI does not police the *editor* argument to ensure that the specified
 
151
   editor is appropriate for the trait being displayed. Thus there is nothing to
 
152
   prevent you from trying to, say, display a Float trait using ColorEditor().
 
153
   The results of such a mismatch are unlikely to be helpful, and can even crash
 
154
   the application; it is up to the programmer to choose an editor sensibly.
 
155
   :ref:`the-predefined-trait-editor-factories` is a useful reference for
 
156
   selecting an appropriate editor for a given task.
 
157
 
 
158
It is possible to specify the trait editor for a trait in other ways: 
 
159
 
 
160
- You can specify a trait editor when you define a trait, by passing the result
 
161
  of a trait editor factory as the *editor* keyword parameter of the callable
 
162
  that creates the trait. However, this approach commingles the :term:`view` of
 
163
  a  trait with its :term:`model`.
 
164
- You can specify the **editor** attribute of a TraitHandler object. This 
 
165
  approach commingles the :term:`view` of a trait with its :term:`controller`.
 
166
 
 
167
Use these approaches very carefully, if at all, as they muddle the :term:`MVC`
 
168
design pattern.
 
169
 
 
170
.. _initializing-editors:
 
171
 
 
172
Initializing Editors
 
173
````````````````````
 
174
 
 
175
Many of the TraitsUI trait editors can be used "straight from the box" as in
 
176
the example above. There are some editors, however, that must be initialized in
 
177
order to be useful. For example, a checklist editor (from CheckListEditor()) and
 
178
a set editor (from SetEditor()) both enable the user to edit a List attribute by
 
179
selecting elements from a specified set; the contents of this set must, of
 
180
course, be known to the editor. This sort of initialization is usually performed
 
181
by means of one or more keyword arguments to the editor factory, for example::
 
182
 
 
183
    Item(name='my_list',editor=CheckListEditor(values=["opt1","opt2","opt3"]))
 
184
 
 
185
The descriptions of trait editor factories in
 
186
:ref:`the-predefined-trait-editor-factories` include a list of required and
 
187
optional initialization keywords for each editor.
 
188
 
 
189
.. _specifying-an-editor-style:
 
190
 
 
191
Specifying an Editor Style
 
192
--------------------------
 
193
 
 
194
In TraitsUI, any given trait editor can be generated in one or more of four
 
195
different styles: *simple*, *custom*, *text* or *readonly*. These styles, which
 
196
are described in general terms below, represent different "flavors" of data
 
197
display, so that a given trait editor can look completely different in one style
 
198
than in another. However, different trait editors displayed in the same style
 
199
(usually) have noticeable characteristics in common. This is useful because
 
200
editor style, unlike individual editors, can be set at the Group or View level,
 
201
not just at the Item level. This point is discussed further in 
 
202
:ref:`using-editor-styles`.
 
203
 
 
204
.. _the-simple-style:
 
205
 
 
206
The 'simple' Style
 
207
``````````````````
 
208
 
 
209
The *simple* editor style is designed to be as functional as possible while
 
210
requiring minimal space within the window. In simple style, most of the Traits
 
211
UI editors take up only a single line of space in the window in which they are
 
212
embedded.
 
213
 
 
214
In some cases, such as the text editor and Boolean editor (see
 
215
:ref:`basic-trait-editor-factories`), the single line is fully sufficient. In
 
216
others, such as the (plain) color editor and the enumeration editor, a more
 
217
detailed interface is required; pop-up panels, drop-down lists, or dialog boxes
 
218
are often used in such cases. For example, the simple version of the enumeration
 
219
editor for the wxWidgets toolkit looks like this:
 
220
 
 
221
.. figure:: images/simple_enum_editor_closed.jpg
 
222
   :alt: Closed drop-list editor
 
223
   
 
224
   Figure 15: Simple style of enumeration editor
 
225
 
 
226
However, when the user clicks on the widget, a drop-down list appears:
 
227
 
 
228
.. figure:: images/simple_enum_editor_open.jpg
 
229
   :alt: Expanded drop-list editor
 
230
   
 
231
   Figure 16: Simple enumeration editor with expanded list
 
232
 
 
233
The simple editor style is most suitable for windows that must be kept small and
 
234
concise.
 
235
 
 
236
The 'custom' Style
 
237
``````````````````
 
238
 
 
239
The *custom* editor style generally generates the most detailed version of any
 
240
given editor. It is intended to provide maximal functionality and information
 
241
without regard to the amount of window space used. For example, in the wxWindows
 
242
toolkit, the custom style the enumeration editor appears as a set of radio
 
243
buttons rather than a drop-down list:
 
244
 
 
245
.. figure:: images/custom_enum_editor.jpg
 
246
   :alt: Radio buttons for a set of values
 
247
   
 
248
   Figure 17: Custom style of enumeration editor
 
249
 
 
250
In general, the custom editor style can be very useful when there is no need to
 
251
conserve window space, as it enables the user to see as much information as
 
252
possible without having to interact with the widget. It also usually provides
 
253
the most intuitive interface of the four.
 
254
 
 
255
Note that this style is not defined explicitly for all trait editor
 
256
implementations. If the custom style is requested for an editor for which it is
 
257
not defined, the simple style is generated instead.
 
258
 
 
259
The 'text' Style
 
260
````````````````
 
261
 
 
262
The *text* editor style is the simplest of the editor styles. When applied to a
 
263
given trait attribute, it generates a text representation of the trait value in
 
264
an editable box. Thus the enumeration editor in text style looks like the
 
265
following:
 
266
 
 
267
.. figure:: images/text_editor.jpg
 
268
   :alt: Text field
 
269
   
 
270
   Figure 18: Text style of enumeration editor
 
271
 
 
272
For this type of editor, the end user must type in a valid value for the
 
273
attribute. If the user types an invalid value, the validation method for the
 
274
attribute (see `Traits User Manual <http://github.enthought.com/traits/index.html>`_) notifies the user of the error (for
 
275
example, by shading the background of the text box red).
 
276
 
 
277
The text representation of an attribute to be edited in a text style editor is
 
278
created in one of the following ways, listed in order of priority:
 
279
 
 
280
#. The function specified in the **format_func** attribute of the Item (see 
 
281
   :ref:`the-item-object`), if any, is called on the attribute value.
 
282
#. Otherwise, the function specified in the *format_func* parameter of the 
 
283
   trait editor factory, if any, is called on the attribute value.
 
284
#. Otherwise, the Python-style formatting string specified in the **format_str**
 
285
   attribute of the Item (see :ref:`the-item-object`), if any, is used to format
 
286
   the attribute value.
 
287
#. The Python-style formatting string specified in the *format_str* parameter 
 
288
   of the trait editor factory, if any, is used to format the attribute value.
 
289
#. Otherwise, the Python str() function is called on the attribute value.
 
290
 
 
291
The 'readonly' style
 
292
````````````````````
 
293
 
 
294
The *readonly* editor style is usually identical in appearance to the text
 
295
style, except that the value appears as static text rather than in an editable
 
296
box:
 
297
 
 
298
.. figure:: images/read_only_editor.jpg
 
299
   :alt: Read-only text field
 
300
   
 
301
   Figure 19: Read-only style of enumeration editor
 
302
 
 
303
This editor style is used to display data values without allowing the user to
 
304
change them.
 
305
 
 
306
.. _using-editor-styles:
 
307
 
 
308
Using Editor Styles
 
309
```````````````````
 
310
 
 
311
As discussed in :ref:`contents-of-a-view` and :ref:`customizing-a-view`, the
 
312
Item, Group and View objects of TraitsUI all have a **style** attribute. The
 
313
style of editor used to display the Items in a View is determined as follows:
 
314
 
 
315
#. The editor style used to display a given Item is the value of its **style**
 
316
   attribute if specifically assigned. Otherwise the editor style of the Group
 
317
   or View that contains the Item is used.
 
318
#. The editor style of a Group is the value of its **style** attribute if 
 
319
   assigned. Otherwise, it is the editor style of the Group or View that 
 
320
   contains the Group.
 
321
#. The editor style of a View is the value of its **style** attribute if 
 
322
   specified, and 'simple' otherwise.
 
323
 
 
324
In other words, editor style can be specified at the Item, Group or View level,
 
325
and in case of conflicts the style of the smaller scope takes precedence. For
 
326
example, consider the following script:
 
327
 
 
328
.. _example-13-using-editor-styles-at-various-levels:
 
329
 
 
330
.. rubric:: Example 13: Using editor styles at various levels
 
331
 
 
332
::
 
333
 
 
334
    # mixed_styles.py -- Example of using editor styles at 
 
335
    #                    various levels
 
336
    
 
337
    from traits.api import HasTraits, Str, Enum
 
338
    from traitsui.api import View, Group, Item
 
339
    
 
340
    class MixedStyles(HasTraits):
 
341
       first_name = Str
 
342
       last_name = Str
 
343
    
 
344
       department = Enum("Business", "Research", "Admin")
 
345
       position_type = Enum("Full-Time", 
 
346
                            "Part-Time", 
 
347
                            "Contract")
 
348
    
 
349
       traits_view = View(Group(Item(name='first_name'),
 
350
                                Item(name='last_name'),
 
351
                                Group(Item(name='department'),
 
352
                                      Item(name='position_type',
 
353
                                           style='custom'),
 
354
                                      style='simple')),
 
355
                          title='Mixed Styles',
 
356
                          style='readonly')
 
357
    
 
358
    ms = MixedStyles(first_name='Sam', last_name='Smith')
 
359
    ms.configure_traits()
 
360
 
 
361
Notice how the editor styles are set for each attribute:
 
362
 
 
363
- **position_type** at the Item level (lines 19-20)
 
364
- **department** at the Group level (lines 18 and 21)
 
365
- **first_name** and **last_name** at the View level (lines 16, 17, and 23)
 
366
 
 
367
The resulting window demonstrates these precedence rules:
 
368
 
 
369
.. figure:: images/ui_for_ex13.jpg
 
370
   :alt: UI showing read-only text, closed drop-list, and radio buttons
 
371
   
 
372
   Figure 20: User interface for Example 13
 
373
 
 
374
 
 
375
.. rubric:: Footnotes
 
376
 
 
377
.. [15] Appendix II contains a table of the predefined trait types in the 
 
378
   Traits package and their default trait editor types. 
 
379
 
 
380
 
 
381
 
 
382