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
;
174 pi
->GetAccessor()->GetPropertyCollection(obj
, data
) ;
175 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
176 for ( size_t i
= 0 ; i
< data
.GetCount() ; ++i
)
178 DoBeginWriteElement() ;
179 wxxVariant value
= data
[i
] ;
180 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
182 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
185 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
186 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
187 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
191 DoWriteSimpleType( value
) ;
194 DoEndWriteElement() ;
199 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
202 const wxObject
* sink
= NULL
;
203 const wxHandlerInfo
*handler
= NULL
;
205 const wxWindow
* evSource
= dynamic_cast<const wxWindow
*>(obj
) ;
206 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
208 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
209 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
211 if ( sink
!= NULL
&& handler
!= NULL
)
213 wxASSERT_MSG( IsObjectKnown( sink
) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
214 DoWriteDelegate( obj
, ci
, pi
, sink
, GetObjectID( sink
) , sink
->GetClassInfo() , handler
) ;
221 pi
->GetAccessor()->GetProperty(obj
, value
) ;
222 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
224 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
227 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
228 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
229 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
233 DoWriteSimpleType( value
) ;
238 DoEndWriteProperty( pi
) ;
244 int wxWriter::GetObjectID(const wxObject
*obj
)
246 if ( !IsObjectKnown( obj
) )
247 return wxInvalidObjectID
;
249 return m_data
->m_writtenObjects
[obj
] ;
252 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
254 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
261 // convenience functions
263 void wxXmlAddContentToNode( wxXmlNode
* node
, const wxString
& data
)
265 node
->AddChild(new wxXmlNode(wxXML_TEXT_NODE
, "value", data
) );
268 wxString
wxXmlGetContentFromNode( wxXmlNode
*node
)
270 if ( node
->GetChildren() )
271 return node
->GetChildren()->GetContent() ;
273 return wxEmptyString
;
276 struct wxXmlWriter::wxXmlWriterInternal
279 wxXmlNode
*m_current
;
280 vector
< wxXmlNode
* > m_objectStack
;
282 void Push( wxXmlNode
*newCurrent
)
284 m_objectStack
.push_back( m_current
) ;
285 m_current
= newCurrent
;
290 m_current
= m_objectStack
.back() ;
291 m_objectStack
.pop_back() ;
295 wxXmlWriter::wxXmlWriter( wxXmlNode
* rootnode
)
297 m_data
= new wxXmlWriterInternal() ;
298 m_data
->m_root
= rootnode
;
299 m_data
->m_current
= rootnode
;
302 wxXmlWriter::~wxXmlWriter()
307 void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString
&name
)
310 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("entry"));
311 pnode
->AddProperty(wxString("name"), name
);
312 m_data
->m_current
->AddChild(pnode
) ;
313 m_data
->Push( pnode
) ;
316 void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString
&WXUNUSED(name
) )
321 void wxXmlWriter::DoBeginWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*classInfo
, int objectID
)
324 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
325 pnode
->AddProperty(wxT("class"), wxString(classInfo
->GetClassName()));
326 pnode
->AddProperty(wxT("id"), wxString::Format( "%d" , objectID
) );
328 m_data
->m_current
->AddChild(pnode
) ;
329 m_data
->Push( pnode
) ;
332 // end of writing the root object
333 void wxXmlWriter::DoEndWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*WXUNUSED(classInfo
), int WXUNUSED(objectID
) )
338 // writes a property in the stream format
339 void wxXmlWriter::DoWriteSimpleType( wxxVariant
&value
)
341 wxXmlAddContentToNode( m_data
->m_current
,value
.GetAsString() ) ;
344 void wxXmlWriter::DoBeginWriteElement()
347 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "element" );
348 m_data
->m_current
->AddChild(pnode
) ;
349 m_data
->Push( pnode
) ;
352 void wxXmlWriter::DoEndWriteElement()
357 void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo
*pi
)
360 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "prop" );
361 pnode
->AddProperty(wxT("name"), pi
->GetName() );
362 m_data
->m_current
->AddChild(pnode
) ;
363 m_data
->Push( pnode
) ;
366 void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo
*WXUNUSED(propInfo
) )
373 // insert an object reference to an already written object
374 void wxXmlWriter::DoWriteRepeatedObject( int objectID
)
377 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
378 pnode
->AddProperty(wxString("href"), wxString::Format( "%d" , objectID
) );
379 m_data
->m_current
->AddChild(pnode
) ;
382 // insert a null reference
383 void wxXmlWriter::DoWriteNullObject()
386 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
387 m_data
->m_current
->AddChild(pnode
) ;
390 // writes a delegate in the stream format
391 void wxXmlWriter::DoWriteDelegate( const wxObject
*WXUNUSED(object
), const wxClassInfo
* WXUNUSED(classInfo
) , const wxPropertyInfo
*WXUNUSED(pi
) ,
392 const wxObject
*eventSink
, int sinkObjectID
, const wxClassInfo
* WXUNUSED(eventSinkClassInfo
) , const wxHandlerInfo
* handlerInfo
)
394 if ( eventSink
!= NULL
&& handlerInfo
!= NULL
)
396 wxXmlAddContentToNode( m_data
->m_current
,wxString::Format(wxT("%d.%s"), sinkObjectID
, handlerInfo
->GetName()) ) ;
400 // ----------------------------------------------------------------------------
401 // reading objects in
402 // ----------------------------------------------------------------------------
404 struct wxReader::wxReaderInternal
406 map
<int,wxClassInfo
*> m_classInfos
;
411 m_data
= new wxReaderInternal
;
414 wxReader::~wxReader()
419 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
421 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
422 return m_data
->m_classInfos
[objectID
] ;
425 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
427 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
428 m_data
->m_classInfos
[objectID
] = classInfo
;
431 bool wxReader::HasObjectClassInfo( int objectID
)
433 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
437 // ----------------------------------------------------------------------------
439 // ----------------------------------------------------------------------------
442 Reading components has not to be extended for components
443 as properties are always sought by typeinfo over all levels
444 and create params are always toplevel class only
447 int wxXmlReader::ReadComponent(wxXmlNode
*node
, wxDepersister
*callbacks
)
449 wxASSERT_MSG( callbacks
, wxT("Does not support reading without a Depersistor") ) ;
451 wxClassInfo
*classInfo
;
453 wxxVariant
*createParams
;
454 int *createParamOids
;
455 const wxClassInfo
** createClassInfos
;
458 wxString ObjectIdString
;
460 children
= node
->GetChildren();
463 // check for a null object or href
464 if (node
->GetPropVal("href" , &ObjectIdString
) )
466 objectID
= atoi( ObjectIdString
.c_str() ) ;
467 wxASSERT_MSG( HasObjectClassInfo( objectID
) , wxT("Forward hrefs are not supported") ) ;
470 if ( !node
->GetPropVal("id" , &ObjectIdString
) )
472 return wxNullObjectID
;
475 if (!node
->GetPropVal("class", &className
))
477 // No class name. Eek. FIXME: error handling
478 return wxInvalidObjectID
;
480 classInfo
= wxClassInfo::FindClass(className
);
481 wxASSERT_MSG( classInfo
, wxString::Format(wxT("unknown class %s"),className
) ) ;
482 wxASSERT_MSG( !children
|| children
->GetType() != wxXML_TEXT_NODE
, wxT("objects cannot have XML Text Nodes") ) ;
483 if (!node
->GetPropVal("id", &ObjectIdString
))
485 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
486 // No object id. Eek. FIXME: error handling
487 return wxInvalidObjectID
;
489 objectID
= atoi( ObjectIdString
.c_str() ) ;
490 // is this object already has been streamed in, return it here
491 wxASSERT_MSG( !HasObjectClassInfo( objectID
) , wxString::Format(wxT("Doubly used id : %d"), objectID
) ) ;
493 // new object, start with allocation
494 // first make the object know to our internal registry
495 SetObjectClassInfo( objectID
, classInfo
) ;
497 callbacks
->AllocateObject(objectID
, classInfo
);
500 // stream back the Create parameters first
501 createParams
= new wxxVariant
[ classInfo
->GetCreateParamCount() ] ;
502 createParamOids
= new int[classInfo
->GetCreateParamCount() ] ;
503 createClassInfos
= new const wxClassInfo
*[classInfo
->GetCreateParamCount() ] ;
505 typedef map
<string
, wxXmlNode
*> PropertyNodes
;
506 typedef vector
<string
> PropertyNames
;
508 PropertyNodes propertyNodes
;
509 PropertyNames propertyNames
;
514 children
->GetPropVal( wxT("name") , &name
) ;
515 propertyNames
.push_back( name
.c_str() ) ;
516 propertyNodes
[name
.c_str()] = children
->GetChildren() ;
517 children
= children
->GetNext() ;
520 for ( int i
= 0 ; i
<classInfo
->GetCreateParamCount() ; ++i
)
522 const wxChar
* paramName
= classInfo
->GetCreateParamName(i
) ;
523 PropertyNodes::iterator propiter
= propertyNodes
.find( paramName
) ;
524 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( paramName
) ;
525 wxASSERT_MSG(pi
,wxString::Format("Unkown Property %s",paramName
) ) ;
526 // if we don't have the value of a create param set in the xml
527 // we use the default value
528 if ( propiter
!= propertyNodes
.end() )
530 wxXmlNode
* prop
= propiter
->second
;
531 if ( pi
->GetTypeInfo()->IsObjectType() )
533 createParamOids
[i
] = ReadComponent( prop
, callbacks
) ;
534 createClassInfos
[i
] = dynamic_cast<const wxClassTypeInfo
*>(pi
->GetTypeInfo())->GetClassInfo() ;
538 createParamOids
[i
] = wxInvalidObjectID
;
539 createParams
[i
] = ReadValue( prop
, pi
->GetTypeInfo() ) ;
540 createClassInfos
[i
] = NULL
;
543 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
545 if ( propertyNames
[j
] == paramName
)
547 propertyNames
[j
] = "" ;
554 createParams
[i
] = pi
->GetDefaultValue() ;
558 // got the parameters. Call the Create method
559 callbacks
->CreateObject(objectID
, classInfo
,
560 classInfo
->GetCreateParamCount(),
561 createParams
, createParamOids
, createClassInfos
);
563 // now stream in the rest of the properties, in the sequence their properties were written in the xml
564 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
566 if ( propertyNames
[j
].length() )
568 PropertyNodes::iterator propiter
= propertyNodes
.find( propertyNames
[j
] ) ;
569 if ( propiter
!= propertyNodes
.end() )
571 wxXmlNode
* prop
= propiter
->second
;
572 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( propertyNames
[j
].c_str() ) ;
573 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
575 const wxCollectionTypeInfo
* collType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() ) ;
576 const wxTypeInfo
* elementType
= collType
->GetElementType() ;
579 wxASSERT_MSG(prop
->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
580 wxXmlNode
* elementContent
= prop
->GetChildren() ;
581 wxASSERT_MSG(elementContent
, wxT("An element node cannot be empty")) ;
582 if ( elementType
->IsObjectType() )
584 int valueId
= ReadComponent( elementContent
, callbacks
) ;
585 if ( valueId
!= wxInvalidObjectID
)
587 if ( pi
->GetAccessor()->HasAdder() )
588 callbacks
->AddToPropertyCollectionAsObject( objectID
, classInfo
, pi
, valueId
) ;
589 // TODO for collections we must have a notation on taking over ownership or not
590 if ( elementType
->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
591 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
596 wxxVariant elementValue
= ReadValue( elementContent
, elementType
) ;
597 if ( pi
->GetAccessor()->HasAdder() )
598 callbacks
->AddToPropertyCollection( objectID
, classInfo
,pi
, elementValue
) ;
600 prop
= prop
->GetNext() ;
603 else if ( pi
->GetTypeInfo()->IsObjectType() )
605 int valueId
= ReadComponent( prop
, callbacks
) ;
606 if ( valueId
!= wxInvalidObjectID
)
608 callbacks
->SetPropertyAsObject( objectID
, classInfo
, pi
, valueId
) ;
609 if ( pi
->GetTypeInfo()->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
610 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
613 else if ( pi
->GetTypeInfo()->IsDelegateType() )
617 wxString resstring
= prop
->GetContent() ;
618 wxInt32 pos
= resstring
.Find('.') ;
619 assert( pos
!= wxNOT_FOUND
) ;
620 int sinkOid
= atol(resstring
.Left(pos
)) ;
621 wxString handlerName
= resstring
.Mid(pos
+1) ;
622 wxClassInfo
* sinkClassInfo
= GetObjectClassInfo( sinkOid
) ;
624 callbacks
->SetConnect( objectID
, classInfo
, dynamic_cast<const wxDelegateTypeInfo
*>(pi
->GetTypeInfo()) , sinkClassInfo
,
625 sinkClassInfo
->FindHandlerInfo(handlerName
) , sinkOid
) ;
632 callbacks
->SetProperty( objectID
, classInfo
,pi
, ReadValue( prop
, pi
->GetTypeInfo() ) ) ;
638 delete[] createParams
;
639 delete[] createParamOids
;
640 delete[] createClassInfos
;
645 wxxVariant
wxXmlReader::ReadValue(wxXmlNode
*node
,
646 const wxTypeInfo
*type
)
650 content
= node
->GetContent() ;
652 type
->ConvertFromString( content
, result
) ;
656 int wxXmlReader::ReadObject( const wxString
&name
, wxDepersister
*callbacks
)
658 wxXmlNode
*iter
= m_parent
->GetChildren() ;
662 if ( iter
->GetPropVal("name", &entryName
) )
664 if ( entryName
== name
)
665 return ReadComponent( iter
->GetChildren() , callbacks
) ;
667 iter
= iter
->GetNext() ;
669 return wxInvalidObjectID
;
672 // ----------------------------------------------------------------------------
673 // depersisting to memory
674 // ----------------------------------------------------------------------------
676 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
678 map
<int,wxObject
*> m_objects
;
680 void SetObject(int objectID
, wxObject
*obj
)
682 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
683 m_objects
[objectID
] = obj
;
685 wxObject
* GetObject( int objectID
)
687 if ( objectID
== wxNullObjectID
)
690 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
691 return m_objects
[objectID
] ;
695 wxRuntimeDepersister::wxRuntimeDepersister()
697 m_data
= new wxRuntimeDepersisterInternal() ;
700 wxRuntimeDepersister::~wxRuntimeDepersister()
705 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
708 O
= classInfo
->CreateObject();
709 m_data
->SetObject(objectID
, O
);
712 void wxRuntimeDepersister::CreateObject(int objectID
,
713 const wxClassInfo
*classInfo
,
717 const wxClassInfo
**objectClassInfos
)
720 o
= m_data
->GetObject(objectID
);
721 for ( int i
= 0 ; i
< paramCount
; ++i
)
723 if ( objectIdValues
[i
] != wxInvalidObjectID
)
726 o
= m_data
->GetObject(objectIdValues
[i
]);
727 // if this is a dynamic object and we are asked for another class
728 // than wxDynamicObject we cast it down manually.
729 wxDynamicObject
*dyno
= dynamic_cast< wxDynamicObject
* > (o
) ;
730 if ( dyno
!=NULL
&& (objectClassInfos
[i
] != dyno
->GetClassInfo()) )
732 o
= dyno
->GetSuperClassInstance() ;
734 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
737 classInfo
->Create(o
, paramCount
, params
);
740 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
743 o
= m_data
->GetObject(objectID
);
747 void wxRuntimeDepersister::SetProperty(int objectID
,
748 const wxClassInfo
*classInfo
,
749 const wxPropertyInfo
* propertyInfo
,
750 const wxxVariant
&value
)
753 o
= m_data
->GetObject(objectID
);
754 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
757 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
758 const wxClassInfo
*classInfo
,
759 const wxPropertyInfo
* propertyInfo
,
763 o
= m_data
->GetObject(objectID
);
764 valo
= m_data
->GetObject(valueObjectId
);
765 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(propertyInfo
->GetTypeInfo()))->GetClassInfo() ;
766 // if this is a dynamic object and we are asked for another class
767 // than wxDynamicObject we cast it down manually.
768 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
769 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
771 valo
= dynvalo
->GetSuperClassInstance() ;
774 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
777 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID
,
778 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
779 const wxDelegateTypeInfo
*delegateInfo
,
780 const wxClassInfo
*WXUNUSED(eventSinkClassInfo
) ,
781 const wxHandlerInfo
* handlerInfo
,
782 int eventSinkObjectID
)
784 wxWindow
*ehsource
= dynamic_cast< wxWindow
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
785 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
787 if ( ehsource
&& ehsink
)
789 ehsource
->Connect( ehsource
->GetId() , delegateInfo
->GetEventType() ,
790 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
795 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
797 return m_data
->GetObject( objectID
) ;
800 // adds an element to a property collection
801 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
802 const wxClassInfo
*classInfo
,
803 const wxPropertyInfo
* propertyInfo
,
804 const wxxVariant
&value
)
807 o
= m_data
->GetObject(objectID
);
808 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
811 // sets the corresponding property (value is an object)
812 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
813 const wxClassInfo
*classInfo
,
814 const wxPropertyInfo
* propertyInfo
,
818 o
= m_data
->GetObject(objectID
);
819 valo
= m_data
->GetObject(valueObjectId
);
820 const wxCollectionTypeInfo
* collectionTypeInfo
= dynamic_cast< const wxCollectionTypeInfo
* >(propertyInfo
->GetTypeInfo() ) ;
821 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(collectionTypeInfo
->GetElementType()))->GetClassInfo() ;
822 // if this is a dynamic object and we are asked for another class
823 // than wxDynamicObject we cast it down manually.
824 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
825 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
827 valo
= dynvalo
->GetSuperClassInstance() ;
830 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
833 // ----------------------------------------------------------------------------
834 // depersisting to code
835 // ----------------------------------------------------------------------------
837 struct wxCodeDepersister::wxCodeDepersisterInternal
839 map
<int,string
> m_objectNames
;
841 void SetObjectName(int objectID
, const wxString
&name
)
843 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
844 m_objectNames
[objectID
] = (const char *)name
;
846 wxString
GetObjectName( int objectID
)
848 if ( objectID
== wxNullObjectID
)
851 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
852 return wxString( m_objectNames
[objectID
].c_str() ) ;
856 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
859 m_data
= new wxCodeDepersisterInternal
;
862 wxCodeDepersister::~wxCodeDepersister()
867 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
869 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
870 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
871 classInfo
->GetClassName(),
873 classInfo
->GetClassName()) );
874 m_data
->SetObjectName( objectID
, objectName
) ;
877 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
879 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
880 m_data
->GetObjectName( objectID
) ) );
883 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
886 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
887 if ( type
->GetKind() == wxT_CUSTOM
)
889 const wxCustomTypeInfo
* cti
= dynamic_cast<const wxCustomTypeInfo
*>(type
) ;
890 wxASSERT_MSG( cti
, wxT("Internal error, illegal wxCustomTypeInfo") ) ;
891 value
.Printf( "%s(%s)",cti
->GetTypeName(),param
.GetAsString() );
893 else if ( type
->GetKind() == wxT_STRING
)
895 value
.Printf( "\"%s\"",param
.GetAsString() );
899 value
.Printf( "%s", param
.GetAsString() );
904 void wxCodeDepersister::CreateObject(int objectID
,
905 const wxClassInfo
*WXUNUSED(classInfo
),
909 const wxClassInfo
**WXUNUSED(objectClassInfos
)
913 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
) ) );
914 for (i
= 0; i
< paramCount
; i
++)
916 if ( objectIDValues
[i
] != wxInvalidObjectID
)
917 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ) ) );
920 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]) ) );
922 if (i
< paramCount
- 1)
923 m_fp
->WriteString( ", ");
925 m_fp
->WriteString( ");\n");
928 void wxCodeDepersister::SetProperty(int objectID
,
929 const wxClassInfo
*WXUNUSED(classInfo
),
930 const wxPropertyInfo
* propertyInfo
,
931 const wxxVariant
&value
)
933 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
934 m_data
->GetObjectName(objectID
),
935 propertyInfo
->GetAccessor()->GetSetterName(),
936 ValueAsCode(value
)) );
939 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
940 const wxClassInfo
*WXUNUSED(classInfo
),
941 const wxPropertyInfo
* propertyInfo
,
944 if ( propertyInfo
->GetTypeInfo()->GetKind() == wxT_OBJECT
)
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
) ) );
950 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
951 m_data
->GetObjectName(objectID
),
952 propertyInfo
->GetAccessor()->GetSetterName(),
953 m_data
->GetObjectName( valueObjectId
) ) );
956 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
957 const wxClassInfo
*classInfo
,
958 const wxPropertyInfo
* propertyInfo
,
959 const wxxVariant
&value
)
961 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
962 m_data
->GetObjectName(objectID
),
963 propertyInfo
->GetAccessor()->GetAdderName(),
964 ValueAsCode(value
)) );
967 // sets the corresponding property (value is an object)
968 void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID
,
969 const wxClassInfo
*classInfo
,
970 const wxPropertyInfo
* propertyInfo
,
976 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
977 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
978 const wxDelegateTypeInfo
*delegateInfo
,
979 const wxClassInfo
*eventSinkClassInfo
,
980 const wxHandlerInfo
* handlerInfo
,
981 int eventSinkObjectID
)
983 wxString ehsource
= m_data
->GetObjectName( eventSourceObjectID
) ;
984 wxString ehsink
= m_data
->GetObjectName(eventSinkObjectID
) ;
985 wxString ehsinkClass
= eventSinkClassInfo
->GetClassName() ;
986 int eventType
= delegateInfo
->GetEventType() ;
987 wxString handlerName
= handlerInfo
->GetName() ;
989 m_fp
->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
990 ehsource
, ehsource
, eventType
, ehsinkClass
, handlerName
, ehsink
) );
993 #include <wx/arrimpl.cpp>
995 WX_DEFINE_OBJARRAY(wxxVariantArray
);