]> git.saurik.com Git - wxWidgets.git/blame - include/wx/weakref.h
extracted wxWrapSizer in separate files and somewhat improved it (heavily modified...
[wxWidgets.git] / include / wx / weakref.h
CommitLineData
db7035e4
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/weakref.h
3// Purpose: wxWeakRef - Generic weak references for wxWidgets
4// Author: Arne Steinarson
cc6ceca7 5// Created: 27 Dec 07
9dd5ff5b 6// RCS-ID: $Id$
db7035e4
VZ
7// Copyright: (c) 2007 Arne Steinarson
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifndef _WX_WEAKREF_H_
12#define _WX_WEAKREF_H_
13
cc6ceca7 14#include "wx/tracker.h"
db7035e4 15
cc6ceca7
VZ
16#include "wx/meta/convertible.h"
17#include "wx/meta/int2type.h"
18
19template <class T>
20struct wxIsStaticTrackable
21{
22 enum { value = wxConvertibleTo<T, wxTrackable>::value };
23};
24
25// Weak ref implementation when T has wxTrackable as a known base class
26template <class T>
27class wxWeakRefStatic : public wxTrackerNode
28{
29public:
30 wxWeakRefStatic() : m_pobj(NULL) { }
31
32 void Release()
33 {
34 // Release old object if any
35 if ( m_pobj )
36 {
37 // Remove ourselves from object tracker list
38 wxTrackable *pt = static_cast<wxTrackable*>(m_pobj);
39 pt->RemoveNode(this);
40 m_pobj = NULL;
41 }
42 }
43
44protected:
45 void Assign(T* pobj)
46 {
47 if ( m_pobj == pobj )
48 return;
49
50 Release();
51
52 // Now set new trackable object
53 if ( pobj )
54 {
55 // Add ourselves to object tracker list
56 wxTrackable *pt = static_cast<wxTrackable*>(pobj);
57 pt->AddNode(this);
58 m_pobj = pobj;
59 }
60 }
61
42d9ad79 62 void AssignCopy(const wxWeakRefStatic& wr)
cc6ceca7
VZ
63 {
64 Assign( wr.m_pobj );
65 }
66
67 virtual void OnObjectDestroy()
68 {
69 // Tracked object itself removes us from list of trackers
70 wxASSERT( m_pobj!=NULL );
71 m_pobj = NULL;
72 }
73
74 T *m_pobj;
75};
76
cc6ceca7 77
7005cf44
VZ
78#if !defined(HAVE_PARTIAL_SPECIALIZATION) || !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION)
79 #define USE_STATIC_WEAKREF
80#endif
81
82
83#ifndef USE_STATIC_WEAKREF
cc6ceca7
VZ
84template<class T,bool use_static>
85struct wxWeakRefImpl;
86
87// Intermediate class, to select the static case above.
88template <class T>
89struct wxWeakRefImpl<T, true> : public wxWeakRefStatic<T>
90{
91 enum { value = 1 };
92};
93
94// Weak ref implementation when T does not have wxTrackable as known base class
db7035e4 95template<class T>
cc6ceca7
VZ
96struct wxWeakRefImpl<T, false> : public wxTrackerNode
97{
98 void Release()
99 {
100 // Release old object if any
101 if ( m_pobj )
102 {
103 // Remove ourselves from object tracker list
104 m_ptbase->RemoveNode(this);
105 m_pobj = NULL;
106 m_ptbase = NULL;
107 }
108 }
109
110protected:
111 wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { }
112
113 // Assign receives most derived class here and can use that
114 template <class TDerived>
115 void Assign( TDerived* pobj )
116 {
117 AssignHelper( pobj, wxInt2Type<wxIsStaticTrackable<TDerived>::value>() );
118 }
119
120 template <class TDerived>
121 void AssignHelper(TDerived* pobj, wxInt2Type<true>)
122 {
123 wxTrackable *ptbase = static_cast<wxTrackable*>(pobj);
124 DoAssign( pobj, ptbase );
125 }
126
127#ifdef HAVE_DYNAMIC_CAST
128 void AssignHelper(T* pobj, wxInt2Type<false>)
129 {
130 // A last way to get a trackable pointer
131 wxTrackable *ptbase = dynamic_cast<wxTrackable*>(pobj);
132 if ( ptbase )
133 {
134 DoAssign( pobj, ptbase );
135 }
136 else
137 {
138 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
139
140 Release();
141 }
142 }
143#endif // HAVE_DYNAMIC_CAST
144
145 void AssignCopy(const wxWeakRefImpl& wr)
146 {
42d9ad79 147 DoAssign(wr.m_pobj, wr.m_ptbase);
cc6ceca7
VZ
148 }
149
150 void DoAssign( T* pobj, wxTrackable *ptbase ) {
151 if( m_pobj==pobj ) return;
152 Release();
153
154 // Now set new trackable object
155 if( pobj )
156 {
157 // Add ourselves to object tracker list
158 wxASSERT( ptbase );
159 ptbase->AddNode( this );
160 m_pobj = pobj;
161 m_ptbase = ptbase;
162 }
163 }
164
165 virtual void OnObjectDestroy()
166 {
167 // Tracked object itself removes us from list of trackers
168 wxASSERT( m_pobj!=NULL );
169 m_pobj = NULL;
170 m_ptbase = NULL;
171 }
172
173 T *m_pobj;
174 wxTrackable *m_ptbase;
175};
176
7005cf44
VZ
177#endif // #ifndef USE_STATIC_WEAKREF
178
cc6ceca7
VZ
179
180
181// A weak reference to an object of type T, where T has type wxTrackable
182// (usually statically but if not dynamic_cast<> is tried).
183template <class T>
184class wxWeakRef : public
7005cf44 185#ifdef USE_STATIC_WEAKREF
cc6ceca7 186 wxWeakRefStatic<T>
7005cf44
VZ
187#else
188 wxWeakRefImpl<T, wxIsStaticTrackable<T>::value>
cc6ceca7 189#endif
db7035e4
VZ
190{
191public:
cc6ceca7
VZ
192 // Default ctor
193 wxWeakRef() { }
194
195 // When we have the full type here, static_cast<> will always work
196 // (or give a straight compiler error).
197 template <class TDerived>
198 wxWeakRef(TDerived* pobj)
199 {
200 Assign(pobj);
201 }
202
6dd21c54
RR
203 // We need this copy ctor, since otherwise a default compiler (binary) copy happens
204 wxWeakRef(const wxWeakRef<T>& wr)
205 {
206 Assign(wr.get());
207 }
208
cc6ceca7
VZ
209 template <class TDerived>
210 wxWeakRef<T>& operator=(TDerived* pobj)
211 {
212 Assign(pobj);
213 return *this;
214 }
215
216 wxWeakRef<T>& operator=(const wxWeakRef<T>& wr)
217 {
218 AssignCopy(wr);
219 return *this;
220 }
db7035e4 221
34bfda8a 222 virtual ~wxWeakRef() { this->Release(); }
cc6ceca7
VZ
223
224 // Smart pointer functions
34bfda8a
VZ
225 T& operator*() const { return *this->m_pobj; }
226 T* operator->() const { return this->m_pobj; }
cc6ceca7 227
34bfda8a
VZ
228 T* get() const { return this->m_pobj; }
229 operator T*() const { return get(); }
cc6ceca7
VZ
230};
231
232
233// Weak ref implementation assign objects are queried for wxTrackable
234// using dynamic_cast<>
42d9ad79 235template <class T>
cc6ceca7
VZ
236class wxWeakRefDynamic : public wxTrackerNode
237{
238public:
239 wxWeakRefDynamic() : m_pobj(NULL) { }
1e9192d0 240
cc6ceca7 241 wxWeakRefDynamic(T* pobj) : m_pobj(pobj)
db7035e4
VZ
242 {
243 Assign(pobj);
db7035e4
VZ
244 }
245
cc6ceca7
VZ
246 virtual ~wxWeakRefDynamic() { Release(); }
247
248 // Smart pointer functions
249 T& operator * (){ wxASSERT(this->m_pobj); return *m_pobj; }
250 T* operator -> (){ wxASSERT(this->m_pobj); return m_pobj; }
251 T* operator = (T* pobj) { Assign(pobj); return m_pobj; }
252
253 T* get(){ return this->m_pobj; }
254
255 // operator T* (){ return this->m_pobj; }
256
257 // test for pointer validity: defining conversion to unspecified_bool_type
258 // and not more obvious bool to avoid implicit conversions to integer types
259 typedef T *(wxWeakRef<T>::*unspecified_bool_type)() const;
260 operator unspecified_bool_type() const
db7035e4 261 {
cc6ceca7 262 return m_pobj ? &wxWeakRef<T>::get : NULL;
db7035e4
VZ
263 }
264
cc6ceca7
VZ
265 // Assign from another weak ref, point to same object
266 T* operator = (const wxWeakRef<T> &wr) { Assign( wr.get() ); return this->m_pobj; }
db7035e4 267
cc6ceca7 268 void Release()
db7035e4 269 {
cc6ceca7
VZ
270 // Release old object if any
271 if( m_pobj )
db7035e4
VZ
272 {
273 // Remove ourselves from object tracker list
cc6ceca7 274 wxTrackable *pt = dynamic_cast<wxTrackable*>(m_pobj);
9dd5ff5b
RR
275 wxASSERT(pt);
276 pt->RemoveNode(this);
db7035e4
VZ
277 m_pobj = NULL;
278 }
cc6ceca7
VZ
279 }
280
281protected:
282 void Assign(T *pobj)
283 {
284 if ( m_pobj == pobj )
285 return;
286
287 Release();
db7035e4
VZ
288
289 // Now set new trackable object
290 if ( pobj )
291 {
cc6ceca7
VZ
292 // Add ourselves to object tracker list
293 wxTrackable *pt = dynamic_cast<wxTrackable*>(pobj);
294 if ( pt )
9dd5ff5b 295 {
cc6ceca7 296 pt->AddNode(this);
9dd5ff5b
RR
297 m_pobj = pobj;
298 }
299 else
300 {
cc6ceca7
VZ
301 // If the object we want to track does not support wxTackable, then
302 // log a message and keep the NULL object pointer.
303 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
9dd5ff5b 304 }
db7035e4
VZ
305 }
306 }
307
cc6ceca7
VZ
308 virtual void OnObjectDestroy()
309 {
310 wxASSERT_MSG( m_pobj, "tracked object should have removed us itself" );
311
312 m_pobj = NULL;
313 }
314
db7035e4
VZ
315 T *m_pobj;
316};
317
318// Provide some basic types of weak references
db7035e4 319class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
5a0c7d66 320class WXDLLIMPEXP_FWD_CORE wxWindow;
db7035e4 321
db7035e4
VZ
322typedef wxWeakRef<wxEvtHandler> wxEvtHandlerRef;
323typedef wxWeakRef<wxWindow> wxWindowRef;
324
325#endif // _WX_WEAKREF_H_
326