Fix several rounding problems with float values in wxPropertyGrid.
See also r85980 in the trunk. Closes #15625. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_3_0_BRANCH@77960 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -577,6 +577,10 @@ Major new features in this release
|
|||||||
3.0.3: (released 2015-??-??)
|
3.0.3: (released 2015-??-??)
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
All (GUI):
|
||||||
|
|
||||||
|
- Fix several floating point rounding bugs in wxPropertyGrid (Artur Wieczorek).
|
||||||
|
|
||||||
|
|
||||||
3.0.2: (released 2014-10-06)
|
3.0.2: (released 2014-10-06)
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@@ -316,6 +316,7 @@ public:
|
|||||||
const wxString& text,
|
const wxString& text,
|
||||||
int argFlags = 0 ) const;
|
int argFlags = 0 ) const;
|
||||||
virtual bool DoSetAttribute( const wxString& name, wxVariant& value );
|
virtual bool DoSetAttribute( const wxString& name, wxVariant& value );
|
||||||
|
virtual wxVariant DoGetAttribute( const wxString& name ) const;
|
||||||
virtual bool ValidateValue( wxVariant& value,
|
virtual bool ValidateValue( wxVariant& value,
|
||||||
wxPGValidationInfo& validationInfo ) const;
|
wxPGValidationInfo& validationInfo ) const;
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/odcombo.h"
|
#include "wx/odcombo.h"
|
||||||
|
#include "wx/numformatter.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -361,7 +362,14 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper
|
|||||||
// Min/Max check
|
// Min/Max check
|
||||||
wxFloatProperty::DoValidation(property, v_d, NULL, mode);
|
wxFloatProperty::DoValidation(property, v_d, NULL, mode);
|
||||||
|
|
||||||
wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL);
|
int precision = -1;
|
||||||
|
wxVariant v = property->GetAttribute(wxPG_FLOAT_PRECISION);
|
||||||
|
if ( !v.IsNull() )
|
||||||
|
{
|
||||||
|
precision = v.GetInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
s = wxNumberFormatter::ToString(v_d, precision, wxNumberFormatter::Style_NoTrailingZeroes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -1770,6 +1770,10 @@ wxVariant wxPGProperty::DoGetAttribute( const wxString& WXUNUSED(name) ) const
|
|||||||
|
|
||||||
wxVariant wxPGProperty::GetAttribute( const wxString& name ) const
|
wxVariant wxPGProperty::GetAttribute( const wxString& name ) const
|
||||||
{
|
{
|
||||||
|
wxVariant value = DoGetAttribute(name);
|
||||||
|
if ( !value.IsNull() )
|
||||||
|
return value;
|
||||||
|
|
||||||
return m_attributes.FindValue(name);
|
return m_attributes.FindValue(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,6 +52,9 @@
|
|||||||
#include "wx/filename.h"
|
#include "wx/filename.h"
|
||||||
|
|
||||||
#include "wx/propgrid/propgrid.h"
|
#include "wx/propgrid/propgrid.h"
|
||||||
|
#include "wx/numformatter.h"
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
#define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc.
|
#define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc.
|
||||||
|
|
||||||
@@ -341,8 +344,8 @@ bool wxIntProperty::IntToValue( wxVariant& variant, int value, int WXUNUSED(argF
|
|||||||
// implementations.
|
// implementations.
|
||||||
//
|
//
|
||||||
// Note that 'value' is reference on purpose, so we can write
|
// Note that 'value' is reference on purpose, so we can write
|
||||||
// back to it when mode is wxPG_PROPERTY_VALIDATION_SATURATE.
|
// back to it when mode is wxPG_PROPERTY_VALIDATION_SATURATE or wxPG_PROPERTY_VALIDATION_WRAP.
|
||||||
//
|
// For argument 'value' of type 'double' there is a specialized function (below).
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool NumericValidation( const wxPGProperty* property,
|
bool NumericValidation( const wxPGProperty* property,
|
||||||
T& value,
|
T& value,
|
||||||
@@ -426,6 +429,115 @@ bool NumericValidation( const wxPGProperty* property,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Template specialization for argument 'value' of type 'double'.
|
||||||
|
// It takes into account required precision of the numbers
|
||||||
|
// to avoid rounding and conversion errors.
|
||||||
|
template<>
|
||||||
|
bool NumericValidation( const wxPGProperty* property,
|
||||||
|
double& value,
|
||||||
|
wxPGValidationInfo* pValidationInfo,
|
||||||
|
int mode,
|
||||||
|
const wxString& strFmt )
|
||||||
|
{
|
||||||
|
double min = DBL_MIN;
|
||||||
|
double max = DBL_MAX;
|
||||||
|
wxVariant variant;
|
||||||
|
bool minOk = false;
|
||||||
|
bool maxOk = false;
|
||||||
|
|
||||||
|
variant = property->GetAttribute(wxPGGlobalVars->m_strMin);
|
||||||
|
if ( !variant.IsNull() )
|
||||||
|
{
|
||||||
|
variant.Convert(&min);
|
||||||
|
minOk = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
variant = property->GetAttribute(wxPGGlobalVars->m_strMax);
|
||||||
|
if ( !variant.IsNull() )
|
||||||
|
{
|
||||||
|
variant.Convert(&max);
|
||||||
|
maxOk = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( minOk || maxOk )
|
||||||
|
{
|
||||||
|
// Get required precision.
|
||||||
|
int precision = -1;
|
||||||
|
variant = property->GetAttribute(wxPG_FLOAT_PRECISION);
|
||||||
|
if ( !variant.IsNull() )
|
||||||
|
{
|
||||||
|
precision = variant.GetInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round current value to the required precision.
|
||||||
|
wxString strVal = wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
|
||||||
|
strVal.ToDouble(&value);
|
||||||
|
|
||||||
|
// Round minimal value to the required precision.
|
||||||
|
strVal = wxNumberFormatter::ToString(min, precision, wxNumberFormatter::Style_None);
|
||||||
|
strVal.ToDouble(&min);
|
||||||
|
|
||||||
|
// Round maximal value to the required precision.
|
||||||
|
strVal = wxNumberFormatter::ToString(max, precision, wxNumberFormatter::Style_None);
|
||||||
|
strVal.ToDouble(&max);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( minOk )
|
||||||
|
{
|
||||||
|
if ( value < min )
|
||||||
|
{
|
||||||
|
if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
wxString smin = wxString::Format(strFmt, min);
|
||||||
|
wxString smax = wxString::Format(strFmt, max);
|
||||||
|
if ( !maxOk )
|
||||||
|
msg = wxString::Format(
|
||||||
|
_("Value must be %s or higher."),
|
||||||
|
smin.c_str());
|
||||||
|
else
|
||||||
|
msg = wxString::Format(
|
||||||
|
_("Value must be between %s and %s."),
|
||||||
|
smin.c_str(), smax.c_str());
|
||||||
|
pValidationInfo->SetFailureMessage(msg);
|
||||||
|
}
|
||||||
|
else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
|
||||||
|
value = min;
|
||||||
|
else
|
||||||
|
value = max - (min - value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( maxOk )
|
||||||
|
{
|
||||||
|
if ( value > max )
|
||||||
|
{
|
||||||
|
if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
wxString smin = wxString::Format(strFmt, min);
|
||||||
|
wxString smax = wxString::Format(strFmt, max);
|
||||||
|
if ( !minOk )
|
||||||
|
msg = wxString::Format(
|
||||||
|
_("Value must be %s or less."),
|
||||||
|
smax.c_str());
|
||||||
|
else
|
||||||
|
msg = wxString::Format(
|
||||||
|
_("Value must be between %s and %s."),
|
||||||
|
smin.c_str(), smax.c_str());
|
||||||
|
pValidationInfo->SetFailureMessage(msg);
|
||||||
|
}
|
||||||
|
else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
|
||||||
|
value = max;
|
||||||
|
else
|
||||||
|
value = min + (value - max);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool wxIntProperty::DoValidation( const wxPGProperty* property,
|
bool wxIntProperty::DoValidation( const wxPGProperty* property,
|
||||||
wxLongLong_t& value,
|
wxLongLong_t& value,
|
||||||
wxPGValidationInfo* pValidationInfo,
|
wxPGValidationInfo* pValidationInfo,
|
||||||
@@ -755,11 +867,9 @@ wxString wxFloatProperty::ValueToString( wxVariant& value,
|
|||||||
wxString text;
|
wxString text;
|
||||||
if ( !value.IsNull() )
|
if ( !value.IsNull() )
|
||||||
{
|
{
|
||||||
wxPropertyGrid::DoubleToString(text,
|
text = wxNumberFormatter::ToString(value.GetDouble(), m_precision,
|
||||||
value,
|
argFlags & wxPG_FULL_VALUE ? wxNumberFormatter::Style_None
|
||||||
m_precision,
|
: wxNumberFormatter::Style_NoTrailingZeroes);
|
||||||
!(argFlags & wxPG_FULL_VALUE),
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@@ -821,6 +931,16 @@ bool wxFloatProperty::DoSetAttribute( const wxString& name, wxVariant& value )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxVariant wxFloatProperty::DoGetAttribute( const wxString& name ) const
|
||||||
|
{
|
||||||
|
wxVariant value;
|
||||||
|
if ( name == wxPG_FLOAT_PRECISION )
|
||||||
|
{
|
||||||
|
value = (long)m_precision;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
wxValidator*
|
wxValidator*
|
||||||
wxFloatProperty::GetClassValidator()
|
wxFloatProperty::GetClassValidator()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user