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