* New function wxObjectInputStream::Recall()
[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 #include "wx/objstrm.h"
26 #endif
27
28 #include <string.h>
29 #include <assert.h>
30
31 #if (WXDEBUG && USE_MEMORY_TRACING) || USE_DEBUG_CONTEXT
32 #include "wx/memory.h"
33 #endif
34
35 #if WXDEBUG || USE_DEBUG_CONTEXT
36 // for wxObject::Dump
37 #include <iostream.h>
38 #endif
39
40 #if !USE_SHARED_LIBRARY
41 wxClassInfo wxObject::classwxObject((char *) "wxObject", (char *) NULL, (char *) NULL, (int ) sizeof(wxObject), (wxObjectConstructorFn) NULL);
42 wxClassInfo *wxClassInfo::first = (wxClassInfo *) NULL;
43 #endif
44
45 /*
46 * wxWindows root object.
47 */
48
49 wxObject::wxObject(void)
50 {
51 m_refData = (wxObjectRefData *) NULL;
52 }
53
54 wxObject::~wxObject(void)
55 {
56 UnRef();
57 }
58
59 /*
60 * Is this object a kind of (a subclass of) 'info'?
61 * E.g. is wxWindow a kind of wxObject?
62 * Go from this class to superclass, taking into account
63 * two possible base classes.
64 */
65
66 bool wxObject::IsKindOf(wxClassInfo *info)
67 {
68 wxClassInfo *thisInfo = GetClassInfo();
69 if (thisInfo)
70 return thisInfo->IsKindOf(info);
71 else
72 return FALSE;
73 }
74
75 #if WXDEBUG || USE_DEBUG_CONTEXT
76 void wxObject::Dump(ostream& str)
77 {
78 if (GetClassInfo() && GetClassInfo()->GetClassName())
79 str << GetClassInfo()->GetClassName();
80 else
81 str << "unknown object class";
82 }
83 #endif
84
85 #if WXDEBUG && USE_MEMORY_TRACING
86
87 #ifdef new
88 #undef new
89 #endif
90
91 void * wxObject::operator new (size_t size, char * fileName, int lineNum)
92 {
93 return wxDebugAlloc(size, fileName, lineNum, TRUE);
94 }
95
96 void wxObject::operator delete (void * buf)
97 {
98 wxDebugFree(buf);
99 }
100
101 // Cause problems for VC++ - crashes
102 #ifndef _MSC_VER
103 void * wxObject::operator new[] (size_t size, char * fileName, int lineNum)
104 {
105 return wxDebugAlloc(size, fileName, lineNum, TRUE, TRUE);
106 }
107
108 void wxObject::operator delete[] (void * buf)
109 {
110 wxDebugFree(buf, TRUE);
111 }
112 #endif
113
114 #endif
115
116 /*
117 * Class info: provides run-time class type information.
118 */
119
120 wxClassInfo::wxClassInfo(char *cName, char *baseName1, char *baseName2, int sz, wxObjectConstructorFn constr)
121 {
122 className = cName;
123 baseClassName1 = baseName1;
124 baseClassName2 = baseName2;
125
126 objectSize = sz;
127 objectConstructor = constr;
128
129 next = first;
130 first = this;
131
132 baseInfo1 = (wxClassInfo *) NULL;
133 baseInfo2 = (wxClassInfo *) NULL;
134 }
135
136 wxObject *wxClassInfo::CreateObject(void)
137 {
138 if (objectConstructor)
139 return (wxObject *)(*objectConstructor)();
140 else
141 return (wxObject *) NULL;
142 }
143
144 wxClassInfo *wxClassInfo::FindClass(char *c)
145 {
146 wxClassInfo *p = first;
147 while (p)
148 {
149 if (p && p->GetClassName() && strcmp(p->GetClassName(), c) == 0)
150 return p;
151 p = p->next;
152 }
153 return (wxClassInfo *) NULL;
154 }
155
156 // Climb upwards through inheritance hierarchy.
157 // Dual inheritance is catered for.
158 bool wxClassInfo::IsKindOf(wxClassInfo *info)
159 {
160 if (info == NULL)
161 return FALSE;
162
163 // For some reason, when making/using a DLL, static data has to be included
164 // in both the DLL and the application. This can lead to duplicate
165 // wxClassInfo objects, so we have to test the name instead of the pointers.
166 #if WXMAKINGDLL
167 if (GetClassName() && info->GetClassName() && (strcmp(GetClassName(), info->GetClassName()) == 0))
168 return TRUE;
169 #else
170 if (this == info)
171 return TRUE;
172 #endif
173
174 if (baseInfo1)
175 if (baseInfo1->IsKindOf(info))
176 return TRUE;
177
178 if (baseInfo2)
179 return baseInfo2->IsKindOf(info);
180
181 return FALSE;
182 }
183
184 // Set pointers to base class(es) to speed up IsKindOf
185 void wxClassInfo::InitializeClasses(void)
186 {
187 wxHashTable table(wxKEY_STRING);
188
189 // Index all class infos by their class name
190 wxClassInfo *info = first;
191 while (info)
192 {
193 if (info->className)
194 table.Put(info->className, (wxObject *)info);
195 info = info->next;
196 }
197
198 // Set base pointers for each wxClassInfo
199 info = first;
200 while (info)
201 {
202 if (info->GetBaseClassName1())
203 info->baseInfo1 = (wxClassInfo *)table.Get(info->GetBaseClassName1());
204 if (info->GetBaseClassName2())
205 info->baseInfo2 = (wxClassInfo *)table.Get(info->GetBaseClassName2());
206 info = info->next;
207 }
208 }
209
210 wxObject *wxCreateDynamicObject(char *name)
211 {
212 wxClassInfo *info = wxClassInfo::first;
213 while (info)
214 {
215 if (info->className && strcmp(info->className, name) == 0)
216 return info->CreateObject();
217 info = info->next;
218 }
219 return (wxObject *) NULL;
220 }
221
222 #ifdef USE_STORABLE_CLASSES
223
224 #include "wx/serbase.h"
225 #include "wx/dynlib.h"
226 #include "wx/msgdlg.h"
227
228 wxObject* wxCreateStoredObject( wxInputStream &stream )
229 {
230 wxObjectInputStream obj_s(stream);
231 return obj_s.LoadObject();
232 };
233
234 void wxObject::StoreObject( wxObjectOutputStream& stream )
235 {
236 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
237 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
238 WXSERIAL(wxObject) *serial;
239
240 if (!lib) {
241 wxMessageBox("Can't load wxSerial dynamic library.", "Alert !");
242 return;
243 }
244 serial = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
245
246 if (!serial) {
247 wxString message;
248
249 message.Printf("Can't find the serialization object (%s) for the object %s",
250 WXSTRINGCAST obj_name, WXSTRINGCAST GetClassInfo()->GetClassName());
251 wxMessageBox(message, "Alert !");
252 return;
253 }
254
255 serial->SetObject(this);
256 serial->StoreObject(stream);
257 }
258
259 void wxObject::LoadObject( wxObjectInputStream& stream )
260 {
261 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
262 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
263 WXSERIAL(wxObject) *serial =
264 (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
265
266 if (!serial) {
267 wxString message;
268
269 message.Printf("Can't find the serialization object (%s) for the object %s",
270 WXSTRINGCAST obj_name,
271 WXSTRINGCAST GetClassInfo()->GetClassName());
272 wxMessageBox(message, "Alert !");
273 return;
274 }
275
276 serial->SetObject(this);
277 serial->LoadObject(stream);
278 }
279
280 #endif
281
282 /*
283 * wxObject: cloning of objects
284 */
285
286 void wxObject::Ref(const wxObject& clone)
287 {
288 // delete reference to old data
289 UnRef();
290 // reference new data
291 if (clone.m_refData) {
292 m_refData = clone.m_refData;
293 ++(m_refData->m_count);
294 }
295 }
296
297 void wxObject::UnRef(void)
298 {
299 if (m_refData) {
300 assert(m_refData->m_count > 0);
301 --(m_refData->m_count);
302 if (m_refData->m_count == 0)
303 delete m_refData;
304 }
305 m_refData = (wxObjectRefData *) NULL;
306 }
307
308 /*
309 * wxObjectData
310 */
311
312 wxObjectRefData::wxObjectRefData(void) : m_count(1)
313 {
314 }
315
316 wxObjectRefData::~wxObjectRefData(void)
317 {
318 }
319