More patches to the masked edit control from Will Sadkin
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@20551 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -54,14 +54,29 @@ mask=
|
|||||||
Allowed mask characters and function:
|
Allowed mask characters and function:
|
||||||
Character Function
|
Character Function
|
||||||
# Allow numeric only (0-9)
|
# Allow numeric only (0-9)
|
||||||
N Allow letters (a-z,A-Z) and numbers (0-9)
|
N Allow letters and numbers (0-9)
|
||||||
A Allow uppercase letters only (A-Z)
|
A Allow uppercase letters only
|
||||||
a Allow lowercase letters only (a-z)
|
a Allow lowercase letters only
|
||||||
X Allow any typeable character
|
C Allow any letter, upper or lower
|
||||||
C Allow any letter, upper or lower (a-z,A-Z)
|
X Allow string.letters, string.punctuation, string.digits
|
||||||
|
|
||||||
Using these characters, a variety of template masks can be built. See the
|
|
||||||
demo for some other common examples include date+time, social security
|
Note:
|
||||||
|
These controls define these sets of characters using string.letters,
|
||||||
|
string.uppercase, etc. These sets are affected by the system locale
|
||||||
|
setting, so in order to have the masked controls accept characters
|
||||||
|
that are specific to your users' language, your application should
|
||||||
|
set the locale.
|
||||||
|
For example, to allow international characters to be used in the
|
||||||
|
above masks, you can place the following in your code as part of
|
||||||
|
your application's initialization code:
|
||||||
|
|
||||||
|
import locale
|
||||||
|
locale.setlocale(locale.LC_ALL, '')
|
||||||
|
|
||||||
|
|
||||||
|
Using these mask characters, a variety of template masks can be built. See
|
||||||
|
the demo for some other common examples include date+time, social security
|
||||||
number, etc. If any of these characters are needed as template rather
|
number, etc. If any of these characters are needed as template rather
|
||||||
than mask characters, they can be escaped with \, ie. \N means "literal N".
|
than mask characters, they can be escaped with \, ie. \N means "literal N".
|
||||||
(use \\ for literal backslash, as in: r'CCC\\NNN'.)
|
(use \\ for literal backslash, as in: r'CCC\\NNN'.)
|
||||||
@@ -561,22 +576,13 @@ control = (WXK_BACK, WXK_DELETE, WXK_CTRL_A, WXK_CTRL_C, WXK_CTRL_S, WXK_CTRL_V,
|
|||||||
## Constants for masking. This is where mask characters
|
## Constants for masking. This is where mask characters
|
||||||
## are defined.
|
## are defined.
|
||||||
## maskchars used to identify valid mask characters from all others
|
## maskchars used to identify valid mask characters from all others
|
||||||
## masktran used to replace mask chars with spaces
|
|
||||||
## maskchardict used to defined allowed character sets for each mask char
|
|
||||||
## #- allow numeric 0-9 only
|
## #- allow numeric 0-9 only
|
||||||
## A- allow uppercase only. Combine with forceupper to force lowercase to upper
|
## A- allow uppercase only. Combine with forceupper to force lowercase to upper
|
||||||
## a- allow lowercase only. Combine with forcelower to force upper to lowercase
|
## a- allow lowercase only. Combine with forcelower to force upper to lowercase
|
||||||
## X- allow any character (letters, punctuation, digits)
|
## X- allow any character (string.letters, string.punctuation, string.digits)
|
||||||
|
## Note: locale settings affect what "uppercase", lowercase, etc comprise.
|
||||||
##
|
##
|
||||||
maskchars = ("#","A","a","X","C","N")
|
maskchars = ("#","A","a","X","C","N")
|
||||||
maskchardict = {
|
|
||||||
"#": string.digits,
|
|
||||||
"A": string.uppercase,
|
|
||||||
"a": string.lowercase,
|
|
||||||
"X": string.letters + string.punctuation + string.digits,
|
|
||||||
"C": string.letters,
|
|
||||||
"N": string.letters + string.digits
|
|
||||||
}
|
|
||||||
|
|
||||||
months = '(01|02|03|04|05|06|07|08|09|10|11|12)'
|
months = '(01|02|03|04|05|06|07|08|09|10|11|12)'
|
||||||
charmonths = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)'
|
charmonths = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)'
|
||||||
@@ -1018,6 +1024,19 @@ class wxMaskedEditMixin:
|
|||||||
self._nav = list(nav)
|
self._nav = list(nav)
|
||||||
self._control = list(control)
|
self._control = list(control)
|
||||||
|
|
||||||
|
## Dynamically evaluate and store string constants for mask chars
|
||||||
|
## so that locale settings can be made after this module is imported
|
||||||
|
## and the controls created after that is done can allow the
|
||||||
|
## appropriate characters:
|
||||||
|
self.maskchardict = {
|
||||||
|
"#": string.digits,
|
||||||
|
"A": string.uppercase,
|
||||||
|
"a": string.lowercase,
|
||||||
|
"X": string.letters + string.punctuation + string.digits,
|
||||||
|
"C": string.letters,
|
||||||
|
"N": string.letters + string.digits
|
||||||
|
}
|
||||||
|
|
||||||
## self._ignoreChange is used by wxMaskedComboBox, because
|
## self._ignoreChange is used by wxMaskedComboBox, because
|
||||||
## of the hack necessary to determine the selection; it causes
|
## of the hack necessary to determine the selection; it causes
|
||||||
## EVT_TEXT messages from the combobox to be ignored if set.
|
## EVT_TEXT messages from the combobox to be ignored if set.
|
||||||
@@ -2978,7 +2997,7 @@ class wxMaskedEditMixin:
|
|||||||
mask character plus control options
|
mask character plus control options
|
||||||
"""
|
"""
|
||||||
maskChar = self.maskdict[pos]
|
maskChar = self.maskdict[pos]
|
||||||
okchars = maskchardict[maskChar] ## entry, get mask approved characters
|
okchars = self.maskchardict[maskChar] ## entry, get mask approved characters
|
||||||
field = self._FindField(pos)
|
field = self._FindField(pos)
|
||||||
if okchars and field._okSpaces: ## Allow spaces?
|
if okchars and field._okSpaces: ## Allow spaces?
|
||||||
okchars += " "
|
okchars += " "
|
||||||
@@ -3952,15 +3971,26 @@ class wxMaskedTextCtrl( wxTextCtrl, wxMaskedEditMixin ):
|
|||||||
self._SetSelection(0, len(self._mask))
|
self._SetSelection(0, len(self._mask))
|
||||||
|
|
||||||
# make SetValue behave the same as if you had typed the value in:
|
# make SetValue behave the same as if you had typed the value in:
|
||||||
value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
|
try:
|
||||||
if self._isDec:
|
value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
|
||||||
self._isNeg = False # (clear current assumptions)
|
if self._isDec:
|
||||||
value = self._adjustDec(value)
|
self._isNeg = False # (clear current assumptions)
|
||||||
elif self._isInt:
|
value = self._adjustDec(value)
|
||||||
self._isNeg = False # (clear current assumptions)
|
elif self._isInt:
|
||||||
value = self._adjustInt(value)
|
self._isNeg = False # (clear current assumptions)
|
||||||
elif self._isDate:
|
value = self._adjustInt(value)
|
||||||
value = self._adjustDate(value)
|
elif self._isDate and not self.IsValid(value) and self._4digityear:
|
||||||
|
value = self._adjustDate(value, fixcentury=true)
|
||||||
|
except ValueError:
|
||||||
|
# If date, year might be 2 digits vs. 4; try adjusting it:
|
||||||
|
if self._isDate and self._4digityear:
|
||||||
|
dateparts = value.split(' ')
|
||||||
|
dateparts[0] = self._adjustDate(dateparts[0], fixcentury=true)
|
||||||
|
value = string.join(dateparts, ' ')
|
||||||
|
dbg('adjusted value: "%s"' % value)
|
||||||
|
value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
self._SetValue(value)
|
self._SetValue(value)
|
||||||
dbg(indent=0)
|
dbg(indent=0)
|
||||||
@@ -4193,15 +4223,26 @@ class wxMaskedComboBox( wxComboBox, wxMaskedEditMixin ):
|
|||||||
self._SetSelection(0, len(self._mask))
|
self._SetSelection(0, len(self._mask))
|
||||||
|
|
||||||
# make SetValue behave the same as if you had typed the value in:
|
# make SetValue behave the same as if you had typed the value in:
|
||||||
value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
|
try:
|
||||||
if self._isDec:
|
value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
|
||||||
self._isNeg = False # (clear current assumptions)
|
if self._isDec:
|
||||||
value = self._adjustDec(value)
|
self._isNeg = False # (clear current assumptions)
|
||||||
elif self._isInt:
|
value = self._adjustDec(value)
|
||||||
self._isNeg = False # (clear current assumptions)
|
elif self._isInt:
|
||||||
value = self._adjustInt(value)
|
self._isNeg = False # (clear current assumptions)
|
||||||
elif self._isDate:
|
value = self._adjustInt(value)
|
||||||
value = self._adjustDate(value)
|
elif self._isDate and not self.IsValid(value) and self._4digityear:
|
||||||
|
value = self._adjustDate(value, fixcentury=true)
|
||||||
|
except ValueError:
|
||||||
|
# If date, year might be 2 digits vs. 4; try adjusting it:
|
||||||
|
if self._isDate and self._4digityear:
|
||||||
|
dateparts = value.split(' ')
|
||||||
|
dateparts[0] = self._adjustDate(dateparts[0], fixcentury=true)
|
||||||
|
value = string.join(dateparts, ' ')
|
||||||
|
dbg('adjusted value: "%s"' % value)
|
||||||
|
value = self._Paste(value, raise_on_invalid=True, just_return_value=True)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
self._SetValue(value)
|
self._SetValue(value)
|
||||||
|
|
||||||
@@ -4311,8 +4352,7 @@ class wxMaskedComboBox( wxComboBox, wxMaskedEditMixin ):
|
|||||||
|
|
||||||
self._ignoreChange = False # tell _OnTextChange() to pay attn again
|
self._ignoreChange = False # tell _OnTextChange() to pay attn again
|
||||||
|
|
||||||
dbg('computed selection:', sel_start, sel_to, indent=0)
|
dbg('computed selection:', sel_start, sel_to, indent=0, suspend=0)
|
||||||
dbg(suspend=0) # resume regular debugging
|
|
||||||
return sel_start, sel_to
|
return sel_start, sel_to
|
||||||
|
|
||||||
|
|
||||||
@@ -4455,6 +4495,45 @@ class wxIpAddrCtrl( wxMaskedTextCtrl ):
|
|||||||
print "value:", self.GetAddress()
|
print "value:", self.GetAddress()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def SetValue(self, value):
|
||||||
|
dbg('wxIpAddrCtrl::SetValue(%s)' % str(value), indent=1)
|
||||||
|
if type(value) != types.StringType:
|
||||||
|
raise ValueError('%s must be a string', str(value))
|
||||||
|
|
||||||
|
bValid = True # assume true
|
||||||
|
parts = value.split('.')
|
||||||
|
if len(parts) != 4:
|
||||||
|
bValid = False
|
||||||
|
else:
|
||||||
|
for i in range(4):
|
||||||
|
part = parts[i]
|
||||||
|
if not 0 <= len(part) <= 3:
|
||||||
|
bValid = False
|
||||||
|
break
|
||||||
|
elif part.strip(): # non-empty part
|
||||||
|
try:
|
||||||
|
j = string.atoi(part)
|
||||||
|
if not 0 <= j <= 255:
|
||||||
|
bValid = False
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
parts[i] = '%3d' % j
|
||||||
|
except:
|
||||||
|
bValid = False
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# allow empty sections for SetValue (will result in "invalid" value,
|
||||||
|
# but this may be useful for initializing the control:
|
||||||
|
parts[i] = ' ' # convert empty field to 3-char length
|
||||||
|
|
||||||
|
if not bValid:
|
||||||
|
dbg(indent=0)
|
||||||
|
raise ValueError('value (%s) must be a string of form n.n.n.n where n is empty or in range 0-255' % str(value))
|
||||||
|
else:
|
||||||
|
dbg('parts:', parts)
|
||||||
|
value = string.join(parts, '.')
|
||||||
|
wxMaskedTextCtrl.SetValue(self, value)
|
||||||
|
dbg(indent=0)
|
||||||
|
|
||||||
|
|
||||||
## ---------- ---------- ---------- ---------- ---------- ---------- ----------
|
## ---------- ---------- ---------- ---------- ---------- ---------- ----------
|
||||||
@@ -4891,11 +4970,13 @@ i=1
|
|||||||
## 9. Exposed all (valid) autoformats to demo, binding descriptions to
|
## 9. Exposed all (valid) autoformats to demo, binding descriptions to
|
||||||
## autoformats.
|
## autoformats.
|
||||||
## 10. Fixed a couple of bugs in email regexp.
|
## 10. Fixed a couple of bugs in email regexp.
|
||||||
## 11. Modified autoformats to be more amenable to international use.
|
## 11. Made maskchardict an instance var, to make mask chars to be more
|
||||||
|
## amenable to international use.
|
||||||
## 12. Clarified meaning of '-' formatcode in doc.
|
## 12. Clarified meaning of '-' formatcode in doc.
|
||||||
## 13. Fixed a couple of coding bugs being flagged by Python2.1.
|
## 13. Fixed a couple of coding bugs being flagged by Python2.1.
|
||||||
## 14. Fixed several issues with sign positioning, erasure and validity
|
## 14. Fixed several issues with sign positioning, erasure and validity
|
||||||
## checking for "numeric" masked controls.
|
## checking for "numeric" masked controls.
|
||||||
|
## 15. Added validation to wxIpAddrCtrl.SetValue().
|
||||||
##
|
##
|
||||||
## Version 1.1
|
## Version 1.1
|
||||||
## 1. Changed calling interface to use boolean "useFixedWidthFont" (True by default)
|
## 1. Changed calling interface to use boolean "useFixedWidthFont" (True by default)
|
||||||
|
Reference in New Issue
Block a user