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