]> git.saurik.com Git - wxWidgets.git/blame - src/common/xtistrm.cpp
xti additions / changes, trying to reduce dependencies
[wxWidgets.git] / src / common / xtistrm.cpp
CommitLineData
70e88103
SC
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
14f355c2 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
70e88103
SC
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
16776ad9
SC
24#include "wx/hash.h"
25#include "wx/object.h"
70e88103
SC
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
ab6e4913
SC
34
35#include "wx/beforestd.h"
70e88103
SC
36#include <map>
37#include <vector>
38#include <string>
ab6e4913 39#include "wx/afterstd.h"
70e88103
SC
40
41using namespace std ;
42
16776ad9
SC
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{
cb73e600 62 char nothing ;
16776ad9
SC
63} ;
64
ab6e4913
SC
65void wxWriter::ClearObjectContext()
66{
67 delete m_data ;
68 m_data = new wxWriterInternal() ;
69 m_data->m_nextId = 0 ;
70}
71
4f8ffae1 72void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name , wxxVariantArray &metadata )
16776ad9 73{
ab6e4913 74 DoBeginWriteTopLevelEntry( name ) ;
4f8ffae1 75 WriteObject( object , classInfo , persister , false , metadata) ;
ab6e4913
SC
76 DoEndWriteTopLevelEntry( name ) ;
77}
78
4f8ffae1 79void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded, wxxVariantArray &metadata )
ab6e4913 80{
c90b8250
SC
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
4f8ffae1 88 if ( persister->BeforeWriteObject( this , object , classInfo , metadata) )
16776ad9 89 {
ab6e4913
SC
90 if ( object == NULL )
91 DoWriteNullObject() ;
92 else if ( IsObjectKnown( object ) )
93 DoWriteRepeatedObject( GetObjectID(object) ) ;
2d51f067
SC
94 else
95 {
96 int oid = m_data->m_nextId++ ;
ab6e4913
SC
97 if ( !isEmbedded )
98 m_data->m_writtenObjects[object] = oid ;
99
2d51f067
SC
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 ) ;
ab6e4913 103 if ( !isEmbedded && dynobj )
2d51f067
SC
104 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
105
4f8ffae1 106 DoBeginWriteObject( object , classInfo , oid , metadata ) ;
2d51f067
SC
107 wxWriterInternalPropertiesData data ;
108 WriteAllProperties( object , classInfo , persister , &data ) ;
ab6e4913 109 DoEndWriteObject( object , classInfo , oid ) ;
2d51f067 110 }
ab6e4913 111 persister->AfterWriteObject( this ,object , classInfo ) ;
16776ad9
SC
112 }
113}
114
ab6e4913
SC
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}
16776ad9
SC
153void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
154{
cb73e600
SC
155 wxPropertyInfoMap map ;
156 ci->GetProperties( map ) ;
157 for ( int i = 0 ; i < ci->GetCreateParamCount() ; ++i )
16a45a23 158 {
cb73e600
SC
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) )
16a45a23 179 {
cb73e600 180 WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ;
16a45a23
SC
181 }
182 }
cb73e600
SC
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() ;
16a45a23 191
cb73e600
SC
192 DoBeginWriteProperty( pi ) ;
193 if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
16776ad9 194 {
cb73e600
SC
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 )
16776ad9 199 {
cb73e600
SC
200 DoBeginWriteElement() ;
201 wxxVariant value = data[i] ;
202 if ( persister->BeforeWriteProperty( this , pi , value ) )
16776ad9 203 {
cb73e600
SC
204 const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( elementType ) ;
205 if ( cti )
16776ad9 206 {
cb73e600
SC
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 ) ;
16776ad9 211 }
cb73e600 212 else
16776ad9 213 {
cb73e600
SC
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 ;
ab6e4913 227
cb73e600
SC
228 const wxWindow * evSource = dynamic_cast<const wxWindow *>(obj) ;
229 wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
a315dda6 230
cb73e600
SC
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 ) ;
16776ad9 238 }
cb73e600
SC
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 )
16776ad9 249 {
cb73e600
SC
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 )
16776ad9 258 {
cb73e600
SC
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 ) ;
16776ad9 262 }
cb73e600 263 DoWriteSimpleType( value ) ;
16776ad9
SC
264 }
265 }
266 }
16776ad9 267 }
cb73e600 268 DoEndWriteProperty( pi ) ;
4f8ffae1 269}
70e88103 270
16776ad9
SC
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 ;
ab6e4913
SC
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 }
16776ad9
SC
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
ab6e4913 334void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString &name )
16776ad9 335{
ab6e4913
SC
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}
16776ad9 342
ab6e4913
SC
343void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString &WXUNUSED(name) )
344{
345 m_data->Pop() ;
346}
347
4f8ffae1 348void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID , wxxVariantArray &metadata )
ab6e4913
SC
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
4f8ffae1
SC
355 for ( size_t i = 0 ; i < metadata.GetCount() ; ++i )
356 {
357 pnode->AddProperty( metadata[i].GetName() , metadata[i].GetAsString() ) ;
358 }
ab6e4913
SC
359 m_data->m_current->AddChild(pnode) ;
360 m_data->Push( pnode ) ;
16776ad9
SC
361}
362
363// end of writing the root object
ab6e4913 364void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) )
16776ad9 365{
ab6e4913 366 m_data->Pop() ;
16776ad9
SC
367}
368
369// writes a property in the stream format
ab6e4913
SC
370void wxXmlWriter::DoWriteSimpleType( wxxVariant &value )
371{
372 wxXmlAddContentToNode( m_data->m_current ,value.GetAsString() ) ;
373}
374
375void wxXmlWriter::DoBeginWriteElement()
16776ad9
SC
376{
377 wxXmlNode *pnode;
ab6e4913
SC
378 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "element" );
379 m_data->m_current->AddChild(pnode) ;
380 m_data->Push( pnode ) ;
16776ad9
SC
381}
382
ab6e4913 383void wxXmlWriter::DoEndWriteElement()
16776ad9 384{
ab6e4913 385 m_data->Pop() ;
16776ad9
SC
386}
387
ab6e4913 388void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo *pi )
16776ad9 389{
ab6e4913
SC
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}
16776ad9 396
ab6e4913
SC
397void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo *WXUNUSED(propInfo) )
398{
399 m_data->Pop() ;
16776ad9
SC
400}
401
ab6e4913
SC
402
403
404// insert an object reference to an already written object
405void wxXmlWriter::DoWriteRepeatedObject( int objectID )
16776ad9 406{
ab6e4913
SC
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) ;
16776ad9
SC
411}
412
ab6e4913
SC
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}
16776ad9
SC
420
421// writes a delegate in the stream format
16a45a23 422void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(pi) ,
16776ad9
SC
423 const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo )
424{
425 if ( eventSink != NULL && handlerInfo != NULL )
426 {
ab6e4913 427 wxXmlAddContentToNode( m_data->m_current ,wxString::Format(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName()) ) ;
16776ad9 428 }
70e88103
SC
429}
430
431// ----------------------------------------------------------------------------
45212047 432// reading objects in
70e88103
SC
433// ----------------------------------------------------------------------------
434
70e88103
SC
435struct wxReader::wxReaderInternal
436{
45212047 437 map<int,wxClassInfo*> m_classInfos;
70e88103
SC
438};
439
45212047 440wxReader::wxReader()
70e88103 441{
45212047 442 m_data = new wxReaderInternal;
70e88103
SC
443}
444
445wxReader::~wxReader()
446{
45212047 447 delete m_data;
70e88103
SC
448}
449
45212047 450wxClassInfo* wxReader::GetObjectClassInfo(int objectID)
70e88103 451{
45212047
SC
452 assert( m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() );
453 return m_data->m_classInfos[objectID] ;
70e88103
SC
454}
455
45212047 456void wxReader::SetObjectClassInfo(int objectID, wxClassInfo *classInfo )
70e88103 457{
16776ad9
SC
458 assert( m_data->m_classInfos.find(objectID) == m_data->m_classInfos.end() ) ;
459 m_data->m_classInfos[objectID] = classInfo ;
70e88103
SC
460}
461
45212047 462bool wxReader::HasObjectClassInfo( int objectID )
70e88103 463{
16776ad9 464 return m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() ;
70e88103
SC
465}
466
70e88103 467
45212047
SC
468// ----------------------------------------------------------------------------
469// reading xml in
470// ----------------------------------------------------------------------------
70e88103
SC
471
472/*
16776ad9
SC
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
70e88103
SC
476*/
477
45212047 478int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
70e88103 479{
16a45a23 480 wxASSERT_MSG( callbacks , wxT("Does not support reading without a Depersistor") ) ;
45212047
SC
481 wxString className;
482 wxClassInfo *classInfo;
70e88103 483
16776ad9
SC
484 wxxVariant *createParams ;
485 int *createParamOids ;
486 const wxClassInfo** createClassInfos ;
45212047
SC
487 wxXmlNode *children;
488 int objectID;
ab6e4913 489 wxString ObjectIdString ;
70e88103 490
45212047 491 children = node->GetChildren();
ab6e4913
SC
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 }
45212047 506 if (!node->GetPropVal("class", &className))
70e88103 507 {
16776ad9
SC
508 // No class name. Eek. FIXME: error handling
509 return wxInvalidObjectID;
70e88103 510 }
16776ad9 511 classInfo = wxClassInfo::FindClass(className);
ab6e4913
SC
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") ) ;
45212047 514 if (!node->GetPropVal("id", &ObjectIdString))
70e88103 515 {
ab6e4913 516 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
16776ad9
SC
517 // No object id. Eek. FIXME: error handling
518 return wxInvalidObjectID;
70e88103 519 }
45212047 520 objectID = atoi( ObjectIdString.c_str() ) ;
16776ad9 521 // is this object already has been streamed in, return it here
ab6e4913 522 wxASSERT_MSG( !HasObjectClassInfo( objectID ) , wxString::Format(wxT("Doubly used id : %d"), objectID ) ) ;
70e88103 523
16776ad9
SC
524 // new object, start with allocation
525 // first make the object know to our internal registry
526 SetObjectClassInfo( objectID , classInfo ) ;
45212047 527
4f8ffae1
SC
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);
70e88103 539
16776ad9 540 //
70e88103 541 // stream back the Create parameters first
16776ad9
SC
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 {
ab6e4913
SC
554 wxString name ;
555 children->GetPropVal( wxT("name") , &name ) ;
556 propertyNames.push_back( name.c_str() ) ;
557 propertyNodes[name.c_str()] = children->GetChildren() ;
16776ad9
SC
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 ) ;
16a45a23 566 wxASSERT_MSG(pi,wxString::Format("Unkown Property %s",paramName) ) ;
16776ad9
SC
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 ;
b8d5be01 580 createParams[i] = ReadValue( prop , pi->GetTypeInfo() ) ;
cb73e600
SC
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 }
16776ad9
SC
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 }
70e88103
SC
607
608 // got the parameters. Call the Create method
45212047 609 callbacks->CreateObject(objectID, classInfo,
16776ad9 610 classInfo->GetCreateParamCount(),
4f8ffae1 611 createParams, createParamOids, createClassInfos, metadata );
70e88103
SC
612
613 // now stream in the rest of the properties, in the sequence their properties were written in the xml
16776ad9
SC
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() ) ;
ab6e4913
SC
623 if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
624 {
16a45a23
SC
625 const wxCollectionTypeInfo* collType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() ) ;
626 const wxTypeInfo * elementType = collType->GetElementType() ;
ab6e4913
SC
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() ;
c90b8250 631 if ( elementContent )
ab6e4913 632 {
c90b8250
SC
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
ab6e4913 647 {
c90b8250 648 wxxVariant elementValue = ReadValue( elementContent , elementType ) ;
16a45a23 649 if ( pi->GetAccessor()->HasAdder() )
c90b8250 650 callbacks->AddToPropertyCollection( objectID , classInfo ,pi , elementValue ) ;
ab6e4913
SC
651 }
652 }
ab6e4913
SC
653 prop = prop->GetNext() ;
654 }
655 }
656 else if ( pi->GetTypeInfo()->IsObjectType() )
16776ad9
SC
657 {
658 int valueId = ReadComponent( prop , callbacks ) ;
16a45a23 659 if ( valueId != wxInvalidObjectID )
16776ad9 660 {
16a45a23
SC
661 callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ;
662 if ( pi->GetTypeInfo()->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
663 callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
16776ad9
SC
664 }
665 }
666 else if ( pi->GetTypeInfo()->IsDelegateType() )
667 {
ab6e4913
SC
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
16a45a23 677 callbacks->SetConnect( objectID , classInfo , dynamic_cast<const wxDelegateTypeInfo*>(pi->GetTypeInfo()) , sinkClassInfo ,
4f8ffae1 678 sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ;
ab6e4913 679 }
16776ad9
SC
680
681 }
682 else
683 {
b8d5be01
SC
684 wxxVariant nodeval ;
685 callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetTypeInfo() ) ) ;
16776ad9
SC
686 }
687 }
688 }
689 }
690
691 delete[] createParams ;
692 delete[] createParamOids ;
693 delete[] createClassInfos ;
70e88103 694
45212047
SC
695 return objectID;
696}
70e88103 697
45212047 698wxxVariant wxXmlReader::ReadValue(wxXmlNode *node,
b8d5be01 699 const wxTypeInfo *type )
45212047 700{
ab6e4913
SC
701 wxString content ;
702 if ( node )
703 content = node->GetContent() ;
b8d5be01
SC
704 wxxVariant result ;
705 type->ConvertFromString( content , result ) ;
706 return result ;
45212047
SC
707}
708
ab6e4913 709int wxXmlReader::ReadObject( const wxString &name , wxDepersister *callbacks)
45212047 710{
ab6e4913
SC
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 ;
70e88103
SC
723}
724
725// ----------------------------------------------------------------------------
726// depersisting to memory
727// ----------------------------------------------------------------------------
728
45212047 729struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
70e88103 730{
45212047
SC
731 map<int,wxObject *> m_objects;
732
16776ad9
SC
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 }
45212047
SC
746} ;
747
748wxRuntimeDepersister::wxRuntimeDepersister()
749{
16776ad9 750 m_data = new wxRuntimeDepersisterInternal() ;
70e88103
SC
751}
752
45212047 753wxRuntimeDepersister::~wxRuntimeDepersister()
70e88103 754{
16776ad9 755 delete m_data ;
70e88103
SC
756}
757
4f8ffae1
SC
758void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo ,
759 wxxVariantArray &metadata)
70e88103
SC
760{
761 wxObject *O;
45212047
SC
762 O = classInfo->CreateObject();
763 m_data->SetObject(objectID, O);
764}
765
766void wxRuntimeDepersister::CreateObject(int objectID,
16776ad9
SC
767 const wxClassInfo *classInfo,
768 int paramCount,
769 wxxVariant *params,
770 int *objectIdValues,
4f8ffae1
SC
771 const wxClassInfo **objectClassInfos ,
772 wxxVariantArray &metadata)
45212047
SC
773{
774 wxObject *o;
775 o = m_data->GetObject(objectID);
16776ad9
SC
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]);
2d51f067
SC
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 }
16776ad9
SC
789 params[i] = objectClassInfos[i]->InstanceToVariant(o) ;
790 }
791 }
45212047
SC
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);
16776ad9 799 delete o ;
70e88103
SC
800}
801
45212047 802void wxRuntimeDepersister::SetProperty(int objectID,
2d51f067 803 const wxClassInfo *classInfo,
16776ad9
SC
804 const wxPropertyInfo* propertyInfo,
805 const wxxVariant &value)
70e88103 806{
45212047
SC
807 wxObject *o;
808 o = m_data->GetObject(objectID);
2d51f067 809 classInfo->SetProperty( o , propertyInfo->GetName() , value ) ;
45212047
SC
810}
811
812void wxRuntimeDepersister::SetPropertyAsObject(int objectID,
2d51f067 813 const wxClassInfo *classInfo,
16776ad9
SC
814 const wxPropertyInfo* propertyInfo,
815 int valueObjectId)
45212047
SC
816{
817 wxObject *o, *valo;
818 o = m_data->GetObject(objectID);
819 valo = m_data->GetObject(valueObjectId);
2d51f067
SC
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) ) ;
45212047
SC
830}
831
832void wxRuntimeDepersister::SetConnect(int eventSourceObjectID,
16776ad9
SC
833 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
834 const wxDelegateTypeInfo *delegateInfo ,
835 const wxClassInfo *WXUNUSED(eventSinkClassInfo) ,
836 const wxHandlerInfo* handlerInfo ,
837 int eventSinkObjectID )
45212047 838{
16776ad9
SC
839 wxWindow *ehsource = dynamic_cast< wxWindow* >( m_data->GetObject( eventSourceObjectID ) ) ;
840 wxEvtHandler *ehsink = dynamic_cast< wxEvtHandler *>(m_data->GetObject(eventSinkObjectID) ) ;
70e88103 841
16776ad9
SC
842 if ( ehsource && ehsink )
843 {
844 ehsource->Connect( ehsource->GetId() , delegateInfo->GetEventType() ,
845 handlerInfo->GetEventFunction() , NULL /*user data*/ ,
846 ehsink ) ;
847 }
70e88103
SC
848}
849
45212047
SC
850wxObject *wxRuntimeDepersister::GetObject(int objectID)
851{
16776ad9 852 return m_data->GetObject( objectID ) ;
45212047
SC
853}
854
16a45a23
SC
855// adds an element to a property collection
856void wxRuntimeDepersister::AddToPropertyCollection( int objectID ,
4f8ffae1
SC
857 const wxClassInfo *classInfo,
858 const wxPropertyInfo* propertyInfo ,
859 const wxxVariant &value)
16a45a23
SC
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,
4f8ffae1
SC
868 const wxClassInfo *classInfo,
869 const wxPropertyInfo* propertyInfo ,
870 int valueObjectId)
16a45a23
SC
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}
45212047 887
70e88103
SC
888// ----------------------------------------------------------------------------
889// depersisting to code
890// ----------------------------------------------------------------------------
891
45212047
SC
892struct wxCodeDepersister::wxCodeDepersisterInternal
893{
894 map<int,string> m_objectNames ;
895
16776ad9
SC
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 }
45212047 909} ;
70e88103 910
45212047 911wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out)
16776ad9 912: m_fp(out)
70e88103 913{
16776ad9 914 m_data = new wxCodeDepersisterInternal ;
45212047
SC
915}
916
917wxCodeDepersister::~wxCodeDepersister()
918{
16776ad9 919 delete m_data ;
45212047
SC
920}
921
4f8ffae1
SC
922void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo ,
923 wxxVariantArray &metadata)
45212047 924{
16776ad9
SC
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 ) ;
45212047
SC
931}
932
933void wxCodeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
934{
16776ad9
SC
935 m_fp->WriteString( wxString::Format( "\tdelete %s;\n",
936 m_data->GetObjectName( objectID) ) );
45212047
SC
937}
938
939wxString wxCodeDepersister::ValueAsCode( const wxxVariant &param )
940{
16776ad9
SC
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 ;
70e88103
SC
958}
959
45212047 960void wxCodeDepersister::CreateObject(int objectID,
16776ad9
SC
961 const wxClassInfo *WXUNUSED(classInfo),
962 int paramCount,
963 wxxVariant *params,
964 int *objectIDValues,
4f8ffae1
SC
965 const wxClassInfo **WXUNUSED(objectClassInfos) ,
966 wxxVariantArray &metadata
16776ad9 967 )
70e88103
SC
968{
969 int i;
16776ad9 970 m_fp->WriteString( wxString::Format( "\t%s->Create(", m_data->GetObjectName(objectID) ) );
45212047 971 for (i = 0; i < paramCount; i++)
70e88103 972 {
16776ad9
SC
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( ", ");
70e88103 981 }
45212047 982 m_fp->WriteString( ");\n");
70e88103
SC
983}
984
45212047 985void wxCodeDepersister::SetProperty(int objectID,
16776ad9
SC
986 const wxClassInfo *WXUNUSED(classInfo),
987 const wxPropertyInfo* propertyInfo,
988 const wxxVariant &value)
70e88103 989{
45212047 990 m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
16776ad9
SC
991 m_data->GetObjectName(objectID),
992 propertyInfo->GetAccessor()->GetSetterName(),
993 ValueAsCode(value)) );
45212047
SC
994}
995
996void wxCodeDepersister::SetPropertyAsObject(int objectID,
16776ad9
SC
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) ) );
70e88103
SC
1011}
1012
16a45a23 1013void wxCodeDepersister::AddToPropertyCollection( int objectID ,
4f8ffae1
SC
1014 const wxClassInfo *classInfo,
1015 const wxPropertyInfo* propertyInfo ,
1016 const wxxVariant &value)
16a45a23
SC
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,
4f8ffae1
SC
1026 const wxClassInfo *classInfo,
1027 const wxPropertyInfo* propertyInfo ,
1028 int valueObjectId)
16a45a23
SC
1029{
1030 // TODO
1031}
1032
45212047 1033void wxCodeDepersister::SetConnect(int eventSourceObjectID,
16776ad9
SC
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 ) );
70e88103
SC
1048}
1049
ab6e4913
SC
1050#include <wx/arrimpl.cpp>
1051
1052WX_DEFINE_OBJARRAY(wxxVariantArray);
1053
70e88103 1054#endif