]> git.saurik.com Git - wxWidgets.git/blob - src/common/objstrm.cpp
1. corrected (but the fix is ugly) the multiple def button problem
[wxWidgets.git] / src / common / objstrm.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: objstrm.cpp
3 // Purpose: wxObjectStream classes
4 // Author: Guilhem Lavaux
5 // Modified by:
6 // Created: 16/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Guilhem Lavaux
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11 #ifdef __GNUG__
12 #pragma implementation "objstrm.h"
13 #endif
14
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #if wxUSE_SERIAL && wxUSE_STREAMS
23
24 #include "wx/object.h"
25 #include "wx/objstrm.h"
26 #include "wx/datstrm.h"
27
28 #define WXOBJ_BEGIN "OBEGIN"
29 #define WXOBJ_BEG_LEN 6
30
31 #define TAG_EMPTY_OBJECT "NULL"
32 #define TAG_DUPLICATE_OBJECT "DUPLIC"
33
34 // ----------------------------------------------------------------------------
35 // wxObjectOutputStream
36 // ----------------------------------------------------------------------------
37
38 wxObjectOutputStream::wxObjectOutputStream(wxOutputStream& s)
39 : wxFilterOutputStream(s)
40 {
41 m_saving = FALSE;
42 }
43
44 wxString wxObjectOutputStream::GetObjectName(wxObject *obj)
45 {
46 wxString name;
47
48 name.Printf(wxT("%x"), (unsigned long)obj);
49 return name;
50 }
51
52 void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo& info)
53 {
54 wxDataOutputStream data_s(*this);
55
56 Write(WXOBJ_BEGIN, WXOBJ_BEG_LEN);
57
58 if (info.duplicate) {
59 data_s.WriteString(TAG_DUPLICATE_OBJECT);
60 data_s.WriteString(GetObjectName(info.object));
61 wxPrintf(wxT("info.object (dup %s)\n"), info.object->GetClassInfo()->GetClassName());
62 return;
63 }
64
65 if (info.object) {
66 data_s.WriteString(info.object->GetClassInfo()->GetClassName());
67 wxPrintf(wxT("info.object (%s)\n"), info.object->GetClassInfo()->GetClassName());
68 } else {
69 data_s.WriteString(TAG_EMPTY_OBJECT);
70 wxPrintf(wxT("info.object (NULL)\n"));
71 return;
72 }
73
74 data_s.WriteString(GetObjectName(info.object));
75
76 // I assume an object will not have millions of children
77 // Hmmm ... it could have (for example wxGrid)
78 data_s.Write32(info.children.Number());
79 }
80
81 void wxObjectOutputStream::AddChild(wxObject *obj)
82 {
83 wxObjectStreamInfo *info;
84
85 if (!FirstStage())
86 return;
87
88 info = new wxObjectStreamInfo;
89
90 if (m_saved_objs.Member(obj) != NULL) {
91 info->duplicate = TRUE;
92 } else {
93 info->duplicate = FALSE;
94 m_saved_objs.Append(obj);
95 }
96 if (!obj)
97 info->duplicate = FALSE;
98
99 info->n_children = 0;
100 info->object = obj;
101 info->parent = m_current_info; // Not useful here.
102 m_current_info->n_children++;
103 m_current_info->children.Append(info);
104 }
105
106 void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo *info)
107 {
108 wxNode *node;
109
110 m_current_info = info;
111 // First stage: get children of obj
112 if (info->object && !info->duplicate)
113 info->object->StoreObject(*this);
114
115 // Prepare and write the sub-entry about the child obj.
116 WriteObjectDef(*info);
117
118 node = info->children.First();
119
120 while (node) {
121 ProcessObjectDef((wxObjectStreamInfo *)node->Data());
122 node = node->Next();
123 }
124 }
125
126 void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo *info)
127 {
128 wxNode *node = info->children.First();
129
130 m_current_info = info;
131
132 if (info->object && !info->duplicate)
133 info->object->StoreObject(*this);
134
135 while (node) {
136 ProcessObjectData((wxObjectStreamInfo *)node->Data());
137 node = node->Next();
138 }
139 }
140
141 bool wxObjectOutputStream::SaveObject(wxObject& obj)
142 {
143 wxObjectStreamInfo info;
144
145 if (m_saving)
146 return FALSE;
147
148 m_saving = TRUE;
149
150 // First stage
151 m_stage = 0;
152 info.object = &obj;
153 info.n_children = 0;
154 info.duplicate = FALSE;
155 ProcessObjectDef(&info);
156
157 m_stage = 1;
158 ProcessObjectData(&info);
159
160 info.children.Clear();
161 m_saved_objs.Clear();
162
163 m_saving = FALSE;
164
165 return TRUE;
166 }
167
168 // ----------------------------------------------------------------------------
169 // wxObjectInputStream
170 // ----------------------------------------------------------------------------
171
172 wxObjectInputStream::wxObjectInputStream(wxInputStream& s)
173 : wxFilterInputStream(s)
174 {
175 m_secondcall = FALSE;
176 }
177
178 wxObject *wxObjectInputStream::SolveName(const wxString& name) const
179 {
180 wxNode *node = m_solver.First();
181 wxObjectStreamInfo *info;
182
183 while (node) {
184 info = (wxObjectStreamInfo *)node->Data();
185 if (info->object_name == name)
186 return info->object;
187
188 node = node->Next();
189 }
190 return (wxObject *) NULL;
191 }
192
193 wxObject *wxObjectInputStream::GetParent() const
194 {
195 if (!m_current_info->parent)
196 return (wxObject *) NULL;
197
198 return m_current_info->parent->object;
199 }
200
201 wxObject *wxObjectInputStream::GetChild()
202 {
203 wxObject *obj = GetChild(0);
204
205 m_current_info->children_removed++;
206
207 return obj;
208 }
209
210 wxObject *wxObjectInputStream::GetChild(int no) const
211 {
212 wxNode *node;
213 wxObjectStreamInfo *info;
214
215 if (m_current_info->children_removed >= m_current_info->n_children)
216 return (wxObject *) NULL;
217
218 node = m_current_info->children.Nth(m_current_info->children_removed+no);
219
220 if (!node)
221 return (wxObject *) NULL;
222
223 info = (wxObjectStreamInfo *)node->Data();
224
225 return info->object;
226 }
227
228 void wxObjectInputStream::RemoveChildren(int nb)
229 {
230 m_current_info->children_removed += nb;
231 }
232
233 bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info)
234 {
235 wxDataInputStream data_s(*this);
236 char sig[WXOBJ_BEG_LEN+1];
237 wxString class_name;
238
239 Read(sig, WXOBJ_BEG_LEN);
240 sig[WXOBJ_BEG_LEN] = 0;
241 if (wxString(sig) != WXOBJ_BEGIN)
242 return FALSE;
243
244 class_name = data_s.ReadString();
245 info->children_removed = 0;
246 info->n_children = 0;
247
248 if (class_name == TAG_EMPTY_OBJECT)
249 info->object = (wxObject *) NULL;
250 else if (class_name == TAG_DUPLICATE_OBJECT) {
251 info->object_name = data_s.ReadString();
252 info->object = SolveName(info->object_name);
253 } else {
254 info->object_name = data_s.ReadString();
255 info->object = wxCreateDynamicObject( WXSTRINGCAST class_name);
256 info->n_children = data_s.Read32();
257 }
258 return TRUE;
259 }
260
261 wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *parent)
262 {
263 wxObjectStreamInfo *info, *c_info;
264 int c;
265
266 info = new wxObjectStreamInfo;
267 info->parent = parent;
268 info->children.DeleteContents(TRUE);
269
270 m_solver.Append(info);
271
272 if (!ReadObjectDef(info))
273 return (wxObjectStreamInfo *) NULL;
274
275 for (c=0;c<info->n_children;c++) {
276 c_info = ProcessObjectDef(info);
277 if (!c_info)
278 return (wxObjectStreamInfo *) NULL;
279 info->children.Append(c_info);
280 }
281
282 return info;
283 }
284
285 void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo *info)
286 {
287 wxNode *node = info->children.First();
288
289 m_current_info = info;
290
291 if (info->object)
292 info->object->LoadObject(*this);
293 while (node) {
294 ProcessObjectData((wxObjectStreamInfo *)node->Data());
295 node = node->Next();
296 }
297
298 m_current_info = info;
299
300 if (info->recall) {
301 m_secondcall = TRUE;
302 info->object->LoadObject(*this);
303 m_secondcall = FALSE;
304 }
305 }
306
307 wxObject *wxObjectInputStream::LoadObject()
308 {
309 wxObjectStreamInfo *info;
310 wxObject *object;
311
312 info = ProcessObjectDef((wxObjectStreamInfo *) NULL);
313 if (!info)
314 return (wxObject *) NULL;
315 ProcessObjectData(info);
316
317 object = info->object;
318
319 delete info; // It's magic ! The whole tree is destroyed.
320
321 return object;
322 }
323
324 #endif
325