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