merging back XTI branch part 2
[wxWidgets.git] / include / wx / object.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/object.h
3 // Purpose: wxObject class, plus run-time type information macros
4 // Author: Julian Smart
5 // Modified by: Ron Lee
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2001 Ron Lee <ron@debian.org>
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifndef _WX_OBJECTH__
14 #define _WX_OBJECTH__
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/memory.h"
21
22 // based on the value of wxUSE_EXTENDED_RTTI symbol,
23 // only one of the RTTI system will be compiled:
24 // - the "old" one (defined by rtti.h) or
25 // - the "new" one (defined by xti.h)
26 #include "wx/xti.h"
27 #include "wx/rtti.h"
28
29 // -----------------------------------
30 // for pluggable classes
31 // -----------------------------------
32
33 // NOTE: this should probably be the very first statement
34 // in the class declaration so wxPluginSentinel is
35 // the first member initialised and the last destroyed.
36
37 // _DECLARE_DL_SENTINEL(name) wxPluginSentinel m_pluginsentinel;
38
39 #if wxUSE_NESTED_CLASSES
40
41 #define _DECLARE_DL_SENTINEL(name, exportdecl) \
42 class exportdecl name##PluginSentinel { \
43 private: \
44 static const wxString sm_className; \
45 public: \
46 name##PluginSentinel(); \
47 ~name##PluginSentinel(); \
48 }; \
49 name##PluginSentinel m_pluginsentinel
50
51 #define _IMPLEMENT_DL_SENTINEL(name) \
52 const wxString name::name##PluginSentinel::sm_className(#name); \
53 name::name##PluginSentinel::name##PluginSentinel() { \
54 wxPluginLibrary *e = (wxPluginLibrary*) wxPluginLibrary::ms_classes.Get(#name); \
55 if( e != 0 ) { e->RefObj(); } \
56 } \
57 name::name##PluginSentinel::~name##PluginSentinel() { \
58 wxPluginLibrary *e = (wxPluginLibrary*) wxPluginLibrary::ms_classes.Get(#name); \
59 if( e != 0 ) { e->UnrefObj(); } \
60 }
61 #else
62
63 #define _DECLARE_DL_SENTINEL(name)
64 #define _IMPLEMENT_DL_SENTINEL(name)
65
66 #endif // wxUSE_NESTED_CLASSES
67
68 #define wxDECLARE_PLUGGABLE_CLASS(name) \
69 wxDECLARE_DYNAMIC_CLASS(name); _DECLARE_DL_SENTINEL(name, WXDLLIMPEXP_CORE)
70 #define wxDECLARE_ABSTRACT_PLUGGABLE_CLASS(name) \
71 wxDECLARE_ABSTRACT_CLASS(name); _DECLARE_DL_SENTINEL(name, WXDLLIMPEXP_CORE)
72
73 #define wxDECLARE_USER_EXPORTED_PLUGGABLE_CLASS(name, usergoo) \
74 wxDECLARE_DYNAMIC_CLASS(name); _DECLARE_DL_SENTINEL(name, usergoo)
75 #define wxDECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(name, usergoo) \
76 wxDECLARE_ABSTRACT_CLASS(name); _DECLARE_DL_SENTINEL(name, usergoo)
77
78 #define wxIMPLEMENT_PLUGGABLE_CLASS(name, basename) \
79 wxIMPLEMENT_DYNAMIC_CLASS(name, basename) _IMPLEMENT_DL_SENTINEL(name)
80 #define wxIMPLEMENT_PLUGGABLE_CLASS2(name, basename1, basename2) \
81 wxIMPLEMENT_DYNAMIC_CLASS2(name, basename1, basename2) _IMPLEMENT_DL_SENTINEL(name)
82 #define wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(name, basename) \
83 wxIMPLEMENT_ABSTRACT_CLASS(name, basename) _IMPLEMENT_DL_SENTINEL(name)
84 #define wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) \
85 wxIMPLEMENT_ABSTRACT_CLASS2(name, basename1, basename2) _IMPLEMENT_DL_SENTINEL(name)
86
87 #define wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(name, basename) \
88 wxIMPLEMENT_PLUGGABLE_CLASS(name, basename)
89 #define wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(name, basename1, basename2) \
90 wxIMPLEMENT_PLUGGABLE_CLASS2(name, basename1, basename2)
91 #define wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(name, basename) \
92 wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(name, basename)
93 #define wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2) \
94 wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(name, basename1, basename2)
95
96 #define wxCLASSINFO(name) (&name::ms_classInfo)
97
98 #define wxIS_KIND_OF(obj, className) obj->IsKindOf(&className::ms_classInfo)
99
100 // Just seems a bit nicer-looking (pretend it's not a macro)
101 #define wxIsKindOf(obj, className) obj->IsKindOf(&className::ms_classInfo)
102
103 // this cast does some more checks at compile time as it uses static_cast
104 // internally
105 //
106 // note that it still has different semantics from dynamic_cast<> and so can't
107 // be replaced by it as long as there are any compilers not supporting it
108 #define wxDynamicCast(obj, className) \
109 ((className *) wxCheckDynamicCast( \
110 const_cast<wxObject *>(static_cast<const wxObject *>(\
111 const_cast<className *>(static_cast<const className *>(obj)))), \
112 &className::ms_classInfo))
113
114 // The 'this' pointer is always true, so use this version
115 // to cast the this pointer and avoid compiler warnings.
116 #define wxDynamicCastThis(className) \
117 (IsKindOf(&className::ms_classInfo) ? (className *)(this) : (className *)0)
118
119 // FIXME-VC6: dummy argument needed because VC6 doesn't support explicitly
120 // choosing the template function to call
121 template <class T>
122 inline T *wxCheckCast(const void *ptr, T * = NULL)
123 {
124 wxASSERT_MSG( wxDynamicCast(ptr, T), "wxStaticCast() used incorrectly" );
125 return const_cast<T *>(static_cast<const T *>(ptr));
126 }
127
128 #define wxStaticCast(obj, className) wxCheckCast((obj), (className *)NULL)
129
130 // ----------------------------------------------------------------------------
131 // set up memory debugging macros
132 // ----------------------------------------------------------------------------
133
134 /*
135 Which new/delete operator variants do we want?
136
137 _WX_WANT_NEW_SIZET_WXCHAR_INT = void *operator new (size_t size, wxChar *fileName = 0, int lineNum = 0)
138 _WX_WANT_DELETE_VOID = void operator delete (void * buf)
139 _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET = void operator delete (void *buf, const char *_fname, size_t _line)
140 _WX_WANT_DELETE_VOID_WXCHAR_INT = void operator delete(void *buf, wxChar*, int)
141 _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT = void *operator new[] (size_t size, wxChar *fileName , int lineNum = 0)
142 _WX_WANT_ARRAY_DELETE_VOID = void operator delete[] (void *buf)
143 _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT = void operator delete[] (void* buf, wxChar*, int )
144 */
145
146 #if wxUSE_MEMORY_TRACING
147
148 // All compilers get this one
149 #define _WX_WANT_NEW_SIZET_WXCHAR_INT
150
151 // Everyone except Visage gets the next one
152 #ifndef __VISAGECPP__
153 #define _WX_WANT_DELETE_VOID
154 #endif
155
156 // Only visage gets this one under the correct circumstances
157 #if defined(__VISAGECPP__) && __DEBUG_ALLOC__
158 #define _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET
159 #endif
160
161 // Only VC++ 6 and CodeWarrior get overloaded delete that matches new
162 #if (defined(__VISUALC__) && (__VISUALC__ >= 1200)) || \
163 (defined(__MWERKS__) && (__MWERKS__ >= 0x2400))
164 #define _WX_WANT_DELETE_VOID_WXCHAR_INT
165 #endif
166
167 // Now see who (if anyone) gets the array memory operators
168 #if wxUSE_ARRAY_MEMORY_OPERATORS
169
170 // Everyone except Visual C++ (cause problems for VC++ - crashes)
171 #if !defined(__VISUALC__)
172 #define _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT
173 #endif
174
175 // Everyone except Visual C++ (cause problems for VC++ - crashes)
176 #if !defined(__VISUALC__)
177 #define _WX_WANT_ARRAY_DELETE_VOID
178 #endif
179
180 // Only CodeWarrior 6 or higher
181 #if defined(__MWERKS__) && (__MWERKS__ >= 0x2400)
182 #define _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT
183 #endif
184
185 #endif // wxUSE_ARRAY_MEMORY_OPERATORS
186
187 #endif // wxUSE_MEMORY_TRACING
188
189 // ----------------------------------------------------------------------------
190 // wxRefCounter: ref counted data "manager"
191 // ----------------------------------------------------------------------------
192
193 class WXDLLIMPEXP_BASE wxRefCounter
194 {
195 public:
196 wxRefCounter() { m_count = 1; }
197
198 int GetRefCount() const { return m_count; }
199
200 void IncRef() { m_count++; }
201 void DecRef();
202
203 protected:
204 // this object should never be destroyed directly but only as a
205 // result of a DecRef() call:
206 virtual ~wxRefCounter() { }
207
208 private:
209 // our refcount:
210 int m_count;
211
212 // It doesn't make sense to copy the reference counted objects, a new ref
213 // counter should be created for a new object instead and compilation
214 // errors in the code using wxRefCounter due to the lack of copy ctor often
215 // indicate a problem, e.g. a forgotten copy ctor implementation somewhere.
216 wxDECLARE_NO_COPY_CLASS(wxRefCounter);
217 };
218
219 // ----------------------------------------------------------------------------
220 // wxObjectRefData: ref counted data meant to be stored in wxObject
221 // ----------------------------------------------------------------------------
222
223 typedef wxRefCounter wxObjectRefData;
224
225
226 // ----------------------------------------------------------------------------
227 // wxObjectDataPtr: helper class to avoid memleaks because of missing calls
228 // to wxObjectRefData::DecRef
229 // ----------------------------------------------------------------------------
230
231 template <class T>
232 class wxObjectDataPtr
233 {
234 public:
235 typedef T element_type;
236
237 wxEXPLICIT wxObjectDataPtr(T *ptr = NULL) : m_ptr(ptr) {}
238
239 // copy ctor
240 wxObjectDataPtr(const wxObjectDataPtr<T> &tocopy)
241 : m_ptr(tocopy.m_ptr)
242 {
243 if (m_ptr)
244 m_ptr->IncRef();
245 }
246
247 ~wxObjectDataPtr()
248 {
249 if (m_ptr)
250 m_ptr->DecRef();
251 }
252
253 T *get() const { return m_ptr; }
254
255 // test for pointer validity: defining conversion to unspecified_bool_type
256 // and not more obvious bool to avoid implicit conversions to integer types
257 typedef T *(wxObjectDataPtr<T>::*unspecified_bool_type)() const;
258 operator unspecified_bool_type() const
259 {
260 return m_ptr ? &wxObjectDataPtr<T>::get : NULL;
261 }
262
263 T& operator*() const
264 {
265 wxASSERT(m_ptr != NULL);
266 return *(m_ptr);
267 }
268
269 T *operator->() const
270 {
271 wxASSERT(m_ptr != NULL);
272 return get();
273 }
274
275 void reset(T *ptr)
276 {
277 if (m_ptr)
278 m_ptr->DecRef();
279 m_ptr = ptr;
280 }
281
282 wxObjectDataPtr& operator=(const wxObjectDataPtr &tocopy)
283 {
284 if (m_ptr)
285 m_ptr->DecRef();
286 m_ptr = tocopy.m_ptr;
287 if (m_ptr)
288 m_ptr->IncRef();
289 return *this;
290 }
291
292 wxObjectDataPtr& operator=(T *ptr)
293 {
294 if (m_ptr)
295 m_ptr->DecRef();
296 m_ptr = ptr;
297 return *this;
298 }
299
300 private:
301 T *m_ptr;
302 };
303
304 // ----------------------------------------------------------------------------
305 // wxObject: the root class of wxWidgets object hierarchy
306 // ----------------------------------------------------------------------------
307
308 class WXDLLIMPEXP_BASE wxObject
309 {
310 wxDECLARE_ABSTRACT_CLASS(wxObject);
311
312 public:
313 wxObject() { m_refData = NULL; }
314 virtual ~wxObject() { UnRef(); }
315
316 wxObject(const wxObject& other)
317 {
318 m_refData = other.m_refData;
319 if (m_refData)
320 m_refData->IncRef();
321 }
322
323 wxObject& operator=(const wxObject& other)
324 {
325 if ( this != &other )
326 {
327 Ref(other);
328 }
329 return *this;
330 }
331
332 bool IsKindOf(const wxClassInfo *info) const;
333
334
335 // Turn on the correct set of new and delete operators
336
337 #ifdef _WX_WANT_NEW_SIZET_WXCHAR_INT
338 void *operator new ( size_t size, const wxChar *fileName = NULL, int lineNum = 0 );
339 #endif
340
341 #ifdef _WX_WANT_DELETE_VOID
342 void operator delete ( void * buf );
343 #endif
344
345 #ifdef _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET
346 void operator delete ( void *buf, const char *_fname, size_t _line );
347 #endif
348
349 #ifdef _WX_WANT_DELETE_VOID_WXCHAR_INT
350 void operator delete ( void *buf, const wxChar*, int );
351 #endif
352
353 #ifdef _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT
354 void *operator new[] ( size_t size, const wxChar *fileName = NULL, int lineNum = 0 );
355 #endif
356
357 #ifdef _WX_WANT_ARRAY_DELETE_VOID
358 void operator delete[] ( void *buf );
359 #endif
360
361 #ifdef _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT
362 void operator delete[] (void* buf, const wxChar*, int );
363 #endif
364
365 // ref counted data handling methods
366
367 // get/set
368 wxObjectRefData *GetRefData() const { return m_refData; }
369 void SetRefData(wxObjectRefData *data) { m_refData = data; }
370
371 // make a 'clone' of the object
372 void Ref(const wxObject& clone);
373
374 // destroy a reference
375 void UnRef();
376
377 // Make sure this object has only one reference
378 void UnShare() { AllocExclusive(); }
379
380 // check if this object references the same data as the other one
381 bool IsSameAs(const wxObject& o) const { return m_refData == o.m_refData; }
382
383 protected:
384 // ensure that our data is not shared with anybody else: if we have no
385 // data, it is created using CreateRefData() below, if we have shared data
386 // it is copied using CloneRefData(), otherwise nothing is done
387 void AllocExclusive();
388
389 // both methods must be implemented if AllocExclusive() is used, not pure
390 // virtual only because of the backwards compatibility reasons
391
392 // create a new m_refData
393 virtual wxObjectRefData *CreateRefData() const;
394
395 // create a new m_refData initialized with the given one
396 virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const;
397
398 wxObjectRefData *m_refData;
399 };
400
401 inline wxObject *wxCheckDynamicCast(wxObject *obj, wxClassInfo *classInfo)
402 {
403 return obj && obj->GetClassInfo()->IsKindOf(classInfo) ? obj : NULL;
404 }
405
406 #if wxUSE_EXTENDED_RTTI
407 class WXDLLIMPEXP_BASE wxDynamicObject : public wxObject
408 {
409 friend class WXDLLIMPEXP_FWD_BASE wxDynamicClassInfo ;
410 public:
411 // instantiates this object with an instance of its superclass
412 wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info) ;
413 virtual ~wxDynamicObject();
414
415 void SetProperty (const wxChar *propertyName, const wxxVariant &value);
416 wxxVariant GetProperty (const wxChar *propertyName) const ;
417
418 // get the runtime identity of this object
419 wxClassInfo *GetClassInfo() const
420 {
421 #ifdef _MSC_VER
422 return (wxClassInfo*) m_classInfo;
423 #else
424 wxDynamicClassInfo *nonconst = const_cast<wxDynamicClassInfo *>(m_classInfo);
425 return static_cast<wxClassInfo *>(nonconst);
426 #endif
427 }
428
429 wxObject* GetSuperClassInstance() const
430 {
431 return m_superClassInstance ;
432 }
433 private :
434 // removes an existing runtime-property
435 void RemoveProperty( const wxChar *propertyName ) ;
436
437 // renames an existing runtime-property
438 void RenameProperty( const wxChar *oldPropertyName , const wxChar *newPropertyName ) ;
439
440 wxObject *m_superClassInstance ;
441 const wxDynamicClassInfo *m_classInfo;
442 struct wxDynamicObjectInternal;
443 wxDynamicObjectInternal *m_data;
444 };
445 #endif
446
447 // ----------------------------------------------------------------------------
448 // more debugging macros
449 // ----------------------------------------------------------------------------
450
451 #if wxUSE_DEBUG_NEW_ALWAYS
452 #define WXDEBUG_NEW new(__TFILE__,__LINE__)
453
454 #if wxUSE_GLOBAL_MEMORY_OPERATORS
455 #define new WXDEBUG_NEW
456 #elif defined(__VISUALC__)
457 // Including this file redefines new and allows leak reports to
458 // contain line numbers
459 #include "wx/msw/msvcrt.h"
460 #endif
461 #endif // wxUSE_DEBUG_NEW_ALWAYS
462
463 // ----------------------------------------------------------------------------
464 // Compatibility macro aliases
465 // ----------------------------------------------------------------------------
466
467 // deprecated variants _not_ requiring a semicolon after them and without wx prefix.
468 // (note that also some wx-prefixed macro do _not_ require a semicolon because
469 // it's not always possible to force the compire to require it)
470
471 #define DECLARE_CLASS_INFO_ITERATORS() wxDECLARE_CLASS_INFO_ITERATORS();
472 #define DECLARE_ABSTRACT_CLASS(n) wxDECLARE_ABSTRACT_CLASS(n);
473 #define DECLARE_DYNAMIC_CLASS_NO_ASSIGN(n) wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(n);
474 #define DECLARE_DYNAMIC_CLASS_NO_COPY(n) wxDECLARE_DYNAMIC_CLASS_NO_COPY(n);
475 #define DECLARE_DYNAMIC_CLASS(n) wxDECLARE_DYNAMIC_CLASS(n);
476 #define DECLARE_CLASS(n) wxDECLARE_CLASS(n);
477
478 #define IMPLEMENT_DYNAMIC_CLASS(n,b) wxIMPLEMENT_DYNAMIC_CLASS(n,b)
479 #define IMPLEMENT_DYNAMIC_CLASS2(n,b1,b2) wxIMPLEMENT_DYNAMIC_CLASS2(n,b1,b2)
480 #define IMPLEMENT_ABSTRACT_CLASS(n,b) wxIMPLEMENT_ABSTRACT_CLASS(n,b)
481 #define IMPLEMENT_ABSTRACT_CLASS2(n,b1,b2) wxIMPLEMENT_ABSTRACT_CLASS2(n,b1,b2)
482 #define IMPLEMENT_CLASS(n,b) wxIMPLEMENT_CLASS(n,b)
483 #define IMPLEMENT_CLASS2(n,b1,b2) wxIMPLEMENT_CLASS2(n,b1,b2)
484
485 #define DECLARE_PLUGGABLE_CLASS(n) wxDECLARE_PLUGGABLE_CLASS(n);
486 #define DECLARE_ABSTRACT_PLUGGABLE_CLASS(n) wxDECLARE_ABSTRACT_PLUGGABLE_CLASS(n);
487 #define DECLARE_USER_EXPORTED_PLUGGABLE_CLASS(n,u) wxDECLARE_USER_EXPORTED_PLUGGABLE_CLASS(n,u);
488 #define DECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,u) wxDECLARE_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,u);
489
490 #define IMPLEMENT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_PLUGGABLE_CLASS(n,b)
491 #define IMPLEMENT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_PLUGGABLE_CLASS2(n,b,b2)
492 #define IMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS(n,b)
493 #define IMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2)
494 #define IMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS(n,b)
495 #define IMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_USER_EXPORTED_PLUGGABLE_CLASS2(n,b,b2)
496 #define IMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,b) wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS(n,b)
497 #define IMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2) wxIMPLEMENT_USER_EXPORTED_ABSTRACT_PLUGGABLE_CLASS2(n,b,b2)
498
499 #define CLASSINFO(n) wxCLASSINFO(n)
500
501 #endif // _WX_OBJECTH__