Added variant.h/cpp; changed variable names in object.h; added some
[wxWidgets.git] / src / common / object.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: object.cpp
3 // Purpose: wxObject implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "object.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/hash.h"
25 #ifdef USE_SERIAL
26 #include "wx/objstrm.h"
27 #include "wx/serbase.h"
28 #endif
29 #endif
30
31 #include <string.h>
32 #include <assert.h>
33
34 #if (WXDEBUG && USE_MEMORY_TRACING) || USE_DEBUG_CONTEXT
35 #include "wx/memory.h"
36 #endif
37
38 #if WXDEBUG || USE_DEBUG_CONTEXT
39 // for wxObject::Dump
40 #include <iostream.h>
41 #endif
42
43 #if !USE_SHARED_LIBRARY
44 wxClassInfo wxObject::sm_classwxObject((char *) "wxObject", (char *) NULL, (char *) NULL, (int ) sizeof(wxObject), (wxObjectConstructorFn) NULL);
45 wxClassInfo* wxClassInfo::sm_first = (wxClassInfo *) NULL;
46 wxHashTable* wxClassInfo::sm_classTable = (wxHashTable*) NULL;
47 #endif
48
49 /*
50 * wxWindows root object.
51 */
52
53 wxObject::wxObject(void)
54 {
55 m_refData = (wxObjectRefData *) NULL;
56 #ifdef USE_SERIAL
57 m_serialObj = (wxObject_Serialize *)NULL;
58 #endif
59 }
60
61 wxObject::~wxObject(void)
62 {
63 UnRef();
64 #ifdef USE_SERIAL
65 if (m_serialObj)
66 delete m_serialObj;
67 #endif
68 }
69
70 /*
71 * Is this object a kind of (a subclass of) 'info'?
72 * E.g. is wxWindow a kind of wxObject?
73 * Go from this class to superclass, taking into account
74 * two possible base classes.
75 */
76
77 bool wxObject::IsKindOf(wxClassInfo *info) const
78 {
79 wxClassInfo *thisInfo = GetClassInfo();
80 if (thisInfo)
81 return thisInfo->IsKindOf(info);
82 else
83 return FALSE;
84 }
85
86 #if WXDEBUG || USE_DEBUG_CONTEXT
87 void wxObject::Dump(ostream& str)
88 {
89 if (GetClassInfo() && GetClassInfo()->GetClassName())
90 str << GetClassInfo()->GetClassName();
91 else
92 str << "unknown object class";
93 }
94 #endif
95
96 #if WXDEBUG && USE_MEMORY_TRACING
97
98 #ifdef new
99 #undef new
100 #endif
101
102 void * wxObject::operator new (size_t size, char * fileName, int lineNum)
103 {
104 return wxDebugAlloc(size, fileName, lineNum, TRUE);
105 }
106
107 void wxObject::operator delete (void * buf)
108 {
109 wxDebugFree(buf);
110 }
111
112 // Cause problems for VC++ - crashes
113 #ifndef _MSC_VER
114 void * wxObject::operator new[] (size_t size, char * fileName, int lineNum)
115 {
116 return wxDebugAlloc(size, fileName, lineNum, TRUE, TRUE);
117 }
118
119 void wxObject::operator delete[] (void * buf)
120 {
121 wxDebugFree(buf, TRUE);
122 }
123 #endif
124
125 #endif
126
127 /*
128 * Class info: provides run-time class type information.
129 */
130
131 wxClassInfo::wxClassInfo(char *cName, char *baseName1, char *baseName2, int sz, wxObjectConstructorFn constr)
132 {
133 m_className = cName;
134 m_baseClassName1 = baseName1;
135 m_baseClassName2 = baseName2;
136
137 m_objectSize = sz;
138 m_objectConstructor = constr;
139
140 m_next = sm_first;
141 sm_first = this;
142
143 m_baseInfo1 = (wxClassInfo *) NULL;
144 m_baseInfo2 = (wxClassInfo *) NULL;
145 }
146
147 wxObject *wxClassInfo::CreateObject(void)
148 {
149 if (m_objectConstructor)
150 return (wxObject *)(*m_objectConstructor)();
151 else
152 return (wxObject *) NULL;
153 }
154
155 wxClassInfo *wxClassInfo::FindClass(char *c)
156 {
157 wxClassInfo *p = sm_first;
158 while (p)
159 {
160 if (p && p->GetClassName() && strcmp(p->GetClassName(), c) == 0)
161 return p;
162 p = p->m_next;
163 }
164 return (wxClassInfo *) NULL;
165 }
166
167 // Climb upwards through inheritance hierarchy.
168 // Dual inheritance is catered for.
169 bool wxClassInfo::IsKindOf(wxClassInfo *info) const
170 {
171 if (info == NULL)
172 return FALSE;
173
174 // For some reason, when making/using a DLL, static data has to be included
175 // in both the DLL and the application. This can lead to duplicate
176 // wxClassInfo objects, so we have to test the name instead of the pointers.
177 // PROBABLY NO LONGER TRUE now I've done DLL creation right.
178 /*
179 #if WXMAKINGDLL
180 if (GetClassName() && info->GetClassName() && (strcmp(GetClassName(), info->GetClassName()) == 0))
181 return TRUE;
182 #else
183 */
184 if (this == info)
185 return TRUE;
186
187 if (m_baseInfo1)
188 if (m_baseInfo1->IsKindOf(info))
189 return TRUE;
190
191 if (m_baseInfo2)
192 return m_baseInfo2->IsKindOf(info);
193
194 return FALSE;
195 }
196
197 // Set pointers to base class(es) to speed up IsKindOf
198 void wxClassInfo::InitializeClasses(void)
199 {
200 wxClassInfo::sm_classTable = new wxHashTable(wxKEY_STRING);
201
202 // Index all class infos by their class name
203 wxClassInfo *info = sm_first;
204 while (info)
205 {
206 if (info->m_className)
207 sm_classTable->Put(info->m_className, (wxObject *)info);
208 info = info->m_next;
209 }
210
211 // Set base pointers for each wxClassInfo
212 info = sm_first;
213 while (info)
214 {
215 if (info->GetBaseClassName1())
216 info->m_baseInfo1 = (wxClassInfo *)sm_classTable->Get(info->GetBaseClassName1());
217 if (info->GetBaseClassName2())
218 info->m_baseInfo2 = (wxClassInfo *)sm_classTable->Get(info->GetBaseClassName2());
219 info = info->m_next;
220 }
221 }
222
223 void wxClassInfo::CleanUpClasses(void)
224 {
225 delete wxClassInfo::sm_classTable;
226 wxClassInfo::sm_classTable = NULL;
227 }
228
229 wxObject *wxCreateDynamicObject(const char *name)
230 {
231 if (wxClassInfo::sm_classTable)
232 {
233 wxClassInfo *info = (wxClassInfo *)wxClassInfo::sm_classTable->Get(name);
234 if (!info)
235 return (wxObject *)NULL;
236
237 return info->CreateObject();
238 }
239 else
240 {
241 wxClassInfo *info = wxClassInfo::sm_first;
242 while (info)
243 {
244 if (info->m_className && strcmp(info->m_className, name) == 0)
245 return info->CreateObject();
246 info = info->m_next;
247 }
248 return (wxObject*) NULL;
249 }
250 return (wxObject*) NULL;
251 }
252
253 #ifdef USE_SERIAL
254
255 #include "wx/serbase.h"
256 #include "wx/dynlib.h"
257 #include "wx/msgdlg.h"
258
259 wxObject* wxCreateStoredObject( wxInputStream &stream )
260 {
261 wxObjectInputStream obj_s(stream);
262 return obj_s.LoadObject();
263 };
264
265 void wxObject::StoreObject( wxObjectOutputStream& stream )
266 {
267 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
268 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
269
270 if (!lib) {
271 wxMessageBox("Can't load wxSerial dynamic library.", "Alert !");
272 return;
273 }
274 if (!m_serialObj) {
275 m_serialObj = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
276
277 if (!m_serialObj) {
278 wxString message;
279
280 message.Printf("Can't find the serialization object (%s) for the object %s",
281 WXSTRINGCAST obj_name,
282 WXSTRINGCAST GetClassInfo()->GetClassName());
283 wxMessageBox(message, "Alert !");
284 return;
285 }
286 m_serialObj->SetObject(this);
287 }
288
289 m_serialObj->StoreObject(stream);
290 }
291
292 void wxObject::LoadObject( wxObjectInputStream& stream )
293 {
294 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
295 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
296
297 if (!m_serialObj) {
298 m_serialObj = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
299
300 if (!m_serialObj) {
301 wxString message;
302
303 message.Printf("Can't find the serialization object (%s) for the object %s",
304 WXSTRINGCAST obj_name,
305 WXSTRINGCAST GetClassInfo()->GetClassName());
306 wxMessageBox(message, "Alert !");
307 return;
308 }
309 m_serialObj->SetObject(this);
310 }
311
312 m_serialObj->LoadObject(stream);
313 }
314
315 #endif
316
317 /*
318 * wxObject: cloning of objects
319 */
320
321 void wxObject::Ref(const wxObject& clone)
322 {
323 // delete reference to old data
324 UnRef();
325 // reference new data
326 if (clone.m_refData) {
327 m_refData = clone.m_refData;
328 ++(m_refData->m_count);
329 }
330 }
331
332 void wxObject::UnRef(void)
333 {
334 if (m_refData) {
335 assert(m_refData->m_count > 0);
336 --(m_refData->m_count);
337 if (m_refData->m_count == 0)
338 delete m_refData;
339 }
340 m_refData = (wxObjectRefData *) NULL;
341 }
342
343 /*
344 * wxObjectData
345 */
346
347 wxObjectRefData::wxObjectRefData(void) : m_count(1)
348 {
349 }
350
351 wxObjectRefData::~wxObjectRefData(void)
352 {
353 }
354
355 // These are here so we can avoid 'always true/false' warnings
356 // by referring to these instead of TRUE/FALSE
357 const bool wxTrue = TRUE;
358 const bool wxFalse = FALSE;