wxVariant <-> wxAny conversion functionality. Includes implicit construction of wxAny from wxVariant, and vice versa. wxVariant->wxAny conversion is implemented by adding new virtual member function into wxVariantData. wxAny->wxVariant conversion is implemented by associating wxAnyValueTypes with functions that generate wxVariantData instances (using a hash map).
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64000 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
134
include/wx/any.h
134
include/wx/any.h
@@ -521,6 +521,76 @@ public: \
|
||||
//wxDECLARE_ANY_TYPE(wxArrayString, WXDLLIMPEXP_BASE)
|
||||
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
|
||||
class WXDLLIMPEXP_FWD_BASE wxAnyToVariantRegistration;
|
||||
|
||||
// Because of header inter-dependencies, cannot include this earlier
|
||||
#include "wx/variant.h"
|
||||
|
||||
//
|
||||
// wxVariantData* data type implementation. For cases when appropriate
|
||||
// wxAny<->wxVariant conversion code is missing.
|
||||
//
|
||||
|
||||
class WXDLLIMPEXP_BASE wxAnyValueTypeImplVariantData :
|
||||
public wxAnyValueTypeImplBase<wxVariantData*>
|
||||
{
|
||||
WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
|
||||
public:
|
||||
wxAnyValueTypeImplVariantData() :
|
||||
wxAnyValueTypeImplBase<wxVariantData*>() { }
|
||||
virtual ~wxAnyValueTypeImplVariantData() { }
|
||||
|
||||
virtual void DeleteValue(wxAnyValueBuffer& buf) const
|
||||
{
|
||||
wxVariantData* data = static_cast<wxVariantData*>(buf.m_ptr);
|
||||
if ( data )
|
||||
data->DecRef();
|
||||
}
|
||||
|
||||
virtual void CopyBuffer(const wxAnyValueBuffer& src,
|
||||
wxAnyValueBuffer& dst) const
|
||||
{
|
||||
wxVariantData* data = static_cast<wxVariantData*>(src.m_ptr);
|
||||
if ( data )
|
||||
data->IncRef();
|
||||
dst.m_ptr = data;
|
||||
}
|
||||
|
||||
static void SetValue(wxVariantData* value,
|
||||
wxAnyValueBuffer& buf)
|
||||
{
|
||||
value->IncRef();
|
||||
buf.m_ptr = value;
|
||||
}
|
||||
|
||||
static wxVariantData* GetValue(const wxAnyValueBuffer& buf)
|
||||
{
|
||||
return static_cast<wxVariantData*>(buf.m_ptr);
|
||||
}
|
||||
|
||||
virtual bool ConvertValue(const wxAnyValueBuffer& src,
|
||||
wxAnyValueType* dstType,
|
||||
wxAnyValueBuffer& dst) const
|
||||
{
|
||||
wxUnusedVar(src);
|
||||
wxUnusedVar(dstType);
|
||||
wxUnusedVar(dst);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class wxAnyValueTypeImpl<wxVariantData*> :
|
||||
public wxAnyValueTypeImplVariantData
|
||||
{
|
||||
public:
|
||||
wxAnyValueTypeImpl() : wxAnyValueTypeImplVariantData() { }
|
||||
virtual ~wxAnyValueTypeImpl() { }
|
||||
};
|
||||
|
||||
#endif // wxUSE_VARIANT
|
||||
|
||||
#ifdef __VISUALC6__
|
||||
// Re-enable useless VC6 warnings
|
||||
@@ -563,6 +633,22 @@ bool operator==(TUS value) const \
|
||||
}
|
||||
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
|
||||
// Note that the following functions are implemented outside wxAny class
|
||||
// so that it can reside entirely in header and lack the export declaration.
|
||||
|
||||
// Helper function used to associate wxAnyValueType with a wxVariantData.
|
||||
extern WXDLLIMPEXP_BASE void
|
||||
wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg);
|
||||
|
||||
// This function performs main wxAny to wxVariant conversion duties.
|
||||
extern WXDLLIMPEXP_BASE bool
|
||||
wxConvertAnyToVariant(const wxAny& any, wxVariant* variant);
|
||||
|
||||
#endif // wxUSE_VARIANT
|
||||
|
||||
|
||||
//
|
||||
// The wxAny class represents a container for any type. A variant's value
|
||||
// can be changed at run time, possibly to a different type of value.
|
||||
@@ -610,6 +696,14 @@ public:
|
||||
AssignAny(any);
|
||||
}
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
wxAny(const wxVariant& variant)
|
||||
{
|
||||
m_type = wxAnyNullValueType;
|
||||
AssignVariant(variant);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
wxAny(const T& value)
|
||||
{
|
||||
@@ -676,6 +770,14 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
wxAny& operator=(const wxVariant &variant)
|
||||
{
|
||||
AssignVariant(variant);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
wxAny& operator=(const T &value)
|
||||
{
|
||||
@@ -810,6 +912,14 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
// GetAs() wxVariant specialization
|
||||
bool GetAs(wxVariant* value) const
|
||||
{
|
||||
return wxConvertAnyToVariant(*this, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Assignment functions
|
||||
void AssignAny(const wxAny& any)
|
||||
@@ -825,6 +935,30 @@ private:
|
||||
newType->CopyBuffer(any.m_buffer, m_buffer);
|
||||
}
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
void AssignVariant(const wxVariant& variant)
|
||||
{
|
||||
wxVariantData* data = variant.GetData();
|
||||
|
||||
if ( data && data->GetAsAny(this) )
|
||||
return;
|
||||
|
||||
m_type->DeleteValue(m_buffer);
|
||||
|
||||
if ( variant.IsNull() )
|
||||
{
|
||||
// Init as Null
|
||||
m_type = wxAnyNullValueType;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If everything else fails, wrap the whole wxVariantData
|
||||
m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance;
|
||||
wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
void Assign(const T &value)
|
||||
{
|
||||
|
@@ -29,6 +29,8 @@
|
||||
|
||||
#include "wx/iosfwrap.h"
|
||||
|
||||
class wxAny;
|
||||
|
||||
/*
|
||||
* wxVariantData stores the actual data in a wxVariant object,
|
||||
* to allow it to store any type of data.
|
||||
@@ -78,6 +80,11 @@ public:
|
||||
// a copy of the data.
|
||||
virtual wxVariantData* Clone() const { return NULL; }
|
||||
|
||||
#if wxUSE_ANY
|
||||
// Converts value to wxAny, if possible. Return true if successful.
|
||||
virtual bool GetAsAny(wxAny* WXUNUSED(any)) const { return false; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Protected dtor should make some incompatible code
|
||||
// break more louder. That is, they should do data->DecRef()
|
||||
@@ -101,6 +108,9 @@ public:
|
||||
|
||||
wxVariant(const wxVariant& variant);
|
||||
wxVariant(wxVariantData* data, const wxString& name = wxEmptyString);
|
||||
#if wxUSE_ANY
|
||||
wxVariant(const wxAny& any);
|
||||
#endif
|
||||
virtual ~wxVariant();
|
||||
|
||||
// generic assignment
|
||||
@@ -150,6 +160,10 @@ public:
|
||||
// write contents to a string (e.g. for debugging)
|
||||
wxString MakeString() const;
|
||||
|
||||
#if wxUSE_ANY
|
||||
wxAny GetAny() const;
|
||||
#endif
|
||||
|
||||
// double
|
||||
wxVariant(double val, const wxString& name = wxEmptyString);
|
||||
bool operator== (double value) const;
|
||||
@@ -341,6 +355,83 @@ private:
|
||||
DECLARE_DYNAMIC_CLASS(wxVariant)
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// wxVariant <-> wxAny conversion code
|
||||
//
|
||||
#if wxUSE_ANY
|
||||
|
||||
#include "wx/any.h"
|
||||
|
||||
// In order to convert wxAny to wxVariant, we need to be able to associate
|
||||
// wxAnyValueType with a wxVariantData factory function.
|
||||
typedef wxVariantData* (*wxVariantDataFactory)(const wxAny& any);
|
||||
|
||||
// Actual Any-to-Variant registration must be postponed to a time when all
|
||||
// global variables have been initialized. Hence this arrangement.
|
||||
// wxAnyToVariantRegistration instances are kept in global scope and
|
||||
// wxAnyValueTypeGlobals in any.cpp will use their data when the time is
|
||||
// right.
|
||||
class WXDLLIMPEXP_BASE wxAnyToVariantRegistration
|
||||
{
|
||||
public:
|
||||
wxAnyToVariantRegistration(wxVariantDataFactory factory);
|
||||
|
||||
virtual wxAnyValueType* GetAssociatedType() = 0;
|
||||
wxVariantDataFactory GetFactory() const { return m_factory; }
|
||||
private:
|
||||
wxVariantDataFactory m_factory;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class wxAnyToVariantRegistrationImpl : public wxAnyToVariantRegistration
|
||||
{
|
||||
public:
|
||||
wxAnyToVariantRegistrationImpl(wxVariantDataFactory factory)
|
||||
: wxAnyToVariantRegistration(factory)
|
||||
{
|
||||
}
|
||||
|
||||
virtual wxAnyValueType* GetAssociatedType()
|
||||
{
|
||||
return wxAnyValueTypeImpl<T>::GetInstance();
|
||||
}
|
||||
private:
|
||||
};
|
||||
|
||||
#define DECLARE_WXANY_CONVERSION() \
|
||||
virtual bool GetAsAny(wxAny* any) const; \
|
||||
static wxVariantData* VariantDataFactory(const wxAny& any);
|
||||
|
||||
#define REGISTER_WXANY_CONVERSION(T, CLASSNAME) \
|
||||
static wxAnyToVariantRegistrationImpl<T> \
|
||||
gs_##CLASSNAME##AnyToVariantRegistration = \
|
||||
wxAnyToVariantRegistrationImpl<T>(&CLASSNAME::VariantDataFactory);
|
||||
|
||||
#define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME) \
|
||||
bool CLASSNAME::GetAsAny(wxAny* any) const \
|
||||
{ \
|
||||
*any = m_value; \
|
||||
return true; \
|
||||
} \
|
||||
wxVariantData* CLASSNAME::VariantDataFactory(const wxAny& any) \
|
||||
{ \
|
||||
return new CLASSNAME(wxANY_AS(any, T)); \
|
||||
} \
|
||||
REGISTER_WXANY_CONVERSION(T, CLASSNAME)
|
||||
|
||||
// This is needed for wxVariantList conversion
|
||||
WX_DECLARE_LIST_WITH_DECL(wxAny, wxAnyList, class WXDLLIMPEXP_BASE);
|
||||
|
||||
#else // if !wxUSE_ANY
|
||||
|
||||
#define DECLARE_WXANY_CONVERSION()
|
||||
#define REGISTER_WXANY_CONVERSION(T, CLASSNAME)
|
||||
#define IMPLEMENT_TRIVIAL_WXANY_CONVERSION(T, CLASSNAME)
|
||||
|
||||
#endif // wxUSE_ANY/!wxUSE_ANY
|
||||
|
||||
|
||||
#define DECLARE_VARIANT_OBJECT(classname) \
|
||||
DECLARE_VARIANT_OBJECT_EXPORTED(classname, wxEMPTY_PARAMETER_VALUE)
|
||||
|
||||
@@ -367,6 +458,7 @@ public:\
|
||||
\
|
||||
virtual wxVariantData* Clone() const { return new classname##VariantData(m_value); } \
|
||||
\
|
||||
DECLARE_WXANY_CONVERSION() \
|
||||
protected:\
|
||||
classname m_value; \
|
||||
};\
|
||||
@@ -395,7 +487,8 @@ expdecl wxVariant& operator << ( wxVariant &variant, const classname &value )\
|
||||
classname##VariantData *data = new classname##VariantData( value );\
|
||||
variant.SetData( data );\
|
||||
return variant;\
|
||||
}
|
||||
} \
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(classname, classname##VariantData)
|
||||
|
||||
// implements a wxVariantData-derived class using for the Eq() method the
|
||||
// operator== which must have been provided by "classname"
|
||||
|
@@ -13,9 +13,9 @@
|
||||
The wxAny class represents a container for any type. Its value
|
||||
can be changed at run time, possibly to a different type of value.
|
||||
|
||||
wxAny is a backwards incompatible successor class for wxVariant,
|
||||
essentially doing the same thing in a more modern, template-based manner
|
||||
and with transparent support for any user data type.
|
||||
wxAny is a backwards-incompatible (but convertible) successor class for
|
||||
wxVariant, essentially doing the same thing in a more modern, template-
|
||||
based manner and with transparent support for any user data type.
|
||||
|
||||
Some pseudo-code'ish example of use with arbitrary user data:
|
||||
|
||||
@@ -87,6 +87,17 @@ public:
|
||||
*/
|
||||
wxAny(const wxAny& any);
|
||||
|
||||
/**
|
||||
Constructs wxAny, converting value from wxVariant.
|
||||
|
||||
@remarks Because of this conversion, it is not usually possible to
|
||||
have wxAny that actually holds a wxVariant. If wxVariant
|
||||
cannot be converted to a specific data type, wxAny will then
|
||||
hold and manage reference to wxVariantData* similar to how
|
||||
wxVariant does.
|
||||
*/
|
||||
wxAny(const wxVariant& variant);
|
||||
|
||||
/**
|
||||
Destructor.
|
||||
*/
|
||||
@@ -127,6 +138,16 @@ public:
|
||||
template<typename T>
|
||||
bool GetAs(T* value) const;
|
||||
|
||||
/**
|
||||
Specialization of GetAs() that allows conversion of wxAny into
|
||||
wxVariant.
|
||||
|
||||
@return Returns @true if conversion was successful. Conversion usually
|
||||
only fails if variant used custom wxVariantData that did not
|
||||
implement the wxAny to wxVariant conversion functions.
|
||||
*/
|
||||
bool GetAs(wxVariant* value) const;
|
||||
|
||||
/**
|
||||
Returns the value type as wxAnyValueType instance.
|
||||
|
||||
@@ -154,6 +175,7 @@ public:
|
||||
template<typename T>
|
||||
wxAny& operator=(const T &value);
|
||||
wxAny& operator=(const wxAny &any);
|
||||
wxAny& operator=(const wxVariant &variant);
|
||||
//@}
|
||||
|
||||
//@{
|
||||
|
@@ -12,6 +12,11 @@
|
||||
The wxVariant class represents a container for any type. A variant's value
|
||||
can be changed at run time, possibly to a different type of value.
|
||||
|
||||
@note As of wxWidgets 2.9.1, wxAny has become the preferred variant class.
|
||||
While most controls still use wxVariant in their interface, you
|
||||
can start using wxAny in your code because of an implicit conversion
|
||||
layer. See below for more information.
|
||||
|
||||
As standard, wxVariant can store values of type bool, wxChar, double, long,
|
||||
string, string list, time, date, void pointer, list of strings, and list of
|
||||
variants. However, an application can extend wxVariant's capabilities by
|
||||
@@ -85,10 +90,71 @@
|
||||
wxDynamicCast(), to use C++ RTTI type information instead of wxWidgets
|
||||
RTTI.
|
||||
|
||||
@section variant_wxanyconversion wxVariant to wxAny Conversion Layer
|
||||
|
||||
wxAny is a more modern, template-based variant class. It is not
|
||||
directly compatible with wxVariant, but there is a transparent conversion
|
||||
layer.
|
||||
|
||||
Following is an example how to use these conversions with wxPropertyGrid's
|
||||
property class wxPGProperty (which currently uses wxVariants both
|
||||
internally and in the public API):
|
||||
|
||||
@code
|
||||
// Get property value as wxAny instead of wxVariant
|
||||
wxAny value = property->GetValue();
|
||||
|
||||
// Do something with it
|
||||
DoSomethingWithString(value.As<wxString>());
|
||||
|
||||
// Write back new value to property
|
||||
value = "New Value";
|
||||
property->SetValue(value);
|
||||
|
||||
@endcode
|
||||
|
||||
Some caveats:
|
||||
@li In wxAny, there are no separate types for handling integers of
|
||||
different sizes, so converting wxAny with 'long long' value
|
||||
will yield wxVariant of "long" type when the value is small
|
||||
enough to fit in without overflow. Otherwise, variant type
|
||||
"longlong" is used. Also note that wxAny holding unsigned integer
|
||||
will always be converted to "ulonglong" wxVariant type.
|
||||
|
||||
@li Unlike wxVariant, wxAny does not store a (rarely needed) name string.
|
||||
|
||||
@li Because of implicit conversion of wxVariant to wxAny, wxAny cannot
|
||||
usually contain value of type wxVariant. In other words,
|
||||
any.CheckType<wxVariant>() can never return @true.
|
||||
|
||||
Supplied conversion functions will automatically work with all
|
||||
built-in wxVariant types, and also with all user-specified types generated
|
||||
using IMPLEMENT_VARIANT_OBJECT(). For hand-built wxVariantData classes,
|
||||
you will need to use supplied macros in a following manner:
|
||||
|
||||
@code
|
||||
|
||||
// Declare wxVariantData for data type Foo
|
||||
class wxVariantDataFoo: public wxVariantData
|
||||
{
|
||||
public:
|
||||
// interface
|
||||
// ...
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
// data storage etc
|
||||
// ...
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(Foo, wxVariantDataFoo)
|
||||
|
||||
@endcode
|
||||
|
||||
@library{wxbase}
|
||||
@category{data}
|
||||
|
||||
@see wxVariantData
|
||||
@see wxVariantData, wxAny
|
||||
*/
|
||||
class wxVariant : public wxObject
|
||||
{
|
||||
@@ -111,6 +177,11 @@ public:
|
||||
*/
|
||||
wxVariant(const wxVariant& variant);
|
||||
|
||||
/**
|
||||
Constructs a variant by converting it from wxAny.
|
||||
*/
|
||||
wxVariant(const wxAny& any);
|
||||
|
||||
/**
|
||||
Constructs a variant from a wide string literal.
|
||||
*/
|
||||
@@ -265,6 +336,11 @@ public:
|
||||
bool Convert(wxDateTime* value) const;
|
||||
//@}
|
||||
|
||||
/**
|
||||
Converts wxVariant into wxAny.
|
||||
*/
|
||||
wxAny GetAny() const;
|
||||
|
||||
/**
|
||||
Returns the string array value.
|
||||
*/
|
||||
@@ -552,6 +628,11 @@ public:
|
||||
*/
|
||||
virtual bool Eq(wxVariantData& data) const = 0;
|
||||
|
||||
/**
|
||||
Converts value to wxAny, if possible. Return @true if successful.
|
||||
*/
|
||||
virtual bool GetAny(wxAny* any) const;
|
||||
|
||||
/**
|
||||
Returns the string type of the data.
|
||||
*/
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "wx/vector.h"
|
||||
#include "wx/module.h"
|
||||
#include "wx/hashmap.h"
|
||||
|
||||
using namespace wxPrivate;
|
||||
|
||||
@@ -34,9 +35,19 @@ using namespace wxPrivate;
|
||||
// wxAnyValueTypeGlobals
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
|
||||
WX_DECLARE_HASH_MAP(wxAnyValueType*,
|
||||
wxVariantDataFactory,
|
||||
wxPointerHash,
|
||||
wxPointerEqual,
|
||||
wxAnyTypeToVariantDataFactoryMap);
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Helper class to manage wxAnyValueType instances and other
|
||||
// related global variables.
|
||||
// Helper class to manage wxAnyValueType instances and and other
|
||||
// related global variables (such as wxAny<->wxVariant type association).
|
||||
//
|
||||
// NB: We really need to have wxAnyValueType instances allocated
|
||||
// in heap. They are stored as static template member variables,
|
||||
@@ -51,6 +62,9 @@ public:
|
||||
}
|
||||
~wxAnyValueTypeGlobals()
|
||||
{
|
||||
#if wxUSE_VARIANT
|
||||
m_anyToVariant.clear();
|
||||
#endif
|
||||
for ( size_t i=0; i<m_valueTypes.size(); i++ )
|
||||
delete m_valueTypes[i];
|
||||
}
|
||||
@@ -60,12 +74,147 @@ public:
|
||||
m_valueTypes.push_back(valueType);
|
||||
}
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
void PreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
|
||||
{
|
||||
m_anyToVariantRegs.push_back(reg);
|
||||
}
|
||||
|
||||
// Find wxVariantData factory function for given value type,
|
||||
// (or compatible, if possible)
|
||||
wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type)
|
||||
{
|
||||
wxAnyTypeToVariantDataFactoryMap& anyToVariant = m_anyToVariant;
|
||||
wxAnyTypeToVariantDataFactoryMap::const_iterator it;
|
||||
it = anyToVariant.find(type);
|
||||
if ( it != anyToVariant.end() )
|
||||
return it->second;
|
||||
|
||||
// Not found, handle pre-registrations
|
||||
size_t i = m_anyToVariantRegs.size();
|
||||
while ( i > 0 )
|
||||
{
|
||||
i--;
|
||||
wxAnyToVariantRegistration* reg = m_anyToVariantRegs[i];
|
||||
wxAnyValueType* assocType = reg->GetAssociatedType();
|
||||
if ( assocType )
|
||||
{
|
||||
// Both variant data and wxAnyValueType have been
|
||||
// now been properly initialized, so remove the
|
||||
// pre-registration entry and move data to anyToVarian
|
||||
// map.
|
||||
anyToVariant[assocType] = reg->GetFactory();
|
||||
m_anyToVariantRegs.erase( m_anyToVariantRegs.begin() + i );
|
||||
}
|
||||
}
|
||||
|
||||
// Then try again
|
||||
it = anyToVariant.find(type);
|
||||
if ( it != anyToVariant.end() )
|
||||
return it->second;
|
||||
|
||||
// Finally, attempt to find a compatible type
|
||||
for ( it = anyToVariant.begin(); it != anyToVariant.end(); it++ )
|
||||
{
|
||||
if ( type->IsSameType(it->first) )
|
||||
{
|
||||
wxVariantDataFactory f = it->second;
|
||||
anyToVariant[type] = f;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
wxVector<wxAnyValueType*> m_valueTypes;
|
||||
wxVector<wxAnyValueType*> m_valueTypes;
|
||||
#if wxUSE_VARIANT
|
||||
wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
|
||||
wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
|
||||
#endif
|
||||
};
|
||||
|
||||
static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
|
||||
WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
|
||||
|
||||
void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
|
||||
{
|
||||
if ( !g_wxAnyValueTypeGlobals )
|
||||
g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
|
||||
g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
|
||||
}
|
||||
|
||||
bool wxConvertAnyToVariant(const wxAny& any, wxVariant* variant)
|
||||
{
|
||||
if ( any.IsNull() )
|
||||
{
|
||||
variant->MakeNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
// (signed) integer is a special case, because there is only one type
|
||||
// in wxAny, and two ("long" and "longlong") in wxVariant. For better
|
||||
// backwards compatibility, convert all values that fit in "long",
|
||||
// and others to "longlong".
|
||||
if ( wxANY_CHECK_TYPE(any, signed int) )
|
||||
{
|
||||
#ifdef wxLongLong_t
|
||||
wxLongLong_t ll;
|
||||
if ( any.GetAs(&ll) )
|
||||
{
|
||||
if ( ll > LONG_MAX )
|
||||
*variant = wxLongLong(ll);
|
||||
else
|
||||
*variant = (long) wxLongLong(ll).GetLo();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
long l;
|
||||
if ( any.GetAs(&l) )
|
||||
*variant = l;
|
||||
else
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find matching factory function
|
||||
wxVariantDataFactory f =
|
||||
g_wxAnyValueTypeGlobals->FindVariantDataFactory(any.GetType());
|
||||
|
||||
wxVariantData* data;
|
||||
|
||||
if ( f )
|
||||
{
|
||||
data = f(any);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if wxAny wrapped wxVariantData*
|
||||
if ( !any.GetAs(&data) )
|
||||
return false;
|
||||
|
||||
// Wrapper's GetValue() does not increase reference
|
||||
// count, se have to do it before the data gets passed
|
||||
// to a new variant.
|
||||
data->IncRef();
|
||||
}
|
||||
|
||||
variant->SetData(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // wxUSE_VARIANT
|
||||
|
||||
//
|
||||
// This class is to make sure that wxAnyValueType instances
|
||||
// etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
|
||||
|
@@ -193,6 +193,48 @@ bool wxVariant::IsValueKindOf(const wxClassInfo* type) const
|
||||
return info ? info->IsKindOf(type) : false ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// wxVariant <-> wxAny conversion code
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
#if wxUSE_ANY
|
||||
|
||||
wxAnyToVariantRegistration::
|
||||
wxAnyToVariantRegistration(wxVariantDataFactory factory)
|
||||
: m_factory(factory)
|
||||
{
|
||||
wxPreRegisterAnyToVariant(this);
|
||||
}
|
||||
|
||||
wxVariant::wxVariant(const wxAny& any)
|
||||
: wxObject()
|
||||
{
|
||||
wxVariant variant;
|
||||
if ( !any.GetAs(&variant) )
|
||||
{
|
||||
wxFAIL_MSG("wxAny of this type cannot be converted to wxVariant");
|
||||
return;
|
||||
}
|
||||
|
||||
*this = variant;
|
||||
}
|
||||
|
||||
wxAny wxVariant::GetAny() const
|
||||
{
|
||||
if ( IsNull() )
|
||||
return wxAny();
|
||||
|
||||
wxVariantData* data = GetData();
|
||||
wxAny any;
|
||||
|
||||
if ( data->GetAsAny(&any) )
|
||||
return any;
|
||||
|
||||
// If everything else fails, wrap the whole wxVariantData
|
||||
return wxAny(data);
|
||||
}
|
||||
|
||||
#endif // wxUSE_ANY
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// wxVariantDataLong
|
||||
@@ -224,10 +266,27 @@ public:
|
||||
|
||||
virtual wxString GetType() const { return wxT("long"); }
|
||||
|
||||
// Since wxAny does not have separate type for integers shorter than
|
||||
// longlong, we do not usually implement wxVariant->wxAny conversion
|
||||
// here (but in wxVariantDataLongLong instead).
|
||||
#ifndef wxLongLong_t
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
#else
|
||||
bool GetAsAny(wxAny* any) const
|
||||
{
|
||||
*any = m_value;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
long m_value;
|
||||
};
|
||||
|
||||
#ifndef wxLongLong_t
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(long, wxVariantDataLong)
|
||||
#endif
|
||||
|
||||
bool wxVariantDataLong::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxT("long")), wxT("wxVariantDataLong::Eq: argument mismatch") );
|
||||
@@ -373,10 +432,14 @@ public:
|
||||
virtual wxString GetType() const { return wxT("double"); }
|
||||
|
||||
wxVariantData* Clone() const { return new wxVariantDoubleData(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
double m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(double, wxVariantDoubleData)
|
||||
|
||||
bool wxVariantDoubleData::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxT("double")), wxT("wxVariantDoubleData::Eq: argument mismatch") );
|
||||
@@ -509,10 +572,14 @@ public:
|
||||
virtual wxString GetType() const { return wxT("bool"); }
|
||||
|
||||
wxVariantData* Clone() const { return new wxVariantDataBool(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(bool, wxVariantDataBool)
|
||||
|
||||
bool wxVariantDataBool::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxT("bool")), wxT("wxVariantDataBool::Eq: argument mismatch") );
|
||||
@@ -646,10 +713,13 @@ public:
|
||||
virtual wxString GetType() const { return wxT("char"); }
|
||||
wxVariantData* Clone() const { return new wxVariantDataChar(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxUniChar m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxUniChar, wxVariantDataChar)
|
||||
|
||||
bool wxVariantDataChar::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxT("char")), wxT("wxVariantDataChar::Eq: argument mismatch") );
|
||||
@@ -798,10 +868,13 @@ public:
|
||||
virtual wxString GetType() const { return wxT("string"); }
|
||||
wxVariantData* Clone() const { return new wxVariantDataString(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxString m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxString, wxVariantDataString)
|
||||
|
||||
bool wxVariantDataString::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxT("string")), wxT("wxVariantDataString::Eq: argument mismatch") );
|
||||
@@ -954,10 +1027,13 @@ public:
|
||||
|
||||
virtual wxClassInfo* GetValueClassInfo();
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxObject* m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxObject*, wxVariantDataWxObjectPtr)
|
||||
|
||||
bool wxVariantDataWxObjectPtr::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( data.GetType() == GetType(), wxT("wxVariantDataWxObjectPtr::Eq: argument mismatch") );
|
||||
@@ -1073,10 +1149,13 @@ public:
|
||||
virtual wxString GetType() const { return wxT("void*"); }
|
||||
virtual wxVariantData* Clone() const { return new wxVariantDataVoidPtr(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
void* m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(void*, wxVariantDataVoidPtr)
|
||||
|
||||
bool wxVariantDataVoidPtr::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( data.GetType() == wxT("void*"), wxT("wxVariantDataVoidPtr::Eq: argument mismatch") );
|
||||
@@ -1185,10 +1264,12 @@ public:
|
||||
virtual wxString GetType() const { return wxT("datetime"); }
|
||||
virtual wxVariantData* Clone() const { return new wxVariantDataDateTime(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxDateTime m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxDateTime, wxVariantDataDateTime)
|
||||
|
||||
bool wxVariantDataDateTime::Eq(wxVariantData& data) const
|
||||
{
|
||||
@@ -1316,10 +1397,13 @@ public:
|
||||
virtual wxString GetType() const { return wxT("arrstring"); }
|
||||
virtual wxVariantData* Clone() const { return new wxVariantDataArrayString(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxArrayString m_value;
|
||||
};
|
||||
|
||||
IMPLEMENT_TRIVIAL_WXANY_CONVERSION(wxArrayString, wxVariantDataArrayString)
|
||||
|
||||
bool wxVariantDataArrayString::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( data.GetType() == GetType(), wxT("wxVariantDataArrayString::Eq: argument mismatch") );
|
||||
@@ -1449,10 +1533,48 @@ public:
|
||||
|
||||
virtual wxString GetType() const { return wxS("longlong"); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxLongLong m_value;
|
||||
};
|
||||
|
||||
//
|
||||
// wxLongLong type requires customized wxAny conversion code
|
||||
//
|
||||
#if wxUSE_ANY
|
||||
#ifdef wxLongLong_t
|
||||
|
||||
bool wxVariantDataLongLong::GetAsAny(wxAny* any) const
|
||||
{
|
||||
*any = m_value.GetValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
wxVariantData* wxVariantDataLongLong::VariantDataFactory(const wxAny& any)
|
||||
{
|
||||
return new wxVariantDataLongLong(wxANY_AS(any, wxLongLong_t));
|
||||
}
|
||||
|
||||
REGISTER_WXANY_CONVERSION(wxLongLong_t, wxVariantDataLongLong)
|
||||
|
||||
#else // if !defined(wxLongLong_t)
|
||||
|
||||
bool wxVariantDataLongLong::GetAsAny(wxAny* any) const
|
||||
{
|
||||
*any = m_value;
|
||||
return true;
|
||||
}
|
||||
|
||||
wxVariantData* wxVariantDataLongLong::VariantDataFactory(const wxAny& any)
|
||||
{
|
||||
return new wxVariantDataLongLong(wxANY_AS(any, wxLongLong));
|
||||
}
|
||||
|
||||
REGISTER_WXANY_CONVERSION(wxLongLong, wxVariantDataLongLong)
|
||||
|
||||
#endif // defined(wxLongLong_t)/!defined(wxLongLong_t)
|
||||
#endif // wxUSE_ANY
|
||||
|
||||
bool wxVariantDataLongLong::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxS("longlong")),
|
||||
@@ -1610,10 +1732,49 @@ public:
|
||||
|
||||
virtual wxString GetType() const { return wxS("ulonglong"); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxULongLong m_value;
|
||||
};
|
||||
|
||||
//
|
||||
// wxULongLong type requires customized wxAny conversion code
|
||||
//
|
||||
#if wxUSE_ANY
|
||||
#ifdef wxLongLong_t
|
||||
|
||||
bool wxVariantDataULongLong::GetAsAny(wxAny* any) const
|
||||
{
|
||||
*any = m_value.GetValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
wxVariantData* wxVariantDataULongLong::VariantDataFactory(const wxAny& any)
|
||||
{
|
||||
return new wxVariantDataULongLong(wxANY_AS(any, wxULongLong_t));
|
||||
}
|
||||
|
||||
REGISTER_WXANY_CONVERSION(wxULongLong_t, wxVariantDataULongLong)
|
||||
|
||||
#else // if !defined(wxLongLong_t)
|
||||
|
||||
bool wxVariantDataULongLong::GetAsAny(wxAny* any) const
|
||||
{
|
||||
*any = m_value;
|
||||
return true;
|
||||
}
|
||||
|
||||
wxVariantData* wxVariantDataULongLong::VariantDataFactory(const wxAny& any)
|
||||
{
|
||||
return new wxVariantDataULongLong(wxANY_AS(any, wxULongLong));
|
||||
}
|
||||
|
||||
REGISTER_WXANY_CONVERSION(wxULongLong, wxVariantDataULongLong)
|
||||
|
||||
#endif // defined(wxLongLong_t)/!defined(wxLongLong_t)
|
||||
#endif // wxUSE_ANY
|
||||
|
||||
|
||||
bool wxVariantDataULongLong::Eq(wxVariantData& data) const
|
||||
{
|
||||
wxASSERT_MSG( (data.GetType() == wxS("ulonglong")),
|
||||
@@ -1764,10 +1925,54 @@ public:
|
||||
void Clear();
|
||||
|
||||
wxVariantData* Clone() const { return new wxVariantDataList(m_value); }
|
||||
|
||||
DECLARE_WXANY_CONVERSION()
|
||||
protected:
|
||||
wxVariantList m_value;
|
||||
};
|
||||
|
||||
#if wxUSE_ANY
|
||||
|
||||
//
|
||||
// Convert to/from list of wxAnys
|
||||
//
|
||||
|
||||
WX_DEFINE_LIST(wxAnyList)
|
||||
|
||||
bool wxVariantDataList::GetAsAny(wxAny* any) const
|
||||
{
|
||||
wxAnyList dst;
|
||||
wxVariantList::compatibility_iterator node = m_value.GetFirst();
|
||||
while (node)
|
||||
{
|
||||
wxVariant* pVar = node->GetData();
|
||||
dst.push_back(new wxAny(*pVar));
|
||||
node = node->GetNext();
|
||||
}
|
||||
|
||||
*any = dst;
|
||||
return true;
|
||||
}
|
||||
|
||||
wxVariantData* wxVariantDataList::VariantDataFactory(const wxAny& any)
|
||||
{
|
||||
wxAnyList src = wxANY_AS(any, wxAnyList);
|
||||
wxVariantList dst;
|
||||
wxAnyList::compatibility_iterator node = src.GetFirst();
|
||||
while (node)
|
||||
{
|
||||
wxAny* pAny = node->GetData();
|
||||
dst.push_back(new wxVariant(*pAny));
|
||||
node = node->GetNext();
|
||||
}
|
||||
|
||||
return new wxVariantDataList(dst);
|
||||
}
|
||||
|
||||
REGISTER_WXANY_CONVERSION(wxAnyList, wxVariantDataList)
|
||||
|
||||
#endif // wxUSE_ANY
|
||||
|
||||
wxVariantDataList::wxVariantDataList(const wxVariantList& list)
|
||||
{
|
||||
SetValue(list);
|
||||
|
@@ -36,6 +36,7 @@ private:
|
||||
CPPUNIT_TEST( As );
|
||||
CPPUNIT_TEST( GetAs );
|
||||
CPPUNIT_TEST( Null );
|
||||
CPPUNIT_TEST( wxVariantConversions );
|
||||
CPPUNIT_TEST( CustomTemplateSpecialization );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
@@ -43,6 +44,7 @@ private:
|
||||
void As();
|
||||
void GetAs();
|
||||
void Null();
|
||||
void wxVariantConversions();
|
||||
void CustomTemplateSpecialization();
|
||||
|
||||
wxDateTime m_testDateTime;
|
||||
@@ -66,6 +68,7 @@ private:
|
||||
wxAny m_anyWxObjectPtr1;
|
||||
wxAny m_anyVoidPtr1;
|
||||
wxAny m_anyDateTime1;
|
||||
wxAny m_anyUniChar1;
|
||||
|
||||
wxAny m_anySignedChar2;
|
||||
wxAny m_anySignedShort2;
|
||||
@@ -156,6 +159,7 @@ wxAnyTestCase::wxAnyTestCase()
|
||||
m_anyFloatDouble2 = (float)TEST_FLOAT_CONST;
|
||||
m_anyDoubleDouble2 = (double)TEST_FLOAT_CONST;
|
||||
m_anyDateTime2 = m_testDateTime;
|
||||
m_anyUniChar1 = wxUniChar('A');
|
||||
m_anyWxObjectPtr2 = dummyWxObjectPointer;
|
||||
m_anyVoidPtr2 = dummyVoidPointer;
|
||||
}
|
||||
@@ -248,6 +252,8 @@ void wxAnyTestCase::As()
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(o, TEST_FLOAT_CONST, FEQ_DELTA);
|
||||
double p = wxANY_AS(m_anyDoubleDouble1, double);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(p, TEST_FLOAT_CONST, FEQ_DELTA);
|
||||
wxUniChar chr = wxANY_AS(m_anyUniChar1, wxUniChar);
|
||||
CPPUNIT_ASSERT(chr == 'A');
|
||||
wxDateTime q = wxANY_AS(m_anyDateTime1, wxDateTime);
|
||||
CPPUNIT_ASSERT(q == m_testDateTime);
|
||||
wxObject* r = wxANY_AS(m_anyWxObjectPtr1, wxObject*);
|
||||
@@ -370,8 +376,10 @@ void wxAnyTestCase::GetAs()
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(d2, TEST_FLOAT_CONST, FEQ_DELTA);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Test user data type specialization of wxAnyValueTypeImpl
|
||||
// Test user data type for wxAnyValueTypeImpl specialization
|
||||
// any hand-built wxVariantData
|
||||
//
|
||||
|
||||
class MyClass
|
||||
@@ -392,6 +400,173 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#if wxUSE_VARIANT
|
||||
|
||||
// For testing purposes, create dummy variant data implementation
|
||||
// that does not have wxAny conversion code
|
||||
class wxMyVariantData : public wxVariantData
|
||||
{
|
||||
public:
|
||||
wxMyVariantData(const MyClass& value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
virtual bool Eq(wxVariantData& WXUNUSED(data)) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// What type is it? Return a string name.
|
||||
virtual wxString GetType() const { return "MyClass"; }
|
||||
|
||||
virtual wxVariantData* Clone() const
|
||||
{
|
||||
return new wxMyVariantData(m_value);
|
||||
}
|
||||
|
||||
protected:
|
||||
MyClass m_value;
|
||||
};
|
||||
|
||||
#endif // wxUSE_VARIANT
|
||||
|
||||
|
||||
void wxAnyTestCase::wxVariantConversions()
|
||||
{
|
||||
#if wxUSE_VARIANT
|
||||
//
|
||||
// Test various conversions to and from wxVariant
|
||||
//
|
||||
bool res;
|
||||
|
||||
// Prepare wxVariants
|
||||
wxVariant vLong(123L);
|
||||
wxVariant vString("ABC");
|
||||
wxVariant vDouble(TEST_FLOAT_CONST);
|
||||
wxVariant vBool((bool)true);
|
||||
wxVariant vChar('A');
|
||||
#ifdef wxLongLong_t
|
||||
wxVariant vLongLong(wxLongLong(wxLL(0xFFFFFFFFFF)));
|
||||
wxVariant vULongLong(wxULongLong(wxULL(123456)));
|
||||
#endif
|
||||
wxArrayString arrstr;
|
||||
arrstr.push_back("test string");
|
||||
wxVariant vArrayString(arrstr);
|
||||
wxVariant vDateTime(m_testDateTime);
|
||||
wxVariant vVoidPtr(dummyVoidPointer);
|
||||
wxVariant vCustomType(new wxMyVariantData(MyClass(101)));
|
||||
wxVariant vList;
|
||||
|
||||
vList.NullList();
|
||||
vList.Append(15);
|
||||
vList.Append("abc");
|
||||
|
||||
// Convert to wxAnys, and then back to wxVariants
|
||||
wxVariant variant;
|
||||
|
||||
wxAny any(vLong);
|
||||
CPPUNIT_ASSERT(any == 123L);
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant == 123L);
|
||||
|
||||
// Make sure integer variant has correct type information
|
||||
CPPUNIT_ASSERT(variant.GetLong() == 123);
|
||||
CPPUNIT_ASSERT(variant.GetType() == "long");
|
||||
|
||||
// Unsigned long wxAny should convert to "ulonglong" wxVariant
|
||||
any = 1000UL;
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetType() == "ulonglong");
|
||||
CPPUNIT_ASSERT(variant.GetLong() == 1000);
|
||||
|
||||
any = vString;
|
||||
CPPUNIT_ASSERT(any == "ABC");
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetString() == "ABC");
|
||||
|
||||
any = vDouble;
|
||||
double d = wxANY_AS(any, double);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(d, TEST_FLOAT_CONST, FEQ_DELTA);
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(variant.GetDouble(),
|
||||
TEST_FLOAT_CONST,
|
||||
FEQ_DELTA);
|
||||
|
||||
any = vBool;
|
||||
CPPUNIT_ASSERT(wxANY_AS(any, bool) == true);
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetBool() == true);
|
||||
|
||||
any = vChar;
|
||||
//CPPUNIT_ASSERT(wxANY_AS(any, wxUniChar) == 'A');
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetChar() == 'A');
|
||||
|
||||
#ifdef wxLongLong_t
|
||||
any = vLongLong;
|
||||
CPPUNIT_ASSERT(any == wxLL(0xFFFFFFFFFF));
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetLongLong() == wxLongLong(wxLL(0xFFFFFFFFFF)));
|
||||
CPPUNIT_ASSERT(variant.GetType() == "longlong");
|
||||
|
||||
any = vULongLong;
|
||||
CPPUNIT_ASSERT(any == wxLL(123456));
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetULongLong() == wxULongLong(wxULL(123456)));
|
||||
#endif
|
||||
|
||||
// Cannot test equality for the rest, just test that they convert
|
||||
// back correctly.
|
||||
any = vArrayString;
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
wxArrayString arrstr2 = variant.GetArrayString();
|
||||
CPPUNIT_ASSERT(arrstr2 == arrstr);
|
||||
|
||||
any = m_testDateTime;
|
||||
CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
|
||||
any = vDateTime;
|
||||
CPPUNIT_ASSERT(wxANY_AS(any, wxDateTime) == m_testDateTime);
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant == m_testDateTime);
|
||||
|
||||
any = vVoidPtr;
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetVoidPtr() == dummyVoidPointer);
|
||||
|
||||
any = vList;
|
||||
CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxAnyList));
|
||||
wxAnyList anyList = wxANY_AS(any, wxAnyList);
|
||||
CPPUNIT_ASSERT(anyList.GetCount() == 2);
|
||||
CPPUNIT_ASSERT(wxANY_AS((*anyList[0]), int) == 15);
|
||||
CPPUNIT_ASSERT(wxANY_AS((*anyList[1]), wxString) == "abc");
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetType() == "list");
|
||||
CPPUNIT_ASSERT(variant.GetCount() == 2);
|
||||
CPPUNIT_ASSERT(variant[0].GetLong() == 15);
|
||||
CPPUNIT_ASSERT(variant[1].GetString() == "abc");
|
||||
|
||||
any = vCustomType;
|
||||
CPPUNIT_ASSERT(wxANY_CHECK_TYPE(any, wxVariantData*));
|
||||
res = any.GetAs(&variant);
|
||||
CPPUNIT_ASSERT(res);
|
||||
CPPUNIT_ASSERT(variant.GetType() == "MyClass");
|
||||
|
||||
#endif // wxUSE_VARIANT
|
||||
}
|
||||
|
||||
template<>
|
||||
class wxAnyValueTypeImpl<MyClass> :
|
||||
public wxAnyValueTypeImplBase<MyClass>
|
||||
|
Reference in New Issue
Block a user