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:
Jaakko Salli
2010-04-16 14:33:52 +00:00
parent 75504144d2
commit 0bf14ab8b1
7 changed files with 868 additions and 9 deletions

View File

@@ -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)
{

View File

@@ -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"