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