]>
Commit | Line | Data |
---|---|---|
9c8046dd | 1 | ///////////////////////////////////////////////////////////////////////////// |
8e3f3880 | 2 | // Name: src/common/xtixml.cpp |
2abce515 | 3 | // Purpose: streaming runtime metadata information |
9c8046dd | 4 | // Author: Stefan Csomor |
2abce515 | 5 | // Modified by: |
9c8046dd SC |
6 | // Created: 27/07/03 |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 2003 Stefan Csomor | |
65571936 | 9 | // Licence: wxWindows licence |
9c8046dd SC |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
9c8046dd SC |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
e765d7ee | 16 | #pragma hdrstop |
9c8046dd SC |
17 | #endif |
18 | ||
8e3f3880 WS |
19 | #if wxUSE_EXTENDED_RTTI |
20 | ||
e765d7ee | 21 | #include "wx/xtistrm.h" |
d5da0ce7 | 22 | |
9c8046dd | 23 | #ifndef WX_PRECOMP |
8e3f3880 WS |
24 | #include "wx/object.h" |
25 | #include "wx/hash.h" | |
d5da0ce7 | 26 | #include "wx/event.h" |
9c8046dd SC |
27 | #endif |
28 | ||
29 | #include "wx/xml/xml.h" | |
30 | #include "wx/tokenzr.h" | |
9c8046dd | 31 | #include "wx/txtstrm.h" |
8347b97a | 32 | #include "wx/xtistrm.h" |
e765d7ee | 33 | #include "wx/xtixml.h" |
8347b97a | 34 | |
5e8b5272 SC |
35 | // STL headers |
36 | ||
9c8046dd SC |
37 | #include "wx/beforestd.h" |
38 | #include <map> | |
39 | #include <vector> | |
40 | #include <string> | |
41 | #include "wx/afterstd.h" | |
42 | ||
5e8b5272 SC |
43 | using namespace std; |
44 | ||
9c8046dd | 45 | |
5e8b5272 SC |
46 | |
47 | ||
48 | // ---------------------------------------------------------------------------- | |
49 | // wxObjectXmlWriter | |
50 | // ---------------------------------------------------------------------------- | |
9c8046dd SC |
51 | |
52 | // convenience functions | |
53 | ||
5e8b5272 | 54 | void wxXmlAddContentToNode( wxXmlNode* node, const wxString& data ) |
9c8046dd | 55 | { |
63691d4f | 56 | node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, wxT("value"), data ) ); |
9c8046dd SC |
57 | } |
58 | ||
59 | wxString wxXmlGetContentFromNode( wxXmlNode *node ) | |
60 | { | |
61 | if ( node->GetChildren() ) | |
5e8b5272 | 62 | return node->GetChildren()->GetContent(); |
9c8046dd | 63 | else |
5e8b5272 | 64 | return wxEmptyString; |
9c8046dd SC |
65 | } |
66 | ||
5e8b5272 | 67 | struct wxObjectXmlWriter::wxObjectXmlWriterInternal |
9c8046dd | 68 | { |
5e8b5272 SC |
69 | wxXmlNode *m_root; |
70 | wxXmlNode *m_current; | |
71 | vector< wxXmlNode * > m_objectStack; | |
9c8046dd SC |
72 | |
73 | void Push( wxXmlNode *newCurrent ) | |
74 | { | |
5e8b5272 SC |
75 | m_objectStack.push_back( m_current ); |
76 | m_current = newCurrent; | |
9c8046dd SC |
77 | } |
78 | ||
79 | void Pop() | |
80 | { | |
5e8b5272 SC |
81 | m_current = m_objectStack.back(); |
82 | m_objectStack.pop_back(); | |
9c8046dd | 83 | } |
5e8b5272 | 84 | }; |
9c8046dd | 85 | |
5e8b5272 | 86 | wxObjectXmlWriter::wxObjectXmlWriter( wxXmlNode * rootnode ) |
9c8046dd | 87 | { |
5e8b5272 SC |
88 | m_data = new wxObjectXmlWriterInternal(); |
89 | m_data->m_root = rootnode; | |
90 | m_data->m_current = rootnode; | |
9c8046dd SC |
91 | } |
92 | ||
5e8b5272 | 93 | wxObjectXmlWriter::~wxObjectXmlWriter() |
9c8046dd | 94 | { |
5e8b5272 | 95 | delete m_data; |
9c8046dd SC |
96 | } |
97 | ||
5e8b5272 | 98 | void wxObjectXmlWriter::DoBeginWriteTopLevelEntry( const wxString &name ) |
9c8046dd SC |
99 | { |
100 | wxXmlNode *pnode; | |
101 | pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("entry")); | |
5e8b5272 SC |
102 | pnode->AddProperty(wxString(wxT("name")), name); |
103 | m_data->m_current->AddChild(pnode); | |
104 | m_data->Push( pnode ); | |
9c8046dd SC |
105 | } |
106 | ||
5e8b5272 | 107 | void wxObjectXmlWriter::DoEndWriteTopLevelEntry( const wxString &WXUNUSED(name) ) |
9c8046dd | 108 | { |
5e8b5272 | 109 | m_data->Pop(); |
9c8046dd SC |
110 | } |
111 | ||
5e8b5272 SC |
112 | void wxObjectXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), |
113 | const wxClassInfo *classInfo, | |
e765d7ee | 114 | int objectID, const wxStringToAnyHashMap &metadata ) |
9c8046dd SC |
115 | { |
116 | wxXmlNode *pnode; | |
117 | pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object")); | |
5e8b5272 SC |
118 | pnode->AddProperty(wxT("class"), wxString(classInfo->GetClassName())); |
119 | pnode->AddProperty(wxT("id"), wxString::Format( wxT("%d"), objectID ) ); | |
9c8046dd | 120 | |
e765d7ee SC |
121 | wxStringToAnyHashMap::const_iterator it, en; |
122 | for( it = metadata.begin(), en = metadata.end(); it != en; ++it ) | |
9c8046dd | 123 | { |
e765d7ee | 124 | pnode->AddProperty( it->first, wxAnyGetAsString(it->second) ); |
9c8046dd | 125 | } |
e765d7ee | 126 | |
5e8b5272 SC |
127 | m_data->m_current->AddChild(pnode); |
128 | m_data->Push( pnode ); | |
9c8046dd SC |
129 | } |
130 | ||
5e8b5272 SC |
131 | void wxObjectXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), |
132 | const wxClassInfo *WXUNUSED(classInfo), | |
133 | int WXUNUSED(objectID) ) | |
9c8046dd | 134 | { |
5e8b5272 | 135 | m_data->Pop(); |
9c8046dd SC |
136 | } |
137 | ||
e765d7ee | 138 | void wxObjectXmlWriter::DoWriteSimpleType( const wxAny &value ) |
9c8046dd | 139 | { |
e765d7ee | 140 | wxXmlAddContentToNode( m_data->m_current,wxAnyGetAsString(value) ); |
9c8046dd SC |
141 | } |
142 | ||
5e8b5272 | 143 | void wxObjectXmlWriter::DoBeginWriteElement() |
9c8046dd SC |
144 | { |
145 | wxXmlNode *pnode; | |
63691d4f | 146 | pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("element") ); |
5e8b5272 SC |
147 | m_data->m_current->AddChild(pnode); |
148 | m_data->Push( pnode ); | |
9c8046dd SC |
149 | } |
150 | ||
5e8b5272 | 151 | void wxObjectXmlWriter::DoEndWriteElement() |
9c8046dd | 152 | { |
5e8b5272 | 153 | m_data->Pop(); |
9c8046dd SC |
154 | } |
155 | ||
5e8b5272 | 156 | void wxObjectXmlWriter::DoBeginWriteProperty(const wxPropertyInfo *pi ) |
9c8046dd SC |
157 | { |
158 | wxXmlNode *pnode; | |
63691d4f | 159 | pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("prop") ); |
5e8b5272 SC |
160 | pnode->AddProperty(wxT("name"), pi->GetName() ); |
161 | m_data->m_current->AddChild(pnode); | |
162 | m_data->Push( pnode ); | |
9c8046dd SC |
163 | } |
164 | ||
5e8b5272 | 165 | void wxObjectXmlWriter::DoEndWriteProperty(const wxPropertyInfo *WXUNUSED(propInfo) ) |
9c8046dd | 166 | { |
5e8b5272 | 167 | m_data->Pop(); |
9c8046dd SC |
168 | } |
169 | ||
5e8b5272 | 170 | void wxObjectXmlWriter::DoWriteRepeatedObject( int objectID ) |
9c8046dd SC |
171 | { |
172 | wxXmlNode *pnode; | |
173 | pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object")); | |
5e8b5272 SC |
174 | pnode->AddProperty(wxString(wxT("href")), wxString::Format( wxT("%d"), objectID ) ); |
175 | m_data->m_current->AddChild(pnode); | |
9c8046dd SC |
176 | } |
177 | ||
5e8b5272 | 178 | void wxObjectXmlWriter::DoWriteNullObject() |
9c8046dd SC |
179 | { |
180 | wxXmlNode *pnode; | |
181 | pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object")); | |
5e8b5272 | 182 | m_data->m_current->AddChild(pnode); |
9c8046dd SC |
183 | } |
184 | ||
5e8b5272 SC |
185 | void wxObjectXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), |
186 | const wxClassInfo* WXUNUSED(classInfo), | |
187 | const wxPropertyInfo *WXUNUSED(pi), | |
188 | const wxObject *eventSink, int sinkObjectID, | |
189 | const wxClassInfo* WXUNUSED(eventSinkClassInfo), | |
190 | const wxHandlerInfo* handlerInfo ) | |
9c8046dd SC |
191 | { |
192 | if ( eventSink != NULL && handlerInfo != NULL ) | |
193 | { | |
5e8b5272 SC |
194 | wxXmlAddContentToNode( m_data->m_current, |
195 | wxString::Format(wxT("%d.%s"), sinkObjectID, handlerInfo->GetName().c_str()) ); | |
9c8046dd SC |
196 | } |
197 | } | |
198 | ||
9c8046dd SC |
199 | |
200 | // ---------------------------------------------------------------------------- | |
5e8b5272 | 201 | // wxObjectXmlReader |
9c8046dd SC |
202 | // ---------------------------------------------------------------------------- |
203 | ||
2abce515 | 204 | /* |
9c8046dd SC |
205 | Reading components has not to be extended for components |
206 | as properties are always sought by typeinfo over all levels | |
207 | and create params are always toplevel class only | |
208 | */ | |
209 | ||
e765d7ee | 210 | int wxObjectXmlReader::ReadComponent(wxXmlNode *node, wxObjectReaderCallback *callbacks) |
9c8046dd | 211 | { |
5e8b5272 | 212 | wxASSERT_MSG( callbacks, wxT("Does not support reading without a Depersistor") ); |
9c8046dd SC |
213 | wxString className; |
214 | wxClassInfo *classInfo; | |
215 | ||
e765d7ee | 216 | wxAny *createParams; |
5e8b5272 SC |
217 | int *createParamOids; |
218 | const wxClassInfo** createClassInfos; | |
9c8046dd SC |
219 | wxXmlNode *children; |
220 | int objectID; | |
5e8b5272 | 221 | wxString ObjectIdString; |
9c8046dd SC |
222 | |
223 | children = node->GetChildren(); | |
224 | if (!children) | |
225 | { | |
226 | // check for a null object or href | |
e765d7ee | 227 | if (node->GetAttribute(wxT("href"), &ObjectIdString ) ) |
9c8046dd | 228 | { |
5e8b5272 | 229 | objectID = atoi( ObjectIdString.ToAscii() ); |
8f2b1cfd SC |
230 | if ( HasObjectClassInfo( objectID ) ) |
231 | { | |
5e8b5272 | 232 | return objectID; |
8f2b1cfd SC |
233 | } |
234 | else | |
235 | { | |
5e8b5272 SC |
236 | wxLogError( _("Forward hrefs are not supported") ); |
237 | return wxInvalidObjectID; | |
8f2b1cfd | 238 | } |
9c8046dd | 239 | } |
e765d7ee | 240 | if ( !node->GetAttribute(wxT("id"), &ObjectIdString ) ) |
9c8046dd SC |
241 | { |
242 | return wxNullObjectID; | |
243 | } | |
244 | } | |
e765d7ee | 245 | if (!node->GetAttribute(wxT("class"), &className)) |
9c8046dd SC |
246 | { |
247 | // No class name. Eek. FIXME: error handling | |
248 | return wxInvalidObjectID; | |
249 | } | |
5e8b5272 | 250 | |
9c8046dd | 251 | classInfo = wxClassInfo::FindClass(className); |
8f2b1cfd SC |
252 | if ( classInfo == NULL ) |
253 | { | |
5e8b5272 SC |
254 | wxLogError( wxString::Format(_("unknown class %s"),className ) ); |
255 | return wxInvalidObjectID; | |
8f2b1cfd SC |
256 | } |
257 | ||
258 | if ( children != NULL && children->GetType() == wxXML_TEXT_NODE ) | |
259 | { | |
5e8b5272 | 260 | wxLogError(_("objects cannot have XML Text Nodes") ); |
8f2b1cfd SC |
261 | return wxInvalidObjectID; |
262 | } | |
e765d7ee | 263 | if (!node->GetAttribute(wxT("id"), &ObjectIdString)) |
9c8046dd | 264 | { |
5e8b5272 | 265 | wxLogError(_("Objects must have an id attribute") ); |
9c8046dd SC |
266 | // No object id. Eek. FIXME: error handling |
267 | return wxInvalidObjectID; | |
268 | } | |
5e8b5272 SC |
269 | objectID = atoi( ObjectIdString.ToAscii() ); |
270 | ||
9c8046dd | 271 | // is this object already has been streamed in, return it here |
8f2b1cfd SC |
272 | if ( HasObjectClassInfo( objectID ) ) |
273 | { | |
5e8b5272 SC |
274 | wxLogError ( wxString::Format(_("Doubly used id : %d"), objectID ) ); |
275 | return wxInvalidObjectID; | |
8f2b1cfd | 276 | } |
9c8046dd SC |
277 | |
278 | // new object, start with allocation | |
279 | // first make the object know to our internal registry | |
5e8b5272 | 280 | SetObjectClassInfo( objectID, classInfo ); |
9c8046dd | 281 | |
e765d7ee SC |
282 | wxStringToAnyHashMap metadata; |
283 | wxXmlProperty *xp = node->GetAttributes(); | |
9c8046dd SC |
284 | while ( xp ) |
285 | { | |
5e8b5272 SC |
286 | if ( xp->GetName() != wxString(wxT("class")) && |
287 | xp->GetName() != wxString(wxT("id")) ) | |
9c8046dd | 288 | { |
e765d7ee | 289 | metadata[xp->GetName()] = wxAny( xp->GetValue() ); |
9c8046dd | 290 | } |
5e8b5272 | 291 | xp = xp->GetNext(); |
9c8046dd | 292 | } |
ed45345e SC |
293 | if ( !classInfo->NeedsDirectConstruction() ) |
294 | callbacks->AllocateObject(objectID, classInfo, metadata); | |
9c8046dd | 295 | |
2abce515 | 296 | // |
9c8046dd | 297 | // stream back the Create parameters first |
e765d7ee | 298 | createParams = new wxAny[ classInfo->GetCreateParamCount() ]; |
5e8b5272 SC |
299 | createParamOids = new int[classInfo->GetCreateParamCount() ]; |
300 | createClassInfos = new const wxClassInfo*[classInfo->GetCreateParamCount() ]; | |
9c8046dd | 301 | |
63691d4f | 302 | #if wxUSE_UNICODE |
5e8b5272 SC |
303 | typedef map<wstring, wxXmlNode *> PropertyNodes; |
304 | typedef vector<wstring> PropertyNames; | |
63691d4f | 305 | #else |
5e8b5272 SC |
306 | typedef map<string, wxXmlNode *> PropertyNodes; |
307 | typedef vector<string> PropertyNames; | |
63691d4f | 308 | #endif |
5e8b5272 SC |
309 | PropertyNodes propertyNodes; |
310 | PropertyNames propertyNames; | |
9c8046dd SC |
311 | |
312 | while( children ) | |
313 | { | |
5e8b5272 | 314 | wxString name; |
e765d7ee | 315 | children->GetAttribute( wxT("name"), &name ); |
5e8b5272 SC |
316 | propertyNames.push_back( (const wxChar*)name.c_str() ); |
317 | propertyNodes[(const wxChar*)name.c_str()] = children->GetChildren(); | |
318 | children = children->GetNext(); | |
9c8046dd SC |
319 | } |
320 | ||
5e8b5272 | 321 | for ( int i = 0; i <classInfo->GetCreateParamCount(); ++i ) |
9c8046dd | 322 | { |
5e8b5272 SC |
323 | const wxChar* paramName = classInfo->GetCreateParamName(i); |
324 | PropertyNodes::iterator propiter = propertyNodes.find( paramName ); | |
325 | const wxPropertyInfo* pi = classInfo->FindPropertyInfo( paramName ); | |
8f2b1cfd SC |
326 | if ( pi == 0 ) |
327 | { | |
758cdca1 | 328 | wxLogError( wxString::Format(_("Unknown Property %s"),paramName) ); |
8f2b1cfd | 329 | } |
9c8046dd SC |
330 | // if we don't have the value of a create param set in the xml |
331 | // we use the default value | |
332 | if ( propiter != propertyNodes.end() ) | |
333 | { | |
5e8b5272 | 334 | wxXmlNode* prop = propiter->second; |
9c8046dd SC |
335 | if ( pi->GetTypeInfo()->IsObjectType() ) |
336 | { | |
5e8b5272 SC |
337 | createParamOids[i] = ReadComponent( prop, callbacks ); |
338 | createClassInfos[i] = | |
339 | wx_dynamic_cast(const wxClassTypeInfo*, pi->GetTypeInfo())->GetClassInfo(); | |
9c8046dd SC |
340 | } |
341 | else | |
342 | { | |
5e8b5272 SC |
343 | createParamOids[i] = wxInvalidObjectID; |
344 | createParams[i] = ReadValue( prop, pi->GetTypeInfo() ); | |
9c8046dd SC |
345 | if( pi->GetFlags() & wxPROP_ENUM_STORE_LONG ) |
346 | { | |
5e8b5272 SC |
347 | const wxEnumTypeInfo *eti = |
348 | wx_dynamic_cast(const wxEnumTypeInfo*, pi->GetTypeInfo() ); | |
8f2b1cfd SC |
349 | if ( eti ) |
350 | { | |
5e8b5272 SC |
351 | long realval; |
352 | eti->ConvertToLong( createParams[i], realval ); | |
e765d7ee | 353 | createParams[i] = wxAny( realval ); |
8f2b1cfd SC |
354 | } |
355 | else | |
356 | { | |
5e8b5272 | 357 | wxLogError( _("Type must have enum - long conversion") ); |
8f2b1cfd | 358 | } |
9c8046dd | 359 | } |
5e8b5272 | 360 | createClassInfos[i] = NULL; |
9c8046dd SC |
361 | } |
362 | ||
5e8b5272 | 363 | for ( size_t j = 0; j < propertyNames.size(); ++j ) |
9c8046dd SC |
364 | { |
365 | if ( propertyNames[j] == paramName ) | |
366 | { | |
5e8b5272 SC |
367 | propertyNames[j] = wxEmptyString; |
368 | break; | |
9c8046dd SC |
369 | } |
370 | } | |
371 | } | |
372 | else | |
373 | { | |
ed45345e SC |
374 | if ( pi->GetTypeInfo()->IsObjectType() ) |
375 | { | |
5e8b5272 SC |
376 | createParamOids[i] = wxNullObjectID; |
377 | createClassInfos[i] = | |
378 | wx_dynamic_cast(const wxClassTypeInfo*, pi->GetTypeInfo())->GetClassInfo(); | |
ed45345e SC |
379 | } |
380 | else | |
381 | { | |
5e8b5272 SC |
382 | createParams[i] = pi->GetDefaultValue(); |
383 | createParamOids[i] = wxInvalidObjectID; | |
ed45345e | 384 | } |
9c8046dd SC |
385 | } |
386 | } | |
387 | ||
388 | // got the parameters. Call the Create method | |
ed45345e SC |
389 | if ( classInfo->NeedsDirectConstruction() ) |
390 | callbacks->ConstructObject(objectID, classInfo, | |
391 | classInfo->GetCreateParamCount(), | |
392 | createParams, createParamOids, createClassInfos, metadata ); | |
393 | else | |
394 | callbacks->CreateObject(objectID, classInfo, | |
395 | classInfo->GetCreateParamCount(), | |
396 | createParams, createParamOids, createClassInfos, metadata ); | |
9c8046dd | 397 | |
5e8b5272 SC |
398 | // now stream in the rest of the properties, in the sequence their |
399 | // properties were written in the xml | |
400 | for ( size_t j = 0; j < propertyNames.size(); ++j ) | |
9c8046dd | 401 | { |
6636ef8d | 402 | if ( !propertyNames[j].empty() ) |
9c8046dd | 403 | { |
5e8b5272 | 404 | PropertyNodes::iterator propiter = propertyNodes.find( propertyNames[j] ); |
9c8046dd SC |
405 | if ( propiter != propertyNodes.end() ) |
406 | { | |
5e8b5272 SC |
407 | wxXmlNode* prop = propiter->second; |
408 | const wxPropertyInfo* pi = | |
409 | classInfo->FindPropertyInfo( propertyNames[j].c_str() ); | |
9c8046dd SC |
410 | if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION ) |
411 | { | |
5e8b5272 SC |
412 | const wxCollectionTypeInfo* collType = |
413 | wx_dynamic_cast( const wxCollectionTypeInfo*, pi->GetTypeInfo() ); | |
414 | const wxTypeInfo * elementType = collType->GetElementType(); | |
9c8046dd SC |
415 | while( prop ) |
416 | { | |
8f2b1cfd SC |
417 | if ( prop->GetName() != wxT("element") ) |
418 | { | |
5e8b5272 SC |
419 | wxLogError( _("A non empty collection must consist of 'element' nodes" ) ); |
420 | break; | |
8f2b1cfd | 421 | } |
5e8b5272 SC |
422 | |
423 | wxXmlNode* elementContent = prop->GetChildren(); | |
9c8046dd SC |
424 | if ( elementContent ) |
425 | { | |
426 | // we skip empty elements | |
427 | if ( elementType->IsObjectType() ) | |
428 | { | |
5e8b5272 | 429 | int valueId = ReadComponent( elementContent, callbacks ); |
9c8046dd SC |
430 | if ( valueId != wxInvalidObjectID ) |
431 | { | |
432 | if ( pi->GetAccessor()->HasAdder() ) | |
5e8b5272 | 433 | callbacks->AddToPropertyCollectionAsObject( objectID, classInfo, pi, valueId ); |
2abce515 | 434 | // TODO for collections we must have a notation on taking over ownership or not |
9c8046dd | 435 | if ( elementType->GetKind() == wxT_OBJECT && valueId != wxNullObjectID ) |
5e8b5272 | 436 | callbacks->DestroyObject( valueId, GetObjectClassInfo( valueId ) ); |
9c8046dd SC |
437 | } |
438 | } | |
439 | else | |
440 | { | |
e765d7ee | 441 | wxAny elementValue = ReadValue( elementContent, elementType ); |
9c8046dd | 442 | if ( pi->GetAccessor()->HasAdder() ) |
5e8b5272 | 443 | callbacks->AddToPropertyCollection( objectID, classInfo,pi, elementValue ); |
9c8046dd SC |
444 | } |
445 | } | |
5e8b5272 | 446 | prop = prop->GetNext(); |
9c8046dd SC |
447 | } |
448 | } | |
449 | else if ( pi->GetTypeInfo()->IsObjectType() ) | |
450 | { | |
ed45345e SC |
451 | // and object can either be streamed out a string or as an object |
452 | // in case we have no node, then the object's streaming out has been vetoed | |
453 | if ( prop ) | |
9c8046dd | 454 | { |
ed45345e SC |
455 | if ( prop->GetName() == wxT("object") ) |
456 | { | |
5e8b5272 | 457 | int valueId = ReadComponent( prop, callbacks ); |
ed45345e SC |
458 | if ( valueId != wxInvalidObjectID ) |
459 | { | |
5e8b5272 | 460 | callbacks->SetPropertyAsObject( objectID, classInfo, pi, valueId ); |
ed45345e | 461 | if ( pi->GetTypeInfo()->GetKind() == wxT_OBJECT && valueId != wxNullObjectID ) |
5e8b5272 | 462 | callbacks->DestroyObject( valueId, GetObjectClassInfo( valueId ) ); |
ed45345e SC |
463 | } |
464 | } | |
465 | else | |
466 | { | |
5e8b5272 | 467 | wxASSERT( pi->GetTypeInfo()->HasStringConverters() ); |
e765d7ee | 468 | wxAny nodeval = ReadValue( prop, pi->GetTypeInfo() ); |
5e8b5272 | 469 | callbacks->SetProperty( objectID, classInfo,pi, nodeval ); |
ed45345e | 470 | } |
9c8046dd SC |
471 | } |
472 | } | |
473 | else if ( pi->GetTypeInfo()->IsDelegateType() ) | |
474 | { | |
475 | if ( prop ) | |
476 | { | |
5e8b5272 SC |
477 | wxString resstring = prop->GetContent(); |
478 | wxInt32 pos = resstring.Find('.'); | |
8f2b1cfd SC |
479 | if ( pos != wxNOT_FOUND ) |
480 | { | |
5e8b5272 SC |
481 | int sinkOid = atol(resstring.Left(pos).ToAscii()); |
482 | wxString handlerName = resstring.Mid(pos+1); | |
483 | wxClassInfo* sinkClassInfo = GetObjectClassInfo( sinkOid ); | |
9c8046dd | 484 | |
5e8b5272 | 485 | callbacks->SetConnect( objectID, classInfo, pi, sinkClassInfo, |
44a00712 | 486 | sinkClassInfo->FindHandlerInfo(handlerName.c_str()), sinkOid ); |
8f2b1cfd SC |
487 | } |
488 | else | |
489 | { | |
5e8b5272 | 490 | wxLogError( _("incorrect event handler string, missing dot") ); |
8f2b1cfd | 491 | } |
9c8046dd SC |
492 | } |
493 | ||
494 | } | |
495 | else | |
496 | { | |
e765d7ee | 497 | wxAny nodeval = ReadValue( prop, pi->GetTypeInfo() ); |
499a9a62 SC |
498 | if( pi->GetFlags() & wxPROP_ENUM_STORE_LONG ) |
499 | { | |
5e8b5272 SC |
500 | const wxEnumTypeInfo *eti = |
501 | wx_dynamic_cast(const wxEnumTypeInfo*, pi->GetTypeInfo() ); | |
8f2b1cfd SC |
502 | if ( eti ) |
503 | { | |
5e8b5272 SC |
504 | long realval; |
505 | eti->ConvertToLong( nodeval, realval ); | |
e765d7ee | 506 | nodeval = wxAny( realval ); |
8f2b1cfd SC |
507 | } |
508 | else | |
509 | { | |
5e8b5272 | 510 | wxLogError( _("Type must have enum - long conversion") ); |
8f2b1cfd | 511 | } |
499a9a62 | 512 | } |
5e8b5272 | 513 | callbacks->SetProperty( objectID, classInfo,pi, nodeval ); |
9c8046dd SC |
514 | } |
515 | } | |
516 | } | |
517 | } | |
518 | ||
5e8b5272 SC |
519 | delete[] createParams; |
520 | delete[] createParamOids; | |
521 | delete[] createClassInfos; | |
9c8046dd SC |
522 | |
523 | return objectID; | |
524 | } | |
525 | ||
e765d7ee | 526 | wxAny wxObjectXmlReader::ReadValue(wxXmlNode *node, |
9c8046dd SC |
527 | const wxTypeInfo *type ) |
528 | { | |
5e8b5272 | 529 | wxString content; |
9c8046dd | 530 | if ( node ) |
5e8b5272 | 531 | content = node->GetContent(); |
e765d7ee | 532 | wxAny result; |
5e8b5272 SC |
533 | type->ConvertFromString( content, result ); |
534 | return result; | |
9c8046dd SC |
535 | } |
536 | ||
e765d7ee | 537 | int wxObjectXmlReader::ReadObject( const wxString &name, wxObjectReaderCallback *callbacks) |
9c8046dd | 538 | { |
5e8b5272 | 539 | wxXmlNode *iter = m_parent->GetChildren(); |
9c8046dd SC |
540 | while ( iter ) |
541 | { | |
5e8b5272 | 542 | wxString entryName; |
e765d7ee | 543 | if ( iter->GetAttribute(wxT("name"), &entryName) ) |
9c8046dd SC |
544 | { |
545 | if ( entryName == name ) | |
5e8b5272 | 546 | return ReadComponent( iter->GetChildren(), callbacks ); |
9c8046dd | 547 | } |
5e8b5272 | 548 | iter = iter->GetNext(); |
9c8046dd | 549 | } |
5e8b5272 | 550 | return wxInvalidObjectID; |
9c8046dd SC |
551 | } |
552 | ||
8e3f3880 | 553 | #endif // wxUSE_EXTENDED_RTTI |