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