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