From cf6ae2907c365869b10b61cbe3bde2768facd4d8 Mon Sep 17 00:00:00 2001 From: Roger Gammans Date: Mon, 2 Jun 2003 21:17:28 +0000 Subject: [PATCH 1/1] Addition at simple wxObject*, support into wxVariant. This includes 2 new methods wxVariant::IsValueKindOf() and wxVariantData::GetValueClassInfo() to allow query of the wxRTTI data of the variant's data. Also included is a macro analogues to dynamicCast for fetching objects out of a wxVariant. Documentation patches for the above. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@20860 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/variant.tex | 37 +++++++++- include/wx/variant.h | 16 +++++ samples/typetest/typetest.cpp | 9 +++ src/common/variant.cpp | 123 ++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 2 deletions(-) diff --git a/docs/latex/wx/variant.tex b/docs/latex/wx/variant.tex index 919900f416..b3ff576d9b 100644 --- a/docs/latex/wx/variant.tex +++ b/docs/latex/wx/variant.tex @@ -80,12 +80,14 @@ Construction from a list of strings. This constructor copies {\it value}, the application is still responsible for deleting {\it value} and its contents. -%Note: this constructor is currently disabled because it causes a C++ ambiguity. - \func{}{wxVariant}{\param{void*}{ value}, \param{const wxString\& }{name = ``"}} Construction from a void pointer. +\func{}{wxVariant}{\param{wxObject*}{ value}, \param{const wxString\& }{name = ``"}} + +Construction from a wxObject pointer. + \func{}{wxVariant}{\param{wxVariantData*}{ data}, \param{const wxString\& }{name = ``"}} Construction from user-defined data. The variant holds on to the {\it data} pointer. @@ -176,6 +178,12 @@ If the variant is null, the value type returned is the string ``null" (not the e Gets the void pointer value. +\membersection{wxVariant::GetWxObjectPtr}\label{wxvariantgetwxobjectptr} + +\constfunc{void*}{GetWxObjectPtr}{\void} + +Gets the wxObject pointer value. + \membersection{wxVariant::Insert}\label{wxvariantinsert} \func{void}{Insert}{\param{const wxVariant\&}{ value}} @@ -194,6 +202,12 @@ Returns true if there is no data associated with this variant, false if there is Returns true if {\it type} matches the type of the variant, false otherwise. +\membersection{wxVariant::IsValueKindOf}\label{wxvariantisvaluekindof} + +\constfunc{bool}{IsValueKindOf}{\param{const wxClassInfo* type}{ type}} + +Returns true if the data is derived from the class described by {\it type}, false otherwise. + \membersection{wxVariant::MakeNull}\label{wxvariantmakenull} \func{void}{MakeNull}{\void} @@ -381,6 +395,13 @@ Returns true if this object is equal to {\it data}. Returns the string type of the data. +\membersection{wxVariantData::GetValueClassInfo}\label{wxvariantdatagetvalueclassinfo} + +\constfunc{wxClassInfo*}{GetValueClassInfo}{\void} + +If the data is a wxObject returns a pointer to the objects wxClassInfo structure, if +the data isn't a wxObject the method returns NULL. + \membersection{wxVariantData::Read}\label{wxvariantdataread} \func{bool}{Read}{\param{ostream\&}{ stream}} @@ -398,4 +419,16 @@ Reads the data from {\it stream} or {\it string}. Writes the data to {\it stream} or {\it string}. +\membersection{wxGetVariantCast}\label{wxgetvariantcast} + +\func{classname *}{wxGetVariantCast}{wxVariant\&, classname} + +This macro returns the data stored in {\it variant} cast to the type {\it classname *} if +the data is of this type (the check is done during the run-time) or +{\tt NULL} otherwise. + + +\wxheading{See also} +\helpref{RTTI overview}{runtimeclassoverview}\\ +\helpref{wxDynamicCast}{wxdynamiccast}\\ diff --git a/include/wx/variant.h b/include/wx/variant.h index e751dde6c1..7c1b224c80 100644 --- a/include/wx/variant.h +++ b/include/wx/variant.h @@ -67,6 +67,8 @@ public: virtual bool Read(wxString& str) = 0; // What type is it? Return a string name. virtual wxString GetType() const = 0; + // If it based on wxObject return the ClassInfo. + virtual wxClassInfo* GetValueClassInfo() { return NULL; } }; /* @@ -95,6 +97,7 @@ public: wxVariant(const wxStringList& val, const wxString& name = wxEmptyString); wxVariant(const wxList& val, const wxString& name = wxEmptyString); // List of variants wxVariant(void* ptr, const wxString& name = wxEmptyString); // void* (general purpose) + wxVariant(wxObject* ptr, const wxString& name = wxEmptyString); //wxObject wxVariant(wxVariantData* data, const wxString& name = wxEmptyString); // User-defined data //TODO: Need to document #if wxUSE_DATETIME @@ -181,6 +184,9 @@ public: inline operator long () const { return GetLong(); } inline operator bool () const { return GetBool(); } inline operator void* () const { return GetVoidPtr(); } + // No implicit conversion to wxObject, as that would really + // confuse people between conversion to our contained data + // and downcasting to see our base type. //TODO: Need to document #if wxUSE_DATETIME inline operator wxDateTime () const { return GetDateTime(); } @@ -203,6 +209,7 @@ public: wxString GetType() const; bool IsType(const wxString& type) const; + bool IsValueKindOf(const wxClassInfo* type) const; // Return the number of elements in a list int GetCount() const; @@ -219,6 +226,7 @@ public: wxStringList& GetStringList() const ; void* GetVoidPtr() const ; + wxObject* GetWxObjectPtr() ; //TODO: Need to document #if wxUSE_DATETIME wxDateTime GetDateTime() const ; @@ -268,6 +276,14 @@ protected: wxString m_name; }; +//Since we want type safety wxVariant we need to fetch and dynamic_cast +//in a seemingly safe way so the compiler can check, so we define +//a dynamic_cast /wxDynamicCast analogue. + +#define wxGetVariantCast(var,classname) \ + ((classname*)(var.IsValueKindOf(&classname::sm_class##classname) ?\ + var.GetWxObjectPtr() : NULL)); + extern wxVariant WXDLLEXPORT wxNullVariant; #endif diff --git a/samples/typetest/typetest.cpp b/samples/typetest/typetest.cpp index 4d8ab2866d..71507f11a1 100644 --- a/samples/typetest/typetest.cpp +++ b/samples/typetest/typetest.cpp @@ -1052,6 +1052,15 @@ void MyApp::DoVariantDemo(wxCommandEvent& WXUNUSED(event) ) { textCtrl << _T("var1[") << (int) i << _T("] (type ") << var1[i].GetType() << _T(") = ") << var1[i].MakeString() << _T("\n"); } + + var1 = wxVariant(new wxFont(wxSystemSettings::GetFont(wxSYS_OEM_FIXED_FONT))); + textCtrl << _T("var1 = (wxfont)\""); + wxFont* font = wxGetVariantCast(var1,wxFont); + if (font) { + textCtrl << font->GetNativeFontInfoDesc() << _T("\"\n"); + } else { + textCtrl << _T("(null)\"\n"); + } } BEGIN_EVENT_TABLE(MyFrame, wxFrame) diff --git a/src/common/variant.cpp b/src/common/variant.cpp index 7b2f9dd943..1d99a6f09a 100644 --- a/src/common/variant.cpp +++ b/src/common/variant.cpp @@ -905,6 +905,111 @@ bool wxVariantDataVoidPtr::Read(wxString& WXUNUSED(str)) return FALSE; } +/* + * wxVariantDataWxObjectPtr + */ + +class wxVariantDataWxObjectPtr: public wxVariantData +{ +DECLARE_DYNAMIC_CLASS(wxVariantDataWxObjectPtr) +public: + wxVariantDataWxObjectPtr() { } + wxVariantDataWxObjectPtr(wxObject* value) { m_value = value; } + + inline wxObject* GetValue() const { return m_value; } + inline void SetValue(wxObject* value) { m_value = value; } + + virtual void Copy(wxVariantData& data); + virtual bool Eq(wxVariantData& data) const; +#if wxUSE_STD_IOSTREAM + virtual bool Write(wxSTD ostream& str) const; +#endif + virtual bool Write(wxString& str) const; +#if wxUSE_STD_IOSTREAM + virtual bool Read(wxSTD istream& str); +#endif + virtual bool Read(wxString& str); + virtual wxString GetType() const ; + virtual wxVariantData* Clone() { return new wxVariantDataWxObjectPtr; } + + virtual wxClassInfo* GetValueClassInfo() ; +protected: + wxObject* m_value; + + DECLARE_NO_COPY_CLASS(wxVariantDataWxObjectPtr) +}; + +IMPLEMENT_DYNAMIC_CLASS(wxVariantDataWxObjectPtr, wxVariantData) + +void wxVariantDataWxObjectPtr::Copy(wxVariantData& data) +{ + wxASSERT_MSG( wxIsKindOf((&data), wxVariantDataWxObjectPtr) ,\ + wxT("wxVariantDataWxObjectPtr::Copy: Can't copy to this type of data") \ + ); + + wxVariantDataWxObjectPtr& otherData = (wxVariantDataWxObjectPtr&) data; + + otherData.m_value = m_value; +} + +bool wxVariantDataWxObjectPtr::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( wxIsKindOf((&data), wxVariantDataWxObjectPtr), wxT("wxVariantDataWxObjectPtr::Eq: argument mismatch") ); + + wxVariantDataWxObjectPtr& otherData = (wxVariantDataWxObjectPtr&) data; + + return (otherData.m_value == m_value); +} + +wxString wxVariantDataWxObjectPtr::GetType() const +{ + wxString returnVal(wxT("wxObject")); + if (m_value) { + returnVal = m_value->GetClassInfo()->GetClassName(); + } + return returnVal; +} + +wxClassInfo* wxVariantDataWxObjectPtr::GetValueClassInfo() +{ + wxClassInfo* returnVal=NULL; + + if (m_value) returnVal = m_value->GetClassInfo(); + + return returnVal; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataWxObjectPtr::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << (const char*) s.mb_str(); + return TRUE; +} +#endif + +bool wxVariantDataWxObjectPtr::Write(wxString& str) const +{ + str.Printf(wxT("%s(%ld)"), GetType().mb_str() ,(long) m_value); + return TRUE; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataWxObjectPtr::Read(wxSTD istream& WXUNUSED(str)) +{ + // Not implemented + return FALSE; +} +#endif + +bool wxVariantDataWxObjectPtr::Read(wxString& WXUNUSED(str)) +{ + // Not implemented + return FALSE; +} + + /* * wxVariantDataDateTime */ @@ -1173,6 +1278,12 @@ wxVariant::wxVariant( void* val, const wxString& name) m_name = name; } +wxVariant::wxVariant( wxObject* val, const wxString& name) +{ + m_data = new wxVariantDataWxObjectPtr(val); + m_name = name; +} + #if wxUSE_DATETIME wxVariant::wxVariant(const wxDateTime& val, const wxString& name) // Date { @@ -1697,6 +1808,12 @@ bool wxVariant::IsType(const wxString& type) const return (GetType() == type); } +bool wxVariant::IsValueKindOf(const wxClassInfo* type) const +{ + wxClassInfo* info=m_data->GetValueClassInfo(); + return info ? info->IsKindOf(type) : false ; +} + // Value accessors double wxVariant::GetReal() const @@ -1765,6 +1882,12 @@ void* wxVariant::GetVoidPtr() const return (void*) ((wxVariantDataVoidPtr*) m_data)->GetValue(); } +wxObject* wxVariant::GetWxObjectPtr() +{ + wxASSERT(wxIsKindOf(m_data, wxVariantDataWxObjectPtr)); + return (wxObject*) ((wxVariantDataWxObjectPtr*) m_data)->GetValue(); +} + #if wxUSE_DATETIME wxDateTime wxVariant::GetDateTime() const { -- 2.45.2