Merge branch 'valnum-unsigned'
Fix handling of unsigned types in numeric validators: don't accept negative numbers as unsigned, allow using the full 64-bit range. See https://github.com/wxWidgets/wxWidgets/pull/2244 Closes #12967.
This commit is contained in:
@@ -34,6 +34,8 @@ public:
|
||||
static wxString ToString(wxLongLong_t val,
|
||||
int style = Style_WithThousandsSep);
|
||||
#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
|
||||
static wxString ToString(wxULongLong_t val,
|
||||
int style = Style_WithThousandsSep);
|
||||
static wxString ToString(double val,
|
||||
int precision,
|
||||
int style = Style_WithThousandsSep);
|
||||
@@ -46,6 +48,7 @@ public:
|
||||
#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
|
||||
static bool FromString(wxString s, wxLongLong_t *val);
|
||||
#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
|
||||
static bool FromString(wxString s, wxULongLong_t *val);
|
||||
static bool FromString(wxString s, double *val);
|
||||
|
||||
|
||||
|
@@ -79,11 +79,6 @@ protected:
|
||||
// bits of our style to the corresponding wxNumberFormatter::Style values.
|
||||
int GetFormatFlags() const;
|
||||
|
||||
// Return true if pressing a '-' key is acceptable for the current control
|
||||
// contents and insertion point. This is meant to be called from the
|
||||
// derived class IsCharOk() implementation.
|
||||
bool IsMinusOk(const wxString& val, int pos) 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
|
||||
@@ -92,6 +87,11 @@ protected:
|
||||
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
|
||||
@@ -114,6 +114,11 @@ private:
|
||||
// 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;
|
||||
@@ -154,22 +159,22 @@ public:
|
||||
|
||||
void SetMin(ValueType min)
|
||||
{
|
||||
this->DoSetMin(static_cast<LongestValueType>(min));
|
||||
m_min = min;
|
||||
}
|
||||
|
||||
ValueType GetMin() const
|
||||
{
|
||||
return static_cast<ValueType>(this->DoGetMin());
|
||||
return m_min;
|
||||
}
|
||||
|
||||
void SetMax(ValueType max)
|
||||
{
|
||||
this->DoSetMax(static_cast<LongestValueType>(max));
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
ValueType GetMax() const
|
||||
{
|
||||
return static_cast<ValueType>(this->DoGetMax());
|
||||
return m_max;
|
||||
}
|
||||
|
||||
void SetRange(ValueType min, ValueType max)
|
||||
@@ -238,6 +243,9 @@ protected:
|
||||
: wxString();
|
||||
}
|
||||
|
||||
virtual bool CanBeNegative() const wxOVERRIDE { 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;
|
||||
@@ -261,6 +269,8 @@ private:
|
||||
return s;
|
||||
}
|
||||
|
||||
// Minimal and maximal values accepted (inclusive).
|
||||
ValueType m_min, m_max;
|
||||
|
||||
wxDECLARE_NO_ASSIGN_CLASS(wxNumValidator);
|
||||
};
|
||||
@@ -283,8 +293,10 @@ protected:
|
||||
// on it.
|
||||
#ifdef wxLongLong_t
|
||||
typedef wxLongLong_t LongestValueType;
|
||||
typedef wxULongLong_t ULongestValueType;
|
||||
#else
|
||||
typedef long LongestValueType;
|
||||
typedef unsigned long ULongestValueType;
|
||||
#endif
|
||||
|
||||
wxIntegerValidatorBase(int style)
|
||||
@@ -294,34 +306,18 @@ protected:
|
||||
"This style doesn't make sense for integers." );
|
||||
}
|
||||
|
||||
wxIntegerValidatorBase(const wxIntegerValidatorBase& other)
|
||||
: wxNumValidatorBase(other)
|
||||
{
|
||||
m_min = other.m_min;
|
||||
m_max = other.m_max;
|
||||
}
|
||||
// Default copy ctor is ok.
|
||||
|
||||
// Provide methods for wxNumValidator use.
|
||||
wxString ToString(LongestValueType value) const;
|
||||
static bool FromString(const wxString& s, LongestValueType *value);
|
||||
bool FromString(const wxString& s, LongestValueType *value) const;
|
||||
|
||||
void DoSetMin(LongestValueType min) { m_min = min; }
|
||||
LongestValueType DoGetMin() const { return m_min; }
|
||||
void DoSetMax(LongestValueType max) { m_max = max; }
|
||||
LongestValueType DoGetMax() const { return m_max; }
|
||||
|
||||
bool IsInRange(LongestValueType value) const
|
||||
{
|
||||
return m_min <= value && value <= m_max;
|
||||
}
|
||||
virtual bool IsInRange(LongestValueType value) const = 0;
|
||||
|
||||
// Implement wxNumValidatorBase pure virtual method.
|
||||
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const wxOVERRIDE;
|
||||
|
||||
private:
|
||||
// Minimal and maximal values accepted (inclusive).
|
||||
LongestValueType m_min, m_max;
|
||||
|
||||
wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidatorBase);
|
||||
};
|
||||
|
||||
@@ -337,6 +333,8 @@ public:
|
||||
|
||||
typedef
|
||||
wxPrivate::wxNumValidator<wxIntegerValidatorBase, T> Base;
|
||||
typedef
|
||||
wxIntegerValidatorBase::LongestValueType LongestValueType;
|
||||
|
||||
// Ctor for an integer validator.
|
||||
//
|
||||
@@ -345,12 +343,30 @@ public:
|
||||
wxIntegerValidator(ValueType *value = NULL, int style = wxNUM_VAL_DEFAULT)
|
||||
: Base(value, style)
|
||||
{
|
||||
this->DoSetMin(std::numeric_limits<ValueType>::min());
|
||||
this->DoSetMax(std::numeric_limits<ValueType>::max());
|
||||
this->SetMin(std::numeric_limits<ValueType>::min());
|
||||
this->SetMax(std::numeric_limits<ValueType>::max());
|
||||
}
|
||||
|
||||
virtual wxObject *Clone() const wxOVERRIDE { return new wxIntegerValidator(*this); }
|
||||
|
||||
virtual bool IsInRange(LongestValueType value) const wxOVERRIDE
|
||||
{
|
||||
// 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 this->GetMin() <= valueT && valueT <= this->GetMax();
|
||||
}
|
||||
|
||||
private:
|
||||
wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidator);
|
||||
};
|
||||
@@ -395,29 +411,13 @@ protected:
|
||||
m_factor = 1.0;
|
||||
}
|
||||
|
||||
wxFloatingPointValidatorBase(const wxFloatingPointValidatorBase& other)
|
||||
: wxNumValidatorBase(other)
|
||||
{
|
||||
m_precision = other.m_precision;
|
||||
m_factor = other.m_factor;
|
||||
|
||||
m_min = other.m_min;
|
||||
m_max = other.m_max;
|
||||
}
|
||||
// Default copy ctor is ok.
|
||||
|
||||
// Provide methods for wxNumValidator use.
|
||||
wxString ToString(LongestValueType value) const;
|
||||
bool FromString(const wxString& s, LongestValueType *value) const;
|
||||
|
||||
void DoSetMin(LongestValueType min) { m_min = min; }
|
||||
LongestValueType DoGetMin() const { return m_min; }
|
||||
void DoSetMax(LongestValueType max) { m_max = max; }
|
||||
LongestValueType DoGetMax() const { return m_max; }
|
||||
|
||||
bool IsInRange(LongestValueType value) const
|
||||
{
|
||||
return m_min <= value && value <= m_max;
|
||||
}
|
||||
virtual bool IsInRange(LongestValueType value) const = 0;
|
||||
|
||||
// Implement wxNumValidatorBase pure virtual method.
|
||||
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const wxOVERRIDE;
|
||||
@@ -429,9 +429,6 @@ private:
|
||||
// Factor applied for the displayed the value.
|
||||
double m_factor;
|
||||
|
||||
// Minimal and maximal values accepted (inclusive).
|
||||
LongestValueType m_min, m_max;
|
||||
|
||||
wxDECLARE_NO_ASSIGN_CLASS(wxFloatingPointValidatorBase);
|
||||
};
|
||||
|
||||
@@ -444,6 +441,8 @@ class wxFloatingPointValidator
|
||||
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 = NULL,
|
||||
@@ -471,16 +470,21 @@ public:
|
||||
return new wxFloatingPointValidator(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename Base::LongestValueType LongestValueType;
|
||||
virtual bool IsInRange(LongestValueType value) const wxOVERRIDE
|
||||
{
|
||||
const ValueType valueT = static_cast<ValueType>(value);
|
||||
|
||||
return this->GetMin() <= valueT && valueT <= this->GetMax();
|
||||
}
|
||||
|
||||
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->DoSetMin(static_cast<LongestValueType>(-std::numeric_limits<ValueType>::max()));
|
||||
this->DoSetMax(static_cast<LongestValueType>( std::numeric_limits<ValueType>::max()));
|
||||
this->SetMin(-std::numeric_limits<ValueType>::max());
|
||||
this->SetMax( std::numeric_limits<ValueType>::max());
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user