1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/xtistrm.cpp
3 // Purpose: streaming runtime metadata information
4 // Author: Stefan Csomor
8 // Copyright: (c) 2003 Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "xtistrm.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/object.h"
28 #include "wx/xml/xml.h"
29 #include "wx/tokenzr.h"
30 #include "wx/xtistrm.h"
31 #include "wx/txtstrm.h"
33 #if wxUSE_EXTENDED_RTTI
35 #include "wx/beforestd.h"
39 #include "wx/afterstd.h"
43 struct wxWriter::wxWriterInternal
45 map
< const wxObject
* , int > m_writtenObjects
;
51 m_data
= new wxWriterInternal
;
52 m_data
->m_nextId
= 0 ;
60 struct wxWriter::wxWriterInternalPropertiesData
62 map
< string
, int > m_writtenProperties
;
65 void wxWriter::ClearObjectContext()
68 m_data
= new wxWriterInternal() ;
69 m_data
->m_nextId
= 0 ;
72 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, const wxString
&name
, wxxVariantArray
&metadata
)
74 DoBeginWriteTopLevelEntry( name
) ;
75 WriteObject( object
, classInfo
, persister
, false , metadata
) ;
76 DoEndWriteTopLevelEntry( name
) ;
79 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, bool isEmbedded
, wxxVariantArray
&metadata
)
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
84 const wxWindow
* win
= dynamic_cast<const wxWindow
*>(object
) ;
85 if ( win
&& win
->GetId() < 0 )
88 if ( persister
->BeforeWriteObject( this , object
, classInfo
, metadata
) )
92 else if ( IsObjectKnown( object
) )
93 DoWriteRepeatedObject( GetObjectID(object
) ) ;
96 int oid
= m_data
->m_nextId
++ ;
98 m_data
->m_writtenObjects
[object
] = oid
;
100 // in case this object is a wxDynamicObject we also have to insert is superclass
101 // instance with the same id, so that object relations are streamed out correctly
102 const wxDynamicObject
* dynobj
= dynamic_cast<const wxDynamicObject
*>( object
) ;
103 if ( !isEmbedded
&& dynobj
)
104 m_data
->m_writtenObjects
[dynobj
->GetSuperClassInstance()] = oid
;
106 DoBeginWriteObject( object
, classInfo
, oid
, metadata
) ;
107 wxWriterInternalPropertiesData data
;
108 WriteAllProperties( object
, classInfo
, persister
, &data
) ;
109 DoEndWriteObject( object
, classInfo
, oid
) ;
111 persister
->AfterWriteObject( this ,object
, classInfo
) ;
115 void wxWriter::FindConnectEntry(const wxWindow
* evSource
,const wxDelegateTypeInfo
* dti
, const wxObject
* &sink
, const wxHandlerInfo
*&handler
)
117 wxList
*dynamicEvents
= evSource
->GetDynamicEventTable() ;
121 wxList::compatibility_iterator node
= dynamicEvents
->GetFirst();
124 wxDynamicEventTableEntry
*entry
= (wxDynamicEventTableEntry
*)node
->GetData();
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
) ) ) &&
135 sink
= entry
->m_eventSink
;
136 const wxClassInfo
* sinkClassInfo
= sink
->GetClassInfo() ;
137 const wxHandlerInfo
* sinkHandler
= sinkClassInfo
->GetFirstHandler() ;
138 while ( sinkHandler
)
140 if ( sinkHandler
->GetEventFunction() == entry
->m_fn
)
142 handler
= sinkHandler
;
145 sinkHandler
= sinkHandler
->GetNext() ;
149 node
= node
->GetNext();
153 void wxWriter::WriteAllProperties( const wxObject
* obj
, const wxClassInfo
* ci
, wxPersister
*persister
, wxWriterInternalPropertiesData
* data
)
155 // in case this object is wxDynamic object we have to hand over the streaming
156 // of the properties of the superclasses to the real super class instance
158 const wxObject
*iterobj
= obj
;
159 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* > (iterobj
) ;
161 iterobj
= dynobj
->GetSuperClassInstance() ;
162 const wxClassInfo
** parents
= ci
->GetParents() ;
163 for ( int i
= 0 ; parents
[i
] ; ++ i
)
165 WriteAllProperties( iterobj
, parents
[i
] , persister
, data
) ;
169 const wxPropertyInfo
*pi
= ci
->GetFirstProperty() ;
172 // this property was not written yet in this object and we don't get a veto
173 // if ( data->m_writtenProperties.find( pi->GetName() ) == data->m_writtenProperties.end() )
174 // we will have to handle property overrides differently
176 data
->m_writtenProperties
[ pi
->GetName() ] = 1 ;
177 DoBeginWriteProperty( pi
) ;
178 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
180 wxxVariantArray data
;
181 pi
->GetAccessor()->GetPropertyCollection(obj
, data
) ;
182 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
183 for ( size_t i
= 0 ; i
< data
.GetCount() ; ++i
)
185 DoBeginWriteElement() ;
186 wxxVariant value
= data
[i
] ;
187 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
189 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
192 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
193 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
195 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
199 DoWriteSimpleType( value
) ;
202 DoEndWriteElement() ;
207 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
210 const wxObject
* sink
= NULL
;
211 const wxHandlerInfo
*handler
= NULL
;
213 const wxWindow
* evSource
= dynamic_cast<const wxWindow
*>(obj
) ;
214 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
216 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
217 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
219 if ( sink
!= NULL
&& handler
!= NULL
)
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
) ;
229 pi
->GetAccessor()->GetProperty(obj
, value
) ;
230 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
232 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
235 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
236 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
238 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
242 DoWriteSimpleType( value
) ;
247 DoEndWriteProperty( pi
) ;
253 int wxWriter::GetObjectID(const wxObject
*obj
)
255 if ( !IsObjectKnown( obj
) )
256 return wxInvalidObjectID
;
258 return m_data
->m_writtenObjects
[obj
] ;
261 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
263 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
270 // convenience functions
272 void wxXmlAddContentToNode( wxXmlNode
* node
, const wxString
& data
)
274 node
->AddChild(new wxXmlNode(wxXML_TEXT_NODE
, "value", data
) );
277 wxString
wxXmlGetContentFromNode( wxXmlNode
*node
)
279 if ( node
->GetChildren() )
280 return node
->GetChildren()->GetContent() ;
282 return wxEmptyString
;
285 struct wxXmlWriter::wxXmlWriterInternal
288 wxXmlNode
*m_current
;
289 vector
< wxXmlNode
* > m_objectStack
;
291 void Push( wxXmlNode
*newCurrent
)
293 m_objectStack
.push_back( m_current
) ;
294 m_current
= newCurrent
;
299 m_current
= m_objectStack
.back() ;
300 m_objectStack
.pop_back() ;
304 wxXmlWriter::wxXmlWriter( wxXmlNode
* rootnode
)
306 m_data
= new wxXmlWriterInternal() ;
307 m_data
->m_root
= rootnode
;
308 m_data
->m_current
= rootnode
;
311 wxXmlWriter::~wxXmlWriter()
316 void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString
&name
)
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
) ;
325 void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString
&WXUNUSED(name
) )
330 void wxXmlWriter::DoBeginWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*classInfo
, int objectID
, wxxVariantArray
&metadata
)
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
) );
337 for ( size_t i
= 0 ; i
< metadata
.GetCount() ; ++i
)
339 pnode
->AddProperty( metadata
[i
].GetName() , metadata
[i
].GetAsString() ) ;
341 m_data
->m_current
->AddChild(pnode
) ;
342 m_data
->Push( pnode
) ;
345 // end of writing the root object
346 void wxXmlWriter::DoEndWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*WXUNUSED(classInfo
), int WXUNUSED(objectID
) )
351 // writes a property in the stream format
352 void wxXmlWriter::DoWriteSimpleType( wxxVariant
&value
)
354 wxXmlAddContentToNode( m_data
->m_current
,value
.GetAsString() ) ;
357 void wxXmlWriter::DoBeginWriteElement()
360 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "element" );
361 m_data
->m_current
->AddChild(pnode
) ;
362 m_data
->Push( pnode
) ;
365 void wxXmlWriter::DoEndWriteElement()
370 void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo
*pi
)
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
) ;
379 void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo
*WXUNUSED(propInfo
) )
386 // insert an object reference to an already written object
387 void wxXmlWriter::DoWriteRepeatedObject( int objectID
)
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
) ;
395 // insert a null reference
396 void wxXmlWriter::DoWriteNullObject()
399 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
400 m_data
->m_current
->AddChild(pnode
) ;
403 // writes a delegate in the stream format
404 void wxXmlWriter::DoWriteDelegate( const wxObject
*WXUNUSED(object
), const wxClassInfo
* WXUNUSED(classInfo
) , const wxPropertyInfo
*WXUNUSED(pi
) ,
405 const wxObject
*eventSink
, int sinkObjectID
, const wxClassInfo
* WXUNUSED(eventSinkClassInfo
) , const wxHandlerInfo
* handlerInfo
)
407 if ( eventSink
!= NULL
&& handlerInfo
!= NULL
)
409 wxXmlAddContentToNode( m_data
->m_current
,wxString::Format(wxT("%d.%s"), sinkObjectID
, handlerInfo
->GetName()) ) ;
413 // ----------------------------------------------------------------------------
414 // reading objects in
415 // ----------------------------------------------------------------------------
417 struct wxReader::wxReaderInternal
419 map
<int,wxClassInfo
*> m_classInfos
;
424 m_data
= new wxReaderInternal
;
427 wxReader::~wxReader()
432 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
434 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
435 return m_data
->m_classInfos
[objectID
] ;
438 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
440 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
441 m_data
->m_classInfos
[objectID
] = classInfo
;
444 bool wxReader::HasObjectClassInfo( int objectID
)
446 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
450 // ----------------------------------------------------------------------------
452 // ----------------------------------------------------------------------------
455 Reading components has not to be extended for components
456 as properties are always sought by typeinfo over all levels
457 and create params are always toplevel class only
460 int wxXmlReader::ReadComponent(wxXmlNode
*node
, wxDepersister
*callbacks
)
462 wxASSERT_MSG( callbacks
, wxT("Does not support reading without a Depersistor") ) ;
464 wxClassInfo
*classInfo
;
466 wxxVariant
*createParams
;
467 int *createParamOids
;
468 const wxClassInfo
** createClassInfos
;
471 wxString ObjectIdString
;
473 children
= node
->GetChildren();
476 // check for a null object or href
477 if (node
->GetPropVal("href" , &ObjectIdString
) )
479 objectID
= atoi( ObjectIdString
.c_str() ) ;
480 wxASSERT_MSG( HasObjectClassInfo( objectID
) , wxT("Forward hrefs are not supported") ) ;
483 if ( !node
->GetPropVal("id" , &ObjectIdString
) )
485 return wxNullObjectID
;
488 if (!node
->GetPropVal("class", &className
))
490 // No class name. Eek. FIXME: error handling
491 return wxInvalidObjectID
;
493 classInfo
= wxClassInfo::FindClass(className
);
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") ) ;
496 if (!node
->GetPropVal("id", &ObjectIdString
))
498 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
499 // No object id. Eek. FIXME: error handling
500 return wxInvalidObjectID
;
502 objectID
= atoi( ObjectIdString
.c_str() ) ;
503 // is this object already has been streamed in, return it here
504 wxASSERT_MSG( !HasObjectClassInfo( objectID
) , wxString::Format(wxT("Doubly used id : %d"), objectID
) ) ;
506 // new object, start with allocation
507 // first make the object know to our internal registry
508 SetObjectClassInfo( objectID
, classInfo
) ;
510 wxxVariantArray metadata
;
511 wxXmlProperty
*xp
= node
->GetProperties() ;
514 if ( xp
->GetName() != wxString("class") && xp
->GetName() != wxString("id") )
516 metadata
.Add( new wxxVariant( xp
->GetValue() , xp
->GetName() ) ) ;
520 callbacks
->AllocateObject(objectID
, classInfo
, metadata
);
523 // stream back the Create parameters first
524 createParams
= new wxxVariant
[ classInfo
->GetCreateParamCount() ] ;
525 createParamOids
= new int[classInfo
->GetCreateParamCount() ] ;
526 createClassInfos
= new const wxClassInfo
*[classInfo
->GetCreateParamCount() ] ;
528 typedef map
<string
, wxXmlNode
*> PropertyNodes
;
529 typedef vector
<string
> PropertyNames
;
531 PropertyNodes propertyNodes
;
532 PropertyNames propertyNames
;
537 children
->GetPropVal( wxT("name") , &name
) ;
538 propertyNames
.push_back( name
.c_str() ) ;
539 propertyNodes
[name
.c_str()] = children
->GetChildren() ;
540 children
= children
->GetNext() ;
543 for ( int i
= 0 ; i
<classInfo
->GetCreateParamCount() ; ++i
)
545 const wxChar
* paramName
= classInfo
->GetCreateParamName(i
) ;
546 PropertyNodes::iterator propiter
= propertyNodes
.find( paramName
) ;
547 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( paramName
) ;
548 wxASSERT_MSG(pi
,wxString::Format("Unkown Property %s",paramName
) ) ;
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() )
553 wxXmlNode
* prop
= propiter
->second
;
554 if ( pi
->GetTypeInfo()->IsObjectType() )
556 createParamOids
[i
] = ReadComponent( prop
, callbacks
) ;
557 createClassInfos
[i
] = dynamic_cast<const wxClassTypeInfo
*>(pi
->GetTypeInfo())->GetClassInfo() ;
561 createParamOids
[i
] = wxInvalidObjectID
;
562 createParams
[i
] = ReadValue( prop
, pi
->GetTypeInfo() ) ;
563 createClassInfos
[i
] = NULL
;
566 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
568 if ( propertyNames
[j
] == paramName
)
570 propertyNames
[j
] = "" ;
577 createParams
[i
] = pi
->GetDefaultValue() ;
581 // got the parameters. Call the Create method
582 callbacks
->CreateObject(objectID
, classInfo
,
583 classInfo
->GetCreateParamCount(),
584 createParams
, createParamOids
, createClassInfos
, metadata
);
586 // now stream in the rest of the properties, in the sequence their properties were written in the xml
587 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
589 if ( propertyNames
[j
].length() )
591 PropertyNodes::iterator propiter
= propertyNodes
.find( propertyNames
[j
] ) ;
592 if ( propiter
!= propertyNodes
.end() )
594 wxXmlNode
* prop
= propiter
->second
;
595 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( propertyNames
[j
].c_str() ) ;
596 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
598 const wxCollectionTypeInfo
* collType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() ) ;
599 const wxTypeInfo
* elementType
= collType
->GetElementType() ;
602 wxASSERT_MSG(prop
->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
603 wxXmlNode
* elementContent
= prop
->GetChildren() ;
604 if ( elementContent
)
606 // we skip empty elements
607 if ( elementType
->IsObjectType() )
609 int valueId
= ReadComponent( elementContent
, callbacks
) ;
610 if ( valueId
!= wxInvalidObjectID
)
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
) ) ;
621 wxxVariant elementValue
= ReadValue( elementContent
, elementType
) ;
622 if ( pi
->GetAccessor()->HasAdder() )
623 callbacks
->AddToPropertyCollection( objectID
, classInfo
,pi
, elementValue
) ;
626 prop
= prop
->GetNext() ;
629 else if ( pi
->GetTypeInfo()->IsObjectType() )
631 int valueId
= ReadComponent( prop
, callbacks
) ;
632 if ( valueId
!= wxInvalidObjectID
)
634 callbacks
->SetPropertyAsObject( objectID
, classInfo
, pi
, valueId
) ;
635 if ( pi
->GetTypeInfo()->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
636 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
639 else if ( pi
->GetTypeInfo()->IsDelegateType() )
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
) ;
650 callbacks
->SetConnect( objectID
, classInfo
, dynamic_cast<const wxDelegateTypeInfo
*>(pi
->GetTypeInfo()) , sinkClassInfo
,
651 sinkClassInfo
->FindHandlerInfo(handlerName
) , sinkOid
) ;
658 callbacks
->SetProperty( objectID
, classInfo
,pi
, ReadValue( prop
, pi
->GetTypeInfo() ) ) ;
664 delete[] createParams
;
665 delete[] createParamOids
;
666 delete[] createClassInfos
;
671 wxxVariant
wxXmlReader::ReadValue(wxXmlNode
*node
,
672 const wxTypeInfo
*type
)
676 content
= node
->GetContent() ;
678 type
->ConvertFromString( content
, result
) ;
682 int wxXmlReader::ReadObject( const wxString
&name
, wxDepersister
*callbacks
)
684 wxXmlNode
*iter
= m_parent
->GetChildren() ;
688 if ( iter
->GetPropVal("name", &entryName
) )
690 if ( entryName
== name
)
691 return ReadComponent( iter
->GetChildren() , callbacks
) ;
693 iter
= iter
->GetNext() ;
695 return wxInvalidObjectID
;
698 // ----------------------------------------------------------------------------
699 // depersisting to memory
700 // ----------------------------------------------------------------------------
702 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
704 map
<int,wxObject
*> m_objects
;
706 void SetObject(int objectID
, wxObject
*obj
)
708 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
709 m_objects
[objectID
] = obj
;
711 wxObject
* GetObject( int objectID
)
713 if ( objectID
== wxNullObjectID
)
716 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
717 return m_objects
[objectID
] ;
721 wxRuntimeDepersister::wxRuntimeDepersister()
723 m_data
= new wxRuntimeDepersisterInternal() ;
726 wxRuntimeDepersister::~wxRuntimeDepersister()
731 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
732 wxxVariantArray
&metadata
)
735 O
= classInfo
->CreateObject();
736 m_data
->SetObject(objectID
, O
);
739 void wxRuntimeDepersister::CreateObject(int objectID
,
740 const wxClassInfo
*classInfo
,
744 const wxClassInfo
**objectClassInfos
,
745 wxxVariantArray
&metadata
)
748 o
= m_data
->GetObject(objectID
);
749 for ( int i
= 0 ; i
< paramCount
; ++i
)
751 if ( objectIdValues
[i
] != wxInvalidObjectID
)
754 o
= m_data
->GetObject(objectIdValues
[i
]);
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()) )
760 o
= dyno
->GetSuperClassInstance() ;
762 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
765 classInfo
->Create(o
, paramCount
, params
);
768 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
771 o
= m_data
->GetObject(objectID
);
775 void wxRuntimeDepersister::SetProperty(int objectID
,
776 const wxClassInfo
*classInfo
,
777 const wxPropertyInfo
* propertyInfo
,
778 const wxxVariant
&value
)
781 o
= m_data
->GetObject(objectID
);
782 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
785 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
786 const wxClassInfo
*classInfo
,
787 const wxPropertyInfo
* propertyInfo
,
791 o
= m_data
->GetObject(objectID
);
792 valo
= m_data
->GetObject(valueObjectId
);
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()) )
799 valo
= dynvalo
->GetSuperClassInstance() ;
802 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
805 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID
,
806 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
807 const wxDelegateTypeInfo
*delegateInfo
,
808 const wxClassInfo
*WXUNUSED(eventSinkClassInfo
) ,
809 const wxHandlerInfo
* handlerInfo
,
810 int eventSinkObjectID
)
812 wxWindow
*ehsource
= dynamic_cast< wxWindow
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
813 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
815 if ( ehsource
&& ehsink
)
817 ehsource
->Connect( ehsource
->GetId() , delegateInfo
->GetEventType() ,
818 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
823 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
825 return m_data
->GetObject( objectID
) ;
828 // adds an element to a property collection
829 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
830 const wxClassInfo
*classInfo
,
831 const wxPropertyInfo
* propertyInfo
,
832 const wxxVariant
&value
)
835 o
= m_data
->GetObject(objectID
);
836 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
839 // sets the corresponding property (value is an object)
840 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
841 const wxClassInfo
*classInfo
,
842 const wxPropertyInfo
* propertyInfo
,
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()) )
855 valo
= dynvalo
->GetSuperClassInstance() ;
858 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
861 // ----------------------------------------------------------------------------
862 // depersisting to code
863 // ----------------------------------------------------------------------------
865 struct wxCodeDepersister::wxCodeDepersisterInternal
867 map
<int,string
> m_objectNames
;
869 void SetObjectName(int objectID
, const wxString
&name
)
871 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
872 m_objectNames
[objectID
] = (const char *)name
;
874 wxString
GetObjectName( int objectID
)
876 if ( objectID
== wxNullObjectID
)
879 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
880 return wxString( m_objectNames
[objectID
].c_str() ) ;
884 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
887 m_data
= new wxCodeDepersisterInternal
;
890 wxCodeDepersister::~wxCodeDepersister()
895 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
896 wxxVariantArray
&metadata
)
898 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
899 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
900 classInfo
->GetClassName(),
902 classInfo
->GetClassName()) );
903 m_data
->SetObjectName( objectID
, objectName
) ;
906 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
908 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
909 m_data
->GetObjectName( objectID
) ) );
912 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
915 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
916 if ( type
->GetKind() == wxT_CUSTOM
)
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() );
922 else if ( type
->GetKind() == wxT_STRING
)
924 value
.Printf( "\"%s\"",param
.GetAsString() );
928 value
.Printf( "%s", param
.GetAsString() );
933 void wxCodeDepersister::CreateObject(int objectID
,
934 const wxClassInfo
*WXUNUSED(classInfo
),
938 const wxClassInfo
**WXUNUSED(objectClassInfos
) ,
939 wxxVariantArray
&metadata
943 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
) ) );
944 for (i
= 0; i
< paramCount
; i
++)
946 if ( objectIDValues
[i
] != wxInvalidObjectID
)
947 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ) ) );
950 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]) ) );
952 if (i
< paramCount
- 1)
953 m_fp
->WriteString( ", ");
955 m_fp
->WriteString( ");\n");
958 void wxCodeDepersister::SetProperty(int objectID
,
959 const wxClassInfo
*WXUNUSED(classInfo
),
960 const wxPropertyInfo
* propertyInfo
,
961 const wxxVariant
&value
)
963 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
964 m_data
->GetObjectName(objectID
),
965 propertyInfo
->GetAccessor()->GetSetterName(),
966 ValueAsCode(value
)) );
969 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
970 const wxClassInfo
*WXUNUSED(classInfo
),
971 const wxPropertyInfo
* propertyInfo
,
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
) ) );
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
) ) );
986 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
987 const wxClassInfo
*classInfo
,
988 const wxPropertyInfo
* propertyInfo
,
989 const wxxVariant
&value
)
991 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
992 m_data
->GetObjectName(objectID
),
993 propertyInfo
->GetAccessor()->GetAdderName(),
994 ValueAsCode(value
)) );
997 // sets the corresponding property (value is an object)
998 void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID
,
999 const wxClassInfo
*classInfo
,
1000 const wxPropertyInfo
* propertyInfo
,
1006 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
1007 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
1008 const wxDelegateTypeInfo
*delegateInfo
,
1009 const wxClassInfo
*eventSinkClassInfo
,
1010 const wxHandlerInfo
* handlerInfo
,
1011 int eventSinkObjectID
)
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() ;
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
) );
1023 #include <wx/arrimpl.cpp>
1025 WX_DEFINE_OBJARRAY(wxxVariantArray
);