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