]> git.saurik.com Git - wxWidgets.git/blame - src/common/valtext.cpp
add a unit test for new events (see #10000)
[wxWidgets.git] / src / common / valtext.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
264cb7f5 2// Name: src/common/valtext.cpp
c801d85f
KB
3// Purpose: wxTextValidator
4// Author: Julian Smart
10b0f489 5// Modified by: Francesco Montorsi
c801d85f
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
55d99c7a 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
c801d85f
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
ce4169a4 16 #pragma hdrstop
c801d85f
KB
17#endif
18
472eec8a 19#if wxUSE_VALIDATORS && (wxUSE_TEXTCTRL || wxUSE_COMBOBOX)
ce4169a4 20
264cb7f5
WS
21#include "wx/valtext.h"
22
ce4169a4
RR
23#ifndef WX_PRECOMP
24 #include <stdio.h>
25 #include "wx/textctrl.h"
92646f5a 26 #include "wx/combobox.h"
ce4169a4
RR
27 #include "wx/utils.h"
28 #include "wx/msgdlg.h"
29 #include "wx/intl.h"
c801d85f
KB
30#endif
31
c801d85f
KB
32#include <ctype.h>
33#include <string.h>
34#include <stdlib.h>
35
40ae9600
FM
36// ----------------------------------------------------------------------------
37// global helpers
38// ----------------------------------------------------------------------------
39
40ae9600
FM
40static bool wxIsNumeric(const wxString& val)
41{
1406dc01 42 for ( wxString::const_iterator i = val.begin(); i != val.end(); ++i )
40ae9600
FM
43 {
44 // Allow for "," (French) as well as "." -- in future we should
45 // use wxSystemSettings or other to do better localisation
1406dc01
FM
46 if ((!wxIsdigit(*i)) && (*i != wxT('.')) && (*i != wxT(',')) && (*i != wxT('e')) &&
47 (*i != wxT('E')) && (*i != wxT('+')) && (*i != wxT('-')))
40ae9600
FM
48 return false;
49 }
50 return true;
51}
52
40ae9600
FM
53// ----------------------------------------------------------------------------
54// wxTextValidator
55// ----------------------------------------------------------------------------
56
57IMPLEMENT_DYNAMIC_CLASS(wxTextValidator, wxValidator)
c801d85f 58BEGIN_EVENT_TABLE(wxTextValidator, wxValidator)
a994f81b 59 EVT_CHAR(wxTextValidator::OnChar)
c801d85f 60END_EVENT_TABLE()
c801d85f 61
386af6a2 62
40ae9600 63#if WXWIN_COMPATIBILITY_2_8
debe6624 64wxTextValidator::wxTextValidator(long style, wxString *val)
40ae9600
FM
65{
66 m_validatorStyle = (wxTextValidatorStyle)style;
67 m_stringValue = val;
68}
69
70void wxTextValidator::SetStyle(long style)
71{
72 SetStyle((wxTextValidatorStyle)style);
73}
74#endif
75
76wxTextValidator::wxTextValidator(wxTextValidatorStyle style, wxString *val)
c801d85f 77{
52cd14b1
VZ
78 m_validatorStyle = style;
79 m_stringValue = val;
c801d85f
KB
80}
81
82wxTextValidator::wxTextValidator(const wxTextValidator& val)
d84afea9 83 : wxValidator()
c801d85f
KB
84{
85 Copy(val);
86}
87
88bool wxTextValidator::Copy(const wxTextValidator& val)
89{
90 wxValidator::Copy(val);
91
52cd14b1
VZ
92 m_validatorStyle = val.m_validatorStyle;
93 m_stringValue = val.m_stringValue;
a994f81b 94
f94a790d
RN
95 m_includes = val.m_includes;
96 m_excludes = val.m_excludes;
52cd14b1 97
cab1a605 98 return true;
c801d85f
KB
99}
100
472eec8a
VZ
101wxTextEntry *wxTextValidator::GetTextEntry()
102{
103#if wxUSE_TEXTCTRL
104 if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)))
105 {
106 return (wxTextCtrl*)m_validatorWindow;
107 }
108#endif
7b235dce 109
472eec8a
VZ
110#if wxUSE_COMBOBOX
111 if (m_validatorWindow->IsKindOf(CLASSINFO(wxComboBox)))
112 {
113 return (wxComboBox*)m_validatorWindow;
114 }
115#endif
116
117 wxFAIL_MSG(
118 _T("wxTextValidator can only be used with wxTextCtrl or wxComboBox")
119 );
120
121 return NULL;
122}
123
c801d85f
KB
124// Called when the value in the window must be validated.
125// This function can pop up an error message.
126bool wxTextValidator::Validate(wxWindow *parent)
127{
6cd47507 128 // If window is disabled, simply return
472eec8a 129 if ( !m_validatorWindow->IsEnabled() )
cab1a605 130 return true;
a994f81b 131
472eec8a
VZ
132 wxTextEntry * const text = GetTextEntry();
133 if ( !text )
134 return false;
135
136 wxString val(text->GetValue());
a994f81b 137
40ae9600 138 // NB: this format string should always contain exactly one '%s'
e9086757 139 wxString errormsg;
10b0f489
FM
140 if (!IsValid(val, &errormsg))
141 {
142 wxASSERT(!errormsg.empty());
143
144 m_validatorWindow->SetFocus();
145
146 wxString buf;
147 buf.Printf(errormsg, val.c_str());
148
149 wxMessageBox(buf, _("Validation conflict"),
150 wxOK | wxICON_EXCLAMATION, parent);
151
152 return false;
153 }
154
155 return true;
156}
157
158// Called to transfer data to the window
159bool wxTextValidator::TransferToWindow()
160{
161 if ( m_stringValue )
162 {
163 wxTextEntry * const text = GetTextEntry();
164 if ( !text )
165 return false;
a994f81b 166
10b0f489
FM
167 text->SetValue(*m_stringValue);
168 }
169
170 return true;
171}
172
173// Called to transfer data to the window
174bool wxTextValidator::TransferFromWindow()
175{
176 if ( m_stringValue )
177 {
178 wxTextEntry * const text = GetTextEntry();
179 if ( !text )
180 return false;
181
182 *m_stringValue = text->GetValue();
183 }
184
185 return true;
186}
187
188bool wxTextValidator::IsValid(const wxString& val, wxString* pErr) const
189{
190 wxString errormsg;
40ae9600 191 switch (m_validatorStyle)
a994f81b 192 {
16d4ffde
FM
193 case wxFILTER_NONE:
194 // nothing to do...
195 break;
196
40ae9600
FM
197 case wxFILTER_INCLUDE_LIST:
198 if ( m_includes.Index(val) == wxNOT_FOUND )
e9086757 199 errormsg = _("'%s' is invalid");
40ae9600 200 break;
a994f81b 201
40ae9600
FM
202 case wxFILTER_EXCLUDE_LIST:
203 if ( m_excludes.Index(val) != wxNOT_FOUND )
204 errormsg = _("'%s' is invalid");
205 break;
206
207 case wxFILTER_ASCII:
208 if ( !val.IsAscii() )
209 errormsg = _("'%s' should only contain ASCII characters.");
210 break;
211
212 case wxFILTER_ALPHA:
1406dc01 213 if ( !wxStringCheck<wxIsalpha>(val) )
40ae9600
FM
214 errormsg = _("'%s' should only contain alphabetic characters.");
215 break;
216
217 case wxFILTER_ALPHANUMERIC:
1406dc01 218 if ( !wxStringCheck<wxIsalnum>(val) )
40ae9600
FM
219 errormsg = _("'%s' should only contain alphabetic or numeric characters.");
220 break;
221
1406dc01
FM
222 case wxFILTER_SIMPLE_NUMBER:
223 if ( !wxStringCheck<wxIsdigit>(val) )
224 errormsg = _("'%s' should be numeric.");
225 break;
226
40ae9600
FM
227 case wxFILTER_NUMERIC:
228 if ( !wxIsNumeric(val) )
229 errormsg = _("'%s' should be numeric.");
230 break;
231
232 case wxFILTER_INCLUDE_CHAR_LIST:
1406dc01 233 if ( !ContainsOnlyIncludedCharacters(val) )
40ae9600
FM
234 errormsg = _("'%s' is invalid");
235 break;
a994f81b 236
40ae9600 237 case wxFILTER_EXCLUDE_CHAR_LIST:
1406dc01 238 if ( ContainsExcludedCharacters(val) )
40ae9600
FM
239 errormsg = _("'%s' is invalid");
240 break;
a994f81b 241
40ae9600
FM
242 default:
243 wxFAIL_MSG("invalid text validator style");
aaae8296 244 }
a994f81b 245
10b0f489
FM
246 if (pErr)
247 *pErr = errormsg;
a994f81b 248
10b0f489 249 return errormsg.empty();
c801d85f
KB
250}
251
1406dc01 252bool wxTextValidator::ContainsOnlyIncludedCharacters(const wxString& val) const
c801d85f 253{
fcd209b6
FM
254 for ( wxString::const_iterator i = val.begin(); i != val.end(); ++i )
255 if (m_includes.Index((wxString) *i) == wxNOT_FOUND)
10b0f489 256 // one character of 'val' is NOT present in m_includes...
472eec8a
VZ
257 return false;
258
10b0f489 259 // all characters of 'val' are present in m_includes
cab1a605 260 return true;
c801d85f
KB
261}
262
1406dc01 263bool wxTextValidator::ContainsExcludedCharacters(const wxString& val) const
c801d85f 264{
fcd209b6
FM
265 for ( wxString::const_iterator i = val.begin(); i != val.end(); ++i )
266 if (m_excludes.Index((wxString) *i) != wxNOT_FOUND)
10b0f489 267 // one character of 'val' is present in m_excludes...
fcd209b6 268 return true;
472eec8a 269
10b0f489 270 // all characters of 'val' are NOT present in m_excludes
fcd209b6
FM
271 return false;
272}
273
274void wxTextValidator::SetCharIncludes(const wxString& chars)
275{
276 wxArrayString arr;
277
278 for ( wxString::const_iterator i = chars.begin(); i != chars.end(); ++i )
279 arr.Add(*i);
280
281 SetIncludes(arr);
282}
283
284void wxTextValidator::SetCharExcludes(const wxString& chars)
285{
286 wxArrayString arr;
287
288 for ( wxString::const_iterator i = chars.begin(); i != chars.end(); ++i )
289 arr.Add(*i);
290
291 SetExcludes(arr);
c801d85f
KB
292}
293
10b0f489 294void wxTextValidator::OnChar(wxKeyEvent& event)
f94a790d 295{
10b0f489 296 if (!m_validatorWindow)
f94a790d 297 {
10b0f489
FM
298 event.Skip();
299 return;
f94a790d 300 }
f94a790d 301
10b0f489 302 int keyCode = event.GetKeyCode();
c801d85f 303
10b0f489
FM
304 // we don't filter special keys and delete
305 if (keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode >= WXK_START)
306 {
307 event.Skip();
a994f81b 308 return;
10b0f489 309 }
c801d85f 310
10b0f489
FM
311 wxString str((wxUniChar)keyCode, 1);
312 if (!IsValid(str, NULL))
a994f81b 313 {
10b0f489
FM
314 if ( !wxValidator::IsSilent() )
315 wxBell();
a994f81b 316
10b0f489
FM
317 // eat message
318 return;
319 }
320 else
321 event.Skip();
c801d85f
KB
322}
323
aaae8296 324
ce4169a4 325#endif
472eec8a 326 // wxUSE_VALIDATORS && (wxUSE_TEXTCTRL || wxUSE_COMBOBOX)