]> git.saurik.com Git - wxWidgets.git/blame - src/common/xtistrm.cpp
return immediately if the XPM is bad instead of spitting out thousands of error messages
[wxWidgets.git] / src / common / xtistrm.cpp
CommitLineData
70e88103
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/xtistrm.cpp
3// Purpose: streaming runtime metadata information
4// Author: Stefan Csomor
5// Modified by:
6// Created: 27/07/03
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
14f355c2 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
70e88103
SC
13#pragma implementation "xtistrm.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
16776ad9
SC
24#include "wx/hash.h"
25#include "wx/object.h"
70e88103
SC
26#endif
27
28#include "wx/xml/xml.h"
29#include "wx/tokenzr.h"
30#include "wx/xtistrm.h"
31#include "wx/txtstrm.h"
32
33#if wxUSE_EXTENDED_RTTI
ab6e4913
SC
34
35#include "wx/beforestd.h"
70e88103
SC
36#include <map>
37#include <vector>
38#include <string>
ab6e4913 39#include "wx/afterstd.h"
70e88103
SC
40
41using namespace std ;
42
16776ad9
SC
43struct wxWriter::wxWriterInternal
44{
45 map< const wxObject* , int > m_writtenObjects ;
46 int m_nextId ;
47} ;
48
49wxWriter::wxWriter()
50{
51 m_data = new wxWriterInternal ;
52 m_data->m_nextId = 0 ;
53}
54
55wxWriter::~wxWriter()
56{
57 delete m_data ;
58}
59
60struct wxWriter::wxWriterInternalPropertiesData
61{
62 map< string , int > m_writtenProperties ;
63} ;
64
ab6e4913
SC
65void wxWriter::ClearObjectContext()
66{
67 delete m_data ;
68 m_data = new wxWriterInternal() ;
69 m_data->m_nextId = 0 ;
70}
71
16776ad9
SC
72void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name )
73{
ab6e4913
SC
74 DoBeginWriteTopLevelEntry( name ) ;
75 WriteObject( object , classInfo , persister , false ) ;
76 DoEndWriteTopLevelEntry( name ) ;
77}
78
79void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded)
80{
81 if ( persister->BeforeWriteObject( this , object , classInfo ) )
16776ad9 82 {
ab6e4913
SC
83 if ( object == NULL )
84 DoWriteNullObject() ;
85 else if ( IsObjectKnown( object ) )
86 DoWriteRepeatedObject( GetObjectID(object) ) ;
2d51f067
SC
87 else
88 {
89 int oid = m_data->m_nextId++ ;
ab6e4913
SC
90 if ( !isEmbedded )
91 m_data->m_writtenObjects[object] = oid ;
92
2d51f067
SC
93 // in case this object is a wxDynamicObject we also have to insert is superclass
94 // instance with the same id, so that object relations are streamed out correctly
95 const wxDynamicObject* dynobj = dynamic_cast<const wxDynamicObject *>( object ) ;
ab6e4913 96 if ( !isEmbedded && dynobj )
2d51f067
SC
97 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
98
ab6e4913 99 DoBeginWriteObject( object , classInfo , oid ) ;
2d51f067
SC
100 wxWriterInternalPropertiesData data ;
101 WriteAllProperties( object , classInfo , persister , &data ) ;
ab6e4913 102 DoEndWriteObject( object , classInfo , oid ) ;
2d51f067 103 }
ab6e4913 104 persister->AfterWriteObject( this ,object , classInfo ) ;
16776ad9
SC
105 }
106}
107
ab6e4913
SC
108void wxWriter::FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler)
109{
110 wxList *dynamicEvents = evSource->GetDynamicEventTable() ;
111
112 if ( dynamicEvents )
113 {
114 wxList::compatibility_iterator node = dynamicEvents->GetFirst();
115 while (node)
116 {
117 wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
118
119 // find the match
120 if ( entry->m_fn && (dti->GetEventType() == entry->m_eventType) &&
121 (entry->m_id == -1 ||
122 (entry->m_lastId == -1 && evSource->GetId() == entry->m_id) ||
123 (entry->m_lastId != -1 &&
124 (evSource->GetId() >= entry->m_id && evSource->GetId() <= entry->m_lastId) ) ) &&
125 entry->m_eventSink
126 )
127 {
128 sink = entry->m_eventSink ;
129 const wxClassInfo* sinkClassInfo = sink->GetClassInfo() ;
130 const wxHandlerInfo* sinkHandler = sinkClassInfo->GetFirstHandler() ;
131 while ( sinkHandler )
132 {
133 if ( sinkHandler->GetEventFunction() == entry->m_fn )
134 {
135 handler = sinkHandler ;
136 break ;
137 }
138 sinkHandler = sinkHandler->GetNext() ;
139 }
140 break ;
141 }
142 node = node->GetNext();
143 }
144 }
145}
16776ad9
SC
146void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
147{
16a45a23
SC
148 // in case this object is wxDynamic object we have to hand over the streaming
149 // of the properties of the superclasses to the real super class instance
150 {
151 const wxObject *iterobj = obj ;
152 const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject* > (iterobj ) ;
153 if ( dynobj )
154 iterobj = dynobj->GetSuperClassInstance() ;
155 const wxClassInfo** parents = ci->GetParents() ;
156 for ( int i = 0 ; parents[i] ; ++ i )
157 {
158 WriteAllProperties( iterobj , parents[i] , persister , data ) ;
159 }
160 }
161
16776ad9
SC
162 const wxPropertyInfo *pi = ci->GetFirstProperty() ;
163 while( pi )
164 {
ab6e4913 165 // this property was not written yet in this object and we don't get a veto
16a45a23
SC
166 // if ( data->m_writtenProperties.find( pi->GetName() ) == data->m_writtenProperties.end() )
167 // we will have to handle property overrides differently
16776ad9
SC
168 {
169 data->m_writtenProperties[ pi->GetName() ] = 1 ;
ab6e4913
SC
170 DoBeginWriteProperty( pi ) ;
171 if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
16776ad9 172 {
ab6e4913
SC
173 wxxVariantArray data = pi->GetAccessor()->GetPropertyCollection(obj) ;
174 const wxTypeInfo * elementType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() )->GetElementType() ;
175 for ( size_t i = 0 ; i < data.GetCount() ; ++i )
16776ad9 176 {
ab6e4913
SC
177 DoBeginWriteElement() ;
178 wxxVariant value = data[i] ;
179 if ( persister->BeforeWriteProperty( this , pi , value ) )
16776ad9 180 {
ab6e4913
SC
181 const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( elementType ) ;
182 if ( cti )
2d51f067 183 {
ab6e4913
SC
184 const wxClassInfo* pci = cti->GetClassInfo() ;
185 wxObject *vobj = pci->VariantToInstance( value ) ;
186 WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT ) ;
2d51f067 187 }
ab6e4913
SC
188 else
189 {
190 DoWriteSimpleType( value ) ;
16776ad9 191 }
16776ad9 192 }
ab6e4913 193 DoEndWriteElement() ;
16776ad9
SC
194 }
195 }
196 else
197 {
198 const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ;
199 if ( dti )
200 {
201 const wxObject* sink = NULL ;
202 const wxHandlerInfo *handler = NULL ;
ab6e4913 203
a315dda6
SC
204 const wxWindow * evSource = dynamic_cast<const wxWindow *>(obj) ;
205 wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
206
ab6e4913
SC
207 FindConnectEntry( evSource , dti , sink , handler ) ;
208 if ( persister->BeforeWriteDelegate( this , obj , ci , pi , sink , handler ) )
16776ad9
SC
209 {
210 if ( sink != NULL && handler != NULL )
211 {
212 wxASSERT_MSG( IsObjectKnown( sink ) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
213 DoWriteDelegate( obj , ci , pi , sink , GetObjectID( sink ) , sink->GetClassInfo() , handler ) ;
214 }
215 }
216 }
217 else
218 {
219 wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
ab6e4913 220 if ( persister->BeforeWriteProperty( this , pi , value ) )
16776ad9 221 {
ab6e4913
SC
222 const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ;
223 if ( cti )
224 {
225 const wxClassInfo* pci = cti->GetClassInfo() ;
226 wxObject *vobj = pci->VariantToInstance( value ) ;
227 WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT ) ;
228 }
229 else
230 {
231 DoWriteSimpleType( value ) ;
232 }
16776ad9
SC
233 }
234 }
235 }
ab6e4913 236 DoEndWriteProperty( pi ) ;
16776ad9
SC
237 }
238 pi = pi->GetNext() ;
239 }
16a45a23 240 }
70e88103 241
16776ad9
SC
242int wxWriter::GetObjectID(const wxObject *obj)
243{
244 if ( !IsObjectKnown( obj ) )
245 return wxInvalidObjectID ;
246
247 return m_data->m_writtenObjects[obj] ;
248}
249
250bool wxWriter::IsObjectKnown( const wxObject *obj )
251{
252 return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ;
253}
254
255//
256// XML Streaming
257//
258
259// convenience functions
260
261void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data )
262{
263 node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) );
264}
265
266wxString wxXmlGetContentFromNode( wxXmlNode *node )
267{
268 if ( node->GetChildren() )
269 return node->GetChildren()->GetContent() ;
270 else
271 return wxEmptyString ;
272}
273
274struct wxXmlWriter::wxXmlWriterInternal
275{
276 wxXmlNode *m_root ;
277 wxXmlNode *m_current ;
278 vector< wxXmlNode * > m_objectStack ;
ab6e4913
SC
279
280 void Push( wxXmlNode *newCurrent )
281 {
282 m_objectStack.push_back( m_current ) ;
283 m_current = newCurrent ;
284 }
285
286 void Pop()
287 {
288 m_current = m_objectStack.back() ;
289 m_objectStack.pop_back() ;
290 }
16776ad9
SC
291} ;
292
293wxXmlWriter::wxXmlWriter( wxXmlNode * rootnode )
294{
295 m_data = new wxXmlWriterInternal() ;
296 m_data->m_root = rootnode ;
297 m_data->m_current = rootnode ;
298}
299
300wxXmlWriter::~wxXmlWriter()
301{
302 delete m_data ;
303}
304
ab6e4913 305void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString &name )
16776ad9 306{
ab6e4913
SC
307 wxXmlNode *pnode;
308 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("entry"));
309 pnode->AddProperty(wxString("name"), name);
310 m_data->m_current->AddChild(pnode) ;
311 m_data->Push( pnode ) ;
312}
16776ad9 313
ab6e4913
SC
314void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString &WXUNUSED(name) )
315{
316 m_data->Pop() ;
317}
318
319void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID )
320{
321 wxXmlNode *pnode;
322 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object"));
323 pnode->AddProperty(wxT("class"), wxString(classInfo->GetClassName()));
324 pnode->AddProperty(wxT("id"), wxString::Format( "%d" , objectID ) );
325
326 m_data->m_current->AddChild(pnode) ;
327 m_data->Push( pnode ) ;
16776ad9
SC
328}
329
330// end of writing the root object
ab6e4913 331void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) )
16776ad9 332{
ab6e4913 333 m_data->Pop() ;
16776ad9
SC
334}
335
336// writes a property in the stream format
ab6e4913
SC
337void wxXmlWriter::DoWriteSimpleType( wxxVariant &value )
338{
339 wxXmlAddContentToNode( m_data->m_current ,value.GetAsString() ) ;
340}
341
342void wxXmlWriter::DoBeginWriteElement()
16776ad9
SC
343{
344 wxXmlNode *pnode;
ab6e4913
SC
345 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "element" );
346 m_data->m_current->AddChild(pnode) ;
347 m_data->Push( pnode ) ;
16776ad9
SC
348}
349
ab6e4913 350void wxXmlWriter::DoEndWriteElement()
16776ad9 351{
ab6e4913 352 m_data->Pop() ;
16776ad9
SC
353}
354
ab6e4913 355void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo *pi )
16776ad9 356{
ab6e4913
SC
357 wxXmlNode *pnode;
358 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "prop" );
359 pnode->AddProperty(wxT("name"), pi->GetName() );
360 m_data->m_current->AddChild(pnode) ;
361 m_data->Push( pnode ) ;
362}
16776ad9 363
ab6e4913
SC
364void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo *WXUNUSED(propInfo) )
365{
366 m_data->Pop() ;
16776ad9
SC
367}
368
ab6e4913
SC
369
370
371// insert an object reference to an already written object
372void wxXmlWriter::DoWriteRepeatedObject( int objectID )
16776ad9 373{
ab6e4913
SC
374 wxXmlNode *pnode;
375 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object"));
376 pnode->AddProperty(wxString("href"), wxString::Format( "%d" , objectID ) );
377 m_data->m_current->AddChild(pnode) ;
16776ad9
SC
378}
379
ab6e4913
SC
380// insert a null reference
381void wxXmlWriter::DoWriteNullObject()
382{
383 wxXmlNode *pnode;
384 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object"));
385 m_data->m_current->AddChild(pnode) ;
386}
16776ad9
SC
387
388// writes a delegate in the stream format
16a45a23 389void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(pi) ,
16776ad9
SC
390 const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo )
391{
392 if ( eventSink != NULL && handlerInfo != NULL )
393 {
ab6e4913 394 wxXmlAddContentToNode( m_data->m_current ,wxString::Format(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName()) ) ;
16776ad9 395 }
70e88103
SC
396}
397
398// ----------------------------------------------------------------------------
45212047 399// reading objects in
70e88103
SC
400// ----------------------------------------------------------------------------
401
70e88103
SC
402struct wxReader::wxReaderInternal
403{
45212047 404 map<int,wxClassInfo*> m_classInfos;
70e88103
SC
405};
406
45212047 407wxReader::wxReader()
70e88103 408{
45212047 409 m_data = new wxReaderInternal;
70e88103
SC
410}
411
412wxReader::~wxReader()
413{
45212047 414 delete m_data;
70e88103
SC
415}
416
45212047 417wxClassInfo* wxReader::GetObjectClassInfo(int objectID)
70e88103 418{
45212047
SC
419 assert( m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() );
420 return m_data->m_classInfos[objectID] ;
70e88103
SC
421}
422
45212047 423void wxReader::SetObjectClassInfo(int objectID, wxClassInfo *classInfo )
70e88103 424{
16776ad9
SC
425 assert( m_data->m_classInfos.find(objectID) == m_data->m_classInfos.end() ) ;
426 m_data->m_classInfos[objectID] = classInfo ;
70e88103
SC
427}
428
45212047 429bool wxReader::HasObjectClassInfo( int objectID )
70e88103 430{
16776ad9 431 return m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() ;
70e88103
SC
432}
433
70e88103 434
45212047
SC
435// ----------------------------------------------------------------------------
436// reading xml in
437// ----------------------------------------------------------------------------
70e88103
SC
438
439/*
16776ad9
SC
440Reading components has not to be extended for components
441as properties are always sought by typeinfo over all levels
442and create params are always toplevel class only
70e88103
SC
443*/
444
45212047 445int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
70e88103 446{
16a45a23 447 wxASSERT_MSG( callbacks , wxT("Does not support reading without a Depersistor") ) ;
45212047
SC
448 wxString className;
449 wxClassInfo *classInfo;
70e88103 450
16776ad9
SC
451 wxxVariant *createParams ;
452 int *createParamOids ;
453 const wxClassInfo** createClassInfos ;
45212047
SC
454 wxXmlNode *children;
455 int objectID;
ab6e4913 456 wxString ObjectIdString ;
70e88103 457
45212047 458 children = node->GetChildren();
ab6e4913
SC
459 if (!children)
460 {
461 // check for a null object or href
462 if (node->GetPropVal("href" , &ObjectIdString ) )
463 {
464 objectID = atoi( ObjectIdString.c_str() ) ;
465 wxASSERT_MSG( HasObjectClassInfo( objectID ) , wxT("Forward hrefs are not supported") ) ;
466 return objectID ;
467 }
468 if ( !node->GetPropVal("id" , &ObjectIdString ) )
469 {
470 return wxNullObjectID;
471 }
472 }
45212047 473 if (!node->GetPropVal("class", &className))
70e88103 474 {
16776ad9
SC
475 // No class name. Eek. FIXME: error handling
476 return wxInvalidObjectID;
70e88103 477 }
16776ad9 478 classInfo = wxClassInfo::FindClass(className);
ab6e4913
SC
479 wxASSERT_MSG( classInfo , wxString::Format(wxT("unknown class %s"),className ) ) ;
480 wxASSERT_MSG( !children || children->GetType() != wxXML_TEXT_NODE , wxT("objects cannot have XML Text Nodes") ) ;
45212047 481 if (!node->GetPropVal("id", &ObjectIdString))
70e88103 482 {
ab6e4913 483 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
16776ad9
SC
484 // No object id. Eek. FIXME: error handling
485 return wxInvalidObjectID;
70e88103 486 }
45212047 487 objectID = atoi( ObjectIdString.c_str() ) ;
16776ad9 488 // is this object already has been streamed in, return it here
ab6e4913 489 wxASSERT_MSG( !HasObjectClassInfo( objectID ) , wxString::Format(wxT("Doubly used id : %d"), objectID ) ) ;
70e88103 490
16776ad9
SC
491 // new object, start with allocation
492 // first make the object know to our internal registry
493 SetObjectClassInfo( objectID , classInfo ) ;
45212047
SC
494
495 callbacks->AllocateObject(objectID, classInfo);
70e88103 496
16776ad9 497 //
70e88103 498 // stream back the Create parameters first
16776ad9
SC
499 createParams = new wxxVariant[ classInfo->GetCreateParamCount() ] ;
500 createParamOids = new int[classInfo->GetCreateParamCount() ] ;
501 createClassInfos = new const wxClassInfo*[classInfo->GetCreateParamCount() ] ;
502
503 typedef map<string, wxXmlNode *> PropertyNodes ;
504 typedef vector<string> PropertyNames ;
505
506 PropertyNodes propertyNodes ;
507 PropertyNames propertyNames ;
508
509 while( children )
510 {
ab6e4913
SC
511 wxString name ;
512 children->GetPropVal( wxT("name") , &name ) ;
513 propertyNames.push_back( name.c_str() ) ;
514 propertyNodes[name.c_str()] = children->GetChildren() ;
16776ad9
SC
515 children = children->GetNext() ;
516 }
517
518 for ( int i = 0 ; i <classInfo->GetCreateParamCount() ; ++i )
519 {
520 const wxChar* paramName = classInfo->GetCreateParamName(i) ;
521 PropertyNodes::iterator propiter = propertyNodes.find( paramName ) ;
522 const wxPropertyInfo* pi = classInfo->FindPropertyInfo( paramName ) ;
16a45a23 523 wxASSERT_MSG(pi,wxString::Format("Unkown Property %s",paramName) ) ;
16776ad9
SC
524 // if we don't have the value of a create param set in the xml
525 // we use the default value
526 if ( propiter != propertyNodes.end() )
527 {
528 wxXmlNode* prop = propiter->second ;
529 if ( pi->GetTypeInfo()->IsObjectType() )
530 {
531 createParamOids[i] = ReadComponent( prop , callbacks ) ;
532 createClassInfos[i] = dynamic_cast<const wxClassTypeInfo*>(pi->GetTypeInfo())->GetClassInfo() ;
533 }
534 else
535 {
536 createParamOids[i] = wxInvalidObjectID ;
537 createParams[i] = ReadValue( prop , pi->GetAccessor() ) ;
538 createClassInfos[i] = NULL ;
539 }
540
541 for ( size_t j = 0 ; j < propertyNames.size() ; ++j )
542 {
543 if ( propertyNames[j] == paramName )
544 {
545 propertyNames[j] = "" ;
546 break ;
547 }
548 }
549 }
550 else
551 {
552 createParams[i] = pi->GetDefaultValue() ;
553 }
554 }
70e88103
SC
555
556 // got the parameters. Call the Create method
45212047 557 callbacks->CreateObject(objectID, classInfo,
16776ad9
SC
558 classInfo->GetCreateParamCount(),
559 createParams, createParamOids, createClassInfos);
70e88103
SC
560
561 // now stream in the rest of the properties, in the sequence their properties were written in the xml
16776ad9
SC
562 for ( size_t j = 0 ; j < propertyNames.size() ; ++j )
563 {
564 if ( propertyNames[j].length() )
565 {
566 PropertyNodes::iterator propiter = propertyNodes.find( propertyNames[j] ) ;
567 if ( propiter != propertyNodes.end() )
568 {
569 wxXmlNode* prop = propiter->second ;
570 const wxPropertyInfo* pi = classInfo->FindPropertyInfo( propertyNames[j].c_str() ) ;
ab6e4913
SC
571 if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
572 {
16a45a23
SC
573 const wxCollectionTypeInfo* collType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() ) ;
574 const wxTypeInfo * elementType = collType->GetElementType() ;
ab6e4913
SC
575 while( prop )
576 {
577 wxASSERT_MSG(prop->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
578 wxXmlNode* elementContent = prop->GetChildren() ;
579 wxASSERT_MSG(elementContent, wxT("An element node cannot be empty")) ;
580 if ( elementType->IsObjectType() )
581 {
582 int valueId = ReadComponent( elementContent , callbacks ) ;
16a45a23 583 if ( valueId != wxInvalidObjectID )
ab6e4913 584 {
16a45a23
SC
585 if ( pi->GetAccessor()->HasAdder() )
586 callbacks->AddToPropertyCollectionAsObject( objectID , classInfo , pi , valueId ) ;
587 // TODO for collections we must have a notation on taking over ownership or not
588 if ( elementType->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
589 callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
ab6e4913
SC
590 }
591 }
592 else
593 {
594 wxxVariant elementValue = ReadValue( prop , pi->GetAccessor() ) ;
16a45a23
SC
595 if ( pi->GetAccessor()->HasAdder() )
596 callbacks->AddToPropertyCollection( objectID , classInfo ,pi , elementValue ) ;
ab6e4913
SC
597 }
598 prop = prop->GetNext() ;
599 }
600 }
601 else if ( pi->GetTypeInfo()->IsObjectType() )
16776ad9
SC
602 {
603 int valueId = ReadComponent( prop , callbacks ) ;
16a45a23 604 if ( valueId != wxInvalidObjectID )
16776ad9 605 {
16a45a23
SC
606 callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ;
607 if ( pi->GetTypeInfo()->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
608 callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
16776ad9
SC
609 }
610 }
611 else if ( pi->GetTypeInfo()->IsDelegateType() )
612 {
ab6e4913
SC
613 if ( prop )
614 {
615 wxString resstring = prop->GetContent() ;
616 wxInt32 pos = resstring.Find('.') ;
617 assert( pos != wxNOT_FOUND ) ;
618 int sinkOid = atol(resstring.Left(pos)) ;
619 wxString handlerName = resstring.Mid(pos+1) ;
620 wxClassInfo* sinkClassInfo = GetObjectClassInfo( sinkOid ) ;
621
16a45a23
SC
622 callbacks->SetConnect( objectID , classInfo , dynamic_cast<const wxDelegateTypeInfo*>(pi->GetTypeInfo()) , sinkClassInfo ,
623 sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ;
ab6e4913 624 }
16776ad9
SC
625
626 }
627 else
628 {
16a45a23 629 callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetAccessor() ) ) ;
16776ad9
SC
630 }
631 }
632 }
633 }
634
635 delete[] createParams ;
636 delete[] createParamOids ;
637 delete[] createClassInfos ;
70e88103 638
45212047
SC
639 return objectID;
640}
70e88103 641
45212047 642wxxVariant wxXmlReader::ReadValue(wxXmlNode *node,
16776ad9 643 wxPropertyAccessor *accessor )
45212047 644{
ab6e4913
SC
645 wxString content ;
646 if ( node )
647 content = node->GetContent() ;
648 return accessor->ReadValue(content) ;
45212047
SC
649}
650
ab6e4913 651int wxXmlReader::ReadObject( const wxString &name , wxDepersister *callbacks)
45212047 652{
ab6e4913
SC
653 wxXmlNode *iter = m_parent->GetChildren() ;
654 while ( iter )
655 {
656 wxString entryName ;
657 if ( iter->GetPropVal("name", &entryName) )
658 {
659 if ( entryName == name )
660 return ReadComponent( iter->GetChildren() , callbacks ) ;
661 }
662 iter = iter->GetNext() ;
663 }
664 return wxInvalidObjectID ;
70e88103
SC
665}
666
667// ----------------------------------------------------------------------------
668// depersisting to memory
669// ----------------------------------------------------------------------------
670
45212047 671struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
70e88103 672{
45212047
SC
673 map<int,wxObject *> m_objects;
674
16776ad9
SC
675 void SetObject(int objectID, wxObject *obj )
676 {
677 assert( m_objects.find(objectID) == m_objects.end() ) ;
678 m_objects[objectID] = obj ;
679 }
680 wxObject* GetObject( int objectID )
681 {
682 if ( objectID == wxNullObjectID )
683 return NULL ;
684
685 assert( m_objects.find(objectID) != m_objects.end() ) ;
686 return m_objects[objectID] ;
687 }
45212047
SC
688} ;
689
690wxRuntimeDepersister::wxRuntimeDepersister()
691{
16776ad9 692 m_data = new wxRuntimeDepersisterInternal() ;
70e88103
SC
693}
694
45212047 695wxRuntimeDepersister::~wxRuntimeDepersister()
70e88103 696{
16776ad9 697 delete m_data ;
70e88103
SC
698}
699
45212047 700void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo)
70e88103
SC
701{
702 wxObject *O;
45212047
SC
703 O = classInfo->CreateObject();
704 m_data->SetObject(objectID, O);
705}
706
707void wxRuntimeDepersister::CreateObject(int objectID,
16776ad9
SC
708 const wxClassInfo *classInfo,
709 int paramCount,
710 wxxVariant *params,
711 int *objectIdValues,
712 const wxClassInfo **objectClassInfos)
45212047
SC
713{
714 wxObject *o;
715 o = m_data->GetObject(objectID);
16776ad9
SC
716 for ( int i = 0 ; i < paramCount ; ++i )
717 {
718 if ( objectIdValues[i] != wxInvalidObjectID )
719 {
720 wxObject *o;
721 o = m_data->GetObject(objectIdValues[i]);
2d51f067
SC
722 // if this is a dynamic object and we are asked for another class
723 // than wxDynamicObject we cast it down manually.
724 wxDynamicObject *dyno = dynamic_cast< wxDynamicObject * > (o) ;
725 if ( dyno!=NULL && (objectClassInfos[i] != dyno->GetClassInfo()) )
726 {
727 o = dyno->GetSuperClassInstance() ;
728 }
16776ad9
SC
729 params[i] = objectClassInfos[i]->InstanceToVariant(o) ;
730 }
731 }
45212047
SC
732 classInfo->Create(o, paramCount, params);
733}
734
735void wxRuntimeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
736{
737 wxObject *o;
738 o = m_data->GetObject(objectID);
16776ad9 739 delete o ;
70e88103
SC
740}
741
45212047 742void wxRuntimeDepersister::SetProperty(int objectID,
2d51f067 743 const wxClassInfo *classInfo,
16776ad9
SC
744 const wxPropertyInfo* propertyInfo,
745 const wxxVariant &value)
70e88103 746{
45212047
SC
747 wxObject *o;
748 o = m_data->GetObject(objectID);
2d51f067 749 classInfo->SetProperty( o , propertyInfo->GetName() , value ) ;
45212047
SC
750}
751
752void wxRuntimeDepersister::SetPropertyAsObject(int objectID,
2d51f067 753 const wxClassInfo *classInfo,
16776ad9
SC
754 const wxPropertyInfo* propertyInfo,
755 int valueObjectId)
45212047
SC
756{
757 wxObject *o, *valo;
758 o = m_data->GetObject(objectID);
759 valo = m_data->GetObject(valueObjectId);
2d51f067
SC
760 const wxClassInfo* valClassInfo = (dynamic_cast<const wxClassTypeInfo*>(propertyInfo->GetTypeInfo()))->GetClassInfo() ;
761 // if this is a dynamic object and we are asked for another class
762 // than wxDynamicObject we cast it down manually.
763 wxDynamicObject *dynvalo = dynamic_cast< wxDynamicObject * > (valo) ;
764 if ( dynvalo!=NULL && (valClassInfo != dynvalo->GetClassInfo()) )
765 {
766 valo = dynvalo->GetSuperClassInstance() ;
767 }
768
769 classInfo->SetProperty( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ;
45212047
SC
770}
771
772void wxRuntimeDepersister::SetConnect(int eventSourceObjectID,
16776ad9
SC
773 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
774 const wxDelegateTypeInfo *delegateInfo ,
775 const wxClassInfo *WXUNUSED(eventSinkClassInfo) ,
776 const wxHandlerInfo* handlerInfo ,
777 int eventSinkObjectID )
45212047 778{
16776ad9
SC
779 wxWindow *ehsource = dynamic_cast< wxWindow* >( m_data->GetObject( eventSourceObjectID ) ) ;
780 wxEvtHandler *ehsink = dynamic_cast< wxEvtHandler *>(m_data->GetObject(eventSinkObjectID) ) ;
70e88103 781
16776ad9
SC
782 if ( ehsource && ehsink )
783 {
784 ehsource->Connect( ehsource->GetId() , delegateInfo->GetEventType() ,
785 handlerInfo->GetEventFunction() , NULL /*user data*/ ,
786 ehsink ) ;
787 }
70e88103
SC
788}
789
45212047
SC
790wxObject *wxRuntimeDepersister::GetObject(int objectID)
791{
16776ad9 792 return m_data->GetObject( objectID ) ;
45212047
SC
793}
794
16a45a23
SC
795// adds an element to a property collection
796void wxRuntimeDepersister::AddToPropertyCollection( int objectID ,
797 const wxClassInfo *classInfo,
798 const wxPropertyInfo* propertyInfo ,
799 const wxxVariant &value)
800{
801 wxObject *o;
802 o = m_data->GetObject(objectID);
803 classInfo->AddToPropertyCollection( o , propertyInfo->GetName() , value ) ;
804}
805
806// sets the corresponding property (value is an object)
807void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID,
808 const wxClassInfo *classInfo,
809 const wxPropertyInfo* propertyInfo ,
810 int valueObjectId)
811{
812 wxObject *o, *valo;
813 o = m_data->GetObject(objectID);
814 valo = m_data->GetObject(valueObjectId);
815 const wxCollectionTypeInfo * collectionTypeInfo = dynamic_cast< const wxCollectionTypeInfo * >(propertyInfo->GetTypeInfo() ) ;
816 const wxClassInfo* valClassInfo = (dynamic_cast<const wxClassTypeInfo*>(collectionTypeInfo->GetElementType()))->GetClassInfo() ;
817 // if this is a dynamic object and we are asked for another class
818 // than wxDynamicObject we cast it down manually.
819 wxDynamicObject *dynvalo = dynamic_cast< wxDynamicObject * > (valo) ;
820 if ( dynvalo!=NULL && (valClassInfo != dynvalo->GetClassInfo()) )
821 {
822 valo = dynvalo->GetSuperClassInstance() ;
823 }
824
825 classInfo->AddToPropertyCollection( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ;
826}
45212047 827
70e88103
SC
828// ----------------------------------------------------------------------------
829// depersisting to code
830// ----------------------------------------------------------------------------
831
45212047
SC
832struct wxCodeDepersister::wxCodeDepersisterInternal
833{
834 map<int,string> m_objectNames ;
835
16776ad9
SC
836 void SetObjectName(int objectID, const wxString &name )
837 {
838 assert( m_objectNames.find(objectID) == m_objectNames.end() ) ;
839 m_objectNames[objectID] = (const char *)name;
840 }
841 wxString GetObjectName( int objectID )
842 {
843 if ( objectID == wxNullObjectID )
844 return "NULL" ;
845
846 assert( m_objectNames.find(objectID) != m_objectNames.end() ) ;
847 return wxString( m_objectNames[objectID].c_str() ) ;
848 }
45212047 849} ;
70e88103 850
45212047 851wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out)
16776ad9 852: m_fp(out)
70e88103 853{
16776ad9 854 m_data = new wxCodeDepersisterInternal ;
45212047
SC
855}
856
857wxCodeDepersister::~wxCodeDepersister()
858{
16776ad9 859 delete m_data ;
45212047
SC
860}
861
862void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo)
863{
16776ad9
SC
864 wxString objectName = wxString::Format( "LocalObject_%d" , objectID ) ;
865 m_fp->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
866 classInfo->GetClassName(),
867 objectName,
868 classInfo->GetClassName()) );
869 m_data->SetObjectName( objectID , objectName ) ;
45212047
SC
870}
871
872void wxCodeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
873{
16776ad9
SC
874 m_fp->WriteString( wxString::Format( "\tdelete %s;\n",
875 m_data->GetObjectName( objectID) ) );
45212047
SC
876}
877
878wxString wxCodeDepersister::ValueAsCode( const wxxVariant &param )
879{
16776ad9
SC
880 wxString value ;
881 const wxTypeInfo* type = param.GetTypeInfo() ;
882 if ( type->GetKind() == wxT_CUSTOM )
883 {
884 const wxCustomTypeInfo* cti = dynamic_cast<const wxCustomTypeInfo*>(type) ;
885 wxASSERT_MSG( cti , wxT("Internal error, illegal wxCustomTypeInfo") ) ;
886 value.Printf( "%s(%s)",cti->GetTypeName(),param.GetAsString() );
887 }
888 else if ( type->GetKind() == wxT_STRING )
889 {
890 value.Printf( "\"%s\"",param.GetAsString() );
891 }
892 else
893 {
894 value.Printf( "%s", param.GetAsString() );
895 }
896 return value ;
70e88103
SC
897}
898
45212047 899void wxCodeDepersister::CreateObject(int objectID,
16776ad9
SC
900 const wxClassInfo *WXUNUSED(classInfo),
901 int paramCount,
902 wxxVariant *params,
903 int *objectIDValues,
904 const wxClassInfo **WXUNUSED(objectClassInfos)
905 )
70e88103
SC
906{
907 int i;
16776ad9 908 m_fp->WriteString( wxString::Format( "\t%s->Create(", m_data->GetObjectName(objectID) ) );
45212047 909 for (i = 0; i < paramCount; i++)
70e88103 910 {
16776ad9
SC
911 if ( objectIDValues[i] != wxInvalidObjectID )
912 m_fp->WriteString( wxString::Format( "%s", m_data->GetObjectName( objectIDValues[i] ) ) );
913 else
914 {
915 m_fp->WriteString( wxString::Format( "%s", ValueAsCode(params[i]) ) );
916 }
917 if (i < paramCount - 1)
918 m_fp->WriteString( ", ");
70e88103 919 }
45212047 920 m_fp->WriteString( ");\n");
70e88103
SC
921}
922
45212047 923void wxCodeDepersister::SetProperty(int objectID,
16776ad9
SC
924 const wxClassInfo *WXUNUSED(classInfo),
925 const wxPropertyInfo* propertyInfo,
926 const wxxVariant &value)
70e88103 927{
45212047 928 m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
16776ad9
SC
929 m_data->GetObjectName(objectID),
930 propertyInfo->GetAccessor()->GetSetterName(),
931 ValueAsCode(value)) );
45212047
SC
932}
933
934void wxCodeDepersister::SetPropertyAsObject(int objectID,
16776ad9
SC
935 const wxClassInfo *WXUNUSED(classInfo),
936 const wxPropertyInfo* propertyInfo,
937 int valueObjectId)
938{
939 if ( propertyInfo->GetTypeInfo()->GetKind() == wxT_OBJECT )
940 m_fp->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
941 m_data->GetObjectName(objectID),
942 propertyInfo->GetAccessor()->GetSetterName(),
943 m_data->GetObjectName( valueObjectId) ) );
944 else
945 m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
946 m_data->GetObjectName(objectID),
947 propertyInfo->GetAccessor()->GetSetterName(),
948 m_data->GetObjectName( valueObjectId) ) );
70e88103
SC
949}
950
16a45a23
SC
951void wxCodeDepersister::AddToPropertyCollection( int objectID ,
952 const wxClassInfo *classInfo,
953 const wxPropertyInfo* propertyInfo ,
954 const wxxVariant &value)
955{
956 m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
957 m_data->GetObjectName(objectID),
958 propertyInfo->GetAccessor()->GetAdderName(),
959 ValueAsCode(value)) );
960}
961
962// sets the corresponding property (value is an object)
963void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID,
964 const wxClassInfo *classInfo,
965 const wxPropertyInfo* propertyInfo ,
966 int valueObjectId)
967{
968 // TODO
969}
970
45212047 971void wxCodeDepersister::SetConnect(int eventSourceObjectID,
16776ad9
SC
972 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
973 const wxDelegateTypeInfo *delegateInfo ,
974 const wxClassInfo *eventSinkClassInfo ,
975 const wxHandlerInfo* handlerInfo ,
976 int eventSinkObjectID )
977{
978 wxString ehsource = m_data->GetObjectName( eventSourceObjectID ) ;
979 wxString ehsink = m_data->GetObjectName(eventSinkObjectID) ;
980 wxString ehsinkClass = eventSinkClassInfo->GetClassName() ;
981 int eventType = delegateInfo->GetEventType() ;
982 wxString handlerName = handlerInfo->GetName() ;
983
984 m_fp->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
985 ehsource , ehsource , eventType , ehsinkClass , handlerName , ehsink ) );
70e88103
SC
986}
987
ab6e4913
SC
988#include <wx/arrimpl.cpp>
989
990WX_DEFINE_OBJARRAY(wxxVariantArray);
991
70e88103 992#endif