]>
Commit | Line | Data |
---|---|---|
8fa876ca RD |
1 | |
2 | import string | |
3 | import sys | |
4 | import traceback | |
5 | ||
6 | import wx | |
c878ceea RD |
7 | from wx.lib import masked |
8 | ||
8b9a4190 RD |
9 | #---------------------------------------------------------------------- |
10 | ||
8fa876ca | 11 | class TestPanel( wx.Panel ): |
8b9a4190 RD |
12 | def __init__( self, parent, log ): |
13 | ||
8fa876ca | 14 | wx.Panel.__init__( self, parent, -1 ) |
8b9a4190 | 15 | self.log = log |
8fa876ca | 16 | panel = wx.Panel( self, -1 ) |
8b9a4190 | 17 | |
8fa876ca | 18 | header = wx.StaticText(panel, -1, """\ |
c878ceea | 19 | This shows the various options for masked.NumCtrl. |
8b9a4190 RD |
20 | The controls at the top reconfigure the resulting control at the bottom. |
21 | """) | |
22 | header.SetForegroundColour( "Blue" ) | |
23 | ||
8fa876ca | 24 | intlabel = wx.StaticText( panel, -1, "Integer width:" ) |
c878ceea | 25 | self.integerwidth = masked.NumCtrl( |
8fa876ca RD |
26 | panel, value=10, integerWidth=2, allowNegative=False |
27 | ) | |
28 | ||
29 | fraclabel = wx.StaticText( panel, -1, "Fraction width:" ) | |
c878ceea RD |
30 | self.fractionwidth = masked.NumCtrl( |
31 | panel, value=0, integerWidth=2, allowNegative=False | |
8fa876ca RD |
32 | ) |
33 | ||
34 | groupcharlabel = wx.StaticText( panel,-1, "Grouping char:" ) | |
c878ceea | 35 | self.groupchar = masked.TextCtrl( |
35d8bffe RD |
36 | panel, -1, value=',', mask='*', includeChars = ' ', excludeChars = '-()0123456789', |
37 | formatcodes='F', emptyInvalid=False, validRequired=True | |
8fa876ca RD |
38 | ) |
39 | ||
40 | decimalcharlabel = wx.StaticText( panel,-1, "Decimal char:" ) | |
c878ceea | 41 | self.decimalchar = masked.TextCtrl( |
8fa876ca RD |
42 | panel, -1, value='.', mask='&', excludeChars = '-()', |
43 | formatcodes='F', emptyInvalid=True, validRequired=True | |
44 | ) | |
45 | ||
46 | self.set_min = wx.CheckBox( panel, -1, "Set minimum value:" ) | |
c878ceea RD |
47 | # Create this masked.NumCtrl using factory, to show how: |
48 | self.min = masked.Ctrl( panel, integerWidth=5, fractionWidth=2, controlType=masked.controlTypes.NUMBER ) | |
8b9a4190 RD |
49 | self.min.Enable( False ) |
50 | ||
8fa876ca | 51 | self.set_max = wx.CheckBox( panel, -1, "Set maximum value:" ) |
c878ceea | 52 | self.max = masked.NumCtrl( panel, integerWidth=5, fractionWidth=2 ) |
8b9a4190 RD |
53 | self.max.Enable( False ) |
54 | ||
55 | ||
8fa876ca | 56 | self.limit_target = wx.CheckBox( panel, -1, "Limit control" ) |
0b0849b5 | 57 | self.limit_on_field_change = wx.CheckBox( panel, -1, "Limit on field change" ) |
8fa876ca RD |
58 | self.allow_none = wx.CheckBox( panel, -1, "Allow empty control" ) |
59 | self.group_digits = wx.CheckBox( panel, -1, "Group digits" ) | |
8b9a4190 | 60 | self.group_digits.SetValue( True ) |
8fa876ca | 61 | self.allow_negative = wx.CheckBox( panel, -1, "Allow negative values" ) |
8b9a4190 | 62 | self.allow_negative.SetValue( True ) |
8fa876ca RD |
63 | self.use_parens = wx.CheckBox( panel, -1, "Use parentheses" ) |
64 | self.select_on_entry = wx.CheckBox( panel, -1, "Select on entry" ) | |
8b9a4190 RD |
65 | self.select_on_entry.SetValue( True ) |
66 | ||
8fa876ca | 67 | label = wx.StaticText( panel, -1, "Resulting numeric control:" ) |
8b9a4190 | 68 | font = label.GetFont() |
8fa876ca | 69 | font.SetWeight(wx.BOLD) |
8b9a4190 RD |
70 | label.SetFont(font) |
71 | ||
c878ceea | 72 | self.target_ctl = masked.NumCtrl( panel, -1, name="target control" ) |
8b9a4190 | 73 | |
8fa876ca | 74 | label_numselect = wx.StaticText( panel, -1, """\ |
8b9a4190 RD |
75 | Programmatically set the above |
76 | value entry ctrl:""") | |
8fa876ca | 77 | self.numselect = wx.ComboBox(panel, -1, choices = [ '0', '111', '222.22', '-3', '54321.666666666', '-1353.978', |
8b9a4190 RD |
78 | '1234567', '-1234567', '123456789', '-123456789.1', |
79 | '1234567890.', '-9876543210.9' ]) | |
80 | ||
8fa876ca RD |
81 | grid1 = wx.FlexGridSizer( 0, 4, 0, 0 ) |
82 | grid1.Add( intlabel, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) | |
3c29a62a | 83 | grid1.Add( self.integerwidth, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
8fa876ca RD |
84 | |
85 | grid1.Add( groupcharlabel, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) | |
3c29a62a | 86 | grid1.Add( self.groupchar, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
8fa876ca RD |
87 | |
88 | grid1.Add( fraclabel, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | |
3c29a62a | 89 | grid1.Add( self.fractionwidth, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
8fa876ca RD |
90 | |
91 | grid1.Add( decimalcharlabel, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) | |
3c29a62a | 92 | grid1.Add( self.decimalchar, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
8fa876ca RD |
93 | |
94 | grid1.Add( self.set_min, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | |
95 | grid1.Add( self.min, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) | |
96 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
97 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
98 | ||
99 | grid1.Add( self.set_max, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | |
100 | grid1.Add( self.max, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) | |
101 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
102 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
103 | ||
104 | ||
105 | grid1.Add( self.limit_target, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) | |
0b0849b5 RD |
106 | grid1.Add( self.limit_on_field_change, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
107 | ||
8fa876ca RD |
108 | hbox1 = wx.BoxSizer( wx.HORIZONTAL ) |
109 | hbox1.Add( (17,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
0b0849b5 | 110 | hbox1.Add( self.allow_none, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
8fa876ca RD |
111 | grid1.Add( hbox1, 0, wx.ALIGN_LEFT|wx.ALL, 5) |
112 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
113 | ||
0b0849b5 RD |
114 | grid1.Add( self.group_digits, 0, wx.ALIGN_LEFT|wx.LEFT, 5 ) |
115 | grid1.Add( self.allow_negative, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) | |
8fa876ca RD |
116 | hbox2 = wx.BoxSizer( wx.HORIZONTAL ) |
117 | hbox2.Add( (17,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
0b0849b5 | 118 | hbox2.Add( self.use_parens, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) |
8fa876ca RD |
119 | grid1.Add( hbox2, 0, wx.ALIGN_LEFT|wx.ALL, 5) |
120 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
0b0849b5 RD |
121 | |
122 | grid1.Add( self.select_on_entry, 0, wx.ALIGN_LEFT|wx.LEFT, 5 ) | |
123 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
124 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
125 | grid1.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
8fa876ca RD |
126 | |
127 | grid2 = wx.FlexGridSizer( 0, 2, 0, 0 ) | |
128 | grid2.Add( label, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | |
129 | grid2.Add( self.target_ctl, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) | |
130 | grid2.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
131 | grid2.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
132 | grid2.Add( label_numselect, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) | |
133 | grid2.Add( self.numselect, 0, wx.ALIGN_LEFT|wx.ALL, 5 ) | |
134 | grid2.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
135 | grid2.Add( (5,5), 0, wx.ALIGN_LEFT|wx.ALL, 5) | |
8b9a4190 RD |
136 | grid2.AddGrowableCol(1) |
137 | ||
8fa876ca RD |
138 | self.outer_box = wx.BoxSizer( wx.VERTICAL ) |
139 | self.outer_box.Add(header, 0, wx.ALIGN_LEFT|wx.TOP|wx.LEFT, 20) | |
140 | self.outer_box.Add( grid1, 0, wx.ALIGN_CENTRE|wx.LEFT|wx.BOTTOM|wx.RIGHT, 20 ) | |
141 | self.outer_box.Add( grid2, 0, wx.ALIGN_LEFT|wx.ALL, 20 ) | |
8b9a4190 RD |
142 | self.grid2 = grid2 |
143 | ||
144 | panel.SetAutoLayout( True ) | |
145 | panel.SetSizer( self.outer_box ) | |
146 | self.outer_box.Fit( panel ) | |
147 | panel.Move( (50,10) ) | |
148 | self.panel = panel | |
149 | ||
c878ceea RD |
150 | self.Bind(masked.EVT_NUM, self.OnSetIntWidth, self.integerwidth ) |
151 | self.Bind(masked.EVT_NUM, self.OnSetFractionWidth, self.fractionwidth ) | |
8fa876ca RD |
152 | self.Bind(wx.EVT_TEXT, self.OnSetGroupChar, self.groupchar ) |
153 | self.Bind(wx.EVT_TEXT, self.OnSetDecimalChar, self.decimalchar ) | |
8b9a4190 | 154 | |
8fa876ca RD |
155 | self.Bind(wx.EVT_CHECKBOX, self.OnSetMin, self.set_min ) |
156 | self.Bind(wx.EVT_CHECKBOX, self.OnSetMax, self.set_max ) | |
c878ceea RD |
157 | self.Bind(masked.EVT_NUM, self.SetTargetMinMax, self.min ) |
158 | self.Bind(masked.EVT_NUM, self.SetTargetMinMax, self.max ) | |
8b9a4190 | 159 | |
0b0849b5 RD |
160 | self.Bind(wx.EVT_CHECKBOX, self.OnSetLimited, self.limit_target ) |
161 | self.Bind(wx.EVT_CHECKBOX, self.OnSetLimitOnFieldChange, self.limit_on_field_change ) | |
8fa876ca RD |
162 | self.Bind(wx.EVT_CHECKBOX, self.OnSetAllowNone, self.allow_none ) |
163 | self.Bind(wx.EVT_CHECKBOX, self.OnSetGroupDigits, self.group_digits ) | |
164 | self.Bind(wx.EVT_CHECKBOX, self.OnSetAllowNegative, self.allow_negative ) | |
165 | self.Bind(wx.EVT_CHECKBOX, self.OnSetUseParens, self.use_parens ) | |
166 | self.Bind(wx.EVT_CHECKBOX, self.OnSetSelectOnEntry, self.select_on_entry ) | |
8b9a4190 | 167 | |
c878ceea | 168 | self.Bind(masked.EVT_NUM, self.OnTargetChange, self.target_ctl ) |
8fa876ca | 169 | self.Bind(wx.EVT_COMBOBOX, self.OnNumberSelect, self.numselect ) |
8b9a4190 RD |
170 | |
171 | ||
172 | def OnSetIntWidth(self, event ): | |
173 | width = self.integerwidth.GetValue() | |
8fa876ca | 174 | |
8b9a4190 RD |
175 | if width < 1: |
176 | self.log.write("integer width must be positive\n") | |
8fa876ca | 177 | self.integerwidth.SetForegroundColour(wx.RED) |
8b9a4190 | 178 | else: |
8fa876ca | 179 | self.integerwidth.SetForegroundColour(wx.BLACK) |
8b9a4190 RD |
180 | self.log.write("setting integer width to %d\n" % width) |
181 | self.target_ctl.SetParameters( integerWidth = width) | |
182 | # Now resize and fit the dialog as appropriate: | |
183 | self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize()) | |
184 | self.outer_box.Fit( self.panel ) | |
185 | self.outer_box.SetSizeHints( self.panel ) | |
186 | ||
187 | ||
188 | def OnSetFractionWidth(self, event ): | |
189 | width = self.fractionwidth.GetValue() | |
190 | self.log.write("setting fraction width to %d\n" % width) | |
191 | self.target_ctl.SetParameters( fractionWidth = width) | |
192 | # Now resize and fit the dialog as appropriate: | |
193 | self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize()) | |
194 | self.outer_box.Fit( self.panel ) | |
195 | self.outer_box.SetSizeHints( self.panel ) | |
196 | ||
197 | ||
198 | def OnSetGroupChar( self, event ): | |
199 | char = self.groupchar.GetValue() | |
200 | if self.target_ctl.GetDecimalChar() == char: | |
201 | self.log.write("group and decimal chars must be different\n") | |
8fa876ca | 202 | self.groupchar.SetForegroundColour(wx.RED) |
8b9a4190 | 203 | else: |
8fa876ca | 204 | self.groupchar.SetForegroundColour(wx.BLACK) |
8b9a4190 RD |
205 | self.log.write("setting group char to %s\n" % char) |
206 | self.target_ctl.SetGroupChar( char ) | |
207 | ||
208 | def OnSetDecimalChar( self, event ): | |
209 | char = self.decimalchar.GetValue() | |
210 | if self.target_ctl.GetGroupChar() == char: | |
211 | self.log.write("group and decimal chars must be different\n") | |
8fa876ca | 212 | self.decimalchar.SetForegroundColour(wx.RED) |
8b9a4190 | 213 | else: |
8fa876ca | 214 | self.decimalchar.SetForegroundColour(wx.BLACK) |
8b9a4190 RD |
215 | self.log.write("setting decimal char to %s\n" % char) |
216 | self.target_ctl.SetDecimalChar( char ) | |
217 | ||
218 | ||
219 | def OnSetMin( self, event ): | |
220 | self.min.Enable( self.set_min.GetValue() ) | |
221 | self.SetTargetMinMax() | |
222 | ||
223 | def OnSetMax( self, event ): | |
224 | self.max.Enable( self.set_max.GetValue() ) | |
225 | self.SetTargetMinMax() | |
226 | ||
227 | ||
0b0849b5 RD |
228 | def OnSetLimited( self, event ): |
229 | limited = self.limit_target.GetValue() | |
230 | self.target_ctl.SetLimited( limited ) | |
231 | limit_on_field_change = self.limit_on_field_change.GetValue() | |
232 | if limited and limit_on_field_change: | |
233 | self.limit_on_field_change.SetValue(False) | |
234 | self.target_ctl.SetLimitOnFieldChange( False ) | |
235 | self.SetTargetMinMax() | |
236 | ||
237 | ||
238 | def OnSetLimitOnFieldChange( self, event ): | |
239 | limit_on_field_change = self.limit_on_field_change.GetValue() | |
240 | self.target_ctl.SetLimitOnFieldChange( limit_on_field_change ) | |
241 | limited = self.limit_target.GetValue() | |
242 | if limited and limit_on_field_change: | |
243 | self.limit_target.SetValue(False) | |
244 | self.target_ctl.SetLimited( False ) | |
245 | ||
8b9a4190 RD |
246 | def SetTargetMinMax( self, event=None ): |
247 | min = max = None | |
8b9a4190 RD |
248 | if self.set_min.GetValue(): |
249 | min = self.min.GetValue() | |
250 | if self.set_max.GetValue(): | |
251 | max = self.max.GetValue() | |
252 | ||
253 | cur_min, cur_max = self.target_ctl.GetBounds() | |
254 | ||
255 | if min != cur_min and not self.target_ctl.SetMin( min ): | |
256 | if self.target_ctl.GetMax() is None and cur_max > min: | |
257 | self.log.write( "min (%d) won't fit in control -- bound not set\n" % min ) | |
258 | else: | |
259 | self.log.write( "min (%d) > current max (%d) -- bound not set\n" % ( min, self.target_ctl.GetMax() ) ) | |
8fa876ca | 260 | self.min.SetParameters( signedForegroundColour=wx.RED, foregroundColour=wx.RED ) |
8b9a4190 | 261 | else: |
8fa876ca | 262 | self.min.SetParameters( signedForegroundColour=wx.BLACK, foregroundColour=wx.BLACK ) |
8b9a4190 RD |
263 | self.min.Refresh() |
264 | ||
265 | if max != cur_max and not self.target_ctl.SetMax( max ): | |
266 | if self.target_ctl.GetMax() is None and cur_min < max: | |
267 | self.log.write( "max (%d) won't fit in control -- bound not set\n" % max ) | |
268 | else: | |
269 | self.log.write( "max (%d) < current min (%d) -- bound not set\n" % ( max, self.target_ctl.GetMin() ) ) | |
8fa876ca | 270 | self.max.SetParameters( signedForegroundColour=wx.RED, foregroundColour=wx.RED ) |
8b9a4190 | 271 | else: |
8fa876ca | 272 | self.max.SetParameters( signedForegroundColour=wx.BLACK, foregroundColour=wx.BLACK ) |
8b9a4190 RD |
273 | self.max.Refresh() |
274 | ||
275 | if min != cur_min or max != cur_max: | |
276 | new_min, new_max = self.target_ctl.GetBounds() | |
277 | self.log.write( "current min, max: (%s, %s)\n" % ( str(new_min), str(new_max) ) ) | |
278 | ||
279 | ||
280 | def OnSetAllowNone( self, event ): | |
281 | self.target_ctl.SetAllowNone( self.allow_none.GetValue() ) | |
282 | ||
283 | ||
284 | def OnSetGroupDigits( self, event ): | |
285 | self.target_ctl.SetGroupDigits( self.group_digits.GetValue() ) | |
286 | # Now resize and fit the dialog as appropriate: | |
287 | self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize()) | |
288 | self.outer_box.Fit( self.panel ) | |
289 | self.outer_box.SetSizeHints( self.panel ) | |
290 | ||
291 | ||
292 | def OnSetAllowNegative( self, event ): | |
293 | if self.allow_negative.GetValue(): | |
294 | self.use_parens.Enable(True) | |
295 | self.target_ctl.SetParameters(allowNegative=True, | |
296 | useParensForNegatives = self.use_parens.GetValue()) | |
297 | else: | |
298 | self.target_ctl.SetAllowNegative(False) | |
299 | # Now resize and fit the dialog as appropriate: | |
300 | self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize()) | |
301 | self.outer_box.Fit( self.panel ) | |
302 | self.outer_box.SetSizeHints( self.panel ) | |
303 | ||
304 | ||
305 | def OnSetUseParens( self, event ): | |
306 | self.target_ctl.SetUseParensForNegatives( self.use_parens.GetValue() ) | |
307 | # Now resize and fit the dialog as appropriate: | |
308 | self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize()) | |
309 | self.outer_box.Fit( self.panel ) | |
310 | self.outer_box.SetSizeHints( self.panel ) | |
311 | ||
312 | ||
313 | def OnSetSelectOnEntry( self, event ): | |
314 | self.target_ctl.SetSelectOnEntry( self.select_on_entry.GetValue() ) | |
315 | ||
316 | ||
317 | def OnTargetChange( self, event ): | |
318 | ctl = event.GetEventObject() | |
319 | value = ctl.GetValue() | |
320 | ib_str = [ " (out of bounds)", "" ] | |
321 | self.log.write( "value = %s (%s)%s\n" % ( repr(value), repr(type(value)), ib_str[ ctl.IsInBounds(value) ] ) ) | |
322 | ||
323 | ||
324 | def OnNumberSelect( self, event ): | |
325 | value = event.GetString() | |
326 | if value: | |
327 | if value.find('.') != -1: | |
328 | numvalue = float(value) | |
329 | else: | |
330 | numvalue = long(value) | |
331 | else: | |
332 | numvalue = value # try to clear the value again | |
333 | ||
334 | try: | |
335 | self.target_ctl.SetValue(numvalue) | |
336 | except: | |
337 | type, value, tb = sys.exc_info() | |
338 | for line in traceback.format_exception_only(type, value): | |
339 | self.log.write(line) | |
340 | ||
341 | ||
342 | #---------------------------------------------------------------------- | |
343 | ||
344 | def runTest( frame, nb, log ): | |
345 | win = TestPanel( nb, log ) | |
346 | return win | |
347 | ||
348 | #---------------------------------------------------------------------- | |
c878ceea | 349 | import wx.lib.masked.numctrl as mnum |
f54a36bb RD |
350 | overview = """<html> |
351 | <PRE><FONT SIZE=-1> | |
352 | """ + mnum.__doc__ + """ | |
353 | </FONT></PRE>""" | |
8b9a4190 RD |
354 | |
355 | if __name__ == '__main__': | |
356 | import sys,os | |
357 | import run | |
8eca4fef | 358 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |