1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Numeric validator classes.
4 // Author: Vadim Zeitlin based on the submission of Fulvio Senore
6 // Copyright: (c) 2010 wxWidgets team
7 // (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
18 #include "wx/validate.h"
22 // Bit masks used for numeric validator styles.
23 enum wxNumValidatorStyle
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
31 // ----------------------------------------------------------------------------
32 // Base class for all numeric validators.
33 // ----------------------------------------------------------------------------
35 class WXDLLIMPEXP_CORE wxNumValidatorBase
: public wxValidator
38 // Change the validator style. Usually it's specified during construction.
39 void SetStyle(int style
) { m_style
= style
; }
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; }
47 wxNumValidatorBase(int style
)
52 wxNumValidatorBase(const wxNumValidatorBase
& other
)
54 m_style
= other
.m_style
;
57 bool HasFlag(wxNumValidatorStyle style
) const
59 return (m_style
& style
) != 0;
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;
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;
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;
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
85 // Check whether the specified character can be inserted in the control at
86 // the given position in the string representing the current controls
89 // Notice that the base class checks for '-' itself so it's never passed to
91 virtual bool IsCharOk(const wxString
& val
, int pos
, wxChar ch
) const = 0;
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;
99 void OnChar(wxKeyEvent
& event
);
100 void OnKillFocus(wxFocusEvent
& event
);
103 // Determine the current insertion point and text in the associated control.
104 void GetCurrentValueAndInsertionPoint(wxString
& val
, int& pos
) const;
107 // Combination of wxVAL_NUM_XXX values.
111 wxDECLARE_EVENT_TABLE();
113 wxDECLARE_NO_ASSIGN_CLASS(wxNumValidatorBase
);
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
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.
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
133 typedef B BaseValidator
;
136 typedef typename
BaseValidator::LongestValueType LongestValueType
;
138 wxCOMPILE_TIME_ASSERT
140 sizeof(ValueType
) <= sizeof(LongestValueType
),
144 void SetMin(ValueType min
)
149 void SetMax(ValueType max
)
154 void SetRange(ValueType min
, ValueType max
)
160 virtual bool TransferToWindow()
164 wxTextEntry
* const control
= BaseValidator::GetTextEntry();
168 control
->SetValue(NormalizeValue(*m_value
));
174 virtual bool TransferFromWindow()
178 wxTextEntry
* const control
= BaseValidator::GetTextEntry();
182 const wxString
s(control
->GetValue());
183 LongestValueType value
;
184 if ( s
.empty() && BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK
) )
186 else if ( !BaseValidator::FromString(s
, &value
) )
189 if ( !IsInRange(value
) )
192 *m_value
= static_cast<ValueType
>(value
);
199 wxNumValidator(ValueType
*value
, int style
)
200 : BaseValidator(style
),
205 // Implement wxNumValidatorBase virtual method which is the same for
206 // both integer and floating point numbers.
207 virtual wxString
NormalizeString(const wxString
& s
) const
209 LongestValueType value
;
210 return BaseValidator::FromString(s
, &value
) ? NormalizeValue(value
)
215 // Just a helper which is a common part of TransferToWindow() and
216 // NormalizeString(): returns string representation of a number honouring
217 // wxNUM_VAL_ZERO_AS_BLANK flag.
218 wxString
NormalizeValue(LongestValueType value
) const
221 if ( value
!= 0 || !BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK
) )
228 ValueType
* const m_value
;
230 wxDECLARE_NO_ASSIGN_CLASS(wxNumValidator
);
233 } // namespace wxPrivate
235 // ----------------------------------------------------------------------------
236 // Validators for integer numbers.
237 // ----------------------------------------------------------------------------
239 // Base class for integer numbers validator. This class contains all non
240 // type-dependent code of wxIntegerValidator<> and always works with values of
241 // type LongestValueType. It is not meant to be used directly, please use
242 // wxIntegerValidator<> only instead.
243 class WXDLLIMPEXP_CORE wxIntegerValidatorBase
: public wxNumValidatorBase
246 // Define the type we use here, it should be the maximal-sized integer type
247 // we support to make it possible to base wxIntegerValidator<> for any type
250 typedef wxLongLong_t LongestValueType
;
252 typedef long LongestValueType
;
255 wxIntegerValidatorBase(int style
)
256 : wxNumValidatorBase(style
)
258 wxASSERT_MSG( !(style
& wxNUM_VAL_NO_TRAILING_ZEROES
),
259 "This style doesn't make sense for integers." );
262 wxIntegerValidatorBase(const wxIntegerValidatorBase
& other
)
263 : wxNumValidatorBase(other
)
269 // Provide methods for wxNumValidator use.
270 wxString
ToString(LongestValueType value
) const;
271 static bool FromString(const wxString
& s
, LongestValueType
*value
);
273 void DoSetMin(LongestValueType min
) { m_min
= min
; }
274 void DoSetMax(LongestValueType max
) { m_max
= max
; }
276 bool IsInRange(LongestValueType value
) const
278 return m_min
<= value
&& value
<= m_max
;
281 // Implement wxNumValidatorBase pure virtual method.
282 virtual bool IsCharOk(const wxString
& val
, int pos
, wxChar ch
) const;
285 // Minimal and maximal values accepted (inclusive).
286 LongestValueType m_min
, m_max
;
288 wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidatorBase
);
291 // Validator for integer numbers. It can actually work with any integer type
292 // (short, int or long and long long if supported) and their unsigned versions
294 template <typename T
>
295 class wxIntegerValidator
296 : public wxPrivate::wxNumValidator
<wxIntegerValidatorBase
, T
>
302 wxPrivate::wxNumValidator
<wxIntegerValidatorBase
, T
> Base
;
304 // Ctor for an integer validator.
306 // Sets the range appropriately for the type, including setting 0 as the
307 // minimal value for the unsigned types.
308 wxIntegerValidator(ValueType
*value
= NULL
, int style
= wxNUM_VAL_DEFAULT
)
311 DoSetMin(std::numeric_limits
<ValueType
>::min());
312 DoSetMax(std::numeric_limits
<ValueType
>::max());
315 virtual wxObject
*Clone() const { return new wxIntegerValidator(*this); }
318 wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidator
);
321 // Helper function for creating integer validators which allows to avoid
322 // explicitly specifying the type as it deduces it from its parameter.
323 template <typename T
>
324 inline wxIntegerValidator
<T
>
325 wxMakeIntegerValidator(T
*value
, int style
= wxNUM_VAL_DEFAULT
)
327 return wxIntegerValidator
<T
>(value
, style
);
330 // ----------------------------------------------------------------------------
331 // Validators for floating point numbers.
332 // ----------------------------------------------------------------------------
334 // Similar to wxIntegerValidatorBase, this class is not meant to be used
335 // directly, only wxFloatingPointValidator<> should be used in the user code.
336 class WXDLLIMPEXP_CORE wxFloatingPointValidatorBase
: public wxNumValidatorBase
339 // Set precision i.e. the number of digits shown (and accepted on input)
340 // after the decimal point. By default this is set to the maximal precision
341 // supported by the type handled by the validator.
342 void SetPrecision(unsigned precision
) { m_precision
= precision
; }
345 // Notice that we can't use "long double" here because it's not supported
346 // by wxNumberFormatter yet, so restrict ourselves to just double (and
348 typedef double LongestValueType
;
350 wxFloatingPointValidatorBase(int style
)
351 : wxNumValidatorBase(style
)
355 wxFloatingPointValidatorBase(const wxFloatingPointValidatorBase
& other
)
356 : wxNumValidatorBase(other
)
358 m_precision
= other
.m_precision
;
364 // Provide methods for wxNumValidator use.
365 wxString
ToString(LongestValueType value
) const;
366 static bool FromString(const wxString
& s
, LongestValueType
*value
);
368 void DoSetMin(LongestValueType min
) { m_min
= min
; }
369 void DoSetMax(LongestValueType max
) { m_max
= max
; }
371 bool IsInRange(LongestValueType value
) const
373 return m_min
<= value
&& value
<= m_max
;
376 // Implement wxNumValidatorBase pure virtual method.
377 virtual bool IsCharOk(const wxString
& val
, int pos
, wxChar ch
) const;
380 // Maximum number of decimals digits after the decimal separator.
381 unsigned m_precision
;
383 // Minimal and maximal values accepted (inclusive).
384 LongestValueType m_min
, m_max
;
386 wxDECLARE_NO_ASSIGN_CLASS(wxFloatingPointValidatorBase
);
389 // Validator for floating point numbers. It can be used with float, double or
390 // long double values.
391 template <typename T
>
392 class wxFloatingPointValidator
393 : public wxPrivate::wxNumValidator
<wxFloatingPointValidatorBase
, T
>
397 typedef wxPrivate::wxNumValidator
<wxFloatingPointValidatorBase
, T
> Base
;
399 // Ctor using implicit (maximal) precision for this type.
400 wxFloatingPointValidator(ValueType
*value
= NULL
,
401 int style
= wxNUM_VAL_DEFAULT
)
406 SetPrecision(std::numeric_limits
<ValueType
>::digits10
);
409 // Ctor specifying an explicit precision.
410 wxFloatingPointValidator(int precision
,
411 ValueType
*value
= NULL
,
412 int style
= wxNUM_VAL_DEFAULT
)
417 this->SetPrecision(precision
);
420 virtual wxObject
*Clone() const
422 return new wxFloatingPointValidator(*this);
428 // NB: Do not use min(), it's not the smallest representable value for
429 // the floating point types but rather the smallest representable
431 DoSetMin(-std::numeric_limits
<ValueType
>::max());
432 DoSetMax( std::numeric_limits
<ValueType
>::max());
436 // Helper similar to wxMakeIntValidator().
438 // NB: Unfortunately we can't just have a wxMakeNumericValidator() which would
439 // return either wxIntegerValidator<> or wxFloatingPointValidator<> so we
440 // do need two different functions.
441 template <typename T
>
442 inline wxFloatingPointValidator
<T
>
443 wxMakeFloatingPointValidator(T
*value
, int style
= wxNUM_VAL_DEFAULT
)
445 return wxFloatingPointValidator
<T
>(value
, style
);
448 template <typename T
>
449 inline wxFloatingPointValidator
<T
>
450 wxMakeFloatingPointValidator(int precision
, T
*value
, int style
= wxNUM_VAL_DEFAULT
)
452 return wxFloatingPointValidator
<T
>(precision
, value
, style
);
455 #endif // wxUSE_VALIDATORS
457 #endif // _WX_VALNUM_H_