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"
|
||||
|
Reference in New Issue
Block a user