]> git.saurik.com Git - wxWidgets.git/blob - include/wx/weakref.h
Applied #15226 with modifications: wxRichTextCtrl: Implement setting properties with...
[wxWidgets.git] / include / wx / weakref.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/weakref.h
3 // Purpose: wxWeakRef - Generic weak references for wxWidgets
4 // Author: Arne Steinarson
5 // Created: 27 Dec 07
6 // Copyright: (c) 2007 Arne Steinarson
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifndef _WX_WEAKREF_H_
11 #define _WX_WEAKREF_H_
12
13 #include "wx/tracker.h"
14
15
16 // Some compilers (VC6, Borland, g++ < 3.3) have problem with template specialization.
17 // However, this is only used for optimization purposes (a smaller wxWeakRef pointer)
18 // (and the corner case of wxWeakRef<wxObject>). So for those compilers, we can fall
19 // back to the non-optimal case, where we use the same type of weak ref (static one)
20 // in all cases. See defs.h for various setting these defines depending on compiler.
21
22 #if !defined(HAVE_PARTIAL_SPECIALIZATION) || \
23 !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION) || \
24 (defined(__GNUC__) && !wxCHECK_GCC_VERSION(3, 3))
25 #define USE_ONLY_STATIC_WEAKREF
26 #endif
27
28
29 #ifndef USE_ONLY_STATIC_WEAKREF
30
31 // Avoid including this for simpler compilers
32 #include "wx/meta/convertible.h"
33 #include "wx/meta/int2type.h"
34
35 template <class T>
36 struct wxIsStaticTrackable
37 {
38 enum { value = wxConvertibleTo<T, wxTrackable>::value };
39 };
40
41 #endif // !USE_ONLY_STATIC_WEAKREF
42
43
44 // Weak ref implementation when T has wxTrackable as a known base class
45 template <class T>
46 class wxWeakRefStatic : public wxTrackerNode
47 {
48 public:
49 wxWeakRefStatic() : m_pobj(NULL) { }
50
51 void Release()
52 {
53 // Release old object if any
54 if ( m_pobj )
55 {
56 // Remove ourselves from object tracker list
57 wxTrackable *pt = static_cast<wxTrackable*>(m_pobj);
58 pt->RemoveNode(this);
59 m_pobj = NULL;
60 }
61 }
62
63 virtual void OnObjectDestroy()
64 {
65 // Tracked object itself removes us from list of trackers
66 wxASSERT(m_pobj != NULL);
67 m_pobj = NULL;
68 }
69
70 protected:
71 void Assign(T* pobj)
72 {
73 if ( m_pobj == pobj )
74 return;
75
76 Release();
77
78 // Now set new trackable object
79 if ( pobj )
80 {
81 // Add ourselves to object tracker list
82 wxTrackable *pt = static_cast<wxTrackable*>(pobj);
83 pt->AddNode(this);
84 m_pobj = pobj;
85 }
86 }
87
88 void AssignCopy(const wxWeakRefStatic& wr)
89 {
90 Assign( wr.m_pobj );
91 }
92
93 T *m_pobj;
94 };
95
96
97
98 #ifndef USE_ONLY_STATIC_WEAKREF
99
100 template<class T,bool use_static>
101 struct wxWeakRefImpl;
102
103 // Intermediate class, to select the static case above.
104 template <class T>
105 struct wxWeakRefImpl<T, true> : public wxWeakRefStatic<T>
106 {
107 enum { value = 1 };
108 };
109
110 // Weak ref implementation when T does not have wxTrackable as known base class
111 template<class T>
112 struct wxWeakRefImpl<T, false> : public wxTrackerNode
113 {
114 void Release()
115 {
116 // Release old object if any
117 if ( m_pobj )
118 {
119 // Remove ourselves from object tracker list
120 m_ptbase->RemoveNode(this);
121 m_pobj = NULL;
122 m_ptbase = NULL;
123 }
124 }
125
126 virtual void OnObjectDestroy()
127 {
128 // Tracked object itself removes us from list of trackers
129 wxASSERT(m_pobj != NULL);
130 m_pobj = NULL;
131 m_ptbase = NULL;
132 }
133
134 protected:
135 wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { }
136
137 // Assign receives most derived class here and can use that
138 template <class TDerived>
139 void Assign( TDerived* pobj )
140 {
141 AssignHelper( pobj, wxInt2Type<wxIsStaticTrackable<TDerived>::value>() );
142 }
143
144 template <class TDerived>
145 void AssignHelper(TDerived* pobj, wxInt2Type<true>)
146 {
147 wxTrackable *ptbase = static_cast<wxTrackable*>(pobj);
148 DoAssign( pobj, ptbase );
149 }
150
151 #ifndef wxNO_RTTI
152 void AssignHelper(T* pobj, wxInt2Type<false>)
153 {
154 // A last way to get a trackable pointer
155 wxTrackable *ptbase = dynamic_cast<wxTrackable*>(pobj);
156 if ( ptbase )
157 {
158 DoAssign( pobj, ptbase );
159 }
160 else
161 {
162 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
163
164 Release();
165 }
166 }
167 #endif // RTTI enabled
168
169 void AssignCopy(const wxWeakRefImpl& wr)
170 {
171 DoAssign(wr.m_pobj, wr.m_ptbase);
172 }
173
174 void DoAssign( T* pobj, wxTrackable *ptbase ) {
175 if( m_pobj==pobj ) return;
176 Release();
177
178 // Now set new trackable object
179 if( pobj )
180 {
181 // Add ourselves to object tracker list
182 wxASSERT( ptbase );
183 ptbase->AddNode( this );
184 m_pobj = pobj;
185 m_ptbase = ptbase;
186 }
187 }
188
189 T *m_pobj;
190 wxTrackable *m_ptbase;
191 };
192
193 #endif // #ifndef USE_ONLY_STATIC_WEAKREF
194
195
196
197 // A weak reference to an object of type T, where T has base wxTrackable
198 // (usually statically but if not dynamic_cast<> is tried).
199 template <class T>
200 class wxWeakRef : public
201 #ifdef USE_ONLY_STATIC_WEAKREF
202 wxWeakRefStatic<T>
203 #else
204 wxWeakRefImpl<T, wxIsStaticTrackable<T>::value != 0>
205 #endif
206 {
207 public:
208 typedef T element_type;
209
210 // Default ctor
211 wxWeakRef() { }
212
213 // Enabling this ctor for VC6 results in mysterious compilation failures in
214 // wx/window.h when assigning wxWindow pointers (FIXME-VC6)
215 #ifndef __VISUALC6__
216 // Ctor from the object of this type: this is needed as the template ctor
217 // below is not used by at least g++4 when a literal NULL is used
218 wxWeakRef(T *pobj)
219 {
220 this->Assign(pobj);
221 }
222 #endif // !__VISUALC6__
223
224 // When we have the full type here, static_cast<> will always work
225 // (or give a straight compiler error).
226 template <class TDerived>
227 wxWeakRef(TDerived* pobj)
228 {
229 this->Assign(pobj);
230 }
231
232 // We need this copy ctor, since otherwise a default compiler (binary) copy
233 // happens (if embedded as an object member).
234 wxWeakRef(const wxWeakRef<T>& wr)
235 {
236 this->Assign(wr.get());
237 }
238
239 wxWeakRef<T>& operator=(const wxWeakRef<T>& wr)
240 {
241 this->AssignCopy(wr);
242 return *this;
243 }
244
245 virtual ~wxWeakRef() { this->Release(); }
246
247 // Smart pointer functions
248 T& operator*() const { return *this->m_pobj; }
249 T* operator->() const { return this->m_pobj; }
250
251 T* get() const { return this->m_pobj; }
252 operator T*() const { return this->m_pobj; }
253 };
254
255
256 #ifndef wxNO_RTTI
257
258 // Weak ref implementation assign objects are queried for wxTrackable
259 // using dynamic_cast<>
260 template <class T>
261 class wxWeakRefDynamic : public wxTrackerNode
262 {
263 public:
264 wxWeakRefDynamic() : m_pobj(NULL) { }
265
266 wxWeakRefDynamic(T* pobj) : m_pobj(pobj)
267 {
268 Assign(pobj);
269 }
270
271 wxWeakRefDynamic(const wxWeakRef<T>& wr)
272 {
273 Assign(wr.get());
274 }
275
276 virtual ~wxWeakRefDynamic() { Release(); }
277
278 // Smart pointer functions
279 T& operator*() const { wxASSERT(m_pobj); return *m_pobj; }
280 T* operator->() const { wxASSERT(m_pobj); return m_pobj; }
281
282 T* get() const { return m_pobj; }
283 operator T* () const { return m_pobj; }
284
285 T* operator = (T* pobj) { Assign(pobj); return m_pobj; }
286
287 // Assign from another weak ref, point to same object
288 T* operator = (const wxWeakRef<T> &wr) { Assign( wr.get() ); return m_pobj; }
289
290 void Release()
291 {
292 // Release old object if any
293 if( m_pobj )
294 {
295 // Remove ourselves from object tracker list
296 wxTrackable *pt = dynamic_cast<wxTrackable*>(m_pobj);
297 wxASSERT(pt);
298 pt->RemoveNode(this);
299 m_pobj = NULL;
300 }
301 }
302
303 virtual void OnObjectDestroy()
304 {
305 wxASSERT_MSG(m_pobj, "tracked object should have removed us itself");
306
307 m_pobj = NULL;
308 }
309
310 protected:
311 void Assign(T *pobj)
312 {
313 if ( m_pobj == pobj )
314 return;
315
316 Release();
317
318 // Now set new trackable object
319 if ( pobj )
320 {
321 // Add ourselves to object tracker list
322 wxTrackable *pt = dynamic_cast<wxTrackable*>(pobj);
323 if ( pt )
324 {
325 pt->AddNode(this);
326 m_pobj = pobj;
327 }
328 else
329 {
330 // If the object we want to track does not support wxTackable, then
331 // log a message and keep the NULL object pointer.
332 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
333 }
334 }
335 }
336
337 T *m_pobj;
338 };
339
340 #endif // RTTI enabled
341
342
343 // Provide some basic types of weak references
344 class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
345 class WXDLLIMPEXP_FWD_CORE wxWindow;
346
347
348 typedef wxWeakRef<wxEvtHandler> wxEvtHandlerRef;
349 typedef wxWeakRef<wxWindow> wxWindowRef;
350
351 #endif // _WX_WEAKREF_H_
352