From cf6ae2907c365869b10b61cbe3bde2768facd4d8 Mon Sep 17 00:00:00 2001
From: Roger Gammans <rgammans@computer-surgery.co.uk>
Date: Mon, 2 Jun 2003 21:17:28 +0000
Subject: [PATCH] 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.50.0

