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