]> git.saurik.com Git - wxWidgets.git/blob - include/wx/valnum.h
Slightly more efficient wxDataViewCtrl::StartEditor().
[wxWidgets.git] / include / wx / valnum.h
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.
23 enum 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
35 class WXDLLIMPEXP_CORE wxNumValidatorBase : public wxValidator
36 {
37 public:
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
46 protected:
47 wxNumValidatorBase(int style)
48 {
49 m_style = style;
50 }
51
52 wxNumValidatorBase(const wxNumValidatorBase& other) : wxValidator()
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
84 private:
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
116 namespace 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.
129 template <class B, typename T>
130 class wxNumValidator : public B
131 {
132 public:
133 typedef B BaseValidator;
134 typedef T ValueType;
135
136 typedef typename BaseValidator::LongestValueType LongestValueType;
137
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__
143 wxCOMPILE_TIME_ASSERT
144 (
145 sizeof(ValueType) <= sizeof(LongestValueType),
146 UnsupportedType
147 );
148 #endif // __VISUALC6__
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
195 if ( !this->IsInRange(value) )
196 return false;
197
198 *m_value = static_cast<ValueType>(value);
199 }
200
201 return true;
202 }
203
204 protected:
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
220 private:
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) )
228 s = this->ToString(value);
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.
249 class WXDLLIMPEXP_CORE wxIntegerValidatorBase : public wxNumValidatorBase
250 {
251 protected:
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
290 private:
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.
300 template <typename T>
301 class wxIntegerValidator
302 : public wxPrivate::wxNumValidator<wxIntegerValidatorBase, T>
303 {
304 public:
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 {
317 this->DoSetMin(std::numeric_limits<ValueType>::min());
318 this->DoSetMax(std::numeric_limits<ValueType>::max());
319 }
320
321 virtual wxObject *Clone() const { return new wxIntegerValidator(*this); }
322
323 private:
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.
329 template <typename T>
330 inline wxIntegerValidator<T>
331 wxMakeIntegerValidator(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.
342 class WXDLLIMPEXP_CORE wxFloatingPointValidatorBase : public wxNumValidatorBase
343 {
344 public:
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
350 protected:
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
385 private:
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.
397 template <typename T>
398 class wxFloatingPointValidator
399 : public wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T>
400 {
401 public:
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
412 this->SetPrecision(std::numeric_limits<ValueType>::digits10);
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
431 private:
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.
437 this->DoSetMin(-std::numeric_limits<ValueType>::max());
438 this->DoSetMax( std::numeric_limits<ValueType>::max());
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.
447 template <typename T>
448 inline wxFloatingPointValidator<T>
449 wxMakeFloatingPointValidator(T *value, int style = wxNUM_VAL_DEFAULT)
450 {
451 return wxFloatingPointValidator<T>(value, style);
452 }
453
454 template <typename T>
455 inline wxFloatingPointValidator<T>
456 wxMakeFloatingPointValidator(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_