initial commit
Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
588
libs/wxWidgets-3.3.1/include/wx/valnum.h
Normal file
588
libs/wxWidgets-3.3.1/include/wx/valnum.h
Normal file
@@ -0,0 +1,588 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/valnum.h
|
||||
// Purpose: Numeric validator classes.
|
||||
// Author: Vadim Zeitlin based on the submission of Fulvio Senore
|
||||
// Created: 2010-11-06
|
||||
// Copyright: (c) 2010 wxWidgets team
|
||||
// (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_VALNUM_H_
|
||||
#define _WX_VALNUM_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#if wxUSE_VALIDATORS
|
||||
|
||||
#include "wx/textentry.h"
|
||||
#include "wx/validate.h"
|
||||
|
||||
// This header uses std::numeric_limits<>::min/max, but these symbols are,
|
||||
// unfortunately, often defined as macros and the code here wouldn't compile in
|
||||
// this case, so preventively undefine them to avoid this problem.
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#include <limits>
|
||||
|
||||
// Bit masks used for numeric validator styles.
|
||||
enum wxNumValidatorStyle
|
||||
{
|
||||
wxNUM_VAL_DEFAULT = 0x0,
|
||||
wxNUM_VAL_THOUSANDS_SEPARATOR = 0x1,
|
||||
wxNUM_VAL_ZERO_AS_BLANK = 0x2,
|
||||
wxNUM_VAL_NO_TRAILING_ZEROES = 0x4,
|
||||
wxNUM_VAL_SIGN_PLUS = 0x8,
|
||||
wxNUM_VAL_SIGN_SPACE = 0x10,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Base class for all numeric validators.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_CORE wxNumValidatorBase : public wxValidator
|
||||
{
|
||||
public:
|
||||
// Change the validator style. Usually it's specified during construction.
|
||||
void SetStyle(int style) { m_style = style; }
|
||||
|
||||
|
||||
// Override base class method to not do anything but always return success:
|
||||
// we don't need this as we do our validation on the fly here.
|
||||
virtual bool Validate(wxWindow * WXUNUSED(parent)) override { return true; }
|
||||
|
||||
// Override base class method to check that the window is a text control or
|
||||
// combobox.
|
||||
virtual void SetWindow(wxWindow *win) override;
|
||||
|
||||
protected:
|
||||
wxNumValidatorBase(int style)
|
||||
{
|
||||
m_style = style;
|
||||
}
|
||||
|
||||
wxNumValidatorBase(const wxNumValidatorBase& other) : wxValidator(other)
|
||||
{
|
||||
m_style = other.m_style;
|
||||
}
|
||||
|
||||
bool HasFlag(wxNumValidatorStyle style) const
|
||||
{
|
||||
return (m_style & style) != 0;
|
||||
}
|
||||
|
||||
// Get the text entry of the associated control. Normally shouldn't ever
|
||||
// return nullptr (and will assert if it does return it) but the caller should
|
||||
// still test the return value for safety.
|
||||
wxTextEntry *GetTextEntry() const;
|
||||
|
||||
// Convert wxNUM_VAL_THOUSANDS_SEPARATOR, wxNUM_VAL_NO_TRAILING_ZEROES,
|
||||
// wxNUM_VAL_SIGN_PLUS, and wxNUM_VAL_SIGN_SPACE
|
||||
// bits of our style to the corresponding wxNumberFormatter::Style values.
|
||||
int GetFormatFlags() const;
|
||||
|
||||
// Return the string which would result from inserting the given character
|
||||
// at the specified position.
|
||||
wxString GetValueAfterInsertingChar(wxString val, int pos, wxChar ch) const
|
||||
{
|
||||
val.insert(pos, ch);
|
||||
return val;
|
||||
}
|
||||
|
||||
// Return true if this control allows negative numbers in it.
|
||||
//
|
||||
// If it doesn't, we don't allow entering "-" at all.
|
||||
virtual bool CanBeNegative() const = 0;
|
||||
|
||||
private:
|
||||
// Check whether the specified character can be inserted in the control at
|
||||
// the given position in the string representing the current controls
|
||||
// contents.
|
||||
//
|
||||
// Notice that the base class checks for '-' itself so it's never passed to
|
||||
// this function.
|
||||
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const = 0;
|
||||
|
||||
// Return the canonical form of the number corresponding to the contents of
|
||||
// the string: if the input string is invalid, return a string representing
|
||||
// some valid value.
|
||||
virtual wxString NormalizeString(const wxString& s) const = 0;
|
||||
|
||||
|
||||
// Event handlers.
|
||||
void OnChar(wxKeyEvent& event);
|
||||
void OnKillFocus(wxFocusEvent& event);
|
||||
|
||||
|
||||
// Determine the current insertion point and text in the associated control.
|
||||
void GetCurrentValueAndInsertionPoint(wxString& val, int& pos) const;
|
||||
|
||||
// Return true if pressing a '-' key is acceptable for the current control
|
||||
// contents and insertion point. This is used by OnChar() to handle '-' and
|
||||
// relies on CanBeNegative() implementation in the derived class.
|
||||
bool IsMinusOk(const wxString& val, int pos) const;
|
||||
|
||||
|
||||
// Combination of wxVAL_NUM_XXX values.
|
||||
int m_style;
|
||||
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
||||
wxDECLARE_NO_ASSIGN_CLASS(wxNumValidatorBase);
|
||||
};
|
||||
|
||||
namespace wxPrivate
|
||||
{
|
||||
|
||||
// This is a helper class used by wxIntegerValidator and wxFloatingPointValidator
|
||||
// below that implements Transfer{To,From}Window() adapted to the type of the
|
||||
// variable.
|
||||
//
|
||||
// The template argument B is the name of the base class which must derive from
|
||||
// wxNumValidatorBase and define LongestValueType type and {To,As}String()
|
||||
// methods i.e. basically be one of wx{Integer,Number}ValidatorBase classes.
|
||||
//
|
||||
// The template argument T is just the type handled by the validator that will
|
||||
// inherit from this one.
|
||||
template <class B, typename T>
|
||||
class wxNumValidator : public B
|
||||
{
|
||||
public:
|
||||
typedef B BaseValidator;
|
||||
typedef T ValueType;
|
||||
|
||||
typedef typename BaseValidator::LongestValueType LongestValueType;
|
||||
|
||||
wxCOMPILE_TIME_ASSERT
|
||||
(
|
||||
sizeof(ValueType) <= sizeof(LongestValueType),
|
||||
UnsupportedType
|
||||
);
|
||||
|
||||
void SetMin(ValueType min)
|
||||
{
|
||||
m_min = min;
|
||||
}
|
||||
|
||||
ValueType GetMin() const
|
||||
{
|
||||
return m_min;
|
||||
}
|
||||
|
||||
void SetMax(ValueType max)
|
||||
{
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
ValueType GetMax() const
|
||||
{
|
||||
return m_max;
|
||||
}
|
||||
|
||||
void SetRange(ValueType min, ValueType max)
|
||||
{
|
||||
SetMin(min);
|
||||
SetMax(max);
|
||||
}
|
||||
|
||||
void GetRange(ValueType& min, ValueType& max) const
|
||||
{
|
||||
min = GetMin();
|
||||
max = GetMax();
|
||||
}
|
||||
|
||||
virtual bool TransferToWindow() override
|
||||
{
|
||||
if ( m_value )
|
||||
{
|
||||
wxTextEntry * const control = BaseValidator::GetTextEntry();
|
||||
if ( !control )
|
||||
return false;
|
||||
|
||||
control->SetValue(NormalizeValue(static_cast<LongestValueType>(*m_value)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool TransferFromWindow() override
|
||||
{
|
||||
if ( m_value )
|
||||
{
|
||||
wxTextEntry * const control = BaseValidator::GetTextEntry();
|
||||
if ( !control )
|
||||
return false;
|
||||
|
||||
const wxString s(control->GetValue());
|
||||
LongestValueType value;
|
||||
if ( s.empty() && BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
|
||||
value = 0;
|
||||
else if ( !BaseValidator::FromString(s, &value) )
|
||||
return false;
|
||||
|
||||
if ( !this->IsInRange(value) )
|
||||
return false;
|
||||
|
||||
*m_value = static_cast<ValueType>(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
wxNumValidator(ValueType *value, int style)
|
||||
: BaseValidator(style),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
// Implement wxNumValidatorBase virtual method which is the same for
|
||||
// both integer and floating point numbers.
|
||||
virtual wxString NormalizeString(const wxString& s) const override
|
||||
{
|
||||
// If empty value is handled as zero, just return it as is for
|
||||
// consistency with TransferFromWindow() and NormalizeValue().
|
||||
if ( s.empty() && BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
|
||||
return wxString();
|
||||
|
||||
LongestValueType value;
|
||||
if ( !BaseValidator::FromString(s, &value) )
|
||||
{
|
||||
// We don't have any valid number at all, just arbitrarily decide
|
||||
// to return the minimum value.
|
||||
value = static_cast<LongestValueType>(m_min);
|
||||
}
|
||||
else if ( !this->IsInRange(value) )
|
||||
{
|
||||
// We do have a value, but it's out of range: clamp it to the
|
||||
// closest limit.
|
||||
if ( value > static_cast<LongestValueType>(m_max) )
|
||||
value = static_cast<LongestValueType>(m_max);
|
||||
else
|
||||
value = static_cast<LongestValueType>(m_min);
|
||||
}
|
||||
|
||||
return NormalizeValue(value);
|
||||
}
|
||||
|
||||
virtual bool CanBeNegative() const override { return m_min < 0; }
|
||||
|
||||
|
||||
// This member is protected because it can be useful to the derived classes
|
||||
// in their Transfer{From,To}Window() implementations.
|
||||
ValueType * const m_value;
|
||||
|
||||
private:
|
||||
// Just a helper which is a common part of TransferToWindow() and
|
||||
// NormalizeString(): returns string representation of a number honouring
|
||||
// wxNUM_VAL_ZERO_AS_BLANK flag.
|
||||
wxString NormalizeValue(LongestValueType value) const
|
||||
{
|
||||
// We really want to compare with the exact 0 here, so disable gcc
|
||||
// warning about doing this.
|
||||
wxGCC_WARNING_SUPPRESS(float-equal)
|
||||
|
||||
wxString s;
|
||||
if ( value != 0 || !BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
|
||||
s = this->ToString(value);
|
||||
|
||||
wxGCC_WARNING_RESTORE(float-equal)
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// Minimal and maximal values accepted (inclusive).
|
||||
ValueType m_min, m_max;
|
||||
|
||||
wxDECLARE_NO_ASSIGN_DEF_COPY(wxNumValidator);
|
||||
};
|
||||
|
||||
} // namespace wxPrivate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Validators for integer numbers.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Base class for integer numbers validator. This class contains all non
|
||||
// type-dependent code of wxIntegerValidator<> and always works with values of
|
||||
// type LongestValueType. It is not meant to be used directly, please use
|
||||
// wxIntegerValidator<> only instead.
|
||||
class WXDLLIMPEXP_CORE wxIntegerValidatorBase : public wxNumValidatorBase
|
||||
{
|
||||
protected:
|
||||
// Define the type we use here, it should be the maximal-sized integer type
|
||||
// we support to make it possible to base wxIntegerValidator<> for any type
|
||||
// on it.
|
||||
typedef wxLongLong_t LongestValueType;
|
||||
typedef wxULongLong_t ULongestValueType;
|
||||
|
||||
wxIntegerValidatorBase(int style)
|
||||
: wxNumValidatorBase(style)
|
||||
{
|
||||
wxASSERT_MSG( !(style & wxNUM_VAL_NO_TRAILING_ZEROES),
|
||||
"This style doesn't make sense for integers." );
|
||||
wxASSERT_MSG(!(style & wxNUM_VAL_SIGN_PLUS) ||
|
||||
!(style & wxNUM_VAL_SIGN_SPACE),
|
||||
"Sign prefix conflict.");
|
||||
}
|
||||
|
||||
// Default copy ctor is ok.
|
||||
|
||||
// Provide methods for wxNumValidator use.
|
||||
wxString ToString(LongestValueType value) const;
|
||||
bool FromString(const wxString& s, LongestValueType *value) const;
|
||||
|
||||
virtual bool IsInRange(LongestValueType value) const = 0;
|
||||
|
||||
// Check whether the value is in the extended range allowed on input.
|
||||
//
|
||||
// Notice that the minimal and maximal values that have to be accepted on
|
||||
// input may differ from the actually defined range to allow entering
|
||||
// a temporarily invalid number because otherwise it would not be possible
|
||||
// to enter any digits in an initially empty control limited to the values
|
||||
// between "10" and "20".
|
||||
virtual bool IsInInputRange(LongestValueType value) const = 0;
|
||||
|
||||
// Implement wxNumValidatorBase pure virtual method.
|
||||
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const override;
|
||||
|
||||
private:
|
||||
wxDECLARE_NO_ASSIGN_DEF_COPY(wxIntegerValidatorBase);
|
||||
};
|
||||
|
||||
// Validator for integer numbers. It can actually work with any integer type
|
||||
// (short, int or long and long long if supported) and their unsigned versions
|
||||
// as well.
|
||||
template <typename T>
|
||||
class wxIntegerValidator
|
||||
: public wxPrivate::wxNumValidator<wxIntegerValidatorBase, T>
|
||||
{
|
||||
public:
|
||||
typedef T ValueType;
|
||||
|
||||
typedef
|
||||
wxPrivate::wxNumValidator<wxIntegerValidatorBase, T> Base;
|
||||
typedef
|
||||
wxIntegerValidatorBase::LongestValueType LongestValueType;
|
||||
|
||||
// Ctor for an integer validator.
|
||||
//
|
||||
// Sets the range appropriately for the type, including setting 0 as the
|
||||
// minimal value for the unsigned types.
|
||||
wxIntegerValidator(ValueType *value = nullptr, int style = wxNUM_VAL_DEFAULT)
|
||||
: Base(value, style)
|
||||
{
|
||||
this->SetMin(std::numeric_limits<ValueType>::min());
|
||||
this->SetMax(std::numeric_limits<ValueType>::max());
|
||||
}
|
||||
|
||||
// Ctor for an integer validator.
|
||||
//
|
||||
// Sets the range to the specified interval [min, max].
|
||||
wxIntegerValidator(ValueType *value,
|
||||
ValueType min,
|
||||
ValueType max,
|
||||
int style = wxNUM_VAL_DEFAULT)
|
||||
: Base(value, style)
|
||||
{
|
||||
this->SetMin(min);
|
||||
this->SetMax(max);
|
||||
}
|
||||
|
||||
wxNODISCARD virtual wxObject *Clone() const override { return new wxIntegerValidator(*this); }
|
||||
|
||||
virtual bool IsInRange(LongestValueType value) const override
|
||||
{
|
||||
return IsValueInRange( value, this->GetMin(), this->GetMax() );
|
||||
}
|
||||
|
||||
virtual bool IsInInputRange(LongestValueType value) const override
|
||||
{
|
||||
ValueType min = wxMin( 1, this->GetMin() );
|
||||
ValueType max = wxMax( 0, this->GetMax() );
|
||||
|
||||
return IsValueInRange( value, min, max );
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsValueInRange(LongestValueType value, ValueType min, ValueType max ) const
|
||||
{
|
||||
// LongestValueType is used as a container for the values of any type
|
||||
// which can be used in type-independent wxIntegerValidatorBase code,
|
||||
// but we need to use the correct type for comparisons, notably for
|
||||
// comparing unsigned values correctly, so cast to this type and check
|
||||
// that we don't lose precision while doing it.
|
||||
const ValueType valueT = static_cast<ValueType>(value);
|
||||
if ( static_cast<LongestValueType>(valueT) != value )
|
||||
{
|
||||
// The conversion wasn't lossless, so the value must not be exactly
|
||||
// representable in this type and so is definitely not in range.
|
||||
return false;
|
||||
}
|
||||
|
||||
return min <= valueT && valueT <= max;
|
||||
}
|
||||
|
||||
wxDECLARE_NO_ASSIGN_DEF_COPY(wxIntegerValidator);
|
||||
};
|
||||
|
||||
// Helper function for creating integer validators which allows to avoid
|
||||
// explicitly specifying the type as it deduces it from its parameter.
|
||||
template <typename T>
|
||||
inline wxIntegerValidator<T>
|
||||
wxMakeIntegerValidator(T *value, int style = wxNUM_VAL_DEFAULT)
|
||||
{
|
||||
return wxIntegerValidator<T>(value, style);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Validators for floating point numbers.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Similar to wxIntegerValidatorBase, this class is not meant to be used
|
||||
// directly, only wxFloatingPointValidator<> should be used in the user code.
|
||||
class WXDLLIMPEXP_CORE wxFloatingPointValidatorBase : public wxNumValidatorBase
|
||||
{
|
||||
public:
|
||||
// Set precision i.e. the number of digits shown (and accepted on input)
|
||||
// after the decimal point. By default this is set to the maximal precision
|
||||
// supported by the type handled by the validator.
|
||||
void SetPrecision(unsigned precision) { m_precision = precision; }
|
||||
|
||||
// Set multiplier applied for displaying the value, e.g. 100 if the value
|
||||
// should be displayed in percents, so that the variable containing 0.5
|
||||
// would be displayed as 50.
|
||||
void SetFactor(double factor) { m_factor = factor; }
|
||||
|
||||
protected:
|
||||
// Notice that we can't use "long double" here because it's not supported
|
||||
// by wxNumberFormatter yet, so restrict ourselves to just double (and
|
||||
// float).
|
||||
typedef double LongestValueType;
|
||||
|
||||
wxFloatingPointValidatorBase(int style)
|
||||
: wxNumValidatorBase(style)
|
||||
{
|
||||
m_factor = 1.0;
|
||||
}
|
||||
|
||||
// Default copy ctor is ok.
|
||||
|
||||
// Provide methods for wxNumValidator use.
|
||||
wxString ToString(LongestValueType value) const;
|
||||
bool FromString(const wxString& s, LongestValueType *value) const;
|
||||
|
||||
virtual bool IsInRange(LongestValueType value) const = 0;
|
||||
|
||||
// Check whether the value is in the extended range allowed on input.
|
||||
//
|
||||
// Notice that the minimal and maximal values that have to be accepted on
|
||||
// input may differ from the actually defined range to allow entering
|
||||
// a temporarily invalid number because otherwise it would not be possible
|
||||
// to enter any digits in an initially empty control limited to the values
|
||||
// between "10" and "20".
|
||||
virtual bool IsInInputRange(LongestValueType value) const = 0;
|
||||
|
||||
// Implement wxNumValidatorBase pure virtual method.
|
||||
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const override;
|
||||
|
||||
private:
|
||||
// Maximum number of decimals digits after the decimal separator.
|
||||
unsigned m_precision;
|
||||
|
||||
// Factor applied for the displayed the value.
|
||||
double m_factor;
|
||||
|
||||
wxDECLARE_NO_ASSIGN_DEF_COPY(wxFloatingPointValidatorBase);
|
||||
};
|
||||
|
||||
// Validator for floating point numbers. It can be used with float, double or
|
||||
// long double values.
|
||||
template <typename T>
|
||||
class wxFloatingPointValidator
|
||||
: public wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T>
|
||||
{
|
||||
public:
|
||||
typedef T ValueType;
|
||||
typedef wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T> Base;
|
||||
typedef wxFloatingPointValidatorBase::LongestValueType LongestValueType;
|
||||
|
||||
|
||||
// Ctor using implicit (maximal) precision for this type.
|
||||
wxFloatingPointValidator(ValueType *value = nullptr,
|
||||
int style = wxNUM_VAL_DEFAULT)
|
||||
: Base(value, style)
|
||||
{
|
||||
DoSetMinMax();
|
||||
|
||||
this->SetPrecision(std::numeric_limits<ValueType>::digits10);
|
||||
}
|
||||
|
||||
// Ctor specifying an explicit precision.
|
||||
wxFloatingPointValidator(int precision,
|
||||
ValueType *value = nullptr,
|
||||
int style = wxNUM_VAL_DEFAULT)
|
||||
: Base(value, style)
|
||||
{
|
||||
DoSetMinMax();
|
||||
|
||||
this->SetPrecision(precision);
|
||||
}
|
||||
|
||||
wxNODISCARD virtual wxObject *Clone() const override
|
||||
{
|
||||
return new wxFloatingPointValidator(*this);
|
||||
}
|
||||
|
||||
virtual bool IsInRange(LongestValueType value) const override
|
||||
{
|
||||
const ValueType valueT = static_cast<ValueType>(value);
|
||||
|
||||
return this->GetMin() <= valueT && valueT <= this->GetMax();
|
||||
}
|
||||
|
||||
virtual bool IsInInputRange(LongestValueType value) const override
|
||||
{
|
||||
const ValueType valueT = static_cast<ValueType>(value);
|
||||
|
||||
ValueType min = wxMin( 0, this->GetMin() );
|
||||
ValueType max = wxMax( 0, this->GetMax() );
|
||||
|
||||
return min <= valueT && valueT <= max;
|
||||
}
|
||||
|
||||
private:
|
||||
void DoSetMinMax()
|
||||
{
|
||||
// NB: Do not use min(), it's not the smallest representable value for
|
||||
// the floating point types but rather the smallest representable
|
||||
// positive value.
|
||||
this->SetMin(-std::numeric_limits<ValueType>::max());
|
||||
this->SetMax( std::numeric_limits<ValueType>::max());
|
||||
}
|
||||
};
|
||||
|
||||
// Helper similar to wxMakeIntValidator().
|
||||
//
|
||||
// NB: Unfortunately we can't just have a wxMakeNumericValidator() which would
|
||||
// return either wxIntegerValidator<> or wxFloatingPointValidator<> so we
|
||||
// do need two different functions.
|
||||
template <typename T>
|
||||
inline wxFloatingPointValidator<T>
|
||||
wxMakeFloatingPointValidator(T *value, int style = wxNUM_VAL_DEFAULT)
|
||||
{
|
||||
return wxFloatingPointValidator<T>(value, style);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline wxFloatingPointValidator<T>
|
||||
wxMakeFloatingPointValidator(int precision, T *value, int style = wxNUM_VAL_DEFAULT)
|
||||
{
|
||||
return wxFloatingPointValidator<T>(precision, value, style);
|
||||
}
|
||||
|
||||
#endif // wxUSE_VALIDATORS
|
||||
|
||||
#endif // _WX_VALNUM_H_
|
||||
Reference in New Issue
Block a user