]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/xtistrm.cpp
fixes for new lib dirs for wxMSW
[wxWidgets.git] / src / common / xtistrm.cpp
... / ...
CommitLineData
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
41using namespace std ;
42
43struct wxWriter::wxWriterInternal
44{
45 map< const wxObject* , int > m_writtenObjects ;
46 int m_nextId ;
47} ;
48
49wxWriter::wxWriter()
50{
51 m_data = new wxWriterInternal ;
52 m_data->m_nextId = 0 ;
53}
54
55wxWriter::~wxWriter()
56{
57 delete m_data ;
58}
59
60struct wxWriter::wxWriterInternalPropertiesData
61{
62 char nothing ;
63} ;
64
65void wxWriter::ClearObjectContext()
66{
67 delete m_data ;
68 m_data = new wxWriterInternal() ;
69 m_data->m_nextId = 0 ;
70}
71
72void 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
79void 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
115void 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}
153void 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
185void 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
271int wxWriter::GetObjectID(const wxObject *obj)
272{
273 if ( !IsObjectKnown( obj ) )
274 return wxInvalidObjectID ;
275
276 return m_data->m_writtenObjects[obj] ;
277}
278
279bool 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
290void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data )
291{
292 node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) );
293}
294
295wxString wxXmlGetContentFromNode( wxXmlNode *node )
296{
297 if ( node->GetChildren() )
298 return node->GetChildren()->GetContent() ;
299 else
300 return wxEmptyString ;
301}
302
303struct 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
322wxXmlWriter::wxXmlWriter( wxXmlNode * rootnode )
323{
324 m_data = new wxXmlWriterInternal() ;
325 m_data->m_root = rootnode ;
326 m_data->m_current = rootnode ;
327}
328
329wxXmlWriter::~wxXmlWriter()
330{
331 delete m_data ;
332}
333
334void 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
343void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString &WXUNUSED(name) )
344{
345 m_data->Pop() ;
346}
347
348void 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
364void 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
370void wxXmlWriter::DoWriteSimpleType( wxxVariant &value )
371{
372 wxXmlAddContentToNode( m_data->m_current ,value.GetAsString() ) ;
373}
374
375void 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
383void wxXmlWriter::DoEndWriteElement()
384{
385 m_data->Pop() ;
386}
387
388void 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
397void 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
405void 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
414void 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
422void 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
435struct wxReader::wxReaderInternal
436{
437 map<int,wxClassInfo*> m_classInfos;
438};
439
440wxReader::wxReader()
441{
442 m_data = new wxReaderInternal;
443}
444
445wxReader::~wxReader()
446{
447 delete m_data;
448}
449
450wxClassInfo* 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
456void 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
462bool 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/*
473Reading components has not to be extended for components
474as properties are always sought by typeinfo over all levels
475and create params are always toplevel class only
476*/
477
478int 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
698wxxVariant 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
709int 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
729struct 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
748wxRuntimeDepersister::wxRuntimeDepersister()
749{
750 m_data = new wxRuntimeDepersisterInternal() ;
751}
752
753wxRuntimeDepersister::~wxRuntimeDepersister()
754{
755 delete m_data ;
756}
757
758void 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
766void 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
795void wxRuntimeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
796{
797 wxObject *o;
798 o = m_data->GetObject(objectID);
799 delete o ;
800}
801
802void 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
812void 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
832void 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
850wxObject *wxRuntimeDepersister::GetObject(int objectID)
851{
852 return m_data->GetObject( objectID ) ;
853}
854
855// adds an element to a property collection
856void 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)
867void 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
892struct 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
911wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out)
912: m_fp(out)
913{
914 m_data = new wxCodeDepersisterInternal ;
915}
916
917wxCodeDepersister::~wxCodeDepersister()
918{
919 delete m_data ;
920}
921
922void 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
933void wxCodeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
934{
935 m_fp->WriteString( wxString::Format( "\tdelete %s;\n",
936 m_data->GetObjectName( objectID) ) );
937}
938
939wxString 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
960void 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
985void 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
996void 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
1013void 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)
1025void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID,
1026 const wxClassInfo *classInfo,
1027 const wxPropertyInfo* propertyInfo ,
1028 int valueObjectId)
1029{
1030 // TODO
1031}
1032
1033void 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
1052WX_DEFINE_OBJARRAY(wxxVariantArray);
1053
1054#endif