Re-add support for multiple text validator styles but

1) catch some invalid configurations in SetStyle()
2) document the order of the checks in wxTextValidator
3) implement wxFILTER_EMPTY
4) rename wxFILTER_SIMPLE_NUMBER => wxFILTER_DIGITS



git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58637 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2009-02-03 21:21:47 +00:00
parent 77cc73a78e
commit 58fa61dbad
4 changed files with 112 additions and 121 deletions

View File

@@ -22,25 +22,23 @@ class WXDLLIMPEXP_FWD_CORE wxTextEntry;
enum wxTextValidatorStyle enum wxTextValidatorStyle
{ {
wxFILTER_NONE, wxFILTER_NONE = 0x0,
wxFILTER_ASCII, wxFILTER_EMPTY = 0x1,
wxFILTER_ALPHA, wxFILTER_ASCII = 0x2,
wxFILTER_ALPHANUMERIC, wxFILTER_ALPHA = 0x4,
wxFILTER_SIMPLE_NUMBER, wxFILTER_ALPHANUMERIC = 0x8,
wxFILTER_NUMERIC, wxFILTER_DIGITS = 0x10,
wxFILTER_INCLUDE_LIST, wxFILTER_NUMERIC = 0x20,
wxFILTER_EXCLUDE_LIST, wxFILTER_INCLUDE_LIST = 0x40,
wxFILTER_INCLUDE_CHAR_LIST, wxFILTER_INCLUDE_CHAR_LIST = 0x80,
wxFILTER_EXCLUDE_CHAR_LIST wxFILTER_EXCLUDE_LIST = 0x100,
wxFILTER_EXCLUDE_CHAR_LIST = 0x200
}; };
class WXDLLIMPEXP_CORE wxTextValidator: public wxValidator class WXDLLIMPEXP_CORE wxTextValidator: public wxValidator
{ {
public: public:
wxTextValidator(wxTextValidatorStyle style = wxFILTER_NONE, wxString *val = NULL); wxTextValidator(long style = wxFILTER_NONE, wxString *val = NULL);
#if WXWIN_COMPATIBILITY_2_8
wxDEPRECATED_CONSTRUCTOR( wxTextValidator(long style, wxString *val) );
#endif
wxTextValidator(const wxTextValidator& val); wxTextValidator(const wxTextValidator& val);
virtual ~wxTextValidator(){} virtual ~wxTextValidator(){}
@@ -66,11 +64,8 @@ public:
void OnChar(wxKeyEvent& event); void OnChar(wxKeyEvent& event);
// ACCESSORS // ACCESSORS
inline wxTextValidatorStyle GetStyle() const { return m_validatorStyle; } inline long GetStyle() const { return m_validatorStyle; }
inline void SetStyle(wxTextValidatorStyle style) { m_validatorStyle = style; } void SetStyle(long style);
#if WXWIN_COMPATIBILITY_2_8
wxDEPRECATED( void SetStyle(long style) );
#endif
wxTextEntry *GetTextEntry(); wxTextEntry *GetTextEntry();
@@ -82,6 +77,9 @@ public:
void SetExcludes(const wxArrayString& excludes) { m_excludes = excludes; } void SetExcludes(const wxArrayString& excludes) { m_excludes = excludes; }
inline wxArrayString& GetExcludes() { return m_excludes; } inline wxArrayString& GetExcludes() { return m_excludes; }
bool HasFlag(wxTextValidatorStyle style) const
{ return m_validatorStyle & style; }
protected: protected:
// returns true if all characters of the given string are present in m_includes // returns true if all characters of the given string are present in m_includes
@@ -90,12 +88,12 @@ protected:
// returns true if all characters of the given string are NOT present in m_excludes // returns true if all characters of the given string are NOT present in m_excludes
bool ContainsExcludedCharacters(const wxString& val) const; bool ContainsExcludedCharacters(const wxString& val) const;
// returns true if the contents of 'val' are valid for the current validation style // returns the error message if the contents of 'val' are invalid
virtual bool IsValid(const wxString& val, wxString* errormsg) const; virtual wxString IsValid(const wxString& val) const;
protected: protected:
wxTextValidatorStyle m_validatorStyle; long m_validatorStyle;
wxString * m_stringValue; wxString* m_stringValue;
wxArrayString m_includes; wxArrayString m_includes;
wxArrayString m_excludes; wxArrayString m_excludes;

View File

@@ -9,12 +9,20 @@
/** /**
Styles used by wxTextValidator. Styles used by wxTextValidator.
Note that when you specify more styles in wxTextValidator the validation checks
are performed in the order in which the styles of this enumeration are defined.
*/ */
enum wxTextValidatorStyle enum wxTextValidatorStyle
{ {
/// No filtering takes place. /// No filtering takes place.
wxFILTER_NONE, wxFILTER_NONE,
/// Empty strings are filtered out.
/// If this style is not specified then empty strings are accepted
/// only if they pass the other checks (if you use more than one wxTextValidatorStyle).
wxFILTER_EMPTY,
/// Non-ASCII characters are filtered out. See wxString::IsAscii. /// Non-ASCII characters are filtered out. See wxString::IsAscii.
wxFILTER_ASCII, wxFILTER_ASCII,
@@ -31,7 +39,7 @@ enum wxTextValidatorStyle
/// Non-numeric characters are filtered out. /// Non-numeric characters are filtered out.
/// Uses the wxWidgets wrapper for the standard CRT function @c isdigit /// Uses the wxWidgets wrapper for the standard CRT function @c isdigit
/// (which is locale-dependent) on all characters of the string. /// (which is locale-dependent) on all characters of the string.
wxFILTER_SIMPLE_NUMBER, wxFILTER_DIGITS,
/// Non-numeric characters are filtered out. /// Non-numeric characters are filtered out.
/// Works like @c wxFILTER_SIMPLE_NUMBER but allows also decimal points, /// Works like @c wxFILTER_SIMPLE_NUMBER but allows also decimal points,
@@ -43,15 +51,15 @@ enum wxTextValidatorStyle
/// the list, complaining if not. See wxTextValidator::SetIncludes(). /// the list, complaining if not. See wxTextValidator::SetIncludes().
wxFILTER_INCLUDE_LIST, wxFILTER_INCLUDE_LIST,
/// Use an exclude list. The validator checks if the user input is on
/// the list, complaining if it is. See wxTextValidator::SetExcludes().
wxFILTER_EXCLUDE_LIST,
/// Use an include list. The validator checks if each input character is /// Use an include list. The validator checks if each input character is
/// in the list (one character per list element), complaining if not. /// in the list (one character per list element), complaining if not.
/// See wxTextValidator::SetCharIncludes(). /// See wxTextValidator::SetCharIncludes().
wxFILTER_INCLUDE_CHAR_LIST, wxFILTER_INCLUDE_CHAR_LIST,
/// Use an exclude list. The validator checks if the user input is on
/// the list, complaining if it is. See wxTextValidator::SetExcludes().
wxFILTER_EXCLUDE_LIST,
/// Use an exclude list. The validator checks if each input character is /// Use an exclude list. The validator checks if each input character is
/// in the list (one character per list element), complaining if it is. /// in the list (one character per list element), complaining if it is.
/// See wxTextValidator::SetCharExcludes(). /// See wxTextValidator::SetCharExcludes().
@@ -83,14 +91,14 @@ public:
Constructor taking a style and optional pointer to a wxString variable. Constructor taking a style and optional pointer to a wxString variable.
@param style @param style
One of the ::wxTextValidatorStyle styles. One or more of the ::wxTextValidatorStyle styles. See SetStyle().
@param valPtr @param valPtr
A pointer to a wxString variable that contains the value. This A pointer to a wxString variable that contains the value. This
variable should have a lifetime equal to or longer than the variable should have a lifetime equal to or longer than the
validator lifetime (which is usually determined by the lifetime of validator lifetime (which is usually determined by the lifetime of
the window). the window).
*/ */
wxTextValidator(wxTextValidatorStyle style = wxFILTER_NONE, wxString* valPtr = NULL); wxTextValidator(long style = wxFILTER_NONE, wxString* valPtr = NULL);
/** /**
Clones the text validator using the copy constructor. Clones the text validator using the copy constructor.
@@ -110,7 +118,7 @@ public:
/** /**
Returns the validator style. Returns the validator style.
*/ */
wxTextValidatorStyle GetStyle() const; long GetStyle() const;
/** /**
Receives character input from the window and filters it according to Receives character input from the window and filters it according to
@@ -147,9 +155,12 @@ public:
void SetCharIncludes(const wxString& chars); void SetCharIncludes(const wxString& chars);
/** /**
Sets the validator style. Sets the validator style which must be a combination of one or more
of the ::wxTextValidatorStyle values.
Note that not all possible combinations make sense!
*/ */
void SetStyle(wxTextValidatorStyle style); void SetStyle(long style);
/** /**
Transfers the value in the text control to the string. Transfers the value in the text control to the string.

View File

@@ -248,15 +248,18 @@ MyDialog::MyDialog( wxWindow *parent, const wxString& title,
m_text = new wxTextCtrl(this, VALIDATE_TEXT, wxEmptyString, m_text = new wxTextCtrl(this, VALIDATE_TEXT, wxEmptyString,
wxDefaultPosition, wxDefaultSize, 0, wxDefaultPosition, wxDefaultSize, 0,
wxTextValidator(wxFILTER_ALPHA, &g_data.m_string)); wxTextValidator(wxFILTER_ALPHA, &g_data.m_string));
m_text->SetToolTip("uses wxTextValidator with wxFILTER_ALPHA");
flexgridsizer->Add(m_text, 1, wxGROW); flexgridsizer->Add(m_text, 1, wxGROW);
// Now set a wxTextValidator with an explicit list of characters NOT allowed: // Now set a wxTextValidator with an explicit list of characters NOT allowed:
wxTextValidator textVal(wxFILTER_EXCLUDE_CHAR_LIST, &g_data.m_string2); wxTextValidator textVal(wxFILTER_EMPTY|wxFILTER_EXCLUDE_LIST, &g_data.m_string2);
textVal.SetCharExcludes("bcwyz"); textVal.SetCharExcludes("bcwyz");
flexgridsizer->Add(new wxTextCtrl(this, VALIDATE_TEXT2, wxEmptyString, wxTextCtrl* txt2 =
wxDefaultPosition, wxDefaultSize, 0, textVal), new wxTextCtrl(this, VALIDATE_TEXT2, wxEmptyString,
1, wxGROW); wxDefaultPosition, wxDefaultSize, 0, textVal);
txt2->SetToolTip("uses wxTextValidator with wxFILTER_EMPTY|");
flexgridsizer->Add(txt2, 1, wxGROW);
flexgridsizer->Add(new wxListBox((wxWindow*)this, VALIDATE_LIST, flexgridsizer->Add(new wxListBox((wxWindow*)this, VALIDATE_LIST,
wxPoint(10, 30), wxSize(120, wxDefaultCoord), wxPoint(10, 30), wxSize(120, wxDefaultCoord),
@@ -268,6 +271,7 @@ MyDialog::MyDialog( wxWindow *parent, const wxString& title,
wxPoint(130, 30), wxSize(120, wxDefaultCoord), wxPoint(130, 30), wxSize(120, wxDefaultCoord),
3, g_combobox_choices, 0L, 3, g_combobox_choices, 0L,
MyComboBoxValidator(&g_data.m_combobox_choice)); MyComboBoxValidator(&g_data.m_combobox_choice));
m_combobox->SetToolTip("uses a custom validator (MyComboBoxValidator)");
flexgridsizer->Add(m_combobox, 1, wxALIGN_CENTER); flexgridsizer->Add(m_combobox, 1, wxALIGN_CENTER);
// This wxCheckBox* doesn't need to be assigned to any pointer // This wxCheckBox* doesn't need to be assigned to any pointer

View File

@@ -43,8 +43,9 @@ static bool wxIsNumeric(const wxString& val)
{ {
// Allow for "," (French) as well as "." -- in future we should // Allow for "," (French) as well as "." -- in future we should
// use wxSystemSettings or other to do better localisation // use wxSystemSettings or other to do better localisation
if ((!wxIsdigit(*i)) && (*i != wxT('.')) && (*i != wxT(',')) && (*i != wxT('e')) && if ((!wxIsdigit(*i)) &&
(*i != wxT('E')) && (*i != wxT('+')) && (*i != wxT('-'))) (*i != wxS('.')) && (*i != wxS(',')) && (*i != wxS('e')) &&
(*i != wxS('E')) && (*i != wxS('+')) && (*i != wxS('-')))
return false; return false;
} }
return true; return true;
@@ -59,24 +60,10 @@ BEGIN_EVENT_TABLE(wxTextValidator, wxValidator)
EVT_CHAR(wxTextValidator::OnChar) EVT_CHAR(wxTextValidator::OnChar)
END_EVENT_TABLE() END_EVENT_TABLE()
#if WXWIN_COMPATIBILITY_2_8
wxTextValidator::wxTextValidator(long style, wxString *val) wxTextValidator::wxTextValidator(long style, wxString *val)
{ {
m_validatorStyle = (wxTextValidatorStyle)style;
m_stringValue = val;
}
void wxTextValidator::SetStyle(long style)
{
SetStyle((wxTextValidatorStyle)style);
}
#endif
wxTextValidator::wxTextValidator(wxTextValidatorStyle style, wxString *val)
{
m_validatorStyle = style;
m_stringValue = val; m_stringValue = val;
SetStyle(style);
} }
wxTextValidator::wxTextValidator(const wxTextValidator& val) wxTextValidator::wxTextValidator(const wxTextValidator& val)
@@ -85,6 +72,30 @@ wxTextValidator::wxTextValidator(const wxTextValidator& val)
Copy(val); Copy(val);
} }
void wxTextValidator::SetStyle(long style)
{
m_validatorStyle = style;
#ifdef __WXDEBUG__
int check;
check = (int)HasFlag(wxFILTER_ALPHA) + (int)HasFlag(wxFILTER_ALPHANUMERIC) +
(int)HasFlag(wxFILTER_DIGITS) + (int)HasFlag(wxFILTER_NUMERIC);
wxASSERT_MSG(check <= 1,
"It makes sense to use only one of the wxFILTER_ALPHA/wxFILTER_ALPHANUMERIC/"
"wxFILTER_SIMPLE_NUMBER/wxFILTER_NUMERIC styles");
wxASSERT_MSG(((int)HasFlag(wxFILTER_INCLUDE_LIST) + (int)HasFlag(wxFILTER_INCLUDE_CHAR_LIST) <= 1) &&
((int)HasFlag(wxFILTER_EXCLUDE_LIST) + (int)HasFlag(wxFILTER_EXCLUDE_CHAR_LIST) <= 1),
"Using both wxFILTER_[IN|EX]CLUDE_LIST _and_ wxFILTER_[IN|EX]CLUDE_CHAR_LIST "
"doesn't work since wxTextValidator internally uses the same array for both");
check = (int)HasFlag(wxFILTER_INCLUDE_LIST) + (int)HasFlag(wxFILTER_INCLUDE_CHAR_LIST) +
(int)HasFlag(wxFILTER_EXCLUDE_LIST) + (int)HasFlag(wxFILTER_EXCLUDE_CHAR_LIST);
wxASSERT_MSG(check <= 1,
"Using both an include/exclude list may lead to unexpected results");
#endif
}
bool wxTextValidator::Copy(const wxTextValidator& val) bool wxTextValidator::Copy(const wxTextValidator& val)
{ {
wxValidator::Copy(val); wxValidator::Copy(val);
@@ -135,18 +146,23 @@ bool wxTextValidator::Validate(wxWindow *parent)
wxString val(text->GetValue()); wxString val(text->GetValue());
// NB: this format string should always contain exactly one '%s'
wxString errormsg; wxString errormsg;
if (!IsValid(val, &errormsg)) if ( HasFlag(wxFILTER_EMPTY) && val.empty() )
{ {
wxASSERT(!errormsg.empty()); errormsg = _("The empty string is not allowed.");
}
m_validatorWindow->SetFocus(); else if ( !(errormsg = IsValid(val)).empty() )
{
// NB: this format string should always contain exactly one '%s'
wxString buf; wxString buf;
buf.Printf(errormsg, val.c_str()); buf.Printf(errormsg, val.c_str());
errormsg = buf;
}
wxMessageBox(buf, _("Validation conflict"), if ( !errormsg.empty() )
{
m_validatorWindow->SetFocus();
wxMessageBox(errormsg, _("Validation conflict"),
wxOK | wxICON_EXCLAMATION, parent); wxOK | wxICON_EXCLAMATION, parent);
return false; return false;
@@ -185,68 +201,30 @@ bool wxTextValidator::TransferFromWindow()
return true; return true;
} }
bool wxTextValidator::IsValid(const wxString& val, wxString* pErr) const wxString wxTextValidator::IsValid(const wxString& val) const
{ {
wxString errormsg; // wxFILTER_EMPTY is checked for in wxTextValidator::Validate
switch (m_validatorStyle)
{
case wxFILTER_NONE:
// nothing to do...
break;
case wxFILTER_INCLUDE_LIST: if ( HasFlag(wxFILTER_ASCII) && !val.IsAscii() )
if ( m_includes.Index(val) == wxNOT_FOUND ) return _("'%s' should only contain ASCII characters.");
errormsg = _("'%s' is invalid"); if ( HasFlag(wxFILTER_ALPHA) && !wxStringCheck<wxIsalpha>(val) )
break; return _("'%s' should only contain alphabetic characters.");
if ( HasFlag(wxFILTER_ALPHANUMERIC) && !wxStringCheck<wxIsalnum>(val) )
return _("'%s' should only contain alphabetic or numeric characters.");
if ( HasFlag(wxFILTER_DIGITS) && !wxStringCheck<wxIsdigit>(val) )
return _("'%s' should only contain digits.");
if ( HasFlag(wxFILTER_NUMERIC) && !wxIsNumeric(val) )
return _("'%s' should be numeric.");
if ( HasFlag(wxFILTER_INCLUDE_LIST) && m_includes.Index(val) == wxNOT_FOUND )
return _("'%s' is invalid");
if ( HasFlag(wxFILTER_INCLUDE_CHAR_LIST) && !ContainsOnlyIncludedCharacters(val) )
return _("'%s' is invalid");
if ( HasFlag(wxFILTER_EXCLUDE_LIST) && m_excludes.Index(val) != wxNOT_FOUND )
return _("'%s' is invalid");
if ( HasFlag(wxFILTER_EXCLUDE_CHAR_LIST) && ContainsExcludedCharacters(val) )
return _("'%s' is invalid");
case wxFILTER_EXCLUDE_LIST: return wxEmptyString;
if ( m_excludes.Index(val) != wxNOT_FOUND )
errormsg = _("'%s' is invalid");
break;
case wxFILTER_ASCII:
if ( !val.IsAscii() )
errormsg = _("'%s' should only contain ASCII characters.");
break;
case wxFILTER_ALPHA:
if ( !wxStringCheck<wxIsalpha>(val) )
errormsg = _("'%s' should only contain alphabetic characters.");
break;
case wxFILTER_ALPHANUMERIC:
if ( !wxStringCheck<wxIsalnum>(val) )
errormsg = _("'%s' should only contain alphabetic or numeric characters.");
break;
case wxFILTER_SIMPLE_NUMBER:
if ( !wxStringCheck<wxIsdigit>(val) )
errormsg = _("'%s' should be numeric.");
break;
case wxFILTER_NUMERIC:
if ( !wxIsNumeric(val) )
errormsg = _("'%s' should be numeric.");
break;
case wxFILTER_INCLUDE_CHAR_LIST:
if ( !ContainsOnlyIncludedCharacters(val) )
errormsg = _("'%s' is invalid");
break;
case wxFILTER_EXCLUDE_CHAR_LIST:
if ( ContainsExcludedCharacters(val) )
errormsg = _("'%s' is invalid");
break;
default:
wxFAIL_MSG("invalid text validator style");
}
if (pErr)
*pErr = errormsg;
return errormsg.empty();
} }
bool wxTextValidator::ContainsOnlyIncludedCharacters(const wxString& val) const bool wxTextValidator::ContainsOnlyIncludedCharacters(const wxString& val) const
@@ -309,7 +287,7 @@ void wxTextValidator::OnChar(wxKeyEvent& event)
} }
wxString str((wxUniChar)keyCode, 1); wxString str((wxUniChar)keyCode, 1);
if (!IsValid(str, NULL)) if (!IsValid(str).empty())
{ {
if ( !wxValidator::IsSilent() ) if ( !wxValidator::IsSilent() )
wxBell(); wxBell();