280 lines
8.3 KiB
C
280 lines
8.3 KiB
C
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Name: wx/variantbase.h
|
||
|
// Purpose: wxVariantBase class, a minimal version of wxVariant used by XTI
|
||
|
// Author: Julian Smart
|
||
|
// Modified by: Francesco Montorsi
|
||
|
// Created: 10/09/98
|
||
|
// RCS-ID: $Id: variantbase.h 66584 2011-01-05 06:56:36Z PC $
|
||
|
// Copyright: (c) Julian Smart
|
||
|
// Licence: wxWindows licence
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#ifndef _WX_VARIANTBASE_H_
|
||
|
#define _WX_VARIANTBASE_H_
|
||
|
|
||
|
#include "wx/defs.h"
|
||
|
|
||
|
#if wxUSE_VARIANT
|
||
|
|
||
|
#include "wx/string.h"
|
||
|
#include "wx/arrstr.h"
|
||
|
#include "wx/cpp.h"
|
||
|
#include <typeinfo>
|
||
|
|
||
|
#if wxUSE_DATETIME
|
||
|
#include "wx/datetime.h"
|
||
|
#endif // wxUSE_DATETIME
|
||
|
|
||
|
#include "wx/iosfwrap.h"
|
||
|
|
||
|
class wxTypeInfo;
|
||
|
class wxObject;
|
||
|
class wxClassInfo;
|
||
|
|
||
|
/*
|
||
|
* wxVariantData stores the actual data in a wxVariant object,
|
||
|
* to allow it to store any type of data.
|
||
|
* Derive from this to provide custom data handling.
|
||
|
*
|
||
|
* NB: To prevent addition of extra vtbl pointer to wxVariantData,
|
||
|
* we don't multiple-inherit from wxObjectRefData. Instead,
|
||
|
* we simply replicate the wxObject ref-counting scheme.
|
||
|
*
|
||
|
* NB: When you construct a wxVariantData, it will have refcount
|
||
|
* of one. Refcount will not be further increased when
|
||
|
* it is passed to wxVariant. This simulates old common
|
||
|
* scenario where wxVariant took ownership of wxVariantData
|
||
|
* passed to it.
|
||
|
* If you create wxVariantData for other reasons than passing
|
||
|
* it to wxVariant, technically you are not required to call
|
||
|
* DecRef() before deleting it.
|
||
|
*
|
||
|
* TODO: in order to replace wxPropertyValue, we would need
|
||
|
* to consider adding constructors that take pointers to C++ variables,
|
||
|
* or removing that functionality from the wxProperty library.
|
||
|
* Essentially wxPropertyValue takes on some of the wxValidator functionality
|
||
|
* by storing pointers and not just actual values, allowing update of C++ data
|
||
|
* to be handled automatically. Perhaps there's another way of doing this without
|
||
|
* overloading wxVariant with unnecessary functionality.
|
||
|
*/
|
||
|
|
||
|
class WXDLLIMPEXP_BASE wxVariantData
|
||
|
{
|
||
|
friend class wxVariantBase;
|
||
|
|
||
|
public:
|
||
|
wxVariantData()
|
||
|
: m_count(1)
|
||
|
{ }
|
||
|
|
||
|
#if wxUSE_STD_IOSTREAM
|
||
|
virtual bool Write(wxSTD ostream& WXUNUSED(str)) const { return false; }
|
||
|
virtual bool Read(wxSTD istream& WXUNUSED(str)) { return false; }
|
||
|
#endif
|
||
|
virtual bool Write(wxString& WXUNUSED(str)) const { return false; }
|
||
|
virtual bool Read(wxString& WXUNUSED(str)) { return false; }
|
||
|
|
||
|
// Override these to provide common functionality
|
||
|
virtual bool Eq(wxVariantData& data) const = 0;
|
||
|
|
||
|
// What type is it? Return a string name.
|
||
|
virtual wxString GetType() const = 0;
|
||
|
|
||
|
// returns the type info of the content
|
||
|
virtual const wxTypeInfo* GetTypeInfo() const = 0;
|
||
|
|
||
|
// If it based on wxObject return the ClassInfo.
|
||
|
virtual wxClassInfo* GetValueClassInfo() { return NULL; }
|
||
|
|
||
|
int GetRefCount() const
|
||
|
{ return m_count; }
|
||
|
void IncRef()
|
||
|
{ m_count++; }
|
||
|
void DecRef()
|
||
|
{
|
||
|
if ( --m_count == 0 )
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
// Protected dtor should make some incompatible code
|
||
|
// break more louder. That is, they should do data->DecRef()
|
||
|
// instead of delete data.
|
||
|
virtual ~wxVariantData() {}
|
||
|
|
||
|
private:
|
||
|
int m_count;
|
||
|
};
|
||
|
|
||
|
template<typename T> class wxVariantDataT : public wxVariantData
|
||
|
{
|
||
|
public:
|
||
|
wxVariantDataT(const T& d) : m_data(d) {}
|
||
|
virtual ~wxVariantDataT() {}
|
||
|
|
||
|
// get a ref to the stored data
|
||
|
T & Get() { return m_data; }
|
||
|
|
||
|
// get a const ref to the stored data
|
||
|
const T & Get() const { return m_data; }
|
||
|
|
||
|
// set the data
|
||
|
void Set(const T& d) { m_data = d; }
|
||
|
|
||
|
// Override these to provide common functionality
|
||
|
virtual bool Eq(wxVariantData& WXUNUSED(data)) const
|
||
|
{ return false; /* FIXME!! */ }
|
||
|
|
||
|
// What type is it? Return a string name.
|
||
|
virtual wxString GetType() const
|
||
|
{ return GetTypeInfo()->GetTypeName(); }
|
||
|
|
||
|
// return a heap allocated duplicate
|
||
|
//virtual wxVariantData* Clone() const { return new wxVariantDataT<T>( Get() ); }
|
||
|
|
||
|
// returns the type info of the contentc
|
||
|
virtual const wxTypeInfo* GetTypeInfo() const { return wxGetTypeInfo( (T*) NULL ); }
|
||
|
|
||
|
private:
|
||
|
T m_data;
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* wxVariantBase can store any kind of data, but has some basic types
|
||
|
* built in.
|
||
|
*/
|
||
|
|
||
|
class WXDLLIMPEXP_BASE wxVariantBase
|
||
|
{
|
||
|
public:
|
||
|
wxVariantBase();
|
||
|
wxVariantBase(const wxVariantBase& variant);
|
||
|
wxVariantBase(wxVariantData* data, const wxString& name = wxEmptyString);
|
||
|
|
||
|
template<typename T>
|
||
|
wxVariantBase(const T& data, const wxString& name = wxEmptyString) :
|
||
|
m_data(new wxVariantDataT<T>(data)), m_name(name) {}
|
||
|
|
||
|
virtual ~wxVariantBase();
|
||
|
|
||
|
// generic assignment
|
||
|
void operator= (const wxVariantBase& variant);
|
||
|
|
||
|
// Assignment using data, e.g.
|
||
|
// myVariant = new wxStringVariantData("hello");
|
||
|
void operator= (wxVariantData* variantData);
|
||
|
|
||
|
bool operator== (const wxVariantBase& variant) const;
|
||
|
bool operator!= (const wxVariantBase& variant) const;
|
||
|
|
||
|
// Sets/gets name
|
||
|
inline void SetName(const wxString& name) { m_name = name; }
|
||
|
inline const wxString& GetName() const { return m_name; }
|
||
|
|
||
|
// Tests whether there is data
|
||
|
bool IsNull() const;
|
||
|
|
||
|
// FIXME: used by wxVariantBase code but is nice wording...
|
||
|
bool IsEmpty() const { return IsNull(); }
|
||
|
|
||
|
// For compatibility with wxWidgets <= 2.6, this doesn't increase
|
||
|
// reference count.
|
||
|
wxVariantData* GetData() const { return m_data; }
|
||
|
void SetData(wxVariantData* data) ;
|
||
|
|
||
|
// make a 'clone' of the object
|
||
|
void Ref(const wxVariantBase& clone);
|
||
|
|
||
|
// destroy a reference
|
||
|
void UnRef();
|
||
|
|
||
|
// Make NULL (i.e. delete the data)
|
||
|
void MakeNull();
|
||
|
|
||
|
// write contents to a string (e.g. for debugging)
|
||
|
wxString MakeString() const;
|
||
|
|
||
|
// Delete data and name
|
||
|
void Clear();
|
||
|
|
||
|
// Returns a string representing the type of the variant,
|
||
|
// e.g. "string", "bool", "stringlist", "list", "double", "long"
|
||
|
wxString GetType() const;
|
||
|
|
||
|
bool IsType(const wxString& type) const;
|
||
|
bool IsValueKindOf(const wxClassInfo* type) const;
|
||
|
|
||
|
// FIXME wxXTI methods:
|
||
|
|
||
|
// get the typeinfo of the stored object
|
||
|
const wxTypeInfo* GetTypeInfo() const
|
||
|
{
|
||
|
if (!m_data)
|
||
|
return NULL;
|
||
|
return m_data->GetTypeInfo();
|
||
|
}
|
||
|
|
||
|
// get a ref to the stored data
|
||
|
template<typename T> T& Get(wxTEMPLATED_MEMBER_FIX(T))
|
||
|
{
|
||
|
wxVariantDataT<T> *dataptr =
|
||
|
wx_dynamic_cast(wxVariantDataT<T>*, m_data);
|
||
|
wxASSERT_MSG( dataptr,
|
||
|
wxString::Format(wxT("Cast to %s not possible"), typeid(T).name()) );
|
||
|
return dataptr->Get();
|
||
|
}
|
||
|
|
||
|
// get a const ref to the stored data
|
||
|
template<typename T> const T& Get(wxTEMPLATED_MEMBER_FIX(T)) const
|
||
|
{
|
||
|
const wxVariantDataT<T> *dataptr =
|
||
|
wx_dynamic_cast(const wxVariantDataT<T>*, m_data);
|
||
|
wxASSERT_MSG( dataptr,
|
||
|
wxString::Format(wxT("Cast to %s not possible"), typeid(T).name()) );
|
||
|
return dataptr->Get();
|
||
|
}
|
||
|
|
||
|
template<typename T> bool HasData(wxTEMPLATED_MEMBER_FIX(T)) const
|
||
|
{
|
||
|
const wxVariantDataT<T> *dataptr =
|
||
|
wx_dynamic_cast(const wxVariantDataT<T>*, m_data);
|
||
|
return dataptr != NULL;
|
||
|
}
|
||
|
|
||
|
// returns this value as string
|
||
|
wxString GetAsString() const;
|
||
|
|
||
|
// gets the stored data casted to a wxObject*,
|
||
|
// returning NULL if cast is not possible
|
||
|
wxObject* GetAsObject();
|
||
|
|
||
|
protected:
|
||
|
wxVariantData* m_data;
|
||
|
wxString m_name;
|
||
|
};
|
||
|
|
||
|
#include "wx/dynarray.h"
|
||
|
WX_DECLARE_OBJARRAY_WITH_DECL(wxVariantBase, wxVariantBaseArray, class WXDLLIMPEXP_BASE);
|
||
|
|
||
|
|
||
|
// templated streaming, every type must have their specialization for these methods
|
||
|
|
||
|
template<typename T>
|
||
|
void wxStringReadValue( const wxString &s, T &data );
|
||
|
|
||
|
template<typename T>
|
||
|
void wxStringWriteValue( wxString &s, const T &data);
|
||
|
|
||
|
template<typename T>
|
||
|
void wxToStringConverter( const wxVariantBase &v, wxString &s wxTEMPLATED_FUNCTION_FIX(T)) \
|
||
|
{ wxStringWriteValue( s, v.wxTEMPLATED_MEMBER_CALL(Get, T) ); }
|
||
|
|
||
|
template<typename T>
|
||
|
void wxFromStringConverter( const wxString &s, wxVariantBase &v wxTEMPLATED_FUNCTION_FIX(T)) \
|
||
|
{ T d; wxStringReadValue( s, d ); v = wxVariantBase(d); }
|
||
|
|
||
|
|
||
|
#endif // wxUSE_VARIANT
|
||
|
#endif // _WX_VARIANTBASE_H_
|