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

View File

@@ -1,10 +1,12 @@
from wxPython.wx import *
from wxPython.lib.maskededit import Field, wxMaskedTextCtrl, wxMaskedComboBox, wxIpAddrCtrl, states, months
from wxPython.lib.maskededit import __doc__ as overviewdoc
from wxPython.lib.maskededit import Field, wxMaskedTextCtrl, wxMaskedComboBox, wxIpAddrCtrl, states, state_names, months
from wxPython.lib.maskededit import __doc__ as maskededit_doc
from wxPython.lib.maskededit import autoformats
from wxPython.lib.maskedctrl import wxMaskedCtrl, controlTypes, MASKEDCOMBO
from wxPython.lib.scrolledpanel import wxScrolledPanel
import string, sys, traceback
class demoMixin:
"""
Centralized routines common to demo pages, to remove repetition.
@@ -14,7 +16,7 @@ class demoMixin:
mask = wxStaticText( self, -1, "Mask Value" )
formatcode = wxStaticText( self, -1, "Format" )
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))
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 ):
""" Highlight empty values"""
self.changeControlParams( event, "emptyBackgroundColor", "Blue", "White" )
self.changeControlParams( event, "emptyBackgroundColour", "Blue", "White" )
def onShowFill( self, event ):
""" Set fillChar parameter to '?' or ' ' """
@@ -144,8 +146,9 @@ class demoPage2(wxScrolledPanel, demoMixin):
self.sizer = wxBoxSizer( wxVERTICAL )
label = wxStaticText( self, -1, """\
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).
All these controls have been created by passing a single parameter, the autoformat code,
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
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")
autofmt = wxStaticText( self, -1, "AutoFormat Code")
ctrl = wxStaticText( self, -1, "wxMaskedEdit Control")
ctrl = wxStaticText( self, -1, "wxMaskedCtrl")
description.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:
grid.Add( wxStaticText( self, -1, desc), 0, wxALIGN_LEFT )
grid.Add( wxStaticText( self, -1, autoformat), 0, wxALIGN_LEFT )
grid.Add( wxMaskedTextCtrl( self, -1, "",
autoformat = autoformat,
demo = True,
name = autoformat),
grid.Add( wxMaskedCtrl( self, -1, "",
autoformat = autoformat,
demo = True,
name = autoformat),
0, wxALIGN_LEFT )
self.sizer.Add( grid, 0, wxALIGN_LEFT|wxALL, border=5 )
@@ -208,7 +211,7 @@ has a legal range specified.
controls = [
#description mask excl format regexp range,list,initial
("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 '),
("Float (signed)", "#{6}.#{9}", "", 'F-_R', "", '','', '000000.000000000'),
("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" )
autofmt = wxStaticText( self, -1, "AutoFormat Code" )
fields = wxStaticText( self, -1, "Field Objects" )
ctrl = wxStaticText( self, -1, "wxMaskedEdit Control" )
ctrl = wxStaticText( self, -1, "wxMaskedTextCtrl" )
description.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) )
autofmt.SetFont( wxFont( 9, wxSWISS, wxNORMAL, wxBOLD ) )
@@ -325,12 +328,33 @@ class demoPage5(wxScrolledPanel, demoMixin):
self.log = log
wxScrolledPanel.__init__( self, parent, -1 )
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.
""")
label.SetForegroundColour( "Blue" )
self.sizer.Add( label, 0, wxALIGN_LEFT|wxALL, 5 )
labelMaskedCombos = wxStaticText( self, -1, """\
These are some examples of wxMaskedComboBox:""")
labelMaskedCombos.SetForegroundColour( "Blue" )
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) ]
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) )
text1 = wxStaticText( self, -1, """\
label_fraction = wxStaticText( self, -1, """\
A masked ComboBox for fraction selection.
Choices for each side of the fraction can be
selected with PageUp/Down:""")
Choices for each side of the fraction can
be selected with PageUp/Down:""")
fraction = wxMaskedComboBox( self, -1, "",
choices = choices,
choiceRequired = True,
mask = "#/##",
formatcodes = "F_",
validRegex = "^\d\/\d\d?",
fields = fieldsDict )
fraction = wxMaskedCtrl( self, -1, "",
controlType = MASKEDCOMBO,
choices = choices,
choiceRequired = True,
mask = "#/##",
formatcodes = "F_",
validRegex = "^\d\/\d\d?",
fields = fieldsDict )
text2 = wxStaticText( self, -1, """
label_code = wxStaticText( self, -1, """\
A masked ComboBox to validate
text from a list of numeric codes:""")
@@ -368,100 +393,155 @@ text from a list of numeric codes:""")
formatcodes = "F_r",
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, """\
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 )
self.dynamicbox.Clear() # get rid of initial choices used to size the dropdown
text5 = wxStaticText( self, -1, "An IP Address control with a restricted mask:")
ip_addr2 = wxIpAddrCtrl( self, -1, mask=" 10. 1.109.###" )
labelIpAddrs = wxStaticText( self, -1, """\
Here are some examples of wxIpAddrCtrl, a control derived from wxMaskedTextCtrl:""")
labelIpAddrs.SetForegroundColour( "Blue" )
text6 = wxStaticText( self, -1, """\
An IP Address control with restricted choices
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_ipaddr1 = wxStaticText( self, -1, "An empty control:")
ipaddr1 = wxIpAddrCtrl( self, -1, style = wxTE_PROCESS_TAB )
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:
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
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(1, defaultValue='00') # don't allow blank fraction
text9 = wxStaticText( self, -1, """\
Use this control to programmatically set
the value of the above float control:""")
number_combo = wxComboBox(self, -1, choices = [ '', '111', '222.22', '-3', '54321.666666666', '-1353.978',
'1234567', '-1234567', '123456789', '-123456789.1',
'1234567890.', '-1234567890.1' ])
label_numselect = wxStaticText( self, -1, """\
<= Programmatically set the value
of the float entry ctrl:""")
numselect = wxComboBox(self, -1, choices = [ '', '111', '222.22', '-3', '54321.666666666', '-1353.978',
'1234567', '-1234567', '123456789', '-123456789.1',
'1234567890.', '-1234567890.1' ])
grid = wxFlexGridSizer( 0, 2, vgap=10, hgap = 5 )
grid.Add( text1, 0, wxALIGN_LEFT )
grid.Add( fraction, 0, wxALIGN_LEFT )
grid.Add( text2, 0, wxALIGN_LEFT )
grid.Add( code, 0, wxALIGN_LEFT )
grid.Add( text3, 0, wxALIGN_LEFT )
grid.Add( state, 0, wxALIGN_LEFT )
grid.Add( text4, 0, wxALIGN_LEFT )
grid.Add( ip_addr1, 0, wxALIGN_LEFT )
grid.Add( text5, 0, wxALIGN_LEFT )
grid.Add( ip_addr2, 0, wxALIGN_LEFT )
grid.Add( text6, 0, wxALIGN_LEFT )
grid.Add( ip_addr3, 0, wxALIGN_LEFT )
grid.Add( text7, 0, wxALIGN_LEFT )
grid.Add( intctrl, 0, wxALIGN_LEFT )
grid.Add( text8, 0, wxALIGN_LEFT )
grid.Add( self.floatctrl, 0, wxALIGN_LEFT )
grid.Add( text9, 0, wxALIGN_LEFT )
grid.Add( number_combo, 0, wxALIGN_LEFT )
parens_check = wxCheckBox(self, -1, "Use () to indicate negatives in above controls")
gridCombos = wxFlexGridSizer( 0, 4, vgap=10, hgap = 10 )
gridCombos.Add( label_statecode, 0, wxALIGN_LEFT )
gridCombos.Add( statecode, 0, wxALIGN_LEFT )
gridCombos.Add( label_fraction, 0, wxALIGN_LEFT )
gridCombos.Add( fraction, 0, wxALIGN_LEFT )
gridCombos.Add( label_statename, 0, wxALIGN_LEFT )
gridCombos.Add( statename, 0, wxALIGN_LEFT )
gridCombos.Add( label_code, 0, wxALIGN_LEFT )
gridCombos.Add( code, 0, wxALIGN_LEFT )
gridCombos.Add( label_selector, 0, wxALIGN_LEFT)
hbox = wxBoxSizer( wxHORIZONTAL )
hbox.Add( self.list_selector, 0, wxALIGN_LEFT )
hbox.Add(wxStaticText(self, -1, ' => '), 0, wxALIGN_LEFT)
hbox.Add( self.dynamicbox, 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.SetAutoLayout(1)
self.SetupScrolling()
EVT_COMBOBOX( self, fraction.GetId(), self.OnComboChange )
EVT_COMBOBOX( self, code.GetId(), self.OnComboChange )
EVT_COMBOBOX( self, state.GetId(), self.OnComboChange )
EVT_TEXT( self, fraction.GetId(), self.OnComboChange )
EVT_TEXT( self, code.GetId(), self.OnComboChange )
EVT_TEXT( self, state.GetId(), self.OnComboChange )
EVT_COMBOBOX( self, fraction.GetId(), self.OnComboSelection )
EVT_COMBOBOX( self, code.GetId(), self.OnComboSelection )
EVT_COMBOBOX( self, statecode.GetId(), self.OnComboSelection )
EVT_COMBOBOX( self, statename.GetId(), self.OnComboSelection )
EVT_TEXT( self, fraction.GetId(), self.OnTextChange )
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, ip_addr2.GetId(), self.OnIpAddrChange )
EVT_TEXT( self, ip_addr3.GetId(), self.OnIpAddrChange )
EVT_TEXT( self, intctrl.GetId(), self.OnTextChange )
EVT_TEXT( self, self.intctrl1.GetId(), self.OnTextChange )
EVT_TEXT( self, self.intctrl2.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() )
if not ctl.IsValid():
self.log.write('current value not a valid choice')
def OnIpAddrChange( self, event ):
ip_addr = self.FindWindowById( event.GetId() )
if ip_addr.IsValid():
self.log.write('new addr = %s\n' % ip_addr.GetAddress() )
self.log.write('new value = %s' % ctl.GetValue())
def OnTextChange( self, event ):
ctl = self.FindWindowById( event.GetId() )
@@ -470,14 +550,8 @@ the value of the above float control:""")
def OnNumberSelect( self, event ):
value = event.GetString()
# Format choice to fit into format for #{9}.#{2}, with sign position reserved:
# (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:
floattext = "%13.2f" % float(value)
else:
@@ -489,6 +563,37 @@ the value of the above float control:""")
for line in traceback.format_exception_only(type, value):
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):
def __init__(self, parent, id, log):
@@ -530,7 +635,7 @@ if __name__ == "__main__":
overview = """<html>
<PRE><FONT SIZE=-1>
""" + overviewdoc + """
""" + maskededit_doc + """
</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,
# 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)
ampmfield = Field(formatcodes='S')
ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
# Field 1 is always a zero-padded right-insert minute field,
# similarly configured as above: