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 if ( persister
->BeforeWriteObject( this , object
, classInfo
) )
85 else if ( IsObjectKnown( object
) )
86 DoWriteRepeatedObject( GetObjectID(object
) ) ;
89 int oid
= m_data
->m_nextId
++ ;
91 m_data
->m_writtenObjects
[object
] = oid
;
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
;
99 DoBeginWriteObject( object
, classInfo
, oid
) ;
100 wxWriterInternalPropertiesData data
;
101 WriteAllProperties( object
, classInfo
, persister
, &data
) ;
102 DoEndWriteObject( object
, classInfo
, oid
) ;
104 persister
->AfterWriteObject( this ,object
, classInfo
) ;
108 void wxWriter::FindConnectEntry(const wxWindow
* evSource
,const wxDelegateTypeInfo
* dti
, const wxObject
* &sink
, const wxHandlerInfo
*&handler
)
110 wxList
*dynamicEvents
= evSource
->GetDynamicEventTable() ;
114 wxList::compatibility_iterator node
= dynamicEvents
->GetFirst();
117 wxDynamicEventTableEntry
*entry
= (wxDynamicEventTableEntry
*)node
->GetData();
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
) ) ) &&
128 sink
= entry
->m_eventSink
;
129 const wxClassInfo
* sinkClassInfo
= sink
->GetClassInfo() ;
130 const wxHandlerInfo
* sinkHandler
= sinkClassInfo
->GetFirstHandler() ;
131 while ( sinkHandler
)
133 if ( sinkHandler
->GetEventFunction() == entry
->m_fn
)
135 handler
= sinkHandler
;
138 sinkHandler
= sinkHandler
->GetNext() ;
142 node
= node
->GetNext();
146 void wxWriter::WriteAllProperties( const wxObject
* obj
, const wxClassInfo
* ci
, wxPersister
*persister
, wxWriterInternalPropertiesData
* data
)
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
151 const wxObject
*iterobj
= obj
;
152 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* > (iterobj
) ;
154 iterobj
= dynobj
->GetSuperClassInstance() ;
155 const wxClassInfo
** parents
= ci
->GetParents() ;
156 for ( int i
= 0 ; parents
[i
] ; ++ i
)
158 WriteAllProperties( iterobj
, parents
[i
] , persister
, data
) ;
162 const wxPropertyInfo
*pi
= ci
->GetFirstProperty() ;
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
169 data
->m_writtenProperties
[ pi
->GetName() ] = 1 ;
170 DoBeginWriteProperty( pi
) ;
171 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
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
)
177 DoBeginWriteElement() ;
178 wxxVariant value
= data
[i
] ;
179 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
181 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
184 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
185 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
186 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
190 DoWriteSimpleType( value
) ;
193 DoEndWriteElement() ;
198 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
201 const wxObject
* sink
= NULL
;
202 const wxHandlerInfo
*handler
= NULL
;
204 const wxWindow
* evSource
= dynamic_cast<const wxWindow
*>(obj
) ;
205 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
207 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
208 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
210 if ( sink
!= NULL
&& handler
!= NULL
)
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
) ;
219 wxxVariant value
= pi
->GetAccessor()->GetProperty(obj
) ;
220 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
222 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
225 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
226 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
227 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
231 DoWriteSimpleType( value
) ;
236 DoEndWriteProperty( pi
) ;
242 int wxWriter::GetObjectID(const wxObject
*obj
)
244 if ( !IsObjectKnown( obj
) )
245 return wxInvalidObjectID
;
247 return m_data
->m_writtenObjects
[obj
] ;
250 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
252 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
259 // convenience functions
261 void wxXmlAddContentToNode( wxXmlNode
* node
, const wxString
& data
)
263 node
->AddChild(new wxXmlNode(wxXML_TEXT_NODE
, "value", data
) );
266 wxString
wxXmlGetContentFromNode( wxXmlNode
*node
)
268 if ( node
->GetChildren() )
269 return node
->GetChildren()->GetContent() ;
271 return wxEmptyString
;
274 struct wxXmlWriter::wxXmlWriterInternal
277 wxXmlNode
*m_current
;
278 vector
< wxXmlNode
* > m_objectStack
;
280 void Push( wxXmlNode
*newCurrent
)
282 m_objectStack
.push_back( m_current
) ;
283 m_current
= newCurrent
;
288 m_current
= m_objectStack
.back() ;
289 m_objectStack
.pop_back() ;
293 wxXmlWriter::wxXmlWriter( wxXmlNode
* rootnode
)
295 m_data
= new wxXmlWriterInternal() ;
296 m_data
->m_root
= rootnode
;
297 m_data
->m_current
= rootnode
;
300 wxXmlWriter::~wxXmlWriter()
305 void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString
&name
)
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
) ;
314 void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString
&WXUNUSED(name
) )
319 void wxXmlWriter::DoBeginWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*classInfo
, int objectID
)
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
) );
326 m_data
->m_current
->AddChild(pnode
) ;
327 m_data
->Push( pnode
) ;
330 // end of writing the root object
331 void wxXmlWriter::DoEndWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*WXUNUSED(classInfo
), int WXUNUSED(objectID
) )
336 // writes a property in the stream format
337 void wxXmlWriter::DoWriteSimpleType( wxxVariant
&value
)
339 wxXmlAddContentToNode( m_data
->m_current
,value
.GetAsString() ) ;
342 void wxXmlWriter::DoBeginWriteElement()
345 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "element" );
346 m_data
->m_current
->AddChild(pnode
) ;
347 m_data
->Push( pnode
) ;
350 void wxXmlWriter::DoEndWriteElement()
355 void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo
*pi
)
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
) ;
364 void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo
*WXUNUSED(propInfo
) )
371 // insert an object reference to an already written object
372 void wxXmlWriter::DoWriteRepeatedObject( int objectID
)
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
) ;
380 // insert a null reference
381 void wxXmlWriter::DoWriteNullObject()
384 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
385 m_data
->m_current
->AddChild(pnode
) ;
388 // writes a delegate in the stream format
389 void 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
)
392 if ( eventSink
!= NULL
&& handlerInfo
!= NULL
)
394 wxXmlAddContentToNode( m_data
->m_current
,wxString::Format(wxT("%d.%s"), sinkObjectID
, handlerInfo
->GetName()) ) ;
398 // ----------------------------------------------------------------------------
399 // reading objects in
400 // ----------------------------------------------------------------------------
402 struct wxReader::wxReaderInternal
404 map
<int,wxClassInfo
*> m_classInfos
;
409 m_data
= new wxReaderInternal
;
412 wxReader::~wxReader()
417 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
419 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
420 return m_data
->m_classInfos
[objectID
] ;
423 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
425 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
426 m_data
->m_classInfos
[objectID
] = classInfo
;
429 bool wxReader::HasObjectClassInfo( int objectID
)
431 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
435 // ----------------------------------------------------------------------------
437 // ----------------------------------------------------------------------------
440 Reading components has not to be extended for components
441 as properties are always sought by typeinfo over all levels
442 and create params are always toplevel class only
445 int wxXmlReader::ReadComponent(wxXmlNode
*node
, wxDepersister
*callbacks
)
447 wxASSERT_MSG( callbacks
, wxT("Does not support reading without a Depersistor") ) ;
449 wxClassInfo
*classInfo
;
451 wxxVariant
*createParams
;
452 int *createParamOids
;
453 const wxClassInfo
** createClassInfos
;
456 wxString ObjectIdString
;
458 children
= node
->GetChildren();
461 // check for a null object or href
462 if (node
->GetPropVal("href" , &ObjectIdString
) )
464 objectID
= atoi( ObjectIdString
.c_str() ) ;
465 wxASSERT_MSG( HasObjectClassInfo( objectID
) , wxT("Forward hrefs are not supported") ) ;
468 if ( !node
->GetPropVal("id" , &ObjectIdString
) )
470 return wxNullObjectID
;
473 if (!node
->GetPropVal("class", &className
))
475 // No class name. Eek. FIXME: error handling
476 return wxInvalidObjectID
;
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
))
483 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
484 // No object id. Eek. FIXME: error handling
485 return wxInvalidObjectID
;
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
) ) ;
491 // new object, start with allocation
492 // first make the object know to our internal registry
493 SetObjectClassInfo( objectID
, classInfo
) ;
495 callbacks
->AllocateObject(objectID
, classInfo
);
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() ] ;
503 typedef map
<string
, wxXmlNode
*> PropertyNodes
;
504 typedef vector
<string
> PropertyNames
;
506 PropertyNodes propertyNodes
;
507 PropertyNames propertyNames
;
512 children
->GetPropVal( wxT("name") , &name
) ;
513 propertyNames
.push_back( name
.c_str() ) ;
514 propertyNodes
[name
.c_str()] = children
->GetChildren() ;
515 children
= children
->GetNext() ;
518 for ( int i
= 0 ; i
<classInfo
->GetCreateParamCount() ; ++i
)
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() )
528 wxXmlNode
* prop
= propiter
->second
;
529 if ( pi
->GetTypeInfo()->IsObjectType() )
531 createParamOids
[i
] = ReadComponent( prop
, callbacks
) ;
532 createClassInfos
[i
] = dynamic_cast<const wxClassTypeInfo
*>(pi
->GetTypeInfo())->GetClassInfo() ;
536 createParamOids
[i
] = wxInvalidObjectID
;
537 createParams
[i
] = ReadValue( prop
, pi
->GetAccessor() ) ;
538 createClassInfos
[i
] = NULL
;
541 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
543 if ( propertyNames
[j
] == paramName
)
545 propertyNames
[j
] = "" ;
552 createParams
[i
] = pi
->GetDefaultValue() ;
556 // got the parameters. Call the Create method
557 callbacks
->CreateObject(objectID
, classInfo
,
558 classInfo
->GetCreateParamCount(),
559 createParams
, createParamOids
, createClassInfos
);
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
)
564 if ( propertyNames
[j
].length() )
566 PropertyNodes::iterator propiter
= propertyNodes
.find( propertyNames
[j
] ) ;
567 if ( propiter
!= propertyNodes
.end() )
569 wxXmlNode
* prop
= propiter
->second
;
570 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( propertyNames
[j
].c_str() ) ;
571 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
573 const wxCollectionTypeInfo
* collType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() ) ;
574 const wxTypeInfo
* elementType
= collType
->GetElementType() ;
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() )
582 int valueId
= ReadComponent( elementContent
, callbacks
) ;
583 if ( valueId
!= wxInvalidObjectID
)
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
) ) ;
594 wxxVariant elementValue
= ReadValue( prop
, pi
->GetAccessor() ) ;
595 if ( pi
->GetAccessor()->HasAdder() )
596 callbacks
->AddToPropertyCollection( objectID
, classInfo
,pi
, elementValue
) ;
598 prop
= prop
->GetNext() ;
601 else if ( pi
->GetTypeInfo()->IsObjectType() )
603 int valueId
= ReadComponent( prop
, callbacks
) ;
604 if ( valueId
!= wxInvalidObjectID
)
606 callbacks
->SetPropertyAsObject( objectID
, classInfo
, pi
, valueId
) ;
607 if ( pi
->GetTypeInfo()->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
608 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
611 else if ( pi
->GetTypeInfo()->IsDelegateType() )
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
) ;
622 callbacks
->SetConnect( objectID
, classInfo
, dynamic_cast<const wxDelegateTypeInfo
*>(pi
->GetTypeInfo()) , sinkClassInfo
,
623 sinkClassInfo
->FindHandlerInfo(handlerName
) , sinkOid
) ;
629 callbacks
->SetProperty( objectID
, classInfo
,pi
, ReadValue( prop
, pi
->GetAccessor() ) ) ;
635 delete[] createParams
;
636 delete[] createParamOids
;
637 delete[] createClassInfos
;
642 wxxVariant
wxXmlReader::ReadValue(wxXmlNode
*node
,
643 wxPropertyAccessor
*accessor
)
647 content
= node
->GetContent() ;
648 return accessor
->ReadValue(content
) ;
651 int wxXmlReader::ReadObject( const wxString
&name
, wxDepersister
*callbacks
)
653 wxXmlNode
*iter
= m_parent
->GetChildren() ;
657 if ( iter
->GetPropVal("name", &entryName
) )
659 if ( entryName
== name
)
660 return ReadComponent( iter
->GetChildren() , callbacks
) ;
662 iter
= iter
->GetNext() ;
664 return wxInvalidObjectID
;
667 // ----------------------------------------------------------------------------
668 // depersisting to memory
669 // ----------------------------------------------------------------------------
671 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
673 map
<int,wxObject
*> m_objects
;
675 void SetObject(int objectID
, wxObject
*obj
)
677 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
678 m_objects
[objectID
] = obj
;
680 wxObject
* GetObject( int objectID
)
682 if ( objectID
== wxNullObjectID
)
685 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
686 return m_objects
[objectID
] ;
690 wxRuntimeDepersister::wxRuntimeDepersister()
692 m_data
= new wxRuntimeDepersisterInternal() ;
695 wxRuntimeDepersister::~wxRuntimeDepersister()
700 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
703 O
= classInfo
->CreateObject();
704 m_data
->SetObject(objectID
, O
);
707 void wxRuntimeDepersister::CreateObject(int objectID
,
708 const wxClassInfo
*classInfo
,
712 const wxClassInfo
**objectClassInfos
)
715 o
= m_data
->GetObject(objectID
);
716 for ( int i
= 0 ; i
< paramCount
; ++i
)
718 if ( objectIdValues
[i
] != wxInvalidObjectID
)
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()) )
727 o
= dyno
->GetSuperClassInstance() ;
729 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
732 classInfo
->Create(o
, paramCount
, params
);
735 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
738 o
= m_data
->GetObject(objectID
);
742 void wxRuntimeDepersister::SetProperty(int objectID
,
743 const wxClassInfo
*classInfo
,
744 const wxPropertyInfo
* propertyInfo
,
745 const wxxVariant
&value
)
748 o
= m_data
->GetObject(objectID
);
749 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
752 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
753 const wxClassInfo
*classInfo
,
754 const wxPropertyInfo
* propertyInfo
,
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()) )
766 valo
= dynvalo
->GetSuperClassInstance() ;
769 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
772 void 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
)
779 wxWindow
*ehsource
= dynamic_cast< wxWindow
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
780 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
782 if ( ehsource
&& ehsink
)
784 ehsource
->Connect( ehsource
->GetId() , delegateInfo
->GetEventType() ,
785 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
790 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
792 return m_data
->GetObject( objectID
) ;
795 // adds an element to a property collection
796 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
797 const wxClassInfo
*classInfo
,
798 const wxPropertyInfo
* propertyInfo
,
799 const wxxVariant
&value
)
802 o
= m_data
->GetObject(objectID
);
803 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
806 // sets the corresponding property (value is an object)
807 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
808 const wxClassInfo
*classInfo
,
809 const wxPropertyInfo
* propertyInfo
,
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()) )
822 valo
= dynvalo
->GetSuperClassInstance() ;
825 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
828 // ----------------------------------------------------------------------------
829 // depersisting to code
830 // ----------------------------------------------------------------------------
832 struct wxCodeDepersister::wxCodeDepersisterInternal
834 map
<int,string
> m_objectNames
;
836 void SetObjectName(int objectID
, const wxString
&name
)
838 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
839 m_objectNames
[objectID
] = (const char *)name
;
841 wxString
GetObjectName( int objectID
)
843 if ( objectID
== wxNullObjectID
)
846 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
847 return wxString( m_objectNames
[objectID
].c_str() ) ;
851 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
854 m_data
= new wxCodeDepersisterInternal
;
857 wxCodeDepersister::~wxCodeDepersister()
862 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
864 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
865 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
866 classInfo
->GetClassName(),
868 classInfo
->GetClassName()) );
869 m_data
->SetObjectName( objectID
, objectName
) ;
872 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
874 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
875 m_data
->GetObjectName( objectID
) ) );
878 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
881 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
882 if ( type
->GetKind() == wxT_CUSTOM
)
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() );
888 else if ( type
->GetKind() == wxT_STRING
)
890 value
.Printf( "\"%s\"",param
.GetAsString() );
894 value
.Printf( "%s", param
.GetAsString() );
899 void wxCodeDepersister::CreateObject(int objectID
,
900 const wxClassInfo
*WXUNUSED(classInfo
),
904 const wxClassInfo
**WXUNUSED(objectClassInfos
)
908 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
) ) );
909 for (i
= 0; i
< paramCount
; i
++)
911 if ( objectIDValues
[i
] != wxInvalidObjectID
)
912 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ) ) );
915 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]) ) );
917 if (i
< paramCount
- 1)
918 m_fp
->WriteString( ", ");
920 m_fp
->WriteString( ");\n");
923 void wxCodeDepersister::SetProperty(int objectID
,
924 const wxClassInfo
*WXUNUSED(classInfo
),
925 const wxPropertyInfo
* propertyInfo
,
926 const wxxVariant
&value
)
928 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
929 m_data
->GetObjectName(objectID
),
930 propertyInfo
->GetAccessor()->GetSetterName(),
931 ValueAsCode(value
)) );
934 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
935 const wxClassInfo
*WXUNUSED(classInfo
),
936 const wxPropertyInfo
* propertyInfo
,
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
) ) );
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
) ) );
951 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
952 const wxClassInfo
*classInfo
,
953 const wxPropertyInfo
* propertyInfo
,
954 const wxxVariant
&value
)
956 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
957 m_data
->GetObjectName(objectID
),
958 propertyInfo
->GetAccessor()->GetAdderName(),
959 ValueAsCode(value
)) );
962 // sets the corresponding property (value is an object)
963 void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID
,
964 const wxClassInfo
*classInfo
,
965 const wxPropertyInfo
* propertyInfo
,
971 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
972 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
973 const wxDelegateTypeInfo
*delegateInfo
,
974 const wxClassInfo
*eventSinkClassInfo
,
975 const wxHandlerInfo
* handlerInfo
,
976 int eventSinkObjectID
)
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() ;
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
) );
988 #include <wx/arrimpl.cpp>
990 WX_DEFINE_OBJARRAY(wxxVariantArray
);