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