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
)
74 DoBeginWriteTopLevelEntry( name
) ;
75 WriteObject( object
, classInfo
, persister
, false ) ;
76 DoEndWriteTopLevelEntry( name
) ;
79 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, bool isEmbedded
)
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
) )
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
) ;
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
) ;
194 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
198 DoWriteSimpleType( value
) ;
201 DoEndWriteElement() ;
206 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
209 const wxObject
* sink
= NULL
;
210 const wxHandlerInfo
*handler
= NULL
;
212 const wxWindow
* evSource
= dynamic_cast<const wxWindow
*>(obj
) ;
213 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
215 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
216 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
218 if ( sink
!= NULL
&& handler
!= NULL
)
220 wxASSERT_MSG( IsObjectKnown( sink
) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
221 DoWriteDelegate( obj
, ci
, pi
, sink
, GetObjectID( sink
) , sink
->GetClassInfo() , handler
) ;
228 pi
->GetAccessor()->GetProperty(obj
, value
) ;
229 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
231 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
234 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
235 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
236 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
240 DoWriteSimpleType( value
) ;
245 DoEndWriteProperty( pi
) ;
251 int wxWriter::GetObjectID(const wxObject
*obj
)
253 if ( !IsObjectKnown( obj
) )
254 return wxInvalidObjectID
;
256 return m_data
->m_writtenObjects
[obj
] ;
259 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
261 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
268 // convenience functions
270 void wxXmlAddContentToNode( wxXmlNode
* node
, const wxString
& data
)
272 node
->AddChild(new wxXmlNode(wxXML_TEXT_NODE
, "value", data
) );
275 wxString
wxXmlGetContentFromNode( wxXmlNode
*node
)
277 if ( node
->GetChildren() )
278 return node
->GetChildren()->GetContent() ;
280 return wxEmptyString
;
283 struct wxXmlWriter::wxXmlWriterInternal
286 wxXmlNode
*m_current
;
287 vector
< wxXmlNode
* > m_objectStack
;
289 void Push( wxXmlNode
*newCurrent
)
291 m_objectStack
.push_back( m_current
) ;
292 m_current
= newCurrent
;
297 m_current
= m_objectStack
.back() ;
298 m_objectStack
.pop_back() ;
302 wxXmlWriter::wxXmlWriter( wxXmlNode
* rootnode
)
304 m_data
= new wxXmlWriterInternal() ;
305 m_data
->m_root
= rootnode
;
306 m_data
->m_current
= rootnode
;
309 wxXmlWriter::~wxXmlWriter()
314 void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString
&name
)
317 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("entry"));
318 pnode
->AddProperty(wxString("name"), name
);
319 m_data
->m_current
->AddChild(pnode
) ;
320 m_data
->Push( pnode
) ;
323 void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString
&WXUNUSED(name
) )
328 void wxXmlWriter::DoBeginWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*classInfo
, int objectID
)
331 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
332 pnode
->AddProperty(wxT("class"), wxString(classInfo
->GetClassName()));
333 pnode
->AddProperty(wxT("id"), wxString::Format( "%d" , objectID
) );
335 m_data
->m_current
->AddChild(pnode
) ;
336 m_data
->Push( pnode
) ;
339 // end of writing the root object
340 void wxXmlWriter::DoEndWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*WXUNUSED(classInfo
), int WXUNUSED(objectID
) )
345 // writes a property in the stream format
346 void wxXmlWriter::DoWriteSimpleType( wxxVariant
&value
)
348 wxXmlAddContentToNode( m_data
->m_current
,value
.GetAsString() ) ;
351 void wxXmlWriter::DoBeginWriteElement()
354 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "element" );
355 m_data
->m_current
->AddChild(pnode
) ;
356 m_data
->Push( pnode
) ;
359 void wxXmlWriter::DoEndWriteElement()
364 void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo
*pi
)
367 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "prop" );
368 pnode
->AddProperty(wxT("name"), pi
->GetName() );
369 m_data
->m_current
->AddChild(pnode
) ;
370 m_data
->Push( pnode
) ;
373 void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo
*WXUNUSED(propInfo
) )
380 // insert an object reference to an already written object
381 void wxXmlWriter::DoWriteRepeatedObject( int objectID
)
384 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
385 pnode
->AddProperty(wxString("href"), wxString::Format( "%d" , objectID
) );
386 m_data
->m_current
->AddChild(pnode
) ;
389 // insert a null reference
390 void wxXmlWriter::DoWriteNullObject()
393 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
394 m_data
->m_current
->AddChild(pnode
) ;
397 // writes a delegate in the stream format
398 void wxXmlWriter::DoWriteDelegate( const wxObject
*WXUNUSED(object
), const wxClassInfo
* WXUNUSED(classInfo
) , const wxPropertyInfo
*WXUNUSED(pi
) ,
399 const wxObject
*eventSink
, int sinkObjectID
, const wxClassInfo
* WXUNUSED(eventSinkClassInfo
) , const wxHandlerInfo
* handlerInfo
)
401 if ( eventSink
!= NULL
&& handlerInfo
!= NULL
)
403 wxXmlAddContentToNode( m_data
->m_current
,wxString::Format(wxT("%d.%s"), sinkObjectID
, handlerInfo
->GetName()) ) ;
407 // ----------------------------------------------------------------------------
408 // reading objects in
409 // ----------------------------------------------------------------------------
411 struct wxReader::wxReaderInternal
413 map
<int,wxClassInfo
*> m_classInfos
;
418 m_data
= new wxReaderInternal
;
421 wxReader::~wxReader()
426 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
428 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
429 return m_data
->m_classInfos
[objectID
] ;
432 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
434 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
435 m_data
->m_classInfos
[objectID
] = classInfo
;
438 bool wxReader::HasObjectClassInfo( int objectID
)
440 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
444 // ----------------------------------------------------------------------------
446 // ----------------------------------------------------------------------------
449 Reading components has not to be extended for components
450 as properties are always sought by typeinfo over all levels
451 and create params are always toplevel class only
454 int wxXmlReader::ReadComponent(wxXmlNode
*node
, wxDepersister
*callbacks
)
456 wxASSERT_MSG( callbacks
, wxT("Does not support reading without a Depersistor") ) ;
458 wxClassInfo
*classInfo
;
460 wxxVariant
*createParams
;
461 int *createParamOids
;
462 const wxClassInfo
** createClassInfos
;
465 wxString ObjectIdString
;
467 children
= node
->GetChildren();
470 // check for a null object or href
471 if (node
->GetPropVal("href" , &ObjectIdString
) )
473 objectID
= atoi( ObjectIdString
.c_str() ) ;
474 wxASSERT_MSG( HasObjectClassInfo( objectID
) , wxT("Forward hrefs are not supported") ) ;
477 if ( !node
->GetPropVal("id" , &ObjectIdString
) )
479 return wxNullObjectID
;
482 if (!node
->GetPropVal("class", &className
))
484 // No class name. Eek. FIXME: error handling
485 return wxInvalidObjectID
;
487 classInfo
= wxClassInfo::FindClass(className
);
488 wxASSERT_MSG( classInfo
, wxString::Format(wxT("unknown class %s"),className
) ) ;
489 wxASSERT_MSG( !children
|| children
->GetType() != wxXML_TEXT_NODE
, wxT("objects cannot have XML Text Nodes") ) ;
490 if (!node
->GetPropVal("id", &ObjectIdString
))
492 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
493 // No object id. Eek. FIXME: error handling
494 return wxInvalidObjectID
;
496 objectID
= atoi( ObjectIdString
.c_str() ) ;
497 // is this object already has been streamed in, return it here
498 wxASSERT_MSG( !HasObjectClassInfo( objectID
) , wxString::Format(wxT("Doubly used id : %d"), objectID
) ) ;
500 // new object, start with allocation
501 // first make the object know to our internal registry
502 SetObjectClassInfo( objectID
, classInfo
) ;
504 callbacks
->AllocateObject(objectID
, classInfo
);
507 // stream back the Create parameters first
508 createParams
= new wxxVariant
[ classInfo
->GetCreateParamCount() ] ;
509 createParamOids
= new int[classInfo
->GetCreateParamCount() ] ;
510 createClassInfos
= new const wxClassInfo
*[classInfo
->GetCreateParamCount() ] ;
512 typedef map
<string
, wxXmlNode
*> PropertyNodes
;
513 typedef vector
<string
> PropertyNames
;
515 PropertyNodes propertyNodes
;
516 PropertyNames propertyNames
;
521 children
->GetPropVal( wxT("name") , &name
) ;
522 propertyNames
.push_back( name
.c_str() ) ;
523 propertyNodes
[name
.c_str()] = children
->GetChildren() ;
524 children
= children
->GetNext() ;
527 for ( int i
= 0 ; i
<classInfo
->GetCreateParamCount() ; ++i
)
529 const wxChar
* paramName
= classInfo
->GetCreateParamName(i
) ;
530 PropertyNodes::iterator propiter
= propertyNodes
.find( paramName
) ;
531 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( paramName
) ;
532 wxASSERT_MSG(pi
,wxString::Format("Unkown Property %s",paramName
) ) ;
533 // if we don't have the value of a create param set in the xml
534 // we use the default value
535 if ( propiter
!= propertyNodes
.end() )
537 wxXmlNode
* prop
= propiter
->second
;
538 if ( pi
->GetTypeInfo()->IsObjectType() )
540 createParamOids
[i
] = ReadComponent( prop
, callbacks
) ;
541 createClassInfos
[i
] = dynamic_cast<const wxClassTypeInfo
*>(pi
->GetTypeInfo())->GetClassInfo() ;
545 createParamOids
[i
] = wxInvalidObjectID
;
546 createParams
[i
] = ReadValue( prop
, pi
->GetTypeInfo() ) ;
547 createClassInfos
[i
] = NULL
;
550 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
552 if ( propertyNames
[j
] == paramName
)
554 propertyNames
[j
] = "" ;
561 createParams
[i
] = pi
->GetDefaultValue() ;
565 // got the parameters. Call the Create method
566 callbacks
->CreateObject(objectID
, classInfo
,
567 classInfo
->GetCreateParamCount(),
568 createParams
, createParamOids
, createClassInfos
);
570 // now stream in the rest of the properties, in the sequence their properties were written in the xml
571 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
573 if ( propertyNames
[j
].length() )
575 PropertyNodes::iterator propiter
= propertyNodes
.find( propertyNames
[j
] ) ;
576 if ( propiter
!= propertyNodes
.end() )
578 wxXmlNode
* prop
= propiter
->second
;
579 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( propertyNames
[j
].c_str() ) ;
580 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
582 const wxCollectionTypeInfo
* collType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() ) ;
583 const wxTypeInfo
* elementType
= collType
->GetElementType() ;
586 wxASSERT_MSG(prop
->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
587 wxXmlNode
* elementContent
= prop
->GetChildren() ;
588 if ( elementContent
)
590 // we skip empty elements
591 if ( elementType
->IsObjectType() )
593 int valueId
= ReadComponent( elementContent
, callbacks
) ;
594 if ( valueId
!= wxInvalidObjectID
)
596 if ( pi
->GetAccessor()->HasAdder() )
597 callbacks
->AddToPropertyCollectionAsObject( objectID
, classInfo
, pi
, valueId
) ;
598 // TODO for collections we must have a notation on taking over ownership or not
599 if ( elementType
->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
600 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
605 wxxVariant elementValue
= ReadValue( elementContent
, elementType
) ;
606 if ( pi
->GetAccessor()->HasAdder() )
607 callbacks
->AddToPropertyCollection( objectID
, classInfo
,pi
, elementValue
) ;
610 prop
= prop
->GetNext() ;
613 else if ( pi
->GetTypeInfo()->IsObjectType() )
615 int valueId
= ReadComponent( prop
, callbacks
) ;
616 if ( valueId
!= wxInvalidObjectID
)
618 callbacks
->SetPropertyAsObject( objectID
, classInfo
, pi
, valueId
) ;
619 if ( pi
->GetTypeInfo()->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
620 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
623 else if ( pi
->GetTypeInfo()->IsDelegateType() )
627 wxString resstring
= prop
->GetContent() ;
628 wxInt32 pos
= resstring
.Find('.') ;
629 assert( pos
!= wxNOT_FOUND
) ;
630 int sinkOid
= atol(resstring
.Left(pos
)) ;
631 wxString handlerName
= resstring
.Mid(pos
+1) ;
632 wxClassInfo
* sinkClassInfo
= GetObjectClassInfo( sinkOid
) ;
634 callbacks
->SetConnect( objectID
, classInfo
, dynamic_cast<const wxDelegateTypeInfo
*>(pi
->GetTypeInfo()) , sinkClassInfo
,
635 sinkClassInfo
->FindHandlerInfo(handlerName
) , sinkOid
) ;
642 callbacks
->SetProperty( objectID
, classInfo
,pi
, ReadValue( prop
, pi
->GetTypeInfo() ) ) ;
648 delete[] createParams
;
649 delete[] createParamOids
;
650 delete[] createClassInfos
;
655 wxxVariant
wxXmlReader::ReadValue(wxXmlNode
*node
,
656 const wxTypeInfo
*type
)
660 content
= node
->GetContent() ;
662 type
->ConvertFromString( content
, result
) ;
666 int wxXmlReader::ReadObject( const wxString
&name
, wxDepersister
*callbacks
)
668 wxXmlNode
*iter
= m_parent
->GetChildren() ;
672 if ( iter
->GetPropVal("name", &entryName
) )
674 if ( entryName
== name
)
675 return ReadComponent( iter
->GetChildren() , callbacks
) ;
677 iter
= iter
->GetNext() ;
679 return wxInvalidObjectID
;
682 // ----------------------------------------------------------------------------
683 // depersisting to memory
684 // ----------------------------------------------------------------------------
686 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
688 map
<int,wxObject
*> m_objects
;
690 void SetObject(int objectID
, wxObject
*obj
)
692 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
693 m_objects
[objectID
] = obj
;
695 wxObject
* GetObject( int objectID
)
697 if ( objectID
== wxNullObjectID
)
700 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
701 return m_objects
[objectID
] ;
705 wxRuntimeDepersister::wxRuntimeDepersister()
707 m_data
= new wxRuntimeDepersisterInternal() ;
710 wxRuntimeDepersister::~wxRuntimeDepersister()
715 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
718 O
= classInfo
->CreateObject();
719 m_data
->SetObject(objectID
, O
);
722 void wxRuntimeDepersister::CreateObject(int objectID
,
723 const wxClassInfo
*classInfo
,
727 const wxClassInfo
**objectClassInfos
)
730 o
= m_data
->GetObject(objectID
);
731 for ( int i
= 0 ; i
< paramCount
; ++i
)
733 if ( objectIdValues
[i
] != wxInvalidObjectID
)
736 o
= m_data
->GetObject(objectIdValues
[i
]);
737 // if this is a dynamic object and we are asked for another class
738 // than wxDynamicObject we cast it down manually.
739 wxDynamicObject
*dyno
= dynamic_cast< wxDynamicObject
* > (o
) ;
740 if ( dyno
!=NULL
&& (objectClassInfos
[i
] != dyno
->GetClassInfo()) )
742 o
= dyno
->GetSuperClassInstance() ;
744 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
747 classInfo
->Create(o
, paramCount
, params
);
750 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
753 o
= m_data
->GetObject(objectID
);
757 void wxRuntimeDepersister::SetProperty(int objectID
,
758 const wxClassInfo
*classInfo
,
759 const wxPropertyInfo
* propertyInfo
,
760 const wxxVariant
&value
)
763 o
= m_data
->GetObject(objectID
);
764 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
767 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
768 const wxClassInfo
*classInfo
,
769 const wxPropertyInfo
* propertyInfo
,
773 o
= m_data
->GetObject(objectID
);
774 valo
= m_data
->GetObject(valueObjectId
);
775 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(propertyInfo
->GetTypeInfo()))->GetClassInfo() ;
776 // if this is a dynamic object and we are asked for another class
777 // than wxDynamicObject we cast it down manually.
778 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
779 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
781 valo
= dynvalo
->GetSuperClassInstance() ;
784 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
787 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID
,
788 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
789 const wxDelegateTypeInfo
*delegateInfo
,
790 const wxClassInfo
*WXUNUSED(eventSinkClassInfo
) ,
791 const wxHandlerInfo
* handlerInfo
,
792 int eventSinkObjectID
)
794 wxWindow
*ehsource
= dynamic_cast< wxWindow
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
795 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
797 if ( ehsource
&& ehsink
)
799 ehsource
->Connect( ehsource
->GetId() , delegateInfo
->GetEventType() ,
800 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
805 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
807 return m_data
->GetObject( objectID
) ;
810 // adds an element to a property collection
811 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
812 const wxClassInfo
*classInfo
,
813 const wxPropertyInfo
* propertyInfo
,
814 const wxxVariant
&value
)
817 o
= m_data
->GetObject(objectID
);
818 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
821 // sets the corresponding property (value is an object)
822 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
823 const wxClassInfo
*classInfo
,
824 const wxPropertyInfo
* propertyInfo
,
828 o
= m_data
->GetObject(objectID
);
829 valo
= m_data
->GetObject(valueObjectId
);
830 const wxCollectionTypeInfo
* collectionTypeInfo
= dynamic_cast< const wxCollectionTypeInfo
* >(propertyInfo
->GetTypeInfo() ) ;
831 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(collectionTypeInfo
->GetElementType()))->GetClassInfo() ;
832 // if this is a dynamic object and we are asked for another class
833 // than wxDynamicObject we cast it down manually.
834 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
835 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
837 valo
= dynvalo
->GetSuperClassInstance() ;
840 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
843 // ----------------------------------------------------------------------------
844 // depersisting to code
845 // ----------------------------------------------------------------------------
847 struct wxCodeDepersister::wxCodeDepersisterInternal
849 map
<int,string
> m_objectNames
;
851 void SetObjectName(int objectID
, const wxString
&name
)
853 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
854 m_objectNames
[objectID
] = (const char *)name
;
856 wxString
GetObjectName( int objectID
)
858 if ( objectID
== wxNullObjectID
)
861 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
862 return wxString( m_objectNames
[objectID
].c_str() ) ;
866 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
869 m_data
= new wxCodeDepersisterInternal
;
872 wxCodeDepersister::~wxCodeDepersister()
877 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
879 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
880 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
881 classInfo
->GetClassName(),
883 classInfo
->GetClassName()) );
884 m_data
->SetObjectName( objectID
, objectName
) ;
887 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
889 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
890 m_data
->GetObjectName( objectID
) ) );
893 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
896 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
897 if ( type
->GetKind() == wxT_CUSTOM
)
899 const wxCustomTypeInfo
* cti
= dynamic_cast<const wxCustomTypeInfo
*>(type
) ;
900 wxASSERT_MSG( cti
, wxT("Internal error, illegal wxCustomTypeInfo") ) ;
901 value
.Printf( "%s(%s)",cti
->GetTypeName(),param
.GetAsString() );
903 else if ( type
->GetKind() == wxT_STRING
)
905 value
.Printf( "\"%s\"",param
.GetAsString() );
909 value
.Printf( "%s", param
.GetAsString() );
914 void wxCodeDepersister::CreateObject(int objectID
,
915 const wxClassInfo
*WXUNUSED(classInfo
),
919 const wxClassInfo
**WXUNUSED(objectClassInfos
)
923 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
) ) );
924 for (i
= 0; i
< paramCount
; i
++)
926 if ( objectIDValues
[i
] != wxInvalidObjectID
)
927 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ) ) );
930 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]) ) );
932 if (i
< paramCount
- 1)
933 m_fp
->WriteString( ", ");
935 m_fp
->WriteString( ");\n");
938 void wxCodeDepersister::SetProperty(int objectID
,
939 const wxClassInfo
*WXUNUSED(classInfo
),
940 const wxPropertyInfo
* propertyInfo
,
941 const wxxVariant
&value
)
943 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
944 m_data
->GetObjectName(objectID
),
945 propertyInfo
->GetAccessor()->GetSetterName(),
946 ValueAsCode(value
)) );
949 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
950 const wxClassInfo
*WXUNUSED(classInfo
),
951 const wxPropertyInfo
* propertyInfo
,
954 if ( propertyInfo
->GetTypeInfo()->GetKind() == wxT_OBJECT
)
955 m_fp
->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
956 m_data
->GetObjectName(objectID
),
957 propertyInfo
->GetAccessor()->GetSetterName(),
958 m_data
->GetObjectName( valueObjectId
) ) );
960 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
961 m_data
->GetObjectName(objectID
),
962 propertyInfo
->GetAccessor()->GetSetterName(),
963 m_data
->GetObjectName( valueObjectId
) ) );
966 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
967 const wxClassInfo
*classInfo
,
968 const wxPropertyInfo
* propertyInfo
,
969 const wxxVariant
&value
)
971 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
972 m_data
->GetObjectName(objectID
),
973 propertyInfo
->GetAccessor()->GetAdderName(),
974 ValueAsCode(value
)) );
977 // sets the corresponding property (value is an object)
978 void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID
,
979 const wxClassInfo
*classInfo
,
980 const wxPropertyInfo
* propertyInfo
,
986 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
987 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
988 const wxDelegateTypeInfo
*delegateInfo
,
989 const wxClassInfo
*eventSinkClassInfo
,
990 const wxHandlerInfo
* handlerInfo
,
991 int eventSinkObjectID
)
993 wxString ehsource
= m_data
->GetObjectName( eventSourceObjectID
) ;
994 wxString ehsink
= m_data
->GetObjectName(eventSinkObjectID
) ;
995 wxString ehsinkClass
= eventSinkClassInfo
->GetClassName() ;
996 int eventType
= delegateInfo
->GetEventType() ;
997 wxString handlerName
= handlerInfo
->GetName() ;
999 m_fp
->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
1000 ehsource
, ehsource
, eventType
, ehsinkClass
, handlerName
, ehsink
) );
1003 #include <wx/arrimpl.cpp>
1005 WX_DEFINE_OBJARRAY(wxxVariantArray
);