Updates to wxMaskedEditCtrl.

Added wxMaskedNumCtrl.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@23909 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2003-09-25 18:29:40 +00:00
parent 3adf0c5b2b
commit f0e615b6ab
8 changed files with 4836 additions and 795 deletions

View File

@@ -11,7 +11,13 @@ Updated to Scintilla 1.54.
Lots of bug fixes and such from the wxWindows folks. Lots of bug fixes and such from the wxWindows folks.
Added wxPython.lib.newevent from Miki Tebeka Added wxPython.lib.newevent from Miki Tebeka. Its usage is
demonstrated in the Threads sample in the demo.
Updates to wxMaskedEditCtrl.
Added wxMaskedNumCtrl.

View File

@@ -25,14 +25,7 @@ import images
_treeList = [ _treeList = [
# new stuff # new stuff
('Recent Additions', [ ('Recent Additions', [
'wxScrolledPanel', 'wxMaskedNumCtrl',
'ShapedWindow',
'NewNamespace',
'PopupMenu',
'AnalogClockWindow',
'MaskedEditControls',
'wxTreeListCtrl',
'wxGrid_MegaExample',
]), ]),
# managed windows == things with a (optional) caption you can close # managed windows == things with a (optional) caption you can close
@@ -132,6 +125,7 @@ _treeList = [
'wxIntCtrl', 'wxIntCtrl',
'wxLEDNumberCtrl', 'wxLEDNumberCtrl',
'wxMimeTypesManager', 'wxMimeTypesManager',
'wxMaskedNumCtrl',
'wxMultiSash', 'wxMultiSash',
'wxPopupControl', 'wxPopupControl',
'wxStyledTextCtrl_1', 'wxStyledTextCtrl_1',

View File

@@ -1,10 +1,12 @@
from wxPython.wx import * from wxPython.wx import *
from wxPython.lib.maskededit import Field, wxMaskedTextCtrl, wxMaskedComboBox, wxIpAddrCtrl, states, months from wxPython.lib.maskededit import Field, wxMaskedTextCtrl, wxMaskedComboBox, wxIpAddrCtrl, states, state_names, months
from wxPython.lib.maskededit import __doc__ as overviewdoc from wxPython.lib.maskededit import __doc__ as maskededit_doc
from wxPython.lib.maskededit import autoformats from wxPython.lib.maskededit import autoformats
from wxPython.lib.maskedctrl import wxMaskedCtrl, controlTypes, MASKEDCOMBO
from wxPython.lib.scrolledpanel import wxScrolledPanel from wxPython.lib.scrolledpanel import wxScrolledPanel
import string, sys, traceback import string, sys, traceback
class demoMixin: class demoMixin:
""" """
Centralized routines common to demo pages, to remove repetition. Centralized routines common to demo pages, to remove repetition.
@@ -14,7 +16,7 @@ class demoMixin:
mask = wxStaticText( self, -1, "Mask Value" ) mask = wxStaticText( self, -1, "Mask Value" )
formatcode = wxStaticText( self, -1, "Format" ) formatcode = wxStaticText( self, -1, "Format" )
regex = wxStaticText( self, -1, "Regexp Validator(opt.)" ) regex = wxStaticText( self, -1, "Regexp Validator(opt.)" )
ctrl = wxStaticText( self, -1, "wxMaskedEdit Ctrl" ) ctrl = wxStaticText( self, -1, "wxMaskedTextCtrl" )
description.SetFont( wxFont(9, wxSWISS, wxNORMAL, wxBOLD)) description.SetFont( wxFont(9, wxSWISS, wxNORMAL, wxBOLD))
mask.SetFont( wxFont(9, wxSWISS, wxNORMAL, wxBOLD)) mask.SetFont( wxFont(9, wxSWISS, wxNORMAL, wxBOLD))
@@ -130,7 +132,7 @@ Smith, Jones, Williams). Signs on numbers can be toggled with the minus key.
def onHighlightEmpty( self, event ): def onHighlightEmpty( self, event ):
""" Highlight empty values""" """ Highlight empty values"""
self.changeControlParams( event, "emptyBackgroundColor", "Blue", "White" ) self.changeControlParams( event, "emptyBackgroundColour", "Blue", "White" )
def onShowFill( self, event ): def onShowFill( self, event ):
""" Set fillChar parameter to '?' or ' ' """ """ Set fillChar parameter to '?' or ' ' """
@@ -144,8 +146,9 @@ class demoPage2(wxScrolledPanel, demoMixin):
self.sizer = wxBoxSizer( wxVERTICAL ) self.sizer = wxBoxSizer( wxVERTICAL )
label = wxStaticText( self, -1, """\ label = wxStaticText( self, -1, """\
All these controls have been created by passing a single parameter, the autoformat code. All these controls have been created by passing a single parameter, the autoformat code,
The class contains an internal dictionary of types and formats (autoformats). and use the factory class wxMaskedCtrl with its default controlType.
The maskededit module contains an internal dictionary of types and formats (autoformats).
Many of these already do complicated validation; To see some examples, try Many of these already do complicated validation; To see some examples, try
29 Feb 2002 vs. 2004 for the date formats, or email address validation. 29 Feb 2002 vs. 2004 for the date formats, or email address validation.
""") """)
@@ -155,7 +158,7 @@ Many of these already do complicated validation; To see some examples, try
description = wxStaticText( self, -1, "Description") description = wxStaticText( self, -1, "Description")
autofmt = wxStaticText( self, -1, "AutoFormat Code") autofmt = wxStaticText( self, -1, "AutoFormat Code")
ctrl = wxStaticText( self, -1, "wxMaskedEdit Control") ctrl = wxStaticText( self, -1, "wxMaskedCtrl")
description.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) ) description.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) )
autofmt.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) ) autofmt.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) )
@@ -169,10 +172,10 @@ Many of these already do complicated validation; To see some examples, try
for autoformat, desc in autoformats: for autoformat, desc in autoformats:
grid.Add( wxStaticText( self, -1, desc), 0, wxALIGN_LEFT ) grid.Add( wxStaticText( self, -1, desc), 0, wxALIGN_LEFT )
grid.Add( wxStaticText( self, -1, autoformat), 0, wxALIGN_LEFT ) grid.Add( wxStaticText( self, -1, autoformat), 0, wxALIGN_LEFT )
grid.Add( wxMaskedTextCtrl( self, -1, "", grid.Add( wxMaskedCtrl( self, -1, "",
autoformat = autoformat, autoformat = autoformat,
demo = True, demo = True,
name = autoformat), name = autoformat),
0, wxALIGN_LEFT ) 0, wxALIGN_LEFT )
self.sizer.Add( grid, 0, wxALIGN_LEFT|wxALL, border=5 ) self.sizer.Add( grid, 0, wxALIGN_LEFT|wxALL, border=5 )
@@ -208,7 +211,7 @@ has a legal range specified.
controls = [ controls = [
#description mask excl format regexp range,list,initial #description mask excl format regexp range,list,initial
("U.S. State (2 char)", "AA", "", 'F!_', "[A-Z]{2}", '',states, states[0]), ("U.S. State (2 char)", "AA", "", 'F!_', "[A-Z]{2}", '',states, states[0]),
("Integer (signed)", "#{6}", "", 'F-_R', "", '','', '0 '), ("Integer (signed)", "#{6}", "", 'F-_', "", '','', ' 0 '),
("Integer (unsigned)\n(1-399)","######", "", 'F_', "", (1,399),'', '1 '), ("Integer (unsigned)\n(1-399)","######", "", 'F_', "", (1,399),'', '1 '),
("Float (signed)", "#{6}.#{9}", "", 'F-_R', "", '','', '000000.000000000'), ("Float (signed)", "#{6}.#{9}", "", 'F-_R', "", '','', '000000.000000000'),
("Date (MDY) + Time", "##/##/#### ##:##:## AM", 'BCDEFGHIJKLMNOQRSTUVWXYZ','DF!',"", '','', wxDateTime_Now().Format("%m/%d/%Y %I:%M:%S %p")), ("Date (MDY) + Time", "##/##/#### ##:##:## AM", 'BCDEFGHIJKLMNOQRSTUVWXYZ','DF!',"", '','', wxDateTime_Now().Format("%m/%d/%Y %I:%M:%S %p")),
@@ -248,7 +251,7 @@ Page Up and Shift-Up arrow will similarly cycle backwards through the list.
description = wxStaticText( self, -1, "Description" ) description = wxStaticText( self, -1, "Description" )
autofmt = wxStaticText( self, -1, "AutoFormat Code" ) autofmt = wxStaticText( self, -1, "AutoFormat Code" )
fields = wxStaticText( self, -1, "Field Objects" ) fields = wxStaticText( self, -1, "Field Objects" )
ctrl = wxStaticText( self, -1, "wxMaskedEdit Control" ) ctrl = wxStaticText( self, -1, "wxMaskedTextCtrl" )
description.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) ) description.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) )
autofmt.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) ) autofmt.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) )
@@ -325,12 +328,33 @@ class demoPage5(wxScrolledPanel, demoMixin):
self.log = log self.log = log
wxScrolledPanel.__init__( self, parent, -1 ) wxScrolledPanel.__init__( self, parent, -1 )
self.sizer = wxBoxSizer( wxVERTICAL ) self.sizer = wxBoxSizer( wxVERTICAL )
label = wxStaticText( self, -1, """\
These are examples of wxMaskedComboBox and wxIpAddrCtrl, and more useful
configurations of a wxMaskedTextCtrl for integer and floating point input. labelMaskedCombos = wxStaticText( self, -1, """\
""") These are some examples of wxMaskedComboBox:""")
label.SetForegroundColour( "Blue" ) labelMaskedCombos.SetForegroundColour( "Blue" )
self.sizer.Add( label, 0, wxALIGN_LEFT|wxALL, 5 )
label_statecode = wxStaticText( self, -1, """\
A state selector; only
"legal" values can be
entered:""")
statecode = wxMaskedComboBox( self, -1, states[0],
choices = states,
autoformat="USSTATE")
label_statename = wxStaticText( self, -1, """\
A state name selector,
with auto-select:""")
# Create this one using factory function:
statename = wxMaskedCtrl( self, -1, state_names[0],
controlType = controlTypes.MASKEDCOMBO,
choices = state_names,
autoformat="USSTATENAME",
autoSelect=True)
statename.SetCtrlParameters(formatcodes = 'F!V_')
numerators = [ str(i) for i in range(1, 4) ] numerators = [ str(i) for i in range(1, 4) ]
denominators = [ string.ljust(str(i), 2) for i in [2,3,4,5,8,16,32,64] ] denominators = [ string.ljust(str(i), 2) for i in [2,3,4,5,8,16,32,64] ]
@@ -343,21 +367,22 @@ configurations of a wxMaskedTextCtrl for integer and floating point input.
choices.append( '%s/%s' % (n,d) ) choices.append( '%s/%s' % (n,d) )
text1 = wxStaticText( self, -1, """\ label_fraction = wxStaticText( self, -1, """\
A masked ComboBox for fraction selection. A masked ComboBox for fraction selection.
Choices for each side of the fraction can be Choices for each side of the fraction can
selected with PageUp/Down:""") be selected with PageUp/Down:""")
fraction = wxMaskedComboBox( self, -1, "", fraction = wxMaskedCtrl( self, -1, "",
choices = choices, controlType = MASKEDCOMBO,
choiceRequired = True, choices = choices,
mask = "#/##", choiceRequired = True,
formatcodes = "F_", mask = "#/##",
validRegex = "^\d\/\d\d?", formatcodes = "F_",
fields = fieldsDict ) validRegex = "^\d\/\d\d?",
fields = fieldsDict )
text2 = wxStaticText( self, -1, """ label_code = wxStaticText( self, -1, """\
A masked ComboBox to validate A masked ComboBox to validate
text from a list of numeric codes:""") text from a list of numeric codes:""")
@@ -368,100 +393,155 @@ text from a list of numeric codes:""")
formatcodes = "F_r", formatcodes = "F_r",
mask = "####") mask = "####")
label_selector = wxStaticText( self, -1, """\
Programmatically set
choice sets:""")
self.list_selector = wxComboBox(self, -1, '', choices = ['list1', 'list2', 'list3'])
self.dynamicbox = wxMaskedCtrl( self, -1, ' ',
controlType = controlTypes.MASKEDCOMBO,
mask = 'XXXX',
formatcodes = 'F_',
# these are to give dropdown some initial height,
# as base control apparently only sets that size
# during initial construction <sigh>:
choices = ['', '1', '2', '3', '4', '5'] )
text3 = wxStaticText( self, -1, """\ self.dynamicbox.Clear() # get rid of initial choices used to size the dropdown
A masked state selector; only "legal" values
can be entered:""")
state = wxMaskedComboBox( self, -1, states[0],
choices = states,
autoformat="USSTATE")
text4 = wxStaticText( self, -1, "An empty IP Address entry control:")
ip_addr1 = wxIpAddrCtrl( self, -1, style = wxTE_PROCESS_TAB )
text5 = wxStaticText( self, -1, "An IP Address control with a restricted mask:") labelIpAddrs = wxStaticText( self, -1, """\
ip_addr2 = wxIpAddrCtrl( self, -1, mask=" 10. 1.109.###" ) Here are some examples of wxIpAddrCtrl, a control derived from wxMaskedTextCtrl:""")
labelIpAddrs.SetForegroundColour( "Blue" )
text6 = wxStaticText( self, -1, """\ label_ipaddr1 = wxStaticText( self, -1, "An empty control:")
An IP Address control with restricted choices ipaddr1 = wxIpAddrCtrl( self, -1, style = wxTE_PROCESS_TAB )
of form: 10. (1|2) . (129..255) . (0..255)""")
ip_addr3 = wxIpAddrCtrl( self, -1, mask=" 10. #.###.###")
ip_addr3.SetFieldParameters(0, validRegex="1|2" ) # requires entry to match or not allowed
label_ipaddr2 = wxStaticText( self, -1, "A restricted mask:")
ipaddr2 = wxIpAddrCtrl( self, -1, mask=" 10. 1.109.###" )
label_ipaddr3 = wxStaticText( self, -1, """\
A control with restricted legal values:
10. (1|2) . (129..255) . (0..255)""")
ipaddr3 = wxMaskedCtrl( self, -1,
controlType = controlTypes.IPADDR,
mask=" 10. #.###.###")
ipaddr3.SetFieldParameters(0, validRegex="1|2",validRequired=False ) # requires entry to match or not allowed
# This allows any value in penultimate field, but colors anything outside of the range invalid: # This allows any value in penultimate field, but colors anything outside of the range invalid:
ip_addr3.SetFieldParameters(1, validRange=(129,255), validRequired=False ) ipaddr3.SetFieldParameters(1, validRange=(129,255), validRequired=False )
text7 = wxStaticText( self, -1, """\
A right-insert integer entry control:""")
intctrl = wxMaskedTextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-r,F')
text8 = wxStaticText( self, -1, """\
labelNumerics = wxStaticText( self, -1, """\
Here are some useful configurations of a wxMaskedTextCtrl for integer and floating point input that still treat
the control as a text control. (For a true numeric control, check out the wxMaskedNumCtrl class!)""")
labelNumerics.SetForegroundColour( "Blue" )
label_intctrl1 = wxStaticText( self, -1, """\
An integer entry control with
shifting insert enabled:""")
self.intctrl1 = wxMaskedTextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-,F>')
label_intctrl2 = wxStaticText( self, -1, """\
Right-insert integer entry:""")
self.intctrl2 = wxMaskedTextCtrl(self, -1, name='intctrl', mask="#{9}", formatcodes = '_-,Fr')
label_floatctrl = wxStaticText( self, -1, """\
A floating point entry control A floating point entry control
with right-insert for ordinal:""") with right-insert for ordinal:""")
self.floatctrl = wxMaskedTextCtrl(self, -1, name='floatctrl', mask="#{9}.#{2}", formatcodes="F,_-R") self.floatctrl = wxMaskedTextCtrl(self, -1, name='floatctrl', mask="#{9}.#{2}", formatcodes="F,_-R", useParensForNegatives=False)
self.floatctrl.SetFieldParameters(0, formatcodes='r<', validRequired=True) # right-insert, require explicit cursor movement to change fields self.floatctrl.SetFieldParameters(0, formatcodes='r<', validRequired=True) # right-insert, require explicit cursor movement to change fields
self.floatctrl.SetFieldParameters(1, defaultValue='00') # don't allow blank fraction self.floatctrl.SetFieldParameters(1, defaultValue='00') # don't allow blank fraction
text9 = wxStaticText( self, -1, """\ label_numselect = wxStaticText( self, -1, """\
Use this control to programmatically set <= Programmatically set the value
the value of the above float control:""") of the float entry ctrl:""")
number_combo = wxComboBox(self, -1, choices = [ '', '111', '222.22', '-3', '54321.666666666', '-1353.978', numselect = wxComboBox(self, -1, choices = [ '', '111', '222.22', '-3', '54321.666666666', '-1353.978',
'1234567', '-1234567', '123456789', '-123456789.1', '1234567', '-1234567', '123456789', '-123456789.1',
'1234567890.', '-1234567890.1' ]) '1234567890.', '-1234567890.1' ])
grid = wxFlexGridSizer( 0, 2, vgap=10, hgap = 5 ) parens_check = wxCheckBox(self, -1, "Use () to indicate negatives in above controls")
grid.Add( text1, 0, wxALIGN_LEFT )
grid.Add( fraction, 0, wxALIGN_LEFT )
grid.Add( text2, 0, wxALIGN_LEFT )
grid.Add( code, 0, wxALIGN_LEFT ) gridCombos = wxFlexGridSizer( 0, 4, vgap=10, hgap = 10 )
grid.Add( text3, 0, wxALIGN_LEFT ) gridCombos.Add( label_statecode, 0, wxALIGN_LEFT )
grid.Add( state, 0, wxALIGN_LEFT ) gridCombos.Add( statecode, 0, wxALIGN_LEFT )
grid.Add( text4, 0, wxALIGN_LEFT ) gridCombos.Add( label_fraction, 0, wxALIGN_LEFT )
grid.Add( ip_addr1, 0, wxALIGN_LEFT ) gridCombos.Add( fraction, 0, wxALIGN_LEFT )
grid.Add( text5, 0, wxALIGN_LEFT ) gridCombos.Add( label_statename, 0, wxALIGN_LEFT )
grid.Add( ip_addr2, 0, wxALIGN_LEFT ) gridCombos.Add( statename, 0, wxALIGN_LEFT )
grid.Add( text6, 0, wxALIGN_LEFT ) gridCombos.Add( label_code, 0, wxALIGN_LEFT )
grid.Add( ip_addr3, 0, wxALIGN_LEFT ) gridCombos.Add( code, 0, wxALIGN_LEFT )
grid.Add( text7, 0, wxALIGN_LEFT ) gridCombos.Add( label_selector, 0, wxALIGN_LEFT)
grid.Add( intctrl, 0, wxALIGN_LEFT ) hbox = wxBoxSizer( wxHORIZONTAL )
grid.Add( text8, 0, wxALIGN_LEFT ) hbox.Add( self.list_selector, 0, wxALIGN_LEFT )
grid.Add( self.floatctrl, 0, wxALIGN_LEFT ) hbox.Add(wxStaticText(self, -1, ' => '), 0, wxALIGN_LEFT)
grid.Add( text9, 0, wxALIGN_LEFT ) hbox.Add( self.dynamicbox, 0, wxALIGN_LEFT )
grid.Add( number_combo, 0, wxALIGN_LEFT ) gridCombos.Add( hbox, 0, wxALIGN_LEFT )
gridIpAddrs = wxFlexGridSizer( 0, 4, vgap=10, hgap = 15 )
gridIpAddrs.Add( label_ipaddr1, 0, wxALIGN_LEFT )
gridIpAddrs.Add( ipaddr1, 0, wxALIGN_LEFT )
gridIpAddrs.Add( label_ipaddr2, 0, wxALIGN_LEFT )
gridIpAddrs.Add( ipaddr2, 0, wxALIGN_LEFT )
gridIpAddrs.Add( label_ipaddr3, 0, wxALIGN_LEFT )
gridIpAddrs.Add( ipaddr3, 0, wxALIGN_LEFT )
gridNumerics = wxFlexGridSizer( 0, 4, vgap=10, hgap = 10 )
gridNumerics.Add( label_intctrl1, 0, wxALIGN_LEFT )
gridNumerics.Add( self.intctrl1, 0, wxALIGN_LEFT )
gridNumerics.Add( label_intctrl2, 0, wxALIGN_RIGHT )
gridNumerics.Add( self.intctrl2, 0, wxALIGN_LEFT )
gridNumerics.Add( label_floatctrl, 0, wxALIGN_LEFT )
gridNumerics.Add( self.floatctrl, 0, wxALIGN_LEFT )
gridNumerics.Add( label_numselect, 0, wxALIGN_RIGHT )
gridNumerics.Add( numselect, 0, wxALIGN_LEFT )
self.sizer.Add( labelMaskedCombos, 0, wxALIGN_LEFT|wxALL, 5 )
self.sizer.Add( gridCombos, 0, wxALIGN_LEFT|wxALL, border=5 )
self.sizer.Add( wxStaticLine(self, -1), 0, wxEXPAND|wxTOP|wxBOTTOM, border=8 )
self.sizer.Add( labelIpAddrs, 0, wxALIGN_LEFT|wxALL, 5 )
self.sizer.Add( gridIpAddrs, 0, wxALIGN_LEFT|wxALL, border=5 )
self.sizer.Add( wxStaticLine(self, -1), 0, wxEXPAND|wxTOP|wxBOTTOM, border=8 )
self.sizer.Add( labelNumerics, 0, wxALIGN_LEFT|wxALL, 5 )
self.sizer.Add( gridNumerics, 0, wxALIGN_LEFT|wxALL, border=5 )
self.sizer.Add( parens_check, 0, wxALIGN_LEFT|wxALL, 5 )
self.sizer.Add( grid, 0, wxALIGN_LEFT|wxALL, border=5 )
self.SetSizer( self.sizer ) self.SetSizer( self.sizer )
self.SetAutoLayout(1) self.SetAutoLayout(1)
self.SetupScrolling() self.SetupScrolling()
EVT_COMBOBOX( self, fraction.GetId(), self.OnComboChange ) EVT_COMBOBOX( self, fraction.GetId(), self.OnComboSelection )
EVT_COMBOBOX( self, code.GetId(), self.OnComboChange ) EVT_COMBOBOX( self, code.GetId(), self.OnComboSelection )
EVT_COMBOBOX( self, state.GetId(), self.OnComboChange ) EVT_COMBOBOX( self, statecode.GetId(), self.OnComboSelection )
EVT_TEXT( self, fraction.GetId(), self.OnComboChange ) EVT_COMBOBOX( self, statename.GetId(), self.OnComboSelection )
EVT_TEXT( self, code.GetId(), self.OnComboChange ) EVT_TEXT( self, fraction.GetId(), self.OnTextChange )
EVT_TEXT( self, state.GetId(), self.OnComboChange ) EVT_TEXT( self, code.GetId(), self.OnTextChange )
EVT_TEXT( self, statecode.GetId(), self.OnTextChange )
EVT_TEXT( self, statename.GetId(), self.OnTextChange )
EVT_COMBOBOX( self, self.list_selector.GetId(), self.OnListSelection )
EVT_TEXT( self, ip_addr1.GetId(), self.OnIpAddrChange ) EVT_TEXT( self, self.intctrl1.GetId(), self.OnTextChange )
EVT_TEXT( self, ip_addr2.GetId(), self.OnIpAddrChange ) EVT_TEXT( self, self.intctrl2.GetId(), self.OnTextChange )
EVT_TEXT( self, ip_addr3.GetId(), self.OnIpAddrChange )
EVT_TEXT( self, intctrl.GetId(), self.OnTextChange )
EVT_TEXT( self, self.floatctrl.GetId(), self.OnTextChange ) EVT_TEXT( self, self.floatctrl.GetId(), self.OnTextChange )
EVT_COMBOBOX( self, number_combo.GetId(), self.OnNumberSelect ) EVT_COMBOBOX( self, numselect.GetId(), self.OnNumberSelect )
EVT_CHECKBOX( self, parens_check.GetId(), self.OnParensCheck )
EVT_TEXT( self, ipaddr1.GetId(), self.OnIpAddrChange )
EVT_TEXT( self, ipaddr2.GetId(), self.OnIpAddrChange )
EVT_TEXT( self, ipaddr3.GetId(), self.OnIpAddrChange )
def OnComboChange( self, event ):
def OnComboSelection( self, event ):
ctl = self.FindWindowById( event.GetId() ) ctl = self.FindWindowById( event.GetId() )
if not ctl.IsValid(): if not ctl.IsValid():
self.log.write('current value not a valid choice') self.log.write('current value not a valid choice')
self.log.write('new value = %s' % ctl.GetValue())
def OnIpAddrChange( self, event ):
ip_addr = self.FindWindowById( event.GetId() )
if ip_addr.IsValid():
self.log.write('new addr = %s\n' % ip_addr.GetAddress() )
def OnTextChange( self, event ): def OnTextChange( self, event ):
ctl = self.FindWindowById( event.GetId() ) ctl = self.FindWindowById( event.GetId() )
@@ -470,14 +550,8 @@ the value of the above float control:""")
def OnNumberSelect( self, event ): def OnNumberSelect( self, event ):
value = event.GetString() value = event.GetString()
# Format choice to fit into format for #{9}.#{2}, with sign position reserved: # Format choice to fit into format for #{9}.#{2}, with sign position reserved:
# (ordinal + fraction == 11 + decimal point + sign == 13) # (ordinal + fraction == 11 + decimal point + sign == 13)
#
# Note: since self.floatctrl a right-aligned control, you could also just use
# "%.2f", but this wouldn't work properly for a left-aligned control.
# (See .SetValue() documentation in Overview.)
#
if value: if value:
floattext = "%13.2f" % float(value) floattext = "%13.2f" % float(value)
else: else:
@@ -489,6 +563,37 @@ the value of the above float control:""")
for line in traceback.format_exception_only(type, value): for line in traceback.format_exception_only(type, value):
self.log.write(line) self.log.write(line)
def OnParensCheck( self, event ):
self.intctrl1.SetCtrlParameters(useParensForNegatives=event.Checked())
self.intctrl2.SetCtrlParameters(useParensForNegatives=event.Checked())
self.floatctrl.SetCtrlParameters(useParensForNegatives=event.Checked())
def OnIpAddrChange( self, event ):
ipaddr = self.FindWindowById( event.GetId() )
if ipaddr.IsValid():
self.log.write('new addr = %s\n' % ipaddr.GetAddress() )
def OnListSelection( self, event ):
list = self.list_selector.GetStringSelection()
formatcodes = 'F_'
if list == 'list1':
choices = ['abc', 'defg', 'hi']
mask = 'aaaa'
elif list == 'list2':
choices = ['1', '2', '34', '567']
formatcodes += 'r'
mask = '###'
else:
choices = states
mask = 'AA'
formatcodes += '!'
self.dynamicbox.SetCtrlParameters( mask = mask,
choices = choices,
choiceRequired=True,
autoSelect=True,
formatcodes=formatcodes)
self.dynamicbox.SetValue(choices[0])
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
class TestMaskedTextCtrls(wxNotebook): class TestMaskedTextCtrls(wxNotebook):
def __init__(self, parent, id, log): def __init__(self, parent, id, log):
@@ -530,7 +635,7 @@ if __name__ == "__main__":
overview = """<html> overview = """<html>
<PRE><FONT SIZE=-1> <PRE><FONT SIZE=-1>
""" + overviewdoc + """ """ + maskededit_doc + """
</FONT></PRE> </FONT></PRE>
""" """

View File

@@ -0,0 +1,335 @@
from wxPython.wx import *
from wxPython.lib.maskednumctrl import wxMaskedNumCtrl, EVT_MASKEDNUM
from wxPython.lib.maskednumctrl import __doc__ as overviewdoc
from wxPython.lib.maskededit import wxMaskedTextCtrl
import string, sys, traceback
#----------------------------------------------------------------------
class TestPanel( wxPanel ):
def __init__( self, parent, log ):
wxPanel.__init__( self, parent, -1 )
self.log = log
panel = wxPanel( self, -1 )
header = wxStaticText(panel, -1, """\
This shows the various options for wxMaskedNumCtrl.
The controls at the top reconfigure the resulting control at the bottom.
""")
header.SetForegroundColour( "Blue" )
intlabel = wxStaticText( panel, -1, "Integer width:" )
self.integerwidth = wxMaskedNumCtrl(
panel, value=10,
integerWidth=2,
allowNegative=False)
fraclabel = wxStaticText( panel, -1, "Fraction width:" )
self.fractionwidth = wxMaskedNumCtrl(
panel, value=0,
integerWidth=2,
allowNegative=False )
groupcharlabel = wxStaticText( panel,-1, "Grouping char:" )
self.groupchar = wxMaskedTextCtrl( panel, -1,
value=',',
mask='&',
excludeChars = '-()',
formatcodes='F',
emptyInvalid=True,
validRequired=True)
decimalcharlabel = wxStaticText( panel,-1, "Decimal char:" )
self.decimalchar = wxMaskedTextCtrl( panel, -1,
value='.',
mask='&',
excludeChars = '-()',
formatcodes='F',
emptyInvalid=True,
validRequired=True)
self.set_min = wxCheckBox( panel, -1, "Set minimum value:" )
# Create this wxMaskedNumCtrl using factory, to show how:
self.min = wxMaskedNumCtrl( panel, integerWidth=5, fractionWidth=2 )
self.min.Enable( False )
self.set_max = wxCheckBox( panel, -1, "Set maximum value:" )
self.max = wxMaskedNumCtrl( panel, integerWidth=5, fractionWidth=2 )
self.max.Enable( False )
self.limit_target = wxCheckBox( panel, -1, "Limit control" )
self.allow_none = wxCheckBox( panel, -1, "Allow empty control" )
self.group_digits = wxCheckBox( panel, -1, "Group digits" )
self.group_digits.SetValue( True )
self.allow_negative = wxCheckBox( panel, -1, "Allow negative values" )
self.allow_negative.SetValue( True )
self.use_parens = wxCheckBox( panel, -1, "Use parentheses" )
self.select_on_entry = wxCheckBox( panel, -1, "Select on entry" )
self.select_on_entry.SetValue( True )
label = wxStaticText( panel, -1, "Resulting numeric control:" )
font = label.GetFont()
font.SetWeight(wxBOLD)
label.SetFont(font)
self.target_ctl = wxMaskedNumCtrl( panel, -1, name="target control" )
label_numselect = wxStaticText( panel, -1, """\
Programmatically set the above
value entry ctrl:""")
self.numselect = wxComboBox(panel, -1, choices = [ '0', '111', '222.22', '-3', '54321.666666666', '-1353.978',
'1234567', '-1234567', '123456789', '-123456789.1',
'1234567890.', '-9876543210.9' ])
grid1 = wxFlexGridSizer( 0, 4, 0, 0 )
grid1.Add( intlabel, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5)
grid1.Add( self.integerwidth, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( groupcharlabel, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5)
grid1.Add( self.groupchar, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( fraclabel, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5 )
grid1.Add( self.fractionwidth, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( decimalcharlabel, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5)
grid1.Add( self.decimalchar, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( self.set_min, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5 )
grid1.Add( self.min, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( self.set_max, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5 )
grid1.Add( self.max, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( self.limit_target, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( self.allow_none, 0, wxALIGN_LEFT|wxALL, 5 )
hbox1 = wxBoxSizer( wxHORIZONTAL )
hbox1.Add( (17,5), 0, wxALIGN_LEFT|wxALL, 5)
hbox1.Add( self.group_digits, 0, wxALIGN_LEFT|wxLEFT, 5 )
grid1.Add( hbox1, 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( self.allow_negative, 0, wxALIGN_LEFT|wxALL, 5 )
grid1.Add( self.use_parens, 0, wxALIGN_LEFT|wxALL, 5 )
hbox2 = wxBoxSizer( wxHORIZONTAL )
hbox2.Add( (17,5), 0, wxALIGN_LEFT|wxALL, 5)
hbox2.Add( self.select_on_entry, 0, wxALIGN_LEFT|wxLEFT, 5 )
grid1.Add( hbox2, 0, wxALIGN_LEFT|wxALL, 5)
grid1.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid2 = wxFlexGridSizer( 0, 2, 0, 0 )
grid2.Add( label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5 )
grid2.Add( self.target_ctl, 0, wxALIGN_LEFT|wxALL, 5 )
grid2.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid2.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid2.Add( label_numselect, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5 )
grid2.Add( self.numselect, 0, wxALIGN_LEFT|wxALL, 5 )
grid2.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid2.Add( (5,5), 0, wxALIGN_LEFT|wxALL, 5)
grid2.AddGrowableCol(1)
self.outer_box = wxBoxSizer( wxVERTICAL )
self.outer_box.Add(header, 0, wxALIGN_LEFT|wxTOP|wxLEFT, 20)
self.outer_box.Add( grid1, 0, wxALIGN_CENTRE|wxLEFT|wxBOTTOM|wxRIGHT, 20 )
self.outer_box.Add( grid2, 0, wxALIGN_LEFT|wxALL, 20 )
self.grid2 = grid2
panel.SetAutoLayout( True )
panel.SetSizer( self.outer_box )
self.outer_box.Fit( panel )
panel.Move( (50,10) )
self.panel = panel
EVT_MASKEDNUM( self, self.integerwidth.GetId(), self.OnSetIntWidth )
EVT_MASKEDNUM( self, self.fractionwidth.GetId(), self.OnSetFractionWidth )
EVT_TEXT( self, self.groupchar.GetId(), self.OnSetGroupChar )
EVT_TEXT( self, self.decimalchar.GetId(), self.OnSetDecimalChar )
EVT_CHECKBOX( self, self.set_min.GetId(), self.OnSetMin )
EVT_CHECKBOX( self, self.set_max.GetId(), self.OnSetMax )
EVT_MASKEDNUM( self, self.min.GetId(), self.SetTargetMinMax )
EVT_MASKEDNUM( self, self.max.GetId(), self.SetTargetMinMax )
EVT_CHECKBOX( self, self.limit_target.GetId(), self.SetTargetMinMax )
EVT_CHECKBOX( self, self.allow_none.GetId(), self.OnSetAllowNone )
EVT_CHECKBOX( self, self.group_digits.GetId(), self.OnSetGroupDigits )
EVT_CHECKBOX( self, self.allow_negative.GetId(), self.OnSetAllowNegative )
EVT_CHECKBOX( self, self.use_parens.GetId(), self.OnSetUseParens )
EVT_CHECKBOX( self, self.select_on_entry.GetId(), self.OnSetSelectOnEntry )
EVT_MASKEDNUM( self, self.target_ctl.GetId(), self.OnTargetChange )
EVT_COMBOBOX( self, self.numselect.GetId(), self.OnNumberSelect )
def OnSetIntWidth(self, event ):
width = self.integerwidth.GetValue()
if width < 1:
self.log.write("integer width must be positive\n")
self.integerwidth.SetForegroundColour(wxRED)
else:
self.integerwidth.SetForegroundColour(wxBLACK)
self.log.write("setting integer width to %d\n" % width)
self.target_ctl.SetParameters( integerWidth = width)
# Now resize and fit the dialog as appropriate:
self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize())
self.outer_box.Fit( self.panel )
self.outer_box.SetSizeHints( self.panel )
def OnSetFractionWidth(self, event ):
width = self.fractionwidth.GetValue()
self.log.write("setting fraction width to %d\n" % width)
self.target_ctl.SetParameters( fractionWidth = width)
# Now resize and fit the dialog as appropriate:
self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize())
self.outer_box.Fit( self.panel )
self.outer_box.SetSizeHints( self.panel )
def OnSetGroupChar( self, event ):
char = self.groupchar.GetValue()
if self.target_ctl.GetDecimalChar() == char:
self.log.write("group and decimal chars must be different\n")
self.groupchar.SetForegroundColour(wxRED)
else:
self.groupchar.SetForegroundColour(wxBLACK)
self.log.write("setting group char to %s\n" % char)
self.target_ctl.SetGroupChar( char )
def OnSetDecimalChar( self, event ):
char = self.decimalchar.GetValue()
if self.target_ctl.GetGroupChar() == char:
self.log.write("group and decimal chars must be different\n")
self.decimalchar.SetForegroundColour(wxRED)
else:
self.decimalchar.SetForegroundColour(wxBLACK)
self.log.write("setting decimal char to %s\n" % char)
self.target_ctl.SetDecimalChar( char )
def OnSetMin( self, event ):
self.min.Enable( self.set_min.GetValue() )
self.SetTargetMinMax()
def OnSetMax( self, event ):
self.max.Enable( self.set_max.GetValue() )
self.SetTargetMinMax()
def SetTargetMinMax( self, event=None ):
min = max = None
self.target_ctl.SetLimited( self.limit_target.GetValue() )
if self.set_min.GetValue():
min = self.min.GetValue()
if self.set_max.GetValue():
max = self.max.GetValue()
cur_min, cur_max = self.target_ctl.GetBounds()
if min != cur_min and not self.target_ctl.SetMin( min ):
if self.target_ctl.GetMax() is None and cur_max > min:
self.log.write( "min (%d) won't fit in control -- bound not set\n" % min )
else:
self.log.write( "min (%d) > current max (%d) -- bound not set\n" % ( min, self.target_ctl.GetMax() ) )
self.min.SetParameters( signedForegroundColour=wxRED, foregroundColour=wxRED )
else:
self.min.SetParameters( signedForegroundColour=wxBLACK, foregroundColour=wxBLACK )
self.min.Refresh()
if max != cur_max and not self.target_ctl.SetMax( max ):
if self.target_ctl.GetMax() is None and cur_min < max:
self.log.write( "max (%d) won't fit in control -- bound not set\n" % max )
else:
self.log.write( "max (%d) < current min (%d) -- bound not set\n" % ( max, self.target_ctl.GetMin() ) )
self.max.SetParameters( signedForegroundColour=wxRED, foregroundColour=wxRED )
else:
self.max.SetParameters( signedForegroundColour=wxBLACK, foregroundColour=wxBLACK )
self.max.Refresh()
if min != cur_min or max != cur_max:
new_min, new_max = self.target_ctl.GetBounds()
self.log.write( "current min, max: (%s, %s)\n" % ( str(new_min), str(new_max) ) )
def OnSetAllowNone( self, event ):
self.target_ctl.SetAllowNone( self.allow_none.GetValue() )
def OnSetGroupDigits( self, event ):
self.target_ctl.SetGroupDigits( self.group_digits.GetValue() )
# Now resize and fit the dialog as appropriate:
self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize())
self.outer_box.Fit( self.panel )
self.outer_box.SetSizeHints( self.panel )
def OnSetAllowNegative( self, event ):
if self.allow_negative.GetValue():
self.use_parens.Enable(True)
self.target_ctl.SetParameters(allowNegative=True,
useParensForNegatives = self.use_parens.GetValue())
else:
self.target_ctl.SetAllowNegative(False)
# Now resize and fit the dialog as appropriate:
self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize())
self.outer_box.Fit( self.panel )
self.outer_box.SetSizeHints( self.panel )
def OnSetUseParens( self, event ):
self.target_ctl.SetUseParensForNegatives( self.use_parens.GetValue() )
# Now resize and fit the dialog as appropriate:
self.grid2.SetItemMinSize(self.target_ctl, self.target_ctl.GetSize())
self.outer_box.Fit( self.panel )
self.outer_box.SetSizeHints( self.panel )
def OnSetSelectOnEntry( self, event ):
self.target_ctl.SetSelectOnEntry( self.select_on_entry.GetValue() )
def OnTargetChange( self, event ):
ctl = event.GetEventObject()
value = ctl.GetValue()
ib_str = [ " (out of bounds)", "" ]
self.log.write( "value = %s (%s)%s\n" % ( repr(value), repr(type(value)), ib_str[ ctl.IsInBounds(value) ] ) )
def OnNumberSelect( self, event ):
value = event.GetString()
if value:
if value.find('.') != -1:
numvalue = float(value)
else:
numvalue = long(value)
else:
numvalue = value # try to clear the value again
try:
self.target_ctl.SetValue(numvalue)
except:
type, value, tb = sys.exc_info()
for line in traceback.format_exception_only(type, value):
self.log.write(line)
#----------------------------------------------------------------------
def runTest( frame, nb, log ):
win = TestPanel( nb, log )
return win
#----------------------------------------------------------------------
overview = overviewdoc
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])])

View File

@@ -0,0 +1,101 @@
#----------------------------------------------------------------------------
# Name: wxPython.lib.maskedctrl.py
# Author: Will Sadkin
# Created: 09/24/2003
# Copyright: (c) 2003 by Will Sadkin
# RCS-ID: $Id$
# License: wxWindows license
#----------------------------------------------------------------------------
"""<html><body>
<P>
<B>wxMaskedCtrl</B> is actually a factory function for several types of
masked edit controls:
<P>
<UL>
<LI><b>wxMaskedTextCtrl</b> - standard masked edit text box</LI>
<LI><b>wxMaskedComboBox</b> - adds combobox capabilities</LI>
<LI><b>wxIpAddrCtrl</b> - adds logical input semantics for IP address entry</LI>
<LI><b>wxTimeCtrl</b> - special subclass handling lots of time formats as values</LI>
<LI><b>wxMaskedNumCtrl</b> - special subclass handling numeric values</LI>
</UL>
<P>
<B>wxMaskedCtrl</B> works by looking for a special <b><i>controlType</i></b>
parameter in the variable arguments of the control, to determine
what kind of instance to return.
controlType can be one of:
<PRE><FONT SIZE=-1>
controlTypes.MASKEDTEXT
controlTypes.MASKEDCOMBO
controlTypes.IPADDR
controlTypes.TIME
controlTypes.NUMBER
</FONT></PRE>
These constants are also available individually, ie, you can
use either of the following:
<PRE><FONT SIZE=-1>
from wxPython.wx.lib.maskedctrl import wxMaskedCtrl, MASKEDCOMBO, MASKEDTEXT, NUMBER
from wxPython.wx.lib.maskedctrl import wxMaskedCtrl, controlTypes
</FONT></PRE>
If not specified as a keyword argument, the default controlType is
controlTypes.MASKEDTEXT.
<P>
Each of the above classes has its own unique arguments, but wxMaskedCtrl
provides a single "unified" interface for masked controls. wxMaskedTextCtrl,
wxMaskedComboBox and wxIpAddrCtrl are all documented below; the others have
their own demo pages and interface descriptions.
</body></html>
"""
from wxPython.lib.maskededit import wxMaskedTextCtrl, wxMaskedComboBox, wxIpAddrCtrl
from wxPython.lib.maskednumctrl import wxMaskedNumCtrl
from wxPython.lib.timectrl import wxTimeCtrl
# "type" enumeration for class instance factory function
MASKEDTEXT = 0
MASKEDCOMBO = 1
IPADDR = 2
TIME = 3
NUMBER = 4
# for ease of import
class controlTypes:
MASKEDTEXT = MASKEDTEXT
MASKEDCOMBO = MASKEDCOMBO
IPADDR = IPADDR
TIME = TIME
NUMBER = NUMBER
def wxMaskedCtrl( *args, **kwargs):
"""
Actually a factory function providing a unifying
interface for generating masked controls.
"""
if not kwargs.has_key('controlType'):
controlType = MASKEDTEXT
else:
controlType = kwargs['controlType']
del kwargs['controlType']
if controlType == MASKEDTEXT:
return wxMaskedTextCtrl(*args, **kwargs)
elif controlType == MASKEDCOMBO:
return wxMaskedComboBox(*args, **kwargs)
elif controlType == IPADDR:
return wxIpAddrCtrl(*args, **kwargs)
elif controlType == TIME:
return wxTimeCtrl(*args, **kwargs)
elif controlType == NUMBER:
return wxMaskedNumCtrl(*args, **kwargs)
else:
raise AttributeError(
"invalid controlType specified: %s" % repr(controlType))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -342,7 +342,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
# require explicit field change, select entire field on entry, # require explicit field change, select entire field on entry,
# and require a resultant valid entry to allow character entry: # and require a resultant valid entry to allow character entry:
hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True) hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True)
ampmfield = Field(formatcodes='S') ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
# Field 1 is always a zero-padded right-insert minute field, # Field 1 is always a zero-padded right-insert minute field,
# similarly configured as above: # similarly configured as above: