Statistics
| Branch: | Tag: | Revision:

root / gr-wxgui / src / python / forms / forms.py @ 51af4269

History | View | Annotate | Download (25.1 kB)

1
#
2
# Copyright 2009 Free Software Foundation, Inc.
3
#
4
# This file is part of GNU Radio
5
#
6
# GNU Radio is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3, or (at your option)
9
# any later version.
10
#
11
# GNU Radio is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with GNU Radio; see the file COPYING.  If not, write to
18
# the Free Software Foundation, Inc., 51 Franklin Street,
19
# Boston, MA 02110-1301, USA.
20
#
21
22
"""
23
The forms module contains general purpose wx-gui forms for gnuradio apps.
24
25
The forms follow a layered model:
26
  * internal layer
27
    * deals with the wxgui objects directly
28
    * implemented in event handler and update methods
29
  * translation layer
30
    * translates the between the external and internal layers
31
    * handles parsing errors between layers
32
  * external layer 
33
    * provided external access to the user
34
    * set_value, get_value, and optional callback
35
    * set and get through optional pubsub and key
36
37
Known problems:
38
  * An empty label in the radio box still consumes space.
39
  * The static text cannot resize the parent at runtime.
40
"""
41
42
EXT_KEY = 'external'
43
INT_KEY = 'internal'
44
45
import wx
46
import sys
47
from gnuradio.gr.pubsub import pubsub
48
import converters
49
50
EVT_DATA = wx.PyEventBinder(wx.NewEventType())
51
class DataEvent(wx.PyEvent):
52
        def __init__(self, data):
53
                wx.PyEvent.__init__(self, wx.NewId(), EVT_DATA.typeId)
54
                self.data = data
55
56
def make_bold(widget):
57
        font = widget.GetFont()
58
        font.SetWeight(wx.FONTWEIGHT_BOLD)
59
        widget.SetFont(font)
60
61
########################################################################
62
# Base Class Form
63
########################################################################
64
class _form_base(pubsub, wx.BoxSizer):
65
        def __init__(self, parent=None, sizer=None, proportion=0, flag=wx.EXPAND, ps=None, key='', value=None, callback=None, converter=converters.identity_converter()):
66
                pubsub.__init__(self)
67
                wx.BoxSizer.__init__(self, wx.HORIZONTAL)
68
                self._parent = parent
69
                self._key = key
70
                self._converter = converter
71
                self._callback = callback
72
                self._widgets = list()
73
                #add to the sizer if provided
74
                if sizer: sizer.Add(self, proportion, flag)
75
                #proxy the pubsub and key into this form
76
                if ps is not None:
77
                        assert key
78
                        self.proxy(EXT_KEY, ps, key)
79
                #no pubsub passed, must set initial value
80
                else: self.set_value(value)
81
82
        def __str__(self):
83
                return "Form: %s -> %s"%(self.__class__, self._key)
84
85
        def _add_widget(self, widget, label='', flag=0, label_prop=0, widget_prop=1):
86
                """
87
                Add the main widget to this object sizer.
88
                If label is passed, add a label as well.
89
                Register the widget and the label in the widgets list (for enable/disable).
90
                Bind the update handler to the widget for data events.
91
                This ensures that the gui thread handles updating widgets.
92
                Setup the pusub triggers for external and internal.
93
                @param widget the main widget
94
                @param label the optional label
95
                @param flag additional flags for widget
96
                @param label_prop the proportion for the label
97
                @param widget_prop the proportion for the widget
98
                """
99
                #setup data event
100
                widget.Bind(EVT_DATA, lambda x: self._update(x.data))
101
                update = lambda x: wx.PostEvent(widget, DataEvent(x))
102
                #register widget
103
                self._widgets.append(widget)
104
                #create optional label
105
                if not label: self.Add(widget, widget_prop, wx.ALIGN_CENTER_VERTICAL | flag)
106
                else:
107
                        label_text = wx.StaticText(self._parent, label='%s: '%label)
108
                        self._widgets.append(label_text)
109
                        self.Add(label_text, label_prop, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
110
                        self.Add(widget, widget_prop, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | flag)
111
                #initialize without triggering pubsubs
112
                self._translate_external_to_internal(self[EXT_KEY])
113
                update(self[INT_KEY])
114
                #subscribe all the functions
115
                self.subscribe(INT_KEY, update)
116
                self.subscribe(INT_KEY, self._translate_internal_to_external)
117
                self.subscribe(EXT_KEY, self._translate_external_to_internal)
118
                if self._callback: self.subscribe(EXT_KEY, self._callback)
119
120
        def _translate_external_to_internal(self, external):
121
                try:
122
                        internal = self._converter.external_to_internal(external)
123
                        #prevent infinite loop between internal and external pubsub keys by only setting if changed
124
                        if self[INT_KEY] != internal: self[INT_KEY] = internal
125
                except Exception, e:
126
                        self._err_msg(external, e)
127
                        self[INT_KEY] = self[INT_KEY] #reset to last good setting
128
129
        def _translate_internal_to_external(self, internal):
130
                try:
131
                        external = self._converter.internal_to_external(internal)
132
                        #prevent infinite loop between internal and external pubsub keys by only setting if changed
133
                        if self[EXT_KEY] != external: self[EXT_KEY] = external
134
                except Exception, e:
135
                        self._err_msg(internal, e)
136
                        self[EXT_KEY] = self[EXT_KEY] #reset to last good setting
137
138
        def _err_msg(self, value, e):
139
                print >> sys.stderr, self, 'Error translating value: "%s"\n\t%s\n\t%s'%(value, e, self._converter.help())
140
141
        #override in subclasses to handle the wxgui object
142
        def _update(self, value): raise NotImplementedError
143
        def _handle(self, event): raise NotImplementedError
144
145
        #provide a set/get interface for this form
146
        def get_value(self): return self[EXT_KEY]
147
        def set_value(self, value): self[EXT_KEY] = value
148
149
        def Disable(self, disable=True): self.Enable(not disable)
150
        def Enable(self, enable=True):
151
                if enable:
152
                        for widget in self._widgets: widget.Enable()
153
                else:
154
                        for widget in self._widgets: widget.Disable()
155
156
########################################################################
157
# Base Class Chooser Form
158
########################################################################
159
class _chooser_base(_form_base):
160
        def __init__(self, choices=[], labels=None, **kwargs):
161
                _form_base.__init__(self, converter=converters.chooser_converter(choices), **kwargs)
162
                self._choices = choices
163
                self._labels = map(str, labels or choices)
164
165
########################################################################
166
# Base Class Slider Form
167
########################################################################
168
class _slider_base(_form_base):
169
        def __init__(self, label='', length=-1, converter=None, num_steps=100, style=wx.SL_HORIZONTAL, **kwargs):
170
                _form_base.__init__(self, converter=converter, **kwargs)
171
                if style & wx.SL_HORIZONTAL: slider_size = wx.Size(length, -1)
172
                elif style & wx.SL_VERTICAL: slider_size = wx.Size(-1, length)
173
                else: raise NotImplementedError
174
                self._slider = wx.Slider(self._parent, minValue=0, maxValue=num_steps, size=slider_size, style=style)
175
                self._slider.Bind(wx.EVT_SCROLL, self._handle)
176
                self._add_widget(self._slider, label, flag=wx.EXPAND)
177
178
        def _handle(self, event): self[INT_KEY] = self._slider.GetValue()
179
        def _update(self, value): self._slider.SetValue(value)
180
181
########################################################################
182
# Static Text Form
183
########################################################################
184
class static_text(_form_base):
185
        """
186
        A text box form.
187
        @param parent the parent widget
188
        @param sizer add this widget to sizer if provided (optional)
189
        @param proportion the proportion when added to the sizer (default=0)
190
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
191
        @param ps the pubsub object (optional)
192
        @param key the pubsub key (optional)
193
        @param value the default value (optional)
194
        @param label title label for this widget (optional)
195
        @param width the width of the form in px
196
        @param bold true to bold-ify the text (default=False)
197
        @param converter forms.str_converter(), int_converter(), float_converter()...
198
        """
199
        def __init__(self, label='', width=-1, bold=False, converter=converters.str_converter(), **kwargs):
200
                _form_base.__init__(self, converter=converter, **kwargs)
201
                self._static_text = wx.StaticText(self._parent, size=wx.Size(width, -1))
202
                if bold: make_bold(self._static_text)
203
                self._add_widget(self._static_text, label)
204
205
        def _update(self, label): self._static_text.SetLabel(label); self._parent.Layout()
206
207
########################################################################
208
# Text Box Form
209
########################################################################
210
class text_box(_form_base):
211
        """
212
        A text box form.
213
        @param parent the parent widget
214
        @param sizer add this widget to sizer if provided (optional)
215
        @param proportion the proportion when added to the sizer (default=0)
216
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
217
        @param ps the pubsub object (optional)
218
        @param key the pubsub key (optional)
219
        @param value the default value (optional)
220
        @param label title label for this widget (optional)
221
        @param width the width of the form in px
222
        @param converter forms.str_converter(), int_converter(), float_converter()...
223
        """
224
        def __init__(self, label='', width=-1, converter=converters.eval_converter(), **kwargs):
225
                _form_base.__init__(self, converter=converter, **kwargs)
226
                self._text_box = wx.TextCtrl(self._parent, size=wx.Size(width, -1), style=wx.TE_PROCESS_ENTER)
227
                self._text_box.Bind(wx.EVT_TEXT_ENTER, self._handle)
228
                self._add_widget(self._text_box, label)
229
230
        def _handle(self, event): self[INT_KEY] = self._text_box.GetValue()
231
        def _update(self, value): self._text_box.SetValue(value)
232
233
########################################################################
234
# Slider Form
235
#  Linear Slider
236
#  Logarithmic Slider
237
########################################################################
238
class slider(_slider_base):
239
        """
240
        A generic linear slider.
241
        @param parent the parent widget
242
        @param sizer add this widget to sizer if provided (optional)
243
        @param proportion the proportion when added to the sizer (default=0)
244
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
245
        @param ps the pubsub object (optional)
246
        @param key the pubsub key (optional)
247
        @param value the default value (optional)
248
        @param label title label for this widget (optional)
249
        @param length the length of the slider in px (optional)
250
        @param style wx.SL_HORIZONTAL or wx.SL_VERTICAL (default=horizontal)
251
        @param minimum the minimum value
252
        @param maximum the maximum value
253
        @param num_steps the number of slider steps (or specify step_size)
254
        @param step_size the step between slider jumps (or specify num_steps)
255
        @param cast a cast function, int, or float (default=float)
256
        """
257
        def __init__(self, minimum=-100, maximum=100, num_steps=100, step_size=None, cast=float, **kwargs):
258
                assert step_size or num_steps
259
                if step_size is not None: num_steps = (maximum - minimum)/step_size
260
                converter = converters.slider_converter(minimum=minimum, maximum=maximum, num_steps=num_steps, cast=cast)
261
                _slider_base.__init__(self, converter=converter, num_steps=num_steps, **kwargs)
262
263
class log_slider(_slider_base):
264
        """
265
        A generic logarithmic slider.
266
        The sliders min and max values are base**min_exp and base**max_exp.
267
        @param parent the parent widget
268
        @param sizer add this widget to sizer if provided (optional)
269
        @param proportion the proportion when added to the sizer (default=0)
270
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
271
        @param ps the pubsub object (optional)
272
        @param key the pubsub key (optional)
273
        @param value the default value (optional)
274
        @param label title label for this widget (optional)
275
        @param length the length of the slider in px (optional)
276
        @param style wx.SL_HORIZONTAL or wx.SL_VERTICAL (default=horizontal)
277
        @param min_exp the minimum exponent
278
        @param max_exp the maximum exponent
279
        @param base the exponent base in base**exp
280
        @param num_steps the number of slider steps (or specify step_size)
281
        @param step_size the exponent step size (or specify num_steps)
282
        """
283
        def __init__(self, min_exp=0, max_exp=1, base=10, num_steps=100, step_size=None, **kwargs):
284
                assert step_size or num_steps
285
                if step_size is not None: num_steps = (max_exp - min_exp)/step_size
286
                converter = converters.log_slider_converter(min_exp=min_exp, max_exp=max_exp, num_steps=num_steps, base=base)
287
                _slider_base.__init__(self, converter=converter, num_steps=num_steps, **kwargs)
288
289
########################################################################
290
# Gauge Form
291
########################################################################
292
class gauge(_form_base):
293
        """
294
        A gauge bar.
295
        The gauge displays floating point values between the minimum and maximum.
296
        @param parent the parent widget
297
        @param sizer add this widget to sizer if provided (optional)
298
        @param proportion the proportion when added to the sizer (default=0)
299
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
300
        @param ps the pubsub object (optional)
301
        @param key the pubsub key (optional)
302
        @param value the default value (optional)
303
        @param label title label for this widget (optional)
304
        @param length the length of the slider in px (optional)
305
        @param style wx.GA_HORIZONTAL or wx.GA_VERTICAL (default=horizontal)
306
        @param minimum the minimum value
307
        @param maximum the maximum value
308
        @param num_steps the number of slider steps (or specify step_size)
309
        @param step_size the step between slider jumps (or specify num_steps)
310
        """
311
        def __init__(self, label='', length=-1, minimum=-100, maximum=100, num_steps=100, step_size=None, style=wx.GA_HORIZONTAL, **kwargs):
312
                assert step_size or num_steps
313
                if step_size is not None: num_steps = (maximum - minimum)/step_size
314
                converter = converters.slider_converter(minimum=minimum, maximum=maximum, num_steps=num_steps, cast=float)
315
                _form_base.__init__(self, converter=converter, **kwargs)
316
                if style & wx.SL_HORIZONTAL: gauge_size = wx.Size(length, -1)
317
                elif style & wx.SL_VERTICAL: gauge_size = wx.Size(-1, length)
318
                else: raise NotImplementedError
319
                self._gauge = wx.Gauge(self._parent, range=num_steps, size=gauge_size, style=style)
320
                self._add_widget(self._gauge, label, flag=wx.EXPAND)
321
322
        def _update(self, value): self._gauge.SetValue(value)
323
324
########################################################################
325
# Check Box Form
326
########################################################################
327
class check_box(_form_base):
328
        """
329
        Create a check box form.
330
        @param parent the parent widget
331
        @param sizer add this widget to sizer if provided (optional)
332
        @param proportion the proportion when added to the sizer (default=0)
333
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
334
        @param ps the pubsub object (optional)
335
        @param key the pubsub key (optional)
336
        @param value the default value (optional)
337
        @param true the value for form when checked (default=True)
338
        @param false the value for form when unchecked (default=False)
339
        @param label title label for this widget (optional)
340
        """
341
        def __init__(self, label='', true=True, false=False, **kwargs):
342
                _form_base.__init__(self, converter=converters.bool_converter(true=true, false=false), **kwargs)
343
                self._check_box = wx.CheckBox(self._parent, style=wx.CHK_2STATE, label=label)
344
                self._check_box.Bind(wx.EVT_CHECKBOX, self._handle)
345
                self._add_widget(self._check_box)
346
347
        def _handle(self, event): self[INT_KEY] = self._check_box.IsChecked()
348
        def _update(self, checked): self._check_box.SetValue(checked)
349
350
########################################################################
351
# Drop Down Chooser Form
352
########################################################################
353
class drop_down(_chooser_base):
354
        """
355
        Create a drop down menu form.
356
        @param parent the parent widget
357
        @param sizer add this widget to sizer if provided (optional)
358
        @param proportion the proportion when added to the sizer (default=0)
359
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
360
        @param ps the pubsub object (optional)
361
        @param key the pubsub key (optional)
362
        @param value the default value (optional)
363
        @param choices list of possible values
364
        @param labels list of labels for each choice (default=choices)
365
        @param label title label for this widget (optional)
366
        @param width the form width in px (optional)
367
        """
368
        def __init__(self, label='', width=-1, **kwargs):
369
                _chooser_base.__init__(self, **kwargs)
370
                self._drop_down = wx.Choice(self._parent, choices=self._labels, size=wx.Size(width, -1))
371
                self._drop_down.Bind(wx.EVT_CHOICE, self._handle)
372
                self._add_widget(self._drop_down, label, widget_prop=0, label_prop=1)
373
374
        def _handle(self, event): self[INT_KEY] = self._drop_down.GetSelection()
375
        def _update(self, i): self._drop_down.SetSelection(i)
376
377
########################################################################
378
# Button Chooser Form
379
#  Circularly move through the choices with each click.
380
#  Can be a single-click button with one choice.
381
#  Can be a 2-state button with two choices.
382
########################################################################
383
class button(_chooser_base):
384
        """
385
        Create a multi-state button.
386
        @param parent the parent widget
387
        @param sizer add this widget to sizer if provided (optional)
388
        @param proportion the proportion when added to the sizer (default=0)
389
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
390
        @param ps the pubsub object (optional)
391
        @param key the pubsub key (optional)
392
        @param value the default value (optional)
393
        @param choices list of possible values
394
        @param labels list of labels for each choice (default=choices)
395
        @param width the width of the button in pixels (optional)
396
        @param style style arguments (optional)
397
        @param label title label for this widget (optional)
398
        """
399
        def __init__(self, label='', style=0, width=-1, **kwargs):
400
                _chooser_base.__init__(self, **kwargs)
401
                self._button = wx.Button(self._parent, size=wx.Size(width, -1), style=style)
402
                self._button.Bind(wx.EVT_BUTTON, self._handle)
403
                self._add_widget(self._button, label, widget_prop=((not style&wx.BU_EXACTFIT) and 1 or 0))
404
405
        def _handle(self, event): self[INT_KEY] = (self[INT_KEY] + 1)%len(self._choices) #circularly increment index
406
        def _update(self, i): self._button.SetLabel(self._labels[i]); self.Layout()
407
408
class toggle_button(button):
409
        """
410
        Create a dual-state button.
411
        This button will alternate between True and False when clicked.
412
        @param parent the parent widget
413
        @param sizer add this widget to sizer if provided (optional)
414
        @param proportion the proportion when added to the sizer (default=0)
415
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
416
        @param ps the pubsub object (optional)
417
        @param key the pubsub key (optional)
418
        @param value the default value (optional)
419
        @param width the width of the button in pixels (optional)
420
        @param style style arguments (optional)
421
        @param true_label the button's label in the true state
422
        @param false_label the button's label in the false state
423
        """
424
        def __init__(self, true_label='On (click to stop)', false_label='Off (click to start)', **kwargs):
425
                button.__init__(self, choices=[True, False], labels=[true_label, false_label], **kwargs)
426
427
class single_button(toggle_button):
428
        """
429
        Create a single state button.
430
        This button will callback() when clicked.
431
        For use when state holding is not important.
432
        @param parent the parent widget
433
        @param sizer add this widget to sizer if provided (optional)
434
        @param proportion the proportion when added to the sizer (default=0)
435
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
436
        @param ps the pubsub object (optional)
437
        @param key the pubsub key (optional)
438
        @param value the default value (optional)
439
        @param width the width of the button in pixels (optional)
440
        @param style style arguments (optional)
441
        @param label the button's label
442
        """
443
        def __init__(self, label='click for callback', **kwargs):
444
                toggle_button.__init__(self, true_label=label, false_label=label, value=True, **kwargs)
445
446
########################################################################
447
# Radio Buttons Chooser Form
448
########################################################################
449
class radio_buttons(_chooser_base):
450
        """
451
        Create a radio button form.
452
        @param parent the parent widget
453
        @param sizer add this widget to sizer if provided (optional)
454
        @param proportion the proportion when added to the sizer (default=0)
455
        @param flag the flag argument when added to the sizer (default=wx.EXPAND)
456
        @param ps the pubsub object (optional)
457
        @param key the pubsub key (optional)
458
        @param value the default value (optional)
459
        @param choices list of possible values
460
        @param labels list of labels for each choice (default=choices)
461
        @param major_dimension the number of rows/cols (default=auto)
462
        @param label title label for this widget (optional)
463
        @param style useful style args: wx.RA_HORIZONTAL, wx.RA_VERTICAL, wx.NO_BORDER (default=wx.RA_HORIZONTAL)
464
        """
465
        def __init__(self, style=wx.RA_HORIZONTAL, label='', major_dimension=0, **kwargs):
466
                _chooser_base.__init__(self, **kwargs)
467
                #create radio buttons
468
                self._radio_buttons = wx.RadioBox(self._parent, choices=self._labels, style=style, label=label, majorDimension=major_dimension)
469
                self._radio_buttons.Bind(wx.EVT_RADIOBOX, self._handle)
470
                self._add_widget(self._radio_buttons)
471
472
        def _handle(self, event): self[INT_KEY] = self._radio_buttons.GetSelection()
473
        def _update(self, i): self._radio_buttons.SetSelection(i)
474
475
########################################################################
476
# Notebook Chooser Form
477
#  The notebook pages/tabs are for selecting between choices.
478
#  A page must be added to the notebook for each choice.
479
########################################################################
480
class notebook(_chooser_base):
481
        def __init__(self, pages, notebook, **kwargs):
482
                _chooser_base.__init__(self, **kwargs)
483
                assert len(pages) == len(self._choices)
484
                self._notebook = notebook
485
                self._notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._handle)
486
                #add pages, setting the label on each tab
487
                for i, page in enumerate(pages):
488
                        self._notebook.AddPage(page, self._labels[i])
489
                self._add_widget(self._notebook)
490
491
        def _handle(self, event): self[INT_KEY] = self._notebook.GetSelection()
492
        def _update(self, i): self._notebook.SetSelection(i)
493
494
# ----------------------------------------------------------------
495
# Stand-alone test application
496
# ----------------------------------------------------------------
497
498
import wx
499
from gnuradio.wxgui import gui
500
501
class app_gui (object):
502
    def __init__(self, frame, panel, vbox, top_block, options, args):
503
        
504
        def callback(v): print v
505
       
506
        radio_buttons(
507
            sizer=vbox,
508
            parent=panel,
509
            choices=[2, 4, 8, 16],
510
            labels=['two', 'four', 'eight', 'sixteen'],
511
            value=4,
512
            style=wx.RA_HORIZONTAL,
513
            label='test radio long string',
514
            callback=callback,
515
            #major_dimension = 2,
516
        )
517
        
518
        radio_buttons(
519
            sizer=vbox,
520
            parent=panel,
521
            choices=[2, 4, 8, 16],
522
            labels=['two', 'four', 'eight', 'sixteen'],
523
            value=4,
524
            style=wx.RA_VERTICAL,
525
            label='test radio long string',
526
            callback=callback,
527
            #major_dimension = 2,
528
        )
529
        
530
        radio_buttons(
531
            sizer=vbox,
532
            parent=panel,
533
            choices=[2, 4, 8, 16],
534
            labels=['two', 'four', 'eight', 'sixteen'],
535
            value=4,
536
            style=wx.RA_VERTICAL | wx.NO_BORDER,
537
            callback=callback,
538
            #major_dimension = 2,
539
        )
540
        
541
        button(
542
            sizer=vbox,
543
            parent=panel,
544
            choices=[2, 4, 8, 16],
545
            labels=['two', 'four', 'eight', 'sixteen'],
546
            value=2,
547
            label='button value',
548
            callback=callback,
549
            #width=100,
550
        )
551
        
552
        
553
        drop_down(
554
            sizer=vbox,
555
            parent=panel,
556
            choices=[2, 4, 8, 16],
557
            value=2,
558
            label='Choose One',
559
            callback=callback,
560
        )
561
        check_box(
562
            sizer=vbox,
563
            parent=panel,
564
            value=False,
565
            label='check me',
566
            callback=callback,
567
        )
568
        text_box(
569
            sizer=vbox,
570
            parent=panel,
571
            value=3,
572
            label='text box',
573
            callback=callback,
574
            width=200,
575
        )
576
        
577
        static_text(
578
            sizer=vbox,
579
            parent=panel,
580
            value='bob',
581
            label='static text',
582
            width=-1,
583
            bold=True,
584
        )
585
        
586
        slider(
587
            sizer=vbox,
588
            parent=panel,
589
            value=12,
590
            label='slider',
591
            callback=callback,
592
        )
593
        
594
        log_slider(
595
            sizer=vbox,
596
            parent=panel,
597
            value=12,
598
            label='slider',
599
            callback=callback,
600
        )
601
        
602
        slider(
603
            sizer=vbox,
604
            parent=panel,
605
            value=12,
606
            label='slider',
607
            callback=callback,
608
            style=wx.SL_VERTICAL,
609
            length=30,
610
        )
611
               
612
        toggle_button(
613
            sizer=vbox,
614
            parent=panel,
615
            value=True,
616
            label='toggle it',
617
            callback=callback,
618
        )
619
        
620
        single_button(
621
            sizer=vbox,
622
            parent=panel,
623
            label='sig test',
624
            callback=callback,
625
        )
626
627
if __name__ == "__main__":
628
    try:
629
630
        # Create the GUI application
631
        app = gui.app(
632
                      gui=app_gui,                     # User interface class
633
                      title="Test Forms",  # Top window title
634
                      )
635
636
        # And run it
637
        app.MainLoop()
638
639
    except RuntimeError, e:
640
        print e
641
        sys.exit(1)