]>
Commit | Line | Data |
---|---|---|
1 | ||
2 | import string | |
3 | import sys | |
4 | import traceback | |
5 | ||
6 | import wx | |
7 | import wx.lib.masked as masked | |
8 | import wx.lib.scrolledpanel as scroll | |
9 | ||
10 | ||
11 | class 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.SWISS, wx.NORMAL, wx.BOLD)) | |
23 | mask.SetFont( wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD)) | |
24 | formatcode.SetFont( wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD) ) | |
25 | regex.SetFont( wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD)) | |
26 | ctrl.SetFont( wx.Font(9, wx.SWISS, wx.NORMAL, wx.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 | #---------------------------------------------------------------------------- | |
74 | class 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, """\ | |
81 | Here are some basic masked TextCtrls to give you an idea of what you can do | |
82 | with this control. Note that all controls have been auto-sized by including 'F' in | |
83 | the format codes. | |
84 | ||
85 | Try entering nonsensical or partial values in validated fields to see what happens. | |
86 | Note that the State and Last Name fields are list-limited (valid last names are: | |
87 | Smith, 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( 0, 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 | ||
146 | class 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, """\ | |
153 | All these controls have been created by passing a single parameter, the autoformat code, | |
154 | and use the factory class masked.Ctrl with its default controlType. | |
155 | The masked package contains an internal dictionary of types and formats (autoformats). | |
156 | Many of these already do complicated validation; To see some examples, try | |
157 | 29 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.SWISS, wx.NORMAL, wx.BOLD ) ) | |
168 | autofmt.SetFont( wx.Font( 9, wx.SWISS, wx.NORMAL, wx.BOLD ) ) | |
169 | ctrl.SetFont( wx.Font( 9, wx.SWISS, wx.NORMAL, wx.BOLD ) ) | |
170 | ||
171 | grid = wx.FlexGridSizer( 0, 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 | ||
191 | class 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, """\ | |
199 | Here masked TextCtrls that have default values. The states | |
200 | control has a list of valid values, and the unsigned integer | |
201 | has 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( 0, 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 | ||
237 | class 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, """\ | |
244 | These controls have field-specific choice lists and allow autocompletion. | |
245 | ||
246 | Down arrow or Page Down in an uncompleted field with an auto-completable field will attempt | |
247 | to auto-complete a field if it has a choice list. | |
248 | Page Down and Shift-Down arrow will also auto-complete, or cycle through the complete list. | |
249 | Page 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.SWISS, wx.NORMAL, wx.BOLD ) ) | |
261 | autofmt.SetFont( wx.Font( 9, wx.SWISS, wx.NORMAL, wx.BOLD ) ) | |
262 | fields.SetFont( wx.Font( 9, wx.SWISS, wx.NORMAL, wx.BOLD ) ) | |
263 | ctrl.SetFont( wx.Font( 9, wx.SWISS, wx.NORMAL, wx.BOLD ) ) | |
264 | ||
265 | grid = wx.FlexGridSizer( 0, 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 | ||
330 | class 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, """\ | |
338 | These are some examples of masked.ComboBox:""") | |
339 | labelMaskedCombos.SetForegroundColour( "Blue" ) | |
340 | ||
341 | ||
342 | label_statecode = wx.StaticText( self, -1, """\ | |
343 | A state selector; only | |
344 | "legal" values can be | |
345 | entered:""") | |
346 | statecode = masked.ComboBox( self, -1, masked.states[0], | |
347 | choices = masked.states, | |
348 | autoformat="USSTATE") | |
349 | ||
350 | label_statename = wx.StaticText( self, -1, """\ | |
351 | A state name selector, | |
352 | with 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 = [ string.ljust(str(i), 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, """\ | |
375 | A masked ComboBox for fraction selection. | |
376 | Choices for each side of the fraction can | |
377 | be 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, """\ | |
390 | A masked ComboBox to validate | |
391 | text 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, """\ | |
401 | Programmatically set | |
402 | choice 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, """\ | |
417 | Here 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, """\ | |
430 | A control with restricted legal values: | |
431 | 10. (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, """\ | |
443 | Here are some useful configurations of a masked.TextCtrl for integer and floating point input that still treat | |
444 | the 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, """\ | |
448 | An integer entry control with | |
449 | shifting 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, """\ | |
456 | A floating point entry control | |
457 | with 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( 0, 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( 0, 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( 0, 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 | # --------------------------------------------------------------------- | |
601 | class 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 | ||
624 | def runTest(frame, nb, log): | |
625 | testWin = TestMaskedTextCtrls(nb, -1, log) | |
626 | return testWin | |
627 | ||
628 | def RunStandalone(): | |
629 | app = wx.PySimpleApp() | |
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 | import wx.lib.masked.maskededit as maskededit | |
636 | overview = """<html> | |
637 | <PRE><FONT SIZE=-1> | |
638 | """ + maskededit.__doc__ + """ | |
639 | </FONT></PRE> | |
640 | """ | |
641 | ||
642 | if __name__ == "__main__": | |
643 | import sys,os | |
644 | import run | |
645 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |