]>
Commit | Line | Data |
---|---|---|
8fa876ca RD |
1 | |
2 | import string | |
3 | import sys | |
4 | import traceback | |
5 | ||
6 | import wx | |
c878ceea RD |
7 | import wx.lib.masked as masked |
8 | import wx.lib.scrolledpanel as scroll | |
1fded56b | 9 | |
8b9a4190 | 10 | |
1fded56b RD |
11 | class demoMixin: |
12 | """ | |
13 | Centralized routines common to demo pages, to remove repetition. | |
14 | """ | |
15 | def labelGeneralTable(self, sizer): | |
8fa876ca RD |
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.)" ) | |
c878ceea | 20 | ctrl = wx.StaticText( self, -1, "Masked TextCtrl" ) |
8fa876ca RD |
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)) | |
1fded56b RD |
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: | |
8fa876ca RD |
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]) ) | |
1fded56b RD |
41 | |
42 | if control in controls: | |
c878ceea | 43 | newControl = masked.TextCtrl( self, -1, "", |
1fded56b RD |
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): | |
8fa876ca | 60 | if event.IsChecked(): value = checked_value |
1fded56b | 61 | else: value = notchecked_value |
8fa876ca | 62 | |
1fded56b | 63 | kwargs = {parameter: value} |
8fa876ca | 64 | |
1fded56b RD |
65 | for control in self.editList: |
66 | control.SetCtrlParameters(**kwargs) | |
67 | control.Refresh() | |
8fa876ca | 68 | |
1fded56b RD |
69 | self.Refresh() |
70 | ||
71 | ||
72 | ||
73 | #---------------------------------------------------------------------------- | |
d4b73b1b | 74 | class demoPage1(scroll.ScrolledPanel, demoMixin): |
1fded56b | 75 | def __init__(self, parent, log): |
d4b73b1b | 76 | scroll.ScrolledPanel.__init__(self, parent, -1) |
8fa876ca | 77 | self.sizer = wx.BoxSizer( wx.VERTICAL ) |
1fded56b RD |
78 | self.editList = [] |
79 | ||
8fa876ca | 80 | label = wx.StaticText( self, -1, """\ |
c878ceea | 81 | Here are some basic masked TextCtrls to give you an idea of what you can do |
1fded56b RD |
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" ) | |
8fa876ca RD |
90 | header = wx.BoxSizer( wx.HORIZONTAL ) |
91 | header.Add( label, 0, flag=wx.ALIGN_LEFT|wx.ALL, border = 5 ) | |
1fded56b | 92 | |
8fa876ca RD |
93 | highlight = wx.CheckBox( self, -1, "Highlight Empty" ) |
94 | disallow = wx.CheckBox( self, -1, "Disallow Empty" ) | |
95 | showFill = wx.CheckBox( self, -1, "change fillChar" ) | |
1fded56b | 96 | |
8fa876ca RD |
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 ) | |
1fded56b | 103 | |
8fa876ca RD |
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()) | |
1fded56b | 107 | |
8fa876ca | 108 | grid = wx.FlexGridSizer( 0, 5, vgap=10, hgap=10 ) |
1fded56b RD |
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) | |
8fa876ca RD |
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 ) | |
1fded56b RD |
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""" | |
8b9a4190 | 139 | self.changeControlParams( event, "emptyBackgroundColour", "Blue", "White" ) |
1fded56b RD |
140 | |
141 | def onShowFill( self, event ): | |
142 | """ Set fillChar parameter to '?' or ' ' """ | |
143 | self.changeControlParams( event, "fillChar", '?', ' ' ) | |
144 | ||
145 | ||
d4b73b1b | 146 | class demoPage2(scroll.ScrolledPanel, demoMixin): |
1fded56b RD |
147 | def __init__( self, parent, log ): |
148 | self.log = log | |
d4b73b1b | 149 | scroll.ScrolledPanel.__init__( self, parent, -1 ) |
8fa876ca | 150 | self.sizer = wx.BoxSizer( wx.VERTICAL ) |
1fded56b | 151 | |
8fa876ca | 152 | label = wx.StaticText( self, -1, """\ |
8b9a4190 | 153 | All these controls have been created by passing a single parameter, the autoformat code, |
c878ceea RD |
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). | |
1fded56b RD |
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" ) | |
8fa876ca | 161 | self.sizer.Add( label, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
1fded56b | 162 | |
8fa876ca RD |
163 | description = wx.StaticText( self, -1, "Description") |
164 | autofmt = wx.StaticText( self, -1, "AutoFormat Code") | |
c878ceea | 165 | ctrl = wx.StaticText( self, -1, "Masked Ctrl") |
1fded56b | 166 | |
8fa876ca RD |
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 ) ) | |
1fded56b | 170 | |
8fa876ca RD |
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 ) | |
1fded56b | 175 | |
c878ceea | 176 | for autoformat, desc in masked.autoformats: |
8fa876ca RD |
177 | grid.Add( wx.StaticText( self, -1, desc), 0, wx.ALIGN_LEFT ) |
178 | grid.Add( wx.StaticText( self, -1, autoformat), 0, wx.ALIGN_LEFT ) | |
c878ceea | 179 | grid.Add( masked.Ctrl( self, -1, "", |
8b9a4190 RD |
180 | autoformat = autoformat, |
181 | demo = True, | |
182 | name = autoformat), | |
8fa876ca | 183 | 0, wx.ALIGN_LEFT ) |
1fded56b | 184 | |
8fa876ca | 185 | self.sizer.Add( grid, 0, wx.ALIGN_LEFT|wx.ALL, border=5 ) |
1fded56b RD |
186 | self.SetSizer( self.sizer ) |
187 | self.SetAutoLayout( 1 ) | |
188 | self.SetupScrolling() | |
189 | ||
190 | ||
d4b73b1b | 191 | class demoPage3(scroll.ScrolledPanel, demoMixin): |
1fded56b RD |
192 | def __init__(self, parent, log): |
193 | self.log = log | |
d4b73b1b | 194 | scroll.ScrolledPanel.__init__(self, parent, -1) |
8fa876ca | 195 | self.sizer = wx.BoxSizer( wx.VERTICAL ) |
1fded56b RD |
196 | self.editList = [] |
197 | ||
8fa876ca | 198 | label = wx.StaticText( self, -1, """\ |
c878ceea | 199 | Here masked TextCtrls that have default values. The states |
1fded56b RD |
200 | control has a list of valid values, and the unsigned integer |
201 | has a legal range specified. | |
202 | """) | |
203 | label.SetForegroundColour( "Blue" ) | |
8fa876ca RD |
204 | requireValid = wx.CheckBox( self, -1, "Require Valid Value" ) |
205 | self.Bind(wx.EVT_CHECKBOX, self.onRequireValid, id=requireValid.GetId()) | |
1fded56b | 206 | |
8fa876ca RD |
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 ) | |
1fded56b | 211 | |
8fa876ca | 212 | grid = wx.FlexGridSizer( 0, 5, vgap=10, hgap=10 ) |
1fded56b RD |
213 | self.labelGeneralTable( grid ) |
214 | ||
215 | controls = [ | |
216 | #description mask excl format regexp range,list,initial | |
c878ceea | 217 | ("U.S. State (2 char)", "AA", "", 'F!_', "[A-Z]{2}", '', masked.states, masked.states[0]), |
8b9a4190 | 218 | ("Integer (signed)", "#{6}", "", 'F-_', "", '','', ' 0 '), |
1fded56b RD |
219 | ("Integer (unsigned)\n(1-399)","######", "", 'F_', "", (1,399),'', '1 '), |
220 | ("Float (signed)", "#{6}.#{9}", "", 'F-_R', "", '','', '000000.000000000'), | |
8fa876ca | 221 | ("Date (MDY) + Time", "##/##/#### ##:##:## AM", 'BCDEFGHIJKLMNOQRSTUVWXYZ','DF!',"", '','', wx.DateTime_Now().Format("%m/%d/%Y %I:%M:%S %p")), |
1fded56b RD |
222 | ] |
223 | self.layoutGeneralTable( controls, grid ) | |
224 | ||
8fa876ca RD |
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 ) | |
1fded56b RD |
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 | ||
d4b73b1b | 237 | class demoPage4(scroll.ScrolledPanel, demoMixin): |
1fded56b RD |
238 | def __init__( self, parent, log ): |
239 | self.log = log | |
d4b73b1b | 240 | scroll.ScrolledPanel.__init__( self, parent, -1 ) |
8fa876ca | 241 | self.sizer = wx.BoxSizer( wx.VERTICAL ) |
1fded56b | 242 | |
8fa876ca | 243 | label = wx.StaticText( self, -1, """\ |
1fded56b RD |
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" ) | |
8fa876ca | 253 | self.sizer.Add( label, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
1fded56b | 254 | |
8fa876ca RD |
255 | description = wx.StaticText( self, -1, "Description" ) |
256 | autofmt = wx.StaticText( self, -1, "AutoFormat Code" ) | |
257 | fields = wx.StaticText( self, -1, "Field Objects" ) | |
c878ceea | 258 | ctrl = wx.StaticText( self, -1, "Masked TextCtrl" ) |
1fded56b | 259 | |
8fa876ca RD |
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 ) ) | |
1fded56b | 264 | |
8fa876ca RD |
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 ) | |
1fded56b RD |
270 | |
271 | autoformat = "USPHONEFULLEXT" | |
c878ceea | 272 | fieldsDict = {0: masked.Field(choices=["617","781","508","978","413"], choiceRequired=True)} |
1fded56b RD |
273 | fieldsLabel = """\ |
274 | {0: Field(choices=[ | |
275 | "617","781", | |
276 | "508","978","413"], | |
277 | choiceRequired=True)}""" | |
8fa876ca RD |
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 ) | |
c878ceea | 281 | grid.Add( masked.TextCtrl( self, -1, "", |
1fded56b RD |
282 | autoformat = autoformat, |
283 | fields = fieldsDict, | |
284 | demo = True, | |
285 | name = autoformat), | |
8fa876ca | 286 | 0, wx.ALIGN_LEFT ) |
1fded56b RD |
287 | |
288 | autoformat = "EXPDATEMMYY" | |
c878ceea | 289 | fieldsDict = {1: masked.Field(choices=["03", "04", "05"], choiceRequired=True)} |
1fded56b RD |
290 | fieldsLabel = """\ |
291 | {1: Field(choices=[ | |
292 | "03", "04", "05"], | |
293 | choiceRequired=True)}""" | |
c878ceea | 294 | exp = masked.TextCtrl( self, -1, "", |
1fded56b RD |
295 | autoformat = autoformat, |
296 | fields = fieldsDict, | |
297 | demo = True, | |
298 | name = autoformat) | |
299 | ||
8fa876ca RD |
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 ) | |
1fded56b | 304 | |
c878ceea RD |
305 | fieldsDict = {0: masked.Field(choices=["02134","02155"], choiceRequired=True), |
306 | 1: masked.Field(choices=["1234", "5678"], choiceRequired=False)} | |
1fded56b RD |
307 | fieldsLabel = """\ |
308 | {0: Field(choices=["02134","02155"], | |
309 | choiceRequired=True), | |
310 | 1: Field(choices=["1234", "5678"], | |
311 | choiceRequired=False)}""" | |
312 | autoformat = "USZIPPLUS4" | |
c878ceea | 313 | zip = masked.TextCtrl( self, -1, "", |
1fded56b RD |
314 | autoformat = autoformat, |
315 | fields = fieldsDict, | |
316 | demo = True, | |
317 | name = autoformat) | |
318 | ||
8fa876ca RD |
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 ) | |
1fded56b | 323 | |
8fa876ca | 324 | self.sizer.Add( grid, 0, wx.ALIGN_LEFT|wx.ALL, border=5 ) |
1fded56b RD |
325 | self.SetSizer( self.sizer ) |
326 | self.SetAutoLayout(1) | |
327 | self.SetupScrolling() | |
328 | ||
329 | ||
d4b73b1b | 330 | class demoPage5(scroll.ScrolledPanel, demoMixin): |
1fded56b RD |
331 | def __init__( self, parent, log ): |
332 | self.log = log | |
d4b73b1b | 333 | scroll.ScrolledPanel.__init__( self, parent, -1 ) |
8fa876ca | 334 | self.sizer = wx.BoxSizer( wx.VERTICAL ) |
8b9a4190 RD |
335 | |
336 | ||
8fa876ca | 337 | labelMaskedCombos = wx.StaticText( self, -1, """\ |
c878ceea | 338 | These are some examples of masked.ComboBox:""") |
8b9a4190 RD |
339 | labelMaskedCombos.SetForegroundColour( "Blue" ) |
340 | ||
341 | ||
8fa876ca | 342 | label_statecode = wx.StaticText( self, -1, """\ |
8b9a4190 RD |
343 | A state selector; only |
344 | "legal" values can be | |
345 | entered:""") | |
c878ceea RD |
346 | statecode = masked.ComboBox( self, -1, masked.states[0], |
347 | choices = masked.states, | |
8b9a4190 RD |
348 | autoformat="USSTATE") |
349 | ||
8fa876ca | 350 | label_statename = wx.StaticText( self, -1, """\ |
8b9a4190 RD |
351 | A state name selector, |
352 | with auto-select:""") | |
353 | ||
354 | # Create this one using factory function: | |
c878ceea RD |
355 | statename = masked.Ctrl( self, -1, masked.state_names[0], |
356 | controlType = masked.controlTypes.COMBO, | |
357 | choices = masked.state_names, | |
8b9a4190 RD |
358 | autoformat="USSTATENAME", |
359 | autoSelect=True) | |
360 | statename.SetCtrlParameters(formatcodes = 'F!V_') | |
361 | ||
1fded56b RD |
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] ] | |
c878ceea RD |
365 | fieldsDict = {0: masked.Field(choices=numerators, choiceRequired=False), |
366 | 1: masked.Field(choices=denominators, choiceRequired=True)} | |
1fded56b RD |
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 | ||
8fa876ca | 374 | label_fraction = wx.StaticText( self, -1, """\ |
1fded56b | 375 | A masked ComboBox for fraction selection. |
8b9a4190 RD |
376 | Choices for each side of the fraction can |
377 | be selected with PageUp/Down:""") | |
1fded56b | 378 | |
c878ceea RD |
379 | fraction = masked.Ctrl( self, -1, "", |
380 | controlType = masked.controlTypes.COMBO, | |
8b9a4190 RD |
381 | choices = choices, |
382 | choiceRequired = True, | |
383 | mask = "#/##", | |
384 | formatcodes = "F_", | |
385 | validRegex = "^\d\/\d\d?", | |
386 | fields = fieldsDict ) | |
1fded56b RD |
387 | |
388 | ||
8fa876ca | 389 | label_code = wx.StaticText( self, -1, """\ |
1fded56b RD |
390 | A masked ComboBox to validate |
391 | text from a list of numeric codes:""") | |
392 | ||
393 | choices = ["91", "136", "305", "4579"] | |
c878ceea | 394 | code = masked.ComboBox( self, -1, choices[0], |
1fded56b RD |
395 | choices = choices, |
396 | choiceRequired = True, | |
397 | formatcodes = "F_r", | |
398 | mask = "####") | |
399 | ||
8fa876ca | 400 | label_selector = wx.StaticText( self, -1, """\ |
8b9a4190 RD |
401 | Programmatically set |
402 | choice sets:""") | |
8fa876ca | 403 | self.list_selector = wx.ComboBox(self, -1, '', choices = ['list1', 'list2', 'list3']) |
c878ceea RD |
404 | self.dynamicbox = masked.Ctrl( self, -1, ' ', |
405 | controlType = masked.controlTypes.COMBO, | |
8b9a4190 RD |
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'] ) | |
1fded56b | 412 | |
8b9a4190 | 413 | self.dynamicbox.Clear() # get rid of initial choices used to size the dropdown |
1fded56b | 414 | |
1fded56b | 415 | |
8fa876ca | 416 | labelIpAddrs = wx.StaticText( self, -1, """\ |
c878ceea | 417 | Here are some examples of IpAddrCtrl, a control derived from masked.TextCtrl:""") |
8b9a4190 | 418 | labelIpAddrs.SetForegroundColour( "Blue" ) |
1fded56b RD |
419 | |
420 | ||
8fa876ca | 421 | label_ipaddr1 = wx.StaticText( self, -1, "An empty control:") |
c878ceea | 422 | ipaddr1 = masked.IpAddrCtrl( self, -1, style = wx.TE_PROCESS_TAB ) |
1fded56b RD |
423 | |
424 | ||
8fa876ca | 425 | label_ipaddr2 = wx.StaticText( self, -1, "A restricted mask:") |
c878ceea | 426 | ipaddr2 = masked.IpAddrCtrl( self, -1, mask=" 10. 1.109.###" ) |
1fded56b RD |
427 | |
428 | ||
8fa876ca | 429 | label_ipaddr3 = wx.StaticText( self, -1, """\ |
8b9a4190 RD |
430 | A control with restricted legal values: |
431 | 10. (1|2) . (129..255) . (0..255)""") | |
c878ceea RD |
432 | ipaddr3 = masked.Ctrl( self, -1, |
433 | controlType = masked.controlTypes.IPADDR, | |
8b9a4190 RD |
434 | mask=" 10. #.###.###") |
435 | ipaddr3.SetFieldParameters(0, validRegex="1|2",validRequired=False ) # requires entry to match or not allowed | |
436 | ||
1fded56b | 437 | # This allows any value in penultimate field, but colors anything outside of the range invalid: |
8b9a4190 RD |
438 | ipaddr3.SetFieldParameters(1, validRange=(129,255), validRequired=False ) |
439 | ||
1fded56b | 440 | |
1fded56b | 441 | |
8fa876ca | 442 | labelNumerics = wx.StaticText( self, -1, """\ |
c878ceea RD |
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!)""") | |
8b9a4190 RD |
445 | labelNumerics.SetForegroundColour( "Blue" ) |
446 | ||
8fa876ca | 447 | label_intctrl1 = wx.StaticText( self, -1, """\ |
8b9a4190 RD |
448 | An integer entry control with |
449 | shifting insert enabled:""") | |
c878ceea | 450 | self.intctrl1 = masked.TextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-,F>') |
8fa876ca | 451 | label_intctrl2 = wx.StaticText( self, -1, """\ |
8b9a4190 | 452 | Right-insert integer entry:""") |
c878ceea | 453 | self.intctrl2 = masked.TextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-,Fr') |
8b9a4190 | 454 | |
8fa876ca | 455 | label_floatctrl = wx.StaticText( self, -1, """\ |
1fded56b RD |
456 | A floating point entry control |
457 | with right-insert for ordinal:""") | |
c878ceea | 458 | self.floatctrl = masked.TextCtrl(self, -1, name='floatctrl', mask="#{9}.#{2}", formatcodes="F,_-R", useParensForNegatives=False) |
1fded56b RD |
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 | ||
8fa876ca | 462 | label_numselect = wx.StaticText( self, -1, """\ |
8b9a4190 RD |
463 | <= Programmatically set the value |
464 | of the float entry ctrl:""") | |
8fa876ca | 465 | numselect = wx.ComboBox(self, -1, choices = [ '', '111', '222.22', '-3', '54321.666666666', '-1353.978', |
8b9a4190 RD |
466 | '1234567', '-1234567', '123456789', '-123456789.1', |
467 | '1234567890.', '-1234567890.1' ]) | |
468 | ||
8fa876ca RD |
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 ) | |
1fded56b | 516 | |
1fded56b RD |
517 | self.SetSizer( self.sizer ) |
518 | self.SetAutoLayout(1) | |
519 | self.SetupScrolling() | |
520 | ||
8fa876ca RD |
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()) | |
8b9a4190 | 529 | |
8fa876ca RD |
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()) | |
8b9a4190 | 535 | |
8fa876ca RD |
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()) | |
1fded56b RD |
539 | |
540 | ||
8b9a4190 RD |
541 | |
542 | ||
543 | def OnComboSelection( self, event ): | |
1fded56b RD |
544 | ctl = self.FindWindowById( event.GetId() ) |
545 | if not ctl.IsValid(): | |
546 | self.log.write('current value not a valid choice') | |
8b9a4190 | 547 | self.log.write('new value = %s' % ctl.GetValue()) |
1fded56b RD |
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() | |
1fded56b RD |
556 | # Format choice to fit into format for #{9}.#{2}, with sign position reserved: |
557 | # (ordinal + fraction == 11 + decimal point + sign == 13) | |
1fded56b RD |
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 | ||
8b9a4190 | 569 | def OnParensCheck( self, event ): |
b881fc78 RD |
570 | self.intctrl1.SetCtrlParameters(useParensForNegatives=event.IsChecked()) |
571 | self.intctrl2.SetCtrlParameters(useParensForNegatives=event.IsChecked()) | |
572 | self.floatctrl.SetCtrlParameters(useParensForNegatives=event.IsChecked()) | |
8b9a4190 RD |
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: | |
c878ceea | 590 | choices = masked.states |
8b9a4190 RD |
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 | ||
1fded56b | 600 | # --------------------------------------------------------------------- |
8fa876ca | 601 | class TestMaskedTextCtrls(wx.Notebook): |
1fded56b | 602 | def __init__(self, parent, id, log): |
8fa876ca | 603 | wx.Notebook.__init__(self, parent, id) |
1fded56b RD |
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(): | |
8fa876ca | 629 | app = wx.PySimpleApp() |
c878ceea | 630 | frame = wx.Frame(None, -1, "Test MaskedEditCtrls", size=(640, 480)) |
1fded56b RD |
631 | win = TestMaskedTextCtrls(frame, -1, sys.stdout) |
632 | frame.Show(True) | |
633 | app.MainLoop() | |
634 | #---------------------------------------------------------------------------- | |
c878ceea | 635 | import wx.lib.masked.maskededit as maskededit |
5fe636c6 RD |
636 | # strip out module header used for pydoc: |
637 | demodoc = '\n'.join(maskededit.__doc__.split('\n')[2:]) | |
1fded56b RD |
638 | overview = """<html> |
639 | <PRE><FONT SIZE=-1> | |
5fe636c6 | 640 | """ + demodoc + """ |
1fded56b RD |
641 | </FONT></PRE> |
642 | """ | |
643 | ||
644 | if __name__ == "__main__": | |
645 | import sys,os | |
646 | import run | |
8eca4fef | 647 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |