From a6162a3eaf655876b1db72228b9788e46fa6b817 Mon Sep 17 00:00:00 2001 From: Jaakko Salli Date: Sun, 21 Sep 2008 16:54:22 +0000 Subject: [PATCH] '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 --- docs/doxygen/overviews/propgrid.h | 3 +- include/wx/propgrid/propgriddefs.h | 60 ++++++++++++++++++++++-------- interface/wx/propgrid/property.h | 12 +++++- samples/propgrid/tests.cpp | 59 +++++++++++++++++++++++++---- src/propgrid/propgridiface.cpp | 56 ++++++++++++++++++++++++---- 5 files changed, 157 insertions(+), 33 deletions(-) diff --git a/docs/doxygen/overviews/propgrid.h b/docs/doxygen/overviews/propgrid.h index 79e65b1087..4da34e5ba7 100644 --- a/docs/doxygen/overviews/propgrid.h +++ b/docs/doxygen/overviews/propgrid.h @@ -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 diff --git a/include/wx/propgrid/propgriddefs.h b/include/wx/propgrid/propgriddefs.h index f6608cef06..0cafff6934 100644 --- a/include/wx/propgrid/propgriddefs.h +++ b/include/wx/propgrid/propgriddefs.h @@ -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 diff --git a/interface/wx/propgrid/property.h b/interface/wx/propgrid/property.h index 59f37bdc1b..766c51ec63 100644 --- a/interface/wx/propgrid/property.h +++ b/interface/wx/propgrid/property.h @@ -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 diff --git a/samples/propgrid/tests.cpp b/samples/propgrid/tests.cpp index 217229f640..7685b2978d 100644 --- a/samples/propgrid/tests.cpp +++ b/samples/propgrid/tests.cpp @@ -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")); diff --git a/src/propgrid/propgridiface.cpp b/src/propgrid/propgridiface.cpp index dcb84e7386..8e20e67d0d 100644 --- a/src/propgrid/propgridiface.cpp +++ b/src/propgrid/propgridiface.cpp @@ -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; } -- 2.45.2