]> git.saurik.com Git - wxWidgets.git/blame - src/common/valtext.cpp
handle correctly never/always shown scrollbars in GetClientSize()
[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
5// Modified by:
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
c801d85f
KB
36IMPLEMENT_DYNAMIC_CLASS(wxTextValidator, wxValidator)
37
38BEGIN_EVENT_TABLE(wxTextValidator, wxValidator)
a994f81b 39 EVT_CHAR(wxTextValidator::OnChar)
c801d85f 40END_EVENT_TABLE()
c801d85f 41
386af6a2
JS
42static bool wxIsNumeric(const wxString& val);
43
debe6624 44wxTextValidator::wxTextValidator(long style, wxString *val)
c801d85f 45{
52cd14b1
VZ
46 m_validatorStyle = style;
47 m_stringValue = val;
c801d85f
KB
48/*
49 m_refData = new wxVTextRefData;
50
52cd14b1
VZ
51 M_VTEXTDATA->m_validatorStyle = style;
52 M_VTEXTDATA->m_stringValue = val;
c801d85f
KB
53*/
54}
55
56wxTextValidator::wxTextValidator(const wxTextValidator& val)
d84afea9 57 : wxValidator()
c801d85f
KB
58{
59 Copy(val);
60}
61
62bool wxTextValidator::Copy(const wxTextValidator& val)
63{
64 wxValidator::Copy(val);
65
52cd14b1
VZ
66 m_validatorStyle = val.m_validatorStyle;
67 m_stringValue = val.m_stringValue;
a994f81b 68
f94a790d
RN
69 m_includes = val.m_includes;
70 m_excludes = val.m_excludes;
52cd14b1 71
cab1a605 72 return true;
c801d85f
KB
73}
74
472eec8a
VZ
75wxTextEntry *wxTextValidator::GetTextEntry()
76{
77#if wxUSE_TEXTCTRL
78 if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)))
79 {
80 return (wxTextCtrl*)m_validatorWindow;
81 }
82#endif
7b235dce 83
472eec8a
VZ
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
c801d85f
KB
98static bool wxIsAlpha(const wxString& val)
99{
a994f81b 100 int i;
264cb7f5 101 for ( i = 0; i < (int)val.length(); i++)
a994f81b 102 {
f6bcfd97 103 if (!wxIsalpha(val[i]))
cab1a605 104 return false;
a994f81b 105 }
cab1a605 106 return true;
c801d85f
KB
107}
108
109static bool wxIsAlphaNumeric(const wxString& val)
110{
a994f81b 111 int i;
264cb7f5 112 for ( i = 0; i < (int)val.length(); i++)
a994f81b 113 {
f6bcfd97 114 if (!wxIsalnum(val[i]))
cab1a605 115 return false;
a994f81b 116 }
cab1a605 117 return true;
c801d85f
KB
118}
119
120// Called when the value in the window must be validated.
121// This function can pop up an error message.
122bool wxTextValidator::Validate(wxWindow *parent)
123{
6cd47507 124 // If window is disabled, simply return
472eec8a 125 if ( !m_validatorWindow->IsEnabled() )
cab1a605 126 return true;
a994f81b 127
472eec8a
VZ
128 wxTextEntry * const text = GetTextEntry();
129 if ( !text )
130 return false;
131
132 wxString val(text->GetValue());
a994f81b 133
cab1a605 134 bool ok = true;
a994f81b 135
e9086757
VZ
136 // NB: this format string should contian exactly one '%s'
137 wxString errormsg;
a994f81b 138
f94a790d
RN
139 bool includes = (m_validatorStyle & wxFILTER_INCLUDE_LIST) != 0;
140 if ( includes || (m_validatorStyle & wxFILTER_EXCLUDE_LIST) )
a994f81b 141 {
f94a790d 142 // if includes, it's only ok to have the members of the list,
e9086757 143 // otherwise it's only ok to have non-members
f94a790d 144 ok = includes == (m_includes.Index(val) != wxNOT_FOUND);
e9086757 145 if ( !ok )
a994f81b 146 {
e9086757 147 errormsg = _("'%s' is invalid");
a994f81b
VZ
148 }
149 }
150 else if ( (m_validatorStyle & wxFILTER_ASCII) && !val.IsAscii() )
151 {
cab1a605 152 ok = false;
a994f81b
VZ
153
154 errormsg = _("'%s' should only contain ASCII characters.");
155 }
156 else if ( (m_validatorStyle & wxFILTER_ALPHA) && !wxIsAlpha(val) )
157 {
cab1a605 158 ok = false;
a994f81b
VZ
159
160 errormsg = _("'%s' should only contain alphabetic characters.");
161 }
162 else if ( (m_validatorStyle & wxFILTER_ALPHANUMERIC) && !wxIsAlphaNumeric(val))
163 {
cab1a605 164 ok = false;
a994f81b
VZ
165
166 errormsg = _("'%s' should only contain alphabetic or numeric characters.");
167 }
168 else if ( (m_validatorStyle & wxFILTER_NUMERIC) && !wxIsNumeric(val))
169 {
cab1a605 170 ok = false;
a994f81b
VZ
171
172 errormsg = _("'%s' should be numeric.");
173 }
f94a790d 174 else if ( (m_validatorStyle & wxFILTER_INCLUDE_CHAR_LIST) && !IsInCharIncludes(val))
aaae8296
JS
175 {
176 //it's only ok to have the members of the list
177 errormsg = _("'%s' is invalid");
cab1a605 178 ok = false;
aaae8296 179 }
f94a790d 180 else if ( (m_validatorStyle & wxFILTER_EXCLUDE_CHAR_LIST) && !IsNotInCharExcludes(val))
aaae8296
JS
181 {
182 // it's only ok to have non-members of the list
183 errormsg = _("'%s' is invalid");
cab1a605 184 ok = false;
aaae8296 185 }
a994f81b
VZ
186
187 if ( !ok )
188 {
e9086757
VZ
189 wxASSERT_MSG( !errormsg.empty(), _T("you forgot to set errormsg") );
190
a994f81b
VZ
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;
c801d85f
KB
201}
202
203// Called to transfer data to the window
204bool wxTextValidator::TransferToWindow(void)
205{
52cd14b1
VZ
206 if ( m_stringValue )
207 {
472eec8a
VZ
208 wxTextEntry * const text = GetTextEntry();
209 if ( !text )
210 return false;
211
212 text->SetValue(*m_stringValue);
52cd14b1 213 }
c801d85f 214
cab1a605 215 return true;
c801d85f
KB
216}
217
218// Called to transfer data to the window
219bool wxTextValidator::TransferFromWindow(void)
220{
52cd14b1
VZ
221 if ( m_stringValue )
222 {
472eec8a
VZ
223 wxTextEntry * const text = GetTextEntry();
224 if ( !text )
225 return false;
226
227 *m_stringValue = text->GetValue();
52cd14b1 228 }
c801d85f 229
cab1a605 230 return true;
c801d85f
KB
231}
232
f94a790d
RN
233bool wxTextValidator::IsInCharIncludes(const wxString& val)
234{
235 size_t i;
264cb7f5 236 for ( i = 0; i < val.length(); i++)
f94a790d
RN
237 {
238 if (m_includes.Index((wxString) val[i]) == wxNOT_FOUND)
239 return false;
240 }
241 return true;
242}
243
244bool wxTextValidator::IsNotInCharExcludes(const wxString& val)
245{
246 size_t i;
264cb7f5 247 for ( i = 0; i < val.length(); i++)
f94a790d
RN
248 {
249 if (m_excludes.Index((wxString) val[i]) != wxNOT_FOUND)
250 return false;
251 }
252 return true;
c801d85f
KB
253}
254
255void wxTextValidator::OnChar(wxKeyEvent& event)
256{
257/*
a994f81b
VZ
258 if ( !M_VTEXTDATA )
259 return;
c801d85f
KB
260*/
261
a994f81b
VZ
262 if ( m_validatorWindow )
263 {
12a3f227 264 int keyCode = event.GetKeyCode();
a994f81b
VZ
265
266 // we don't filter special keys and Delete
267 if (
268 !(keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode > WXK_START) &&
269 (
f94a790d
RN
270 ((m_validatorStyle & wxFILTER_INCLUDE_CHAR_LIST) && !IsInCharIncludes(wxString((wxChar) keyCode, 1))) ||
271 ((m_validatorStyle & wxFILTER_EXCLUDE_CHAR_LIST) && !IsNotInCharExcludes(wxString((wxChar) keyCode, 1))) ||
b1e4e7cc 272 ((m_validatorStyle & wxFILTER_ASCII) && !isascii(keyCode)) ||
0c6099b7
RN
273 ((m_validatorStyle & wxFILTER_ALPHA) && !wxIsalpha(keyCode)) ||
274 ((m_validatorStyle & wxFILTER_ALPHANUMERIC) && !wxIsalnum(keyCode)) ||
275 ((m_validatorStyle & wxFILTER_NUMERIC) && !wxIsdigit(keyCode)
14d77693 276 && keyCode != wxT('.') && keyCode != wxT(',') && keyCode != wxT('-') && keyCode != wxT('+') && keyCode != wxT('e') && keyCode != wxT('E'))
a994f81b
VZ
277 )
278 )
279 {
280 if ( !wxValidator::IsSilent() )
281 wxBell();
282
283 // eat message
284 return;
285 }
286 }
287
288 event.Skip();
c801d85f
KB
289}
290
386af6a2
JS
291static bool wxIsNumeric(const wxString& val)
292{
a994f81b 293 int i;
264cb7f5 294 for ( i = 0; i < (int)val.length(); i++)
a994f81b 295 {
543f08a6
JS
296 // Allow for "," (French) as well as "." -- in future we should
297 // use wxSystemSettings or other to do better localisation
f7f00d8a 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('-')))
cab1a605 299 return false;
a994f81b 300 }
cab1a605 301 return true;
386af6a2 302}
c801d85f 303
aaae8296 304
ce4169a4 305#endif
472eec8a 306 // wxUSE_VALIDATORS && (wxUSE_TEXTCTRL || wxUSE_COMBOBOX)