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