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