From 9dd5ff5baafda3cd6c427047b92886933bdec6a5 Mon Sep 17 00:00:00 2001
From: Robert Roebling <robert@roebling.de>
Date: Tue, 8 Jan 2008 09:55:21 +0000
Subject: [PATCH] Updated wxWeakRef<T> to patch Weak references for wx - part
 2, removed T*() and added T* get(), other minor docs corr

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51100 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/scopedptr.tex |   8 +--
 docs/latex/wx/sharedptr.tex |  12 ++++-
 docs/latex/wx/weakref.tex   | 103 ++++++++++++++++++++++++++++--------
 include/wx/weakref.h        |  65 ++++++++++++++++-------
 4 files changed, 142 insertions(+), 46 deletions(-)

diff --git a/docs/latex/wx/scopedptr.tex b/docs/latex/wx/scopedptr.tex
index 1da69e6dfe..952c0d451f 100644
--- a/docs/latex/wx/scopedptr.tex
+++ b/docs/latex/wx/scopedptr.tex
@@ -40,12 +40,12 @@ Destructor.
 
 Returns pointer to object or NULL.
 
-\membersection{wxScopedPtr<T>::operator*}\label{wxscopedptrtemplateoperatorptrt}
+\membersection{wxScopedPtr<T>::operator*}\label{wxscopedptrtemplateoperatorreft}
 
 \constfunc{T \&}{operator*}{\void}
 
-Returns pointer to object. If the pointer is NULL this method will 
-cause an assert in debug mode.
+Returns a reference to the object. If the internal pointer is NULL
+this method will cause an assert in debug mode.
 
 \membersection{wxScopedPtr<T>::operator->}\label{wxscopedptrtemplateoperatorderef}
 
@@ -58,7 +58,7 @@ cause an assert in debug mode.
 
 \func{T*}{release}{\void}
 
-Returns pointer to object or NULL.
+Releases the current pointer and returns NULL.
 
 \membersection{wxScopedPtr<T>::reset}\label{wxscopedptrtemplatereset}
 
diff --git a/docs/latex/wx/sharedptr.tex b/docs/latex/wx/sharedptr.tex
index 31f4ae9a5c..fb6b9d84bd 100644
--- a/docs/latex/wx/sharedptr.tex
+++ b/docs/latex/wx/sharedptr.tex
@@ -41,11 +41,12 @@ Destructor.
 
 Returns pointer to its object or NULL.
 
-\membersection{wxSharedPtr<T>::operator*}\label{wxsharedptroperatorptrt}
+\membersection{wxSharedPtr<T>::operator*}\label{wxsharedptroperatorreft}
 
 \constfunc{T\&}{operator*}{\void}
 
-Returns pointer to its object or NULL.
+Returns a reference to the object. If the internal pointer is NULL this
+method will cause an assert in debug mode.
 
 \membersection{wxSharedPtr<T>::operator->}\label{wxsharedptroperatorderef}
 
@@ -71,3 +72,10 @@ Returns true if this is the only pointer pointing to its object.
 
 Returns the number of pointers pointing to its object.
 
+\membersection{wxSharedPtr<T>::reset}\label{wxsharedptrreset}
+
+\func{void}{reset}{\param{T * }{ptr = NULL}}
+
+Reset pointer to {\it ptr}. Afterwards the caller is responsible
+for deleting the data contained in the pointer before.
+
diff --git a/docs/latex/wx/weakref.tex b/docs/latex/wx/weakref.tex
index bda7029a8c..35e965c334 100644
--- a/docs/latex/wx/weakref.tex
+++ b/docs/latex/wx/weakref.tex
@@ -1,18 +1,66 @@
 \section{\class{wxWeakRef<T>}}\label{wxweakref}
 
-A weak reference to an object of type T, where T has type 
-\helpref{wxTrackableBase}{wxtrackablebase} as one of its
-base classes  (in a static or dynamic sense).
+{\bf wxWeakRef} is a template class for weak references to wxWidgets objects, 
+such as {\bf wxEvtHandler}, {\bf wxWindow} and {\bf wxObject}. A weak 
+reference behaves much like an ordinary pointer, but when the object pointed 
+to goes out of scope (is destroyed), the weak reference is automatically 
+reset to a NULL pointer. 
+
+wxWeakref<T> can be used whenever one must keep a pointer to an object 
+that does not directly own, and that may be destroyed before the object 
+holding the reference. 
+
+wxWeakref<T> is a small object and the mechanism behind it is fast 
+({\bf O(1)}). So the overall cost of using it is small. 
+
+
+\wxheading{Example}
+
+\begin{verbatim}
+    wxWindow *parent = /* Get parent window from somewhere */;
+    wxWindow *wnd = new wxWindow( parent, wxID_ANY, "wxWindow" );
+    wxWeakRef<wxWindow> wr = wnd;  
+    wxWindowRef wr2 = wnd;        // Same as above, but using a typedef
+    // Do things with window
+    wnd->Show( true );
+    // Weak ref is used like an ordinary pointer 
+    wr->Show( false );
+    wnd->Destroy(); 
+    // Now the weak ref has been reset, so we don't risk accessing
+    // a dangling pointer:
+    wxASSERT( wr==NULL );
+\end{verbatim}
+
+wxWeakref<T> works for any objects that are derived from {\bf wxTrackableBase} 
+or {\bf wxTrackable}. By default, wxEvtHandler and wxWindow derive from 
+wxTrackableBase. However, wxObject does not, so types like {\bf wxFont} and 
+{\bf wxColour} are not trackable. The example below shows how to create a 
+wxObject derived class that is trackable: 
 
 \begin{verbatim}
-class MyClass: public Foo, public TrackableBase
-{
-   // whatever
-}
+    class wxMyTrackableObject : public wxObject, public wxTrackable { 
+        // ... other members here 
+    }; 
+\end{verbatim}
+
+{\bf Note:} Custom trackable objects should derive from wxTrackable 
+if one wants to reference them from a {\bf wxWeakRef<wxObject>}. The 
+difference between the two base classes is that wxTrackableBase 
+has no virtual member functions (no VTable), and thus cannot be detected
+through {\bf dynamic_cast<>}.
+
+
+\wxheading{Predefined types}
 
-typedef wxWeakRef<MyClass> MyClassRef;
+The following types of weak references are predefined: 
+
+\begin{verbatim}
+typedef wxWeakRef<wxObject>      wxObjectRef;
+typedef wxWeakRef<wxEvtHandler>  wxEvtHandlerRef;
+typedef wxWeakRef<wxWindow>      wxWindowRef;
 \end{verbatim}
 
+
 \wxheading{Derived from}
 
 wxTrackerNode
@@ -30,7 +78,8 @@ wxTrackerNode
 
 \func{}{wxWeakRef<T>}{\param{T* }{pobj = NULL}}
 
-Constructor.
+Constructor. The weak reference is initialized to {\it pobj}.
+
 
 \membersection{wxWeakRef<T>::\destruct{wxWeakRef<T>}}\label{wxweakrefdtor}
 
@@ -38,36 +87,46 @@ Constructor.
 
 Destructor.
 
-\membersection{wxWeakRef<T>::T*}\label{wxweakreft}
 
-\func{operator}{T*}{\void}
+\membersection{wxWeakRef<T>::get}\label{wxweakrefget}
+
+\constfunc{T *}{get}{\void}
+
+Returns pointer to the tracked object or NULL.
+
+
+\membersection{wxWeakRef<T>::operator*}\label{wxweakrefoperatorreft}
+
+\constfunc{T \&}{operator*}{\void}
+
+Returns a reference to the tracked object. If the internal pointer is NULL
+this method will cause an assert in debug mode.
 
-Returns pointer to tracked object or NULL.
 
 \membersection{wxWeakRef<T>::operator->}\label{wxweakrefoperatorderef}
 
 \func{T*}{operator->}{\void}
 
-Returns pointer to tracked object or NULL.
+Smart pointer member access. Returns a pointer to the
+tracked object. If the internal pointer is NULL this
+method will cause an assert in debug mode.
+
 
 \membersection{wxWeakRef<T>::operator=}\label{wxweakrefoperatorassign}
 
 \func{T* operator}{operator=}{\param{T* }{pobj}}
 
-Assigns pointer to trackable object to this weak reference.
-
-\membersection{wxWeakRef<T>::Assign}\label{wxweakrefassign}
+Releases the currently tracked object and starts tracking {\it pobj}.
+A weak reference may be reset by passing {\it NULL} as {\it pobj}.
 
-\func{void}{Assign}{\param{T* }{pobj}}
 
-This uses static\_cast if possible or dynamic\_cast otherwise.
+\membersection{wxWeakRef<T>::operator =}\label{wxweakrefoperatorassign2}
 
-\membersection{wxWeakRef<T>::GetTrackable}\label{wxweakrefgettrackable}
+\func{T* operator}{operator =}{\param{wxWeakRef<T>\& }{wr}}
 
-\func{wxTrackableBase*}{GetTrackable}{\param{T* }{pobj}}
+Release currently tracked object and start tracking the same object as
+the wxWeakRef {\it wr}.
 
-Returns the trackable objects to which the weak reference
-points or NULL if it has been destroyed.
 
 \membersection{wxWeakRef<T>::OnObjectDestroy}\label{wxweakrefonobjectdestroy}
 
diff --git a/include/wx/weakref.h b/include/wx/weakref.h
index 7d8ac8c5b9..a893ba4049 100644
--- a/include/wx/weakref.h
+++ b/include/wx/weakref.h
@@ -3,7 +3,7 @@
 // Purpose:     wxWeakRef - Generic weak references for wxWidgets
 // Author:      Arne Steinarson
 // Created:     2007-12-27
-// RCS-ID:      $Id:$
+// RCS-ID:      $Id$
 // Copyright:   (c) 2007 Arne Steinarson
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
@@ -19,19 +19,42 @@ template<class T>
 class wxWeakRef : public wxTrackerNode
 {
 public:
+    typedef T element_type;
+    
     wxWeakRef(T *pobj = NULL) : m_pobj(NULL) { Assign(pobj); }
 
     virtual ~wxWeakRef() { Assign(NULL); }
 
-    // Smart pointer functions
-    operator T*(){ return m_pobj; }
-    T* operator->(){ return m_pobj; }
+    T * get() const                 
+    {                               
+        return m_pobj;
+    }                               
+    
+    T* operator->()
+    { 
+        wxASSERT(m_pobj != NULL);    
+        return m_pobj; 
+    }
+    
+    T& operator*() const           
+    {                               
+        wxASSERT(m_pobj != NULL);    
+        return *m_pobj;              
+    }                               
+                                    
     T* operator=(T *pobj)
     {
         Assign(pobj);
         return m_pobj;
     }
 
+    // Assign from another weak ref, point to same object
+    T* operator = (const wxWeakRef<T> &wr)
+    { 
+        Assign(wr); 
+        return m_pobj; 
+    }
+    
     virtual void OnObjectDestroy()
     {
         // Tracked object itself removes us from list of trackers
@@ -39,16 +62,12 @@ public:
         m_pobj = NULL;
     }
 
-    virtual wxTrackerNodeType GetType() { return WeakRef; }
-
 protected:
-    wxTrackableBase *GetTrackable(T *pobj)
-    {
-        // this uses static_cast if possible or dynamic_cast otherwise
-        return wxTrackableCaster<T, wxHasBase<T, wxTrackableBase>::value>
-                ::Cast(pobj);
-    }
+    friend class wxTrackableBase; 
+    friend class wxEvtHandler;
 
+    virtual wxTrackerNodeType GetType() { return WeakRef; }
+    
     void Assign(T* pobj)
     {
         if ( m_pobj == pobj )
@@ -58,18 +77,28 @@ protected:
         if ( m_pobj )
         {
             // Remove ourselves from object tracker list
-            GetTrackable(m_pobj)->RemoveNode(this);
+            // This does static_cast if available, otherwise it tries dynamic cast
+            wxTrackableBase *pt = wxTrackableCaster<T,wxHasBase<T,wxTrackableBase>::value >::Cast(m_pobj);
+            wxASSERT(pt);
+            pt->RemoveNode(this);
             m_pobj = NULL;
         }
 
         // Now set new trackable object
         if ( pobj )
         {
-            wxTrackableBase * const pt = GetTrackable(pobj);
-            wxCHECK_RET( pt, "type must derive from wxTrackableBase" );
-
-            pt->AddNode(this);
-            m_pobj = pobj;
+            wxTrackableBase *pt = wxTrackableCaster<T,wxHasBase<T,wxTrackableBase>::value >::Cast(pobj);
+            if( pt )
+            {
+                pt->AddNode( this );
+                m_pobj = pobj;
+            }
+            else
+            {
+                // If the tracked we want to track does not support wxTackableBase, then 
+                // log a message and keep the NULL object pointer. 
+                wxLogWarning( _T("wxWeakRef::Assign - Type does not provide wxTrackableBase - resetting tracked object") );
+            }
         }
     }
 
-- 
2.47.2

