'wx(U)LongLong << variant' type safety improved (now works even if variant has plain long value). Added << operator and WXVARIANT template specialization for wx(U)LongLong_t as well. Changed WX_PG_DECLARE/IMPLEMENT_VARIANT_DATA so that classname << variant can be customized.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55771 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli
2008-09-21 16:54:22 +00:00
parent bc35c72867
commit a6162a3eaf
5 changed files with 157 additions and 33 deletions

View File

@@ -455,7 +455,8 @@ supports wxArrayString and nothing else.
In any case, you will need to take extra care when dealing with
raw wxVariant values. For instance, wxIntProperty and wxUIntProperty,
store value internally as wx(U)LongLong when number doesn't fit into
standard long type.
standard long type. Using << operator to get wx(U)LongLong from wxVariant
is customized to work quite safely with various types of variant data.
You may have noticed that properties store, in wxVariant, values of many
types which are not natively supported by it. Custom wxVariantDatas

View File

@@ -513,7 +513,9 @@ extern expdecl const char* classname##_VariantType;
#define WX_PG_IMPLEMENT_VARIANT_DATA(classname) \
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE)
#define WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ(classname,expdecl) \
// Add getter (ie. classname << variant) separately to allow
// custom implementations.
#define WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(classname,expdecl) \
const char* classname##_VariantType = #classname; \
class classname##VariantData: public wxVariantData \
{ \
@@ -540,15 +542,6 @@ wxString classname##VariantData::GetType() const\
return wxS(#classname);\
}\
\
expdecl classname& operator << ( classname &value, const wxVariant &variant )\
{\
wxASSERT( variant.GetType() == #classname );\
\
classname##VariantData *data = (classname##VariantData*) variant.GetData();\
value = data->GetValue();\
return value;\
}\
\
expdecl wxVariant& operator << ( wxVariant &variant, const classname &value )\
{\
classname##VariantData *data = new classname##VariantData( value );\
@@ -568,11 +561,17 @@ expdecl const classname& classname##RefFromVariant( const wxVariant& variant ) \
return data->GetValue();\
}
// implements a wxVariantData-derived class using for the Eq() method the
// operator== which must have been provided by "classname"
#define WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(classname,expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl) \
#define WX_PG_IMPLEMENT_VARIANT_DATA_GETTER(classname, expdecl) \
expdecl classname& operator << ( classname &value, const wxVariant &variant )\
{\
wxASSERT( variant.GetType() == #classname );\
\
classname##VariantData *data = (classname##VariantData*) variant.GetData();\
value = data->GetValue();\
return value;\
}
#define WX_PG_IMPLEMENT_VARIANT_DATA_EQ(classname, expdecl) \
bool classname##VariantData::Eq(wxVariantData& data) const \
{\
wxASSERT( GetType() == data.GetType() );\
@@ -582,12 +581,20 @@ bool classname##VariantData::Eq(wxVariantData& data) const \
return otherData.m_value == m_value;\
}
// implements a wxVariantData-derived class using for the Eq() method the
// operator== which must have been provided by "classname"
#define WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(classname,expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(classname,wxEMPTY_PARAMETER_VALUE expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_GETTER(classname,wxEMPTY_PARAMETER_VALUE expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl)
#define WX_PG_IMPLEMENT_VARIANT_DATA(classname) \
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE)
// with Eq() implementation that always returns false
#define WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(classname,expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ(classname,wxEMPTY_PARAMETER_VALUE expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(classname,wxEMPTY_PARAMETER_VALUE expdecl) \
WX_PG_IMPLEMENT_VARIANT_DATA_GETTER(classname,wxEMPTY_PARAMETER_VALUE expdecl) \
\
bool classname##VariantData::Eq(wxVariantData& WXUNUSED(data)) const \
{\
@@ -617,6 +624,27 @@ template<> inline wxVariant WXVARIANT( const wxColour& value )
return variant;
}
#if wxUSE_LONGLONG_NATIVE
template<> inline wxVariant WXVARIANT( const wxLongLong_t& value )
{
wxVariant variant;
variant << wxLongLong(value);
return variant;
}
template<> inline wxVariant WXVARIANT( const wxULongLong_t& value )
{
wxVariant variant;
variant << wxULongLong(value);
return variant;
}
WXDLLIMPEXP_PROPGRID wxLongLong_t& operator << ( wxLongLong_t &value, const wxVariant &variant );
WXDLLIMPEXP_PROPGRID wxULongLong_t& operator << ( wxULongLong_t &value, const wxVariant &variant );
#endif // wxUSE_LONGLONG_NATIVE
// Define constants for common wxVariant type strings
#define wxPG_VARIANT_TYPE_STRING wxPGGlobalVars->m_strstring

View File

@@ -197,6 +197,15 @@
Like wxStringProperty, but converts text to a signed long integer.
wxIntProperty seamlessly supports 64-bit integers (ie. wxLongLong).
To safely convert variant to integer, use code like this:
@code
wxLongLong ll;
ll << property->GetValue();
// or
wxLongLong ll = propertyGrid->GetPropertyValueAsLong(property);
@endcode
@subsection wxUIntProperty
@@ -205,7 +214,8 @@
To set the globally used base, manipulate wxPG_UINT_BASE int
attribute. Regardless of current prefix, understands (hex) values starting
with both "0x" and "$".
wxUIntProperty seamlessly supports 64-bit unsigned integers (ie. wxULongLong).
Like wxIntProperty, wxUIntProperty seamlessly supports 64-bit unsigned
integers (ie. wxULongLong). Same wxVariant safety rules apply.
@subsection wxFloatProperty

View File

@@ -755,7 +755,6 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
pgman->SetPropertyValue(wxT("FloatProperty"),1024.0000000001);
pgman->SetPropertyValue(wxT("BoolProperty"),FALSE);
pgman->SetPropertyValue(wxT("EnumProperty"),120);
pgman->SetPropertyValue(wxT("Custom FlagsProperty"),FLAG_TEST_SET1);
pgman->SetPropertyValue(wxT("ArrayStringProperty"),test_arrstr_1);
wxColour emptyCol;
pgman->SetPropertyValue(wxT("ColourProperty"),emptyCol);
@@ -782,8 +781,6 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
RT_FAILURE();
if ( pg->GetPropertyValueAsArrayString(wxT("ArrayStringProperty")) != test_arrstr_1 )
RT_FAILURE();
if ( pg->GetPropertyValueAsLong(wxT("Custom FlagsProperty")) != FLAG_TEST_SET1 )
RT_FAILURE();
wxColour col;
col << pgman->GetPropertyValue(wxT("ColourProperty"));
if ( col != *wxBLACK )
@@ -809,7 +806,6 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
pg->SetPropertyValue(wxT("BoolProperty"),TRUE);
pg->SetPropertyValue(wxT("EnumProperty"),80);
pg->SetPropertyValue(wxT("ArrayStringProperty"),test_arrstr_2);
pg->SetPropertyValue(wxT("Custom FlagsProperty"),FLAG_TEST_SET2);
pg->SetPropertyValue(wxT("ColourProperty"),(wxObject*)wxWHITE);
pg->SetPropertyValue(wxT("Size"),wxSize(300,300));
pg->SetPropertyValue(wxT("Position"),wxPoint(300,300));
@@ -834,8 +830,6 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
RT_FAILURE();
if ( pgman->GetPropertyValueAsArrayString(wxT("ArrayStringProperty")) != test_arrstr_2 )
RT_FAILURE();
if ( pgman->GetPropertyValueAsLong(wxT("Custom FlagsProperty")) != FLAG_TEST_SET2 )
RT_FAILURE();
col << pgman->GetPropertyValue(wxT("ColourProperty"));
if ( col != *wxWHITE )
RT_FAILURE();
@@ -854,6 +848,58 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
if ( pgman->GetPropertyValueAsLongLong(wxT("IntProperty")) != wxLL(-80000000000) )
RT_FAILURE();
//
// Flexible wx(U)LongLong << operator safety conformance tests
wxPGProperty* prop;
wxLongLong ll;
wxULongLong ull;
prop = pgman->GetProperty(wxT("IntProperty"));
prop->SetValue(128);
ll << prop->GetValue();
if ( ll != 128 )
RT_FAILURE();
prop->SetValue(WXVARIANT(wxLL(68719476736)));
ll << prop->GetValue();
if ( ll.GetValue() != wxLL(68719476736) )
RT_FAILURE();
#if wxUSE_LONGLONG_NATIVE
wxLongLong_t ll_t;
ll_t << prop->GetValue();
if ( ll_t != wxLL(68719476736) )
RT_FAILURE();
#endif
prop->SetValue(256);
ll << prop->GetValue();
if ( ll != 256 )
RT_FAILURE();
prop = pgman->GetProperty(wxT("UIntProperty"));
prop->SetValue(128);
ull << prop->GetValue();
if ( ull != 128 )
RT_FAILURE();
prop->SetValue(WXVARIANT(wxULL(68719476739)));
ull << prop->GetValue();
if ( ull.GetValue() != wxULL(68719476739) )
RT_FAILURE();
#if wxUSE_LONGLONG_NATIVE
wxULongLong_t ull_t;
ull_t << prop->GetValue();
if ( ull_t != wxLL(68719476739) )
RT_FAILURE();
#endif
prop->SetValue(256);
ull << prop->GetValue();
if ( ull != 256 )
RT_FAILURE();
// Make sure children of composite parent get updated as well
// Original string value: "Lamborghini Diablo SV; 5707; [300; 3.9; 8.6] 300000"
@@ -891,7 +937,6 @@ bool FormMain::RunTests( bool fullTest, bool interactive )
pgman->SetPropertyValueUnspecified(wxT("BoolProperty"));
pgman->SetPropertyValueUnspecified(wxT("EnumProperty"));
pgman->SetPropertyValueUnspecified(wxT("ArrayStringProperty"));
pgman->SetPropertyValueUnspecified(wxT("Custom FlagsProperty"));
pgman->SetPropertyValueUnspecified(wxT("ColourProperty"));
pgman->SetPropertyValueUnspecified(wxT("Size"));
pgman->SetPropertyValueUnspecified(wxT("Position"));

View File

@@ -68,8 +68,50 @@ const wxChar *wxPGTypeName_wxArrayString = wxT("arrstring");
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxPoint, WXDLLIMPEXP_PROPGRID)
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxSize, WXDLLIMPEXP_PROPGRID)
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(wxArrayInt, WXDLLIMPEXP_PROPGRID)
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxLongLong, WXDLLIMPEXP_PROPGRID)
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxULongLong, WXDLLIMPEXP_PROPGRID)
// For wxLongLong and wxULongLong have custom classname << variant
// implementation for improved flexibility.
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(wxLongLong, WXDLLIMPEXP_PROPGRID)
WX_PG_IMPLEMENT_VARIANT_DATA_EQ(wxLongLong, WXDLLIMPEXP_PROPGRID)
WXDLLIMPEXP_PROPGRID wxLongLong& operator << ( wxLongLong &value, const wxVariant &variant )
{
wxLongLong_t ll;
if ( !wxPGVariantToLongLong(variant, &ll) )
{
wxFAIL_MSG("Cannot convert to wxLongLong");
}
value = ll;
return value;
}
WXDLLIMPEXP_PROPGRID wxLongLong_t& operator << ( wxLongLong_t &value, const wxVariant &variant )
{
if ( !wxPGVariantToLongLong(variant, &value) )
{
wxFAIL_MSG("Cannot convert to wxLongLong");
}
return value;
}
WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(wxULongLong, WXDLLIMPEXP_PROPGRID)
WX_PG_IMPLEMENT_VARIANT_DATA_EQ(wxULongLong, WXDLLIMPEXP_PROPGRID)
WXDLLIMPEXP_PROPGRID wxULongLong& operator << ( wxULongLong &value, const wxVariant &variant )
{
wxULongLong_t ull;
if ( !wxPGVariantToULongLong(variant, &ull) )
{
wxFAIL_MSG("Cannot convert to wxULongLong");
}
value = ull;
return value;
}
WXDLLIMPEXP_PROPGRID wxULongLong_t& operator << ( wxULongLong_t &value, const wxVariant &variant )
{
if ( !wxPGVariantToULongLong(variant, &value) )
{
wxFAIL_MSG("Cannot convert to wxULongLong");
}
return value;
}
IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxFont, WXDLLIMPEXP_PROPGRID)
@@ -124,9 +166,8 @@ bool wxPGVariantToLongLong( const wxVariant& variant, wxLongLong_t* pResult )
if ( variantType == wxLongLong_VariantType )
{
wxLongLong ll;
ll << variant;
*pResult = ll.GetValue();
// NOTE: << operator uses this functions, so we can't use it here
*pResult = wxLongLongRefFromVariant(variant).GetValue();
return true;
}
@@ -150,9 +191,8 @@ bool wxPGVariantToULongLong( const wxVariant& variant, wxULongLong_t* pResult )
if ( variantType == wxULongLong_VariantType )
{
wxULongLong ull;
ull << variant;
*pResult = ull.GetValue();
// NOTE: << operator uses this functions, so we can't use it here
*pResult = wxULongLongRefFromVariant(variant).GetValue();
return true;
}