]> git.saurik.com Git - wxWidgets.git/blame - include/wx/valnum.h
Allow associating a validator with wxGridCellTextEditor.
[wxWidgets.git] / include / wx / valnum.h
CommitLineData
a54cf371
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/valnum.h
3// Purpose: Numeric validator classes.
4// Author: Vadim Zeitlin based on the submission of Fulvio Senore
5// Created: 2010-11-06
6// Copyright: (c) 2010 wxWidgets team
7// (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifndef _WX_VALNUM_H_
12#define _WX_VALNUM_H_
13
14#include "wx/defs.h"
15
16#if wxUSE_VALIDATORS
17
18#include "wx/validate.h"
19
20#include <limits>
21
22// Bit masks used for numeric validator styles.
23enum wxNumValidatorStyle
24{
25 wxNUM_VAL_DEFAULT = 0x0,
26 wxNUM_VAL_THOUSANDS_SEPARATOR = 0x1,
27 wxNUM_VAL_ZERO_AS_BLANK = 0x2,
28 wxNUM_VAL_NO_TRAILING_ZEROES = 0x4
29};
30
31// ----------------------------------------------------------------------------
32// Base class for all numeric validators.
33// ----------------------------------------------------------------------------
34
35class WXDLLIMPEXP_CORE wxNumValidatorBase : public wxValidator
36{
37public:
38 // Change the validator style. Usually it's specified during construction.
39 void SetStyle(int style) { m_style = style; }
40
41
42 // Override base class method to not do anything but always return success:
43 // we don't need this as we do our validation on the fly here.
44 virtual bool Validate(wxWindow * WXUNUSED(parent)) { return true; }
45
46protected:
47 wxNumValidatorBase(int style)
48 {
49 m_style = style;
50 }
51
e71baaa8 52 wxNumValidatorBase(const wxNumValidatorBase& other) : wxValidator()
a54cf371
VZ
53 {
54 m_style = other.m_style;
55 }
56
57 bool HasFlag(wxNumValidatorStyle style) const
58 {
59 return (m_style & style) != 0;
60 }
61
62 // Get the text entry of the associated control. Normally shouldn't ever
63 // return NULL (and will assert if it does return it) but the caller should
64 // still test the return value for safety.
65 wxTextEntry *GetTextEntry() const;
66
67 // Convert wxNUM_VAL_THOUSANDS_SEPARATOR and wxNUM_VAL_NO_TRAILING_ZEROES
68 // bits of our style to the corresponding wxNumberFormatter::Style values.
69 int GetFormatFlags() const;
70
71 // Return true if pressing a '-' key is acceptable for the current control
72 // contents and insertion point. This is meant to be called from the
73 // derived class IsCharOk() implementation.
74 bool IsMinusOk(const wxString& val, int pos) const;
75
76 // Return the string which would result from inserting the given character
77 // at the specified position.
78 wxString GetValueAfterInsertingChar(wxString val, int pos, wxChar ch) const
79 {
80 val.insert(pos, ch);
81 return val;
82 }
83
84private:
85 // Check whether the specified character can be inserted in the control at
86 // the given position in the string representing the current controls
87 // contents.
88 //
89 // Notice that the base class checks for '-' itself so it's never passed to
90 // this function.
91 virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const = 0;
92
93 // NormalizeString the contents of the string if it's a valid number, return
94 // empty string otherwise.
95 virtual wxString NormalizeString(const wxString& s) const = 0;
96
97
98 // Event handlers.
99 void OnChar(wxKeyEvent& event);
100 void OnKillFocus(wxFocusEvent& event);
101
102
103 // Determine the current insertion point and text in the associated control.
104 void GetCurrentValueAndInsertionPoint(wxString& val, int& pos) const;
105
106
107 // Combination of wxVAL_NUM_XXX values.
108 int m_style;
109
110
111 wxDECLARE_EVENT_TABLE();
112
113 wxDECLARE_NO_ASSIGN_CLASS(wxNumValidatorBase);
114};
115
116namespace wxPrivate
117{
118
119// This is a helper class used by wxIntegerValidator and wxFloatingPointValidator
120// below that implements Transfer{To,From}Window() adapted to the type of the
121// variable.
122//
123// The template argument B is the name of the base class which must derive from
124// wxNumValidatorBase and define LongestValueType type and {To,As}String()
125// methods i.e. basically be one of wx{Integer,Number}ValidatorBase classes.
126//
127// The template argument T is just the type handled by the validator that will
128// inherit from this one.
129template <class B, typename T>
130class wxNumValidator : public B
131{
132public:
133 typedef B BaseValidator;
134 typedef T ValueType;
135
136 typedef typename BaseValidator::LongestValueType LongestValueType;
137
6496afba
VZ
138 // FIXME-VC6: This compiler fails to compile the assert below with a
139 // nonsensical error C2248: "'LongestValueType' : cannot access protected
140 // typedef declared in class 'wxIntegerValidatorBase'" so just disable the
141 // check for it.
142#ifndef __VISUALC6__
a54cf371
VZ
143 wxCOMPILE_TIME_ASSERT
144 (
145 sizeof(ValueType) <= sizeof(LongestValueType),
146 UnsupportedType
147 );
6496afba 148#endif // __VISUALC6__
a54cf371
VZ
149
150 void SetMin(ValueType min)
151 {
152 this->DoSetMin(min);
153 }
154
155 void SetMax(ValueType max)
156 {
157 this->DoSetMax(max);
158 }
159
160 void SetRange(ValueType min, ValueType max)
161 {
162 SetMin(min);
163 SetMax(max);
164 }
165
166 virtual bool TransferToWindow()
167 {
168 if ( m_value )
169 {
170 wxTextEntry * const control = BaseValidator::GetTextEntry();
171 if ( !control )
172 return false;
173
174 control->SetValue(NormalizeValue(*m_value));
175 }
176
177 return true;
178 }
179
180 virtual bool TransferFromWindow()
181 {
182 if ( m_value )
183 {
184 wxTextEntry * const control = BaseValidator::GetTextEntry();
185 if ( !control )
186 return false;
187
188 const wxString s(control->GetValue());
189 LongestValueType value;
190 if ( s.empty() && BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
191 value = 0;
192 else if ( !BaseValidator::FromString(s, &value) )
193 return false;
194
df04f800 195 if ( !this->IsInRange(value) )
a54cf371
VZ
196 return false;
197
198 *m_value = static_cast<ValueType>(value);
199 }
200
201 return true;
202 }
203
204protected:
205 wxNumValidator(ValueType *value, int style)
206 : BaseValidator(style),
207 m_value(value)
208 {
209 }
210
211 // Implement wxNumValidatorBase virtual method which is the same for
212 // both integer and floating point numbers.
213 virtual wxString NormalizeString(const wxString& s) const
214 {
215 LongestValueType value;
216 return BaseValidator::FromString(s, &value) ? NormalizeValue(value)
217 : wxString();
218 }
219
220private:
221 // Just a helper which is a common part of TransferToWindow() and
222 // NormalizeString(): returns string representation of a number honouring
223 // wxNUM_VAL_ZERO_AS_BLANK flag.
224 wxString NormalizeValue(LongestValueType value) const
225 {
226 wxString s;
227 if ( value != 0 || !BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
df04f800 228 s = this->ToString(value);
a54cf371
VZ
229
230 return s;
231 }
232
233
234 ValueType * const m_value;
235
236 wxDECLARE_NO_ASSIGN_CLASS(wxNumValidator);
237};
238
239} // namespace wxPrivate
240
241// ----------------------------------------------------------------------------
242// Validators for integer numbers.
243// ----------------------------------------------------------------------------
244
245// Base class for integer numbers validator. This class contains all non
246// type-dependent code of wxIntegerValidator<> and always works with values of
247// type LongestValueType. It is not meant to be used directly, please use
248// wxIntegerValidator<> only instead.
249class WXDLLIMPEXP_CORE wxIntegerValidatorBase : public wxNumValidatorBase
250{
251protected:
252 // Define the type we use here, it should be the maximal-sized integer type
253 // we support to make it possible to base wxIntegerValidator<> for any type
254 // on it.
255#ifdef wxLongLong_t
256 typedef wxLongLong_t LongestValueType;
257#else
258 typedef long LongestValueType;
259#endif
260
261 wxIntegerValidatorBase(int style)
262 : wxNumValidatorBase(style)
263 {
264 wxASSERT_MSG( !(style & wxNUM_VAL_NO_TRAILING_ZEROES),
265 "This style doesn't make sense for integers." );
266 }
267
268 wxIntegerValidatorBase(const wxIntegerValidatorBase& other)
269 : wxNumValidatorBase(other)
270 {
271 m_min = other.m_min;
272 m_max = other.m_max;
273 }
274
275 // Provide methods for wxNumValidator use.
276 wxString ToString(LongestValueType value) const;
277 static bool FromString(const wxString& s, LongestValueType *value);
278
279 void DoSetMin(LongestValueType min) { m_min = min; }
280 void DoSetMax(LongestValueType max) { m_max = max; }
281
282 bool IsInRange(LongestValueType value) const
283 {
284 return m_min <= value && value <= m_max;
285 }
286
287 // Implement wxNumValidatorBase pure virtual method.
288 virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const;
289
290private:
291 // Minimal and maximal values accepted (inclusive).
292 LongestValueType m_min, m_max;
293
294 wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidatorBase);
295};
296
297// Validator for integer numbers. It can actually work with any integer type
298// (short, int or long and long long if supported) and their unsigned versions
299// as well.
300template <typename T>
301class wxIntegerValidator
302 : public wxPrivate::wxNumValidator<wxIntegerValidatorBase, T>
303{
304public:
305 typedef T ValueType;
306
307 typedef
308 wxPrivate::wxNumValidator<wxIntegerValidatorBase, T> Base;
309
310 // Ctor for an integer validator.
311 //
312 // Sets the range appropriately for the type, including setting 0 as the
313 // minimal value for the unsigned types.
314 wxIntegerValidator(ValueType *value = NULL, int style = wxNUM_VAL_DEFAULT)
315 : Base(value, style)
316 {
df04f800
SC
317 this->DoSetMin(std::numeric_limits<ValueType>::min());
318 this->DoSetMax(std::numeric_limits<ValueType>::max());
a54cf371
VZ
319 }
320
321 virtual wxObject *Clone() const { return new wxIntegerValidator(*this); }
322
323private:
324 wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidator);
325};
326
327// Helper function for creating integer validators which allows to avoid
328// explicitly specifying the type as it deduces it from its parameter.
329template <typename T>
330inline wxIntegerValidator<T>
331wxMakeIntegerValidator(T *value, int style = wxNUM_VAL_DEFAULT)
332{
333 return wxIntegerValidator<T>(value, style);
334}
335
336// ----------------------------------------------------------------------------
337// Validators for floating point numbers.
338// ----------------------------------------------------------------------------
339
340// Similar to wxIntegerValidatorBase, this class is not meant to be used
341// directly, only wxFloatingPointValidator<> should be used in the user code.
342class WXDLLIMPEXP_CORE wxFloatingPointValidatorBase : public wxNumValidatorBase
343{
344public:
345 // Set precision i.e. the number of digits shown (and accepted on input)
346 // after the decimal point. By default this is set to the maximal precision
347 // supported by the type handled by the validator.
348 void SetPrecision(unsigned precision) { m_precision = precision; }
349
350protected:
351 // Notice that we can't use "long double" here because it's not supported
352 // by wxNumberFormatter yet, so restrict ourselves to just double (and
353 // float).
354 typedef double LongestValueType;
355
356 wxFloatingPointValidatorBase(int style)
357 : wxNumValidatorBase(style)
358 {
359 }
360
361 wxFloatingPointValidatorBase(const wxFloatingPointValidatorBase& other)
362 : wxNumValidatorBase(other)
363 {
364 m_precision = other.m_precision;
365
366 m_min = other.m_min;
367 m_max = other.m_max;
368 }
369
370 // Provide methods for wxNumValidator use.
371 wxString ToString(LongestValueType value) const;
372 static bool FromString(const wxString& s, LongestValueType *value);
373
374 void DoSetMin(LongestValueType min) { m_min = min; }
375 void DoSetMax(LongestValueType max) { m_max = max; }
376
377 bool IsInRange(LongestValueType value) const
378 {
379 return m_min <= value && value <= m_max;
380 }
381
382 // Implement wxNumValidatorBase pure virtual method.
383 virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const;
384
385private:
386 // Maximum number of decimals digits after the decimal separator.
387 unsigned m_precision;
388
389 // Minimal and maximal values accepted (inclusive).
390 LongestValueType m_min, m_max;
391
392 wxDECLARE_NO_ASSIGN_CLASS(wxFloatingPointValidatorBase);
393};
394
395// Validator for floating point numbers. It can be used with float, double or
396// long double values.
397template <typename T>
398class wxFloatingPointValidator
399 : public wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T>
400{
401public:
402 typedef T ValueType;
403 typedef wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T> Base;
404
405 // Ctor using implicit (maximal) precision for this type.
406 wxFloatingPointValidator(ValueType *value = NULL,
407 int style = wxNUM_VAL_DEFAULT)
408 : Base(value, style)
409 {
410 DoSetMinMax();
411
f5f3d4ec 412 this->SetPrecision(std::numeric_limits<ValueType>::digits10);
a54cf371
VZ
413 }
414
415 // Ctor specifying an explicit precision.
416 wxFloatingPointValidator(int precision,
417 ValueType *value = NULL,
418 int style = wxNUM_VAL_DEFAULT)
419 : Base(value, style)
420 {
421 DoSetMinMax();
422
423 this->SetPrecision(precision);
424 }
425
426 virtual wxObject *Clone() const
427 {
428 return new wxFloatingPointValidator(*this);
429 }
430
431private:
432 void DoSetMinMax()
433 {
434 // NB: Do not use min(), it's not the smallest representable value for
435 // the floating point types but rather the smallest representable
436 // positive value.
df04f800
SC
437 this->DoSetMin(-std::numeric_limits<ValueType>::max());
438 this->DoSetMax( std::numeric_limits<ValueType>::max());
a54cf371
VZ
439 }
440};
441
442// Helper similar to wxMakeIntValidator().
443//
444// NB: Unfortunately we can't just have a wxMakeNumericValidator() which would
445// return either wxIntegerValidator<> or wxFloatingPointValidator<> so we
446// do need two different functions.
447template <typename T>
448inline wxFloatingPointValidator<T>
449wxMakeFloatingPointValidator(T *value, int style = wxNUM_VAL_DEFAULT)
450{
451 return wxFloatingPointValidator<T>(value, style);
452}
453
454template <typename T>
455inline wxFloatingPointValidator<T>
456wxMakeFloatingPointValidator(int precision, T *value, int style = wxNUM_VAL_DEFAULT)
457{
458 return wxFloatingPointValidator<T>(precision, value, style);
459}
460
461#endif // wxUSE_VALIDATORS
462
463#endif // _WX_VALNUM_H_