1#!/usr/bin/env python
2
3import sys
4import traceback
5
6import wx
7import wx.lib.masked as masked
8import wx.lib.scrolledpanel as scroll
9
10
11class demoMixin:
12    """
13    Centralized routines common to demo pages, to remove repetition.
14    """
15    def labelGeneralTable(self, sizer):
16        description = wx.StaticText( self, -1, "Description", )
17        mask        = wx.StaticText( self, -1, "Mask Value" )
18        formatcode  = wx.StaticText( self, -1, "Format" )
19        regex       = wx.StaticText( self, -1, "Regexp Validator(opt.)" )
20        ctrl        = wx.StaticText( self, -1, "Masked TextCtrl" )
21
22        description.SetFont( wx.Font(9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
23        mask.SetFont( wx.Font(9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
24        formatcode.SetFont( wx.Font(9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) )
25        regex.SetFont( wx.Font(9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
26        ctrl.SetFont( wx.Font(9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))
27
28        sizer.Add(description)
29        sizer.Add(mask)
30        sizer.Add(formatcode)
31        sizer.Add(regex)
32        sizer.Add(ctrl)
33
34
35    def layoutGeneralTable(self, controls, sizer):
36        for control in controls:
37            sizer.Add( wx.StaticText( self, -1, control[0]) )
38            sizer.Add( wx.StaticText( self, -1, control[1]) )
39            sizer.Add( wx.StaticText( self, -1, control[3]) )
40            sizer.Add( wx.StaticText( self, -1, control[4]) )
41
42            if control in controls:
43                newControl  = masked.TextCtrl( self, -1, "",
44                                                mask         = control[1],
45                                                excludeChars = control[2],
46                                                formatcodes  = control[3],
47                                                includeChars = "",
48                                                validRegex   = control[4],
49                                                validRange   = control[5],
50                                                choices      = control[6],
51                                                choiceRequired = True,
52                                                defaultValue = control[7],
53                                                demo         = True,
54                                                name         = control[0])
55            self.editList.append(newControl)
56            sizer.Add(newControl)
57
58
59    def changeControlParams(self, event, parameter, checked_value, notchecked_value):
60        if event.IsChecked(): value = checked_value
61        else:               value = notchecked_value
62
63        kwargs = {parameter: value}
64
65        for control in self.editList:
66            control.SetCtrlParameters(**kwargs)
67            control.Refresh()
68
69        self.Refresh()
70
71
72
73#----------------------------------------------------------------------------
74class demoPage1(scroll.ScrolledPanel, demoMixin):
75    def __init__(self, parent, log):
76        scroll.ScrolledPanel.__init__(self, parent, -1)
77        self.sizer = wx.BoxSizer( wx.VERTICAL )
78        self.editList  = []
79
80        label = wx.StaticText( self, -1, """\
81Here are some basic masked TextCtrls to give you an idea of what you can do
82with this control.  Note that all controls have been auto-sized by including 'F' in
83the format codes.
84
85Try entering nonsensical or partial values in validated fields to see what happens.
86Note that the State and Last Name fields are list-limited (valid last names are:
87Smith, Jones, Williams).  Signs on numbers can be toggled with the minus key.
88""")
89        label.SetForegroundColour( "Blue" )
90        header = wx.BoxSizer( wx.HORIZONTAL )
91        header.Add( label, 0, flag=wx.ALIGN_LEFT|wx.ALL, border = 5 )
92
93        highlight = wx.CheckBox( self, -1, "Highlight Empty" )
94        disallow =  wx.CheckBox( self, -1, "Disallow Empty" )
95        showFill = wx.CheckBox( self, -1, "change fillChar" )
96
97        vbox = wx.BoxSizer( wx.VERTICAL )
98        vbox.Add( highlight, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
99        vbox.Add( disallow, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
100        vbox.Add( showFill, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
101        header.Add((15, 0))
102        header.Add(vbox, 0, flag=wx.ALIGN_LEFT|wx.ALL, border=5 )
103
104        self.Bind(wx.EVT_CHECKBOX, self.onHighlightEmpty, id=highlight.GetId())
105        self.Bind(wx.EVT_CHECKBOX, self.onDisallowEmpty, id=disallow.GetId())
106        self.Bind(wx.EVT_CHECKBOX, self.onShowFill, id=showFill.GetId())
107
108        grid = wx.FlexGridSizer( cols=5, vgap=10, hgap=10 )
109        self.labelGeneralTable(grid)
110
111        # The following list is of the controls for the demo. Feel free to play around with
112        # the options!
113        controls = [
114        #description        mask                    excl format     regexp                              range,list,initial
115       ("Phone No",         "(###) ###-#### x:###", "", 'F^-',     "^\(\d{3}\) \d{3}-\d{4}",           '','',''),
116       ("Social Sec#",      "###-##-####",          "", 'F',        "\d{3}-\d{2}-\d{4}",                '','',''),
117       ("Full Name",        "C{14}",                "", 'F_',       '^[A-Z][a-zA-Z]+ [A-Z][a-zA-Z]+',   '','',''),
118       ("Last Name Only",   "C{14}",                "", 'F {list}', '^[A-Z][a-zA-Z]+',                  '',('Smith','Jones','Williams'),''),
119       ("Zip plus 4",       "#{5}-#{4}",            "", 'F',        "\d{5}-(\s{4}|\d{4})",              '','',''),
120       ("Customer No",      "\CAA-###",             "", 'F!',       "C[A-Z]{2}-\d{3}",                  '','',''),
121       ("Invoice Total",    "#{9}.##",              "", 'F-_,',     "",                                 '','',''),
122       ("Integer",          "#{9}",                 "", 'F-_',      "",                                 '','',''),
123       ]
124
125        self.layoutGeneralTable(controls, grid)
126        self.sizer.Add( header, 0, flag=wx.ALIGN_LEFT|wx.ALL, border=5 )
127        self.sizer.Add( grid, 0, flag= wx.ALIGN_LEFT|wx.LEFT, border=5 )
128        self.SetSizer(self.sizer)
129        self.SetupScrolling()
130        self.SetAutoLayout(1)
131
132
133    def onDisallowEmpty( self, event ):
134        """ Set emptyInvalid parameter on/off """
135        self.changeControlParams( event, "emptyInvalid", True, False )
136
137    def onHighlightEmpty( self, event ):
138        """ Highlight empty values"""
139        self.changeControlParams( event, "emptyBackgroundColour", "Blue", "White" )
140
141    def onShowFill( self, event ):
142        """ Set fillChar parameter to '?' or ' ' """
143        self.changeControlParams( event, "fillChar", '?', ' ' )
144
145
146class demoPage2(scroll.ScrolledPanel, demoMixin):
147    def __init__( self, parent, log ):
148        self.log = log
149        scroll.ScrolledPanel.__init__( self, parent, -1 )
150        self.sizer = wx.BoxSizer( wx.VERTICAL )
151
152        label = wx.StaticText( self, -1, """\
153All these controls have been created by passing a single parameter, the autoformat code,
154and use the factory class masked.Ctrl with its default controlType.
155The masked package contains an internal dictionary of types and formats (autoformats).
156Many of these already do complicated validation; To see some examples, try
15729 Feb 2002 vs. 2004 for the date formats, or email address validation.
158""")
159
160        label.SetForegroundColour( "Blue" )
161        self.sizer.Add( label, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
162
163        description = wx.StaticText( self, -1, "Description")
164        autofmt     = wx.StaticText( self, -1, "AutoFormat Code")
165        ctrl        = wx.StaticText( self, -1, "Masked Ctrl")
166
167        description.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
168        autofmt.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
169        ctrl.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
170
171        grid = wx.FlexGridSizer( cols=3, vgap=10, hgap=5 )
172        grid.Add( description, 0, wx.ALIGN_LEFT )
173        grid.Add( autofmt,     0, wx.ALIGN_LEFT )
174        grid.Add( ctrl,        0, wx.ALIGN_LEFT )
175
176        for autoformat, desc in masked.autoformats:
177            grid.Add( wx.StaticText( self, -1, desc), 0, wx.ALIGN_LEFT )
178            grid.Add( wx.StaticText( self, -1, autoformat), 0, wx.ALIGN_LEFT )
179            grid.Add( masked.Ctrl( self, -1, "",
180                                    autoformat       = autoformat,
181                                    demo             = True,
182                                    name             = autoformat),
183                            0, wx.ALIGN_LEFT )
184
185        self.sizer.Add( grid, 0, wx.ALIGN_LEFT|wx.ALL, border=5 )
186        self.SetSizer( self.sizer )
187        self.SetAutoLayout( 1 )
188        self.SetupScrolling()
189
190
191class demoPage3(scroll.ScrolledPanel, demoMixin):
192    def __init__(self, parent, log):
193        self.log = log
194        scroll.ScrolledPanel.__init__(self, parent, -1)
195        self.sizer = wx.BoxSizer( wx.VERTICAL )
196        self.editList  = []
197
198        label = wx.StaticText( self, -1, """\
199Here masked TextCtrls that have default values.  The states
200control has a list of valid values, and the unsigned integer
201has a legal range specified.
202""")
203        label.SetForegroundColour( "Blue" )
204        requireValid =  wx.CheckBox( self, -1, "Require Valid Value" )
205        self.Bind(wx.EVT_CHECKBOX, self.onRequireValid, id=requireValid.GetId())
206
207        header = wx.BoxSizer( wx.HORIZONTAL )
208        header.Add( label, 0, flag=wx.ALIGN_LEFT|wx.ALL, border = 5)
209        header.Add((75, 0))
210        header.Add( requireValid, 0, flag=wx.ALIGN_LEFT|wx.ALL, border=10 )
211
212        grid = wx.FlexGridSizer( cols=5, vgap=10, hgap=10 )
213        self.labelGeneralTable( grid )
214
215        controls = [
216        #description        mask                    excl format     regexp                              range,list,initial
217       ("U.S. State (2 char)",      "AA",            "", 'F!_',       "[A-Z]{2}",                         '', masked.states, masked.states[0]),
218       ("Integer (signed)",         "#{6}",          "", 'F-_',       "",                                 '','', ' 0    '),
219       ("Integer (unsigned)\n(1-399)","######",      "", 'F_',        "",                                 (1,399),'', '1     '),
220       ("Float (signed)",           "#{6}.#{9}",     "", 'F-_R',      "",                                 '','', '000000.000000000'),
221       ("Date (MDY) + Time",        "##/##/#### ##:##:## AM",  'BCDEFGHIJKLMNOQRSTUVWXYZ','DF!',"",          '','', wx.DateTime.Now().Format("%m/%d/%Y %I:%M:%S %p")),
222       ]
223        self.layoutGeneralTable( controls, grid )
224
225        self.sizer.Add( header, 0, flag=wx.ALIGN_LEFT|wx.ALL, border=5 )
226        self.sizer.Add( grid, 0, flag=wx.ALIGN_LEFT|wx.ALL, border=5 )
227
228        self.SetSizer( self.sizer )
229        self.SetAutoLayout( 1 )
230        self.SetupScrolling()
231
232    def onRequireValid( self, event ):
233        """ Set validRequired parameter on/off """
234        self.changeControlParams( event, "validRequired", True, False )
235
236
237class demoPage4(scroll.ScrolledPanel, demoMixin):
238    def __init__( self, parent, log ):
239        self.log = log
240        scroll.ScrolledPanel.__init__( self, parent, -1 )
241        self.sizer = wx.BoxSizer( wx.VERTICAL )
242
243        label = wx.StaticText( self, -1, """\
244These controls have field-specific choice lists and allow autocompletion.
245
246Down arrow or Page Down in an uncompleted field with an auto-completable field will attempt
247to auto-complete a field if it has a choice list.
248Page Down and Shift-Down arrow will also auto-complete, or cycle through the complete list.
249Page Up and Shift-Up arrow will similarly cycle backwards through the list.
250""")
251
252        label.SetForegroundColour( "Blue" )
253        self.sizer.Add( label, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
254
255        description  = wx.StaticText( self, -1, "Description" )
256        autofmt      = wx.StaticText( self, -1, "AutoFormat Code" )
257        fields       = wx.StaticText( self, -1, "Field Objects" )
258        ctrl         = wx.StaticText( self, -1, "Masked TextCtrl" )
259
260        description.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
261        autofmt.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
262        fields.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
263        ctrl.SetFont( wx.Font( 9, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ) )
264
265        grid = wx.FlexGridSizer( cols=4, vgap=10, hgap=10 )
266        grid.Add( description, 0, wx.ALIGN_LEFT )
267        grid.Add( autofmt,     0, wx.ALIGN_LEFT )
268        grid.Add( fields,      0, wx.ALIGN_LEFT )
269        grid.Add( ctrl,        0, wx.ALIGN_LEFT )
270
271        autoformat = "USPHONEFULLEXT"
272        fieldsDict = {0: masked.Field(choices=["617","781","508","978","413"], choiceRequired=True)}
273        fieldsLabel = """\
274{0: Field(choices=[
275            "617","781",
276            "508","978","413"],
277          choiceRequired=True)}"""
278        grid.Add( wx.StaticText( self, -1, "Restricted Area Code"), 0, wx.ALIGN_LEFT )
279        grid.Add( wx.StaticText( self, -1, autoformat), 0, wx.ALIGN_LEFT )
280        grid.Add( wx.StaticText( self, -1, fieldsLabel), 0, wx.ALIGN_LEFT )
281        grid.Add( masked.TextCtrl( self, -1, "",
282                                    autoformat       = autoformat,
283                                    fields           = fieldsDict,
284                                    demo             = True,
285                                    name             = autoformat),
286                  0, wx.ALIGN_LEFT )
287
288        autoformat = "EXPDATEMMYY"
289        fieldsDict = {1: masked.Field(choices=["03", "04", "05"], choiceRequired=True)}
290        fieldsLabel = """\
291{1: Field(choices=[
292            "03", "04", "05"],
293          choiceRequired=True)}"""
294        exp =  masked.TextCtrl( self, -1, "",
295                                 autoformat       = autoformat,
296                                 fields           = fieldsDict,
297                                 demo             = True,
298                                 name             = autoformat)
299
300        grid.Add( wx.StaticText( self, -1, "Restricted Expiration"), 0, wx.ALIGN_LEFT )
301        grid.Add( wx.StaticText( self, -1, autoformat), 0, wx.ALIGN_LEFT )
302        grid.Add( wx.StaticText( self, -1, fieldsLabel), 0, wx.ALIGN_LEFT )
303        grid.Add( exp, 0, wx.ALIGN_LEFT )
304
305        fieldsDict = {0: masked.Field(choices=["02134","02155"], choiceRequired=True),
306                      1: masked.Field(choices=["1234", "5678"],  choiceRequired=False)}
307        fieldsLabel = """\
308{0: Field(choices=["02134","02155"],
309          choiceRequired=True),
310 1: Field(choices=["1234", "5678"],
311          choiceRequired=False)}"""
312        autoformat = "USZIPPLUS4"
313        zip =  masked.TextCtrl( self, -1, "",
314                                 autoformat       = autoformat,
315                                 fields           = fieldsDict,
316                                 demo             = True,
317                                 name             = autoformat)
318
319        grid.Add( wx.StaticText( self, -1, "Restricted Zip + 4"), 0, wx.ALIGN_LEFT )
320        grid.Add( wx.StaticText( self, -1, autoformat), 0, wx.ALIGN_LEFT )
321        grid.Add( wx.StaticText( self, -1, fieldsLabel), 0, wx.ALIGN_LEFT )
322        grid.Add( zip, 0, wx.ALIGN_LEFT )
323
324        self.sizer.Add( grid, 0, wx.ALIGN_LEFT|wx.ALL, border=5 )
325        self.SetSizer( self.sizer )
326        self.SetAutoLayout(1)
327        self.SetupScrolling()
328
329
330class demoPage5(scroll.ScrolledPanel, demoMixin):
331    def __init__( self, parent, log ):
332        self.log = log
333        scroll.ScrolledPanel.__init__( self, parent, -1 )
334        self.sizer = wx.BoxSizer( wx.VERTICAL )
335
336
337        labelMaskedCombos = wx.StaticText( self, -1, """\
338These are some examples of masked.ComboBox:""")
339        labelMaskedCombos.SetForegroundColour( "Blue" )
340
341
342        label_statecode = wx.StaticText( self, -1, """\
343A state selector; only
344"legal" values can be
345entered:""")
346        statecode = masked.ComboBox( self, -1, masked.states[0],
347                                  choices = masked.states,
348                                  autoformat="USSTATE")
349
350        label_statename = wx.StaticText( self, -1, """\
351A state name selector,
352with auto-select:""")
353
354        # Create this one using factory function:
355        statename = masked.Ctrl( self, -1, masked.state_names[0],
356                                  controlType = masked.controlTypes.COMBO,
357                                  choices = masked.state_names,
358                                  autoformat="USSTATENAME",
359                                  autoSelect=True)
360        statename.SetCtrlParameters(formatcodes = 'F!V_')
361
362
363        numerators = [ str(i) for i in range(1, 4) ]
364        denominators = [ str(i).ljust(2) for i in [2,3,4,5,8,16,32,64] ]
365        fieldsDict = {0: masked.Field(choices=numerators, choiceRequired=False),
366                      1: masked.Field(choices=denominators, choiceRequired=True)}
367        choices = []
368        for n in numerators:
369            for d in denominators:
370                if n != d:
371                    choices.append( '%s/%s' % (n,d) )
372
373
374        label_fraction = wx.StaticText( self, -1, """\
375A masked ComboBox for fraction selection.
376Choices for each side of the fraction can
377be selected with PageUp/Down:""")
378
379        fraction = masked.Ctrl( self, -1, "",
380                                 controlType = masked.controlTypes.COMBO,
381                                 choices = choices,
382                                 choiceRequired = True,
383                                 mask = "#/##",
384                                 formatcodes = "F_",
385                                 validRegex = "^\d\/\d\d?",
386                                 fields = fieldsDict )
387
388
389        label_code = wx.StaticText( self, -1, """\
390A masked ComboBox to validate
391text from a list of numeric codes:""")
392
393        choices = ["91", "136", "305", "4579"]
394        code = masked.ComboBox( self, -1, choices[0],
395                                 choices = choices,
396                                 choiceRequired = True,
397                                 formatcodes = "F_r",
398                                 mask = "####")
399
400        label_selector = wx.StaticText( self, -1, """\
401Programmatically set
402choice sets:""")
403        self.list_selector = wx.ComboBox(self, -1, '', choices = ['list1', 'list2', 'list3'])
404        self.dynamicbox = masked.Ctrl( self, -1, '    ',
405                                      controlType = masked.controlTypes.COMBO,
406                                      mask =    'XXXX',
407                                      formatcodes = 'F_',
408                                      # these are to give dropdown some initial height,
409                                      # as base control apparently only sets that size
410                                      # during initial construction <sigh>:
411                                      choices = ['', '1', '2', '3', '4', '5'] )
412
413        self.dynamicbox.Clear()   # get rid of initial choices used to size the dropdown
414
415
416        labelIpAddrs = wx.StaticText( self, -1, """\
417Here are some examples of IpAddrCtrl, a control derived from masked.TextCtrl:""")
418        labelIpAddrs.SetForegroundColour( "Blue" )
419
420
421        label_ipaddr1 = wx.StaticText( self, -1, "An empty control:")
422        ipaddr1 = masked.IpAddrCtrl( self, -1, style = wx.TE_PROCESS_TAB )
423
424
425        label_ipaddr2 = wx.StaticText( self, -1, "A restricted mask:")
426        ipaddr2 = masked.IpAddrCtrl( self, -1, mask=" 10.  1.109.###" )
427
428
429        label_ipaddr3 = wx.StaticText( self, -1, """\
430A control with restricted legal values:
43110. (1|2) . (129..255) . (0..255)""")
432        ipaddr3 = masked.Ctrl( self, -1,
433                                controlType = masked.controlTypes.IPADDR,
434                                mask=" 10.  #.###.###")
435        ipaddr3.SetFieldParameters(0, validRegex="1|2",validRequired=False )   # requires entry to match or not allowed
436
437        # This allows any value in penultimate field, but colors anything outside of the range invalid:
438        ipaddr3.SetFieldParameters(1, validRange=(129,255), validRequired=False )
439
440
441
442        labelNumerics = wx.StaticText( self, -1, """\
443Here are some useful configurations of a masked.TextCtrl for integer and floating point input that still treat
444the control as a text control.  (For a true numeric control, check out the masked.NumCtrl class!)""")
445        labelNumerics.SetForegroundColour( "Blue" )
446
447        label_intctrl1 = wx.StaticText( self, -1, """\
448An integer entry control with
449shifting insert enabled:""")
450        self.intctrl1 = masked.TextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-,F>')
451        label_intctrl2 = wx.StaticText( self, -1, """\
452     Right-insert integer entry:""")
453        self.intctrl2 = masked.TextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-,Fr')
454
455        label_floatctrl = wx.StaticText( self, -1, """\
456A floating point entry control
457with right-insert for ordinal:""")
458        self.floatctrl = masked.TextCtrl(self, -1, name='floatctrl', mask="#{9}.#{2}", formatcodes="F,_-R", useParensForNegatives=False)
459        self.floatctrl.SetFieldParameters(0, formatcodes='r<', validRequired=True)  # right-insert, require explicit cursor movement to change fields
460        self.floatctrl.SetFieldParameters(1, defaultValue='00')                     # don't allow blank fraction
461
462        label_numselect = wx.StaticText( self, -1, """\
463<= Programmatically set the value
464     of the float entry ctrl:""")
465        numselect = wx.ComboBox(self, -1, choices = [ '', '111', '222.22', '-3', '54321.666666666', '-1353.978',
466                                                     '1234567', '-1234567', '123456789', '-123456789.1',
467                                                     '1234567890.', '-1234567890.1' ])
468
469        parens_check = wx.CheckBox(self, -1, "Use () to indicate negatives in above controls")
470
471
472
473        gridCombos = wx.FlexGridSizer( cols=4, vgap=10, hgap = 10 )
474        gridCombos.Add( label_statecode, 0, wx.ALIGN_LEFT )
475        gridCombos.Add( statecode, 0, wx.ALIGN_LEFT )
476        gridCombos.Add( label_fraction, 0, wx.ALIGN_LEFT )
477        gridCombos.Add( fraction, 0, wx.ALIGN_LEFT )
478        gridCombos.Add( label_statename, 0, wx.ALIGN_LEFT )
479        gridCombos.Add( statename, 0, wx.ALIGN_LEFT )
480        gridCombos.Add( label_code, 0, wx.ALIGN_LEFT )
481        gridCombos.Add( code, 0, wx.ALIGN_LEFT )
482        gridCombos.Add( label_selector, 0, wx.ALIGN_LEFT)
483        hbox = wx.BoxSizer( wx.HORIZONTAL )
484        hbox.Add( self.list_selector, 0, wx.ALIGN_LEFT )
485        hbox.Add(wx.StaticText(self, -1, ' => '), 0, wx.ALIGN_LEFT)
486        hbox.Add( self.dynamicbox, 0, wx.ALIGN_LEFT )
487        gridCombos.Add( hbox, 0, wx.ALIGN_LEFT )
488
489        gridIpAddrs = wx.FlexGridSizer( cols=4, vgap=10, hgap = 15 )
490        gridIpAddrs.Add( label_ipaddr1, 0, wx.ALIGN_LEFT )
491        gridIpAddrs.Add( ipaddr1, 0, wx.ALIGN_LEFT )
492        gridIpAddrs.Add( label_ipaddr2, 0, wx.ALIGN_LEFT )
493        gridIpAddrs.Add( ipaddr2, 0, wx.ALIGN_LEFT )
494        gridIpAddrs.Add( label_ipaddr3, 0, wx.ALIGN_LEFT )
495        gridIpAddrs.Add( ipaddr3, 0, wx.ALIGN_LEFT )
496
497        gridNumerics = wx.FlexGridSizer( cols=4, vgap=10, hgap = 10 )
498        gridNumerics.Add( label_intctrl1, 0, wx.ALIGN_LEFT )
499        gridNumerics.Add( self.intctrl1, 0, wx.ALIGN_LEFT )
500        gridNumerics.Add( label_intctrl2, 0, wx.ALIGN_RIGHT )
501        gridNumerics.Add( self.intctrl2, 0, wx.ALIGN_LEFT )
502        gridNumerics.Add( label_floatctrl, 0, wx.ALIGN_LEFT )
503        gridNumerics.Add( self.floatctrl, 0, wx.ALIGN_LEFT )
504        gridNumerics.Add( label_numselect, 0, wx.ALIGN_RIGHT )
505        gridNumerics.Add( numselect, 0, wx.ALIGN_LEFT )
506
507        self.sizer.Add( labelMaskedCombos, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
508        self.sizer.Add( gridCombos, 0, wx.ALIGN_LEFT|wx.ALL, border=5 )
509        self.sizer.Add( wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, border=8 )
510        self.sizer.Add( labelIpAddrs, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
511        self.sizer.Add( gridIpAddrs, 0, wx.ALIGN_LEFT|wx.ALL, border=5 )
512        self.sizer.Add( wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, border=8 )
513        self.sizer.Add( labelNumerics, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
514        self.sizer.Add( gridNumerics, 0, wx.ALIGN_LEFT|wx.ALL, border=5 )
515        self.sizer.Add( parens_check, 0, wx.ALIGN_LEFT|wx.ALL, 5 )
516
517        self.SetSizer( self.sizer )
518        self.SetAutoLayout(1)
519        self.SetupScrolling()
520
521        self.Bind(wx.EVT_COMBOBOX, self.OnComboSelection, id=fraction.GetId())
522        self.Bind(wx.EVT_COMBOBOX, self.OnComboSelection, id=code.GetId())
523        self.Bind(wx.EVT_COMBOBOX, self.OnComboSelection, id=statecode.GetId())
524        self.Bind(wx.EVT_COMBOBOX, self.OnComboSelection, id=statename.GetId())
525        self.Bind(wx.EVT_TEXT, self.OnTextChange, id=code.GetId())
526        self.Bind(wx.EVT_TEXT, self.OnTextChange, id=statecode.GetId())
527        self.Bind(wx.EVT_TEXT, self.OnTextChange, id=statename.GetId())
528        self.Bind(wx.EVT_COMBOBOX, self.OnListSelection, id=self.list_selector.GetId())
529
530        self.Bind(wx.EVT_TEXT, self.OnTextChange, id=self.intctrl1.GetId())
531        self.Bind(wx.EVT_TEXT, self.OnTextChange, id=self.intctrl2.GetId())
532        self.Bind(wx.EVT_TEXT, self.OnTextChange, id=self.floatctrl.GetId())
533        self.Bind(wx.EVT_COMBOBOX, self.OnNumberSelect, id=numselect.GetId())
534        self.Bind(wx.EVT_CHECKBOX, self.OnParensCheck, id=parens_check.GetId())
535
536        self.Bind(wx.EVT_TEXT, self.OnIpAddrChange, id=ipaddr1.GetId())
537        self.Bind(wx.EVT_TEXT, self.OnIpAddrChange, id=ipaddr2.GetId())
538        self.Bind(wx.EVT_TEXT, self.OnIpAddrChange, id=ipaddr3.GetId())
539
540
541
542
543    def OnComboSelection( self, event ):
544        ctl = self.FindWindowById( event.GetId() )
545        if not ctl.IsValid():
546            self.log.write('current value not a valid choice')
547        self.log.write('new value = %s' % ctl.GetValue())
548
549    def OnTextChange( self, event ):
550        ctl = self.FindWindowById( event.GetId() )
551        if ctl.IsValid():
552            self.log.write('new value = %s\n' % ctl.GetValue() )
553
554    def OnNumberSelect( self, event ):
555        value = event.GetString()
556        # Format choice to fit into format for #{9}.#{2}, with sign position reserved:
557        # (ordinal + fraction == 11 + decimal point + sign == 13)
558        if value:
559            floattext = "%13.2f" % float(value)
560        else:
561            floattext = value   # clear the value again
562        try:
563            self.floatctrl.SetValue(floattext)
564        except:
565            type, value, tb = sys.exc_info()
566            for line in traceback.format_exception_only(type, value):
567                self.log.write(line)
568
569    def OnParensCheck( self, event ):
570        self.intctrl1.SetCtrlParameters(useParensForNegatives=event.IsChecked())
571        self.intctrl2.SetCtrlParameters(useParensForNegatives=event.IsChecked())
572        self.floatctrl.SetCtrlParameters(useParensForNegatives=event.IsChecked())
573
574    def OnIpAddrChange( self, event ):
575        ipaddr = self.FindWindowById( event.GetId() )
576        if ipaddr.IsValid():
577            self.log.write('new addr = %s\n' % ipaddr.GetAddress() )
578
579    def OnListSelection( self, event ):
580        list = self.list_selector.GetStringSelection()
581        formatcodes = 'F_'
582        if list == 'list1':
583            choices = ['abc', 'defg', 'hi']
584            mask = 'aaaa'
585        elif list == 'list2':
586            choices = ['1', '2', '34', '567']
587            formatcodes += 'r'
588            mask = '###'
589        else:
590            choices = masked.states
591            mask = 'AA'
592            formatcodes += '!'
593        self.dynamicbox.SetCtrlParameters( mask = mask,
594                                           choices = choices,
595                                           choiceRequired=True,
596                                           autoSelect=True,
597                                           formatcodes=formatcodes)
598        self.dynamicbox.SetValue(choices[0])
599
600# ---------------------------------------------------------------------
601class TestMaskedTextCtrls(wx.Notebook):
602    def __init__(self, parent, id, log):
603        wx.Notebook.__init__(self, parent, id)
604        self.log = log
605
606        win = demoPage1(self, log)
607        self.AddPage(win, "General examples")
608
609        win = demoPage2(self, log)
610        self.AddPage(win, 'Auto-formatted controls')
611
612        win = demoPage3(self, log)
613        self.AddPage(win, "Using default values")
614
615        win = demoPage4(self, log)
616        self.AddPage(win, 'Using auto-complete fields')
617
618        win = demoPage5(self, log)
619        self.AddPage(win, 'Other masked controls')
620
621
622#----------------------------------------------------------------------------
623
624def runTest(frame, nb, log):
625    testWin = TestMaskedTextCtrls(nb, -1, log)
626    return testWin
627
628def RunStandalone():
629    app = wx.App()
630    frame = wx.Frame(None, -1, "Test MaskedEditCtrls", size=(640, 480))
631    win = TestMaskedTextCtrls(frame, -1, sys.stdout)
632    frame.Show(True)
633    app.MainLoop()
634
635#----------------------------------------------------------------------------
636import wx.lib.masked.maskededit as maskededit
637# strip out module header used for pydoc:
638demodoc = '\n'.join(maskededit.__doc__.split('\n')[2:])
639overview = """<html>
640<PRE><FONT SIZE=-1>
641""" + demodoc + """
642</FONT></PRE>
643"""
644
645if __name__ == "__main__":
646    import sys,os
647    import run
648    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
649