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