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