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 const wxPropertyInfo
*pi
= ci
->GetFirstProperty() ;
151 // this property was not written yet in this object and we don't get a veto
152 if ( data
->m_writtenProperties
.find( pi
->GetName() ) == data
->m_writtenProperties
.end() )
154 data
->m_writtenProperties
[ pi
->GetName() ] = 1 ;
155 DoBeginWriteProperty( pi
) ;
156 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
158 wxxVariantArray data
= pi
->GetAccessor()->GetPropertyCollection(obj
) ;
159 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
160 for ( size_t i
= 0 ; i
< data
.GetCount() ; ++i
)
162 DoBeginWriteElement() ;
163 wxxVariant value
= data
[i
] ;
164 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
166 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
169 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
170 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
171 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
175 DoWriteSimpleType( value
) ;
178 DoEndWriteElement() ;
183 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
186 const wxObject
* sink
= NULL
;
187 const wxHandlerInfo
*handler
= NULL
;
189 const wxWindow
* evSource
= dynamic_cast<const wxWindow
*>(obj
) ;
190 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
192 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
193 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
195 if ( sink
!= NULL
&& handler
!= NULL
)
197 wxASSERT_MSG( IsObjectKnown( sink
) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
198 DoWriteDelegate( obj
, ci
, pi
, sink
, GetObjectID( sink
) , sink
->GetClassInfo() , handler
) ;
204 wxxVariant value
= pi
->GetAccessor()->GetProperty(obj
) ;
205 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
207 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
210 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
211 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
212 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
) ;
216 DoWriteSimpleType( value
) ;
221 DoEndWriteProperty( pi
) ;
225 // in case this object is wxDynamic object we have to hand over the streaming
226 // of the properties of the superclasses to the real super class instance
227 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* > (obj
) ;
229 obj
= dynobj
->GetSuperClassInstance() ;
230 const wxClassInfo
** parents
= ci
->GetParents() ;
231 for ( int i
= 0 ; parents
[i
] ; ++ i
)
233 WriteAllProperties( obj
, parents
[i
] , persister
, data
) ;
237 int wxWriter::GetObjectID(const wxObject
*obj
)
239 if ( !IsObjectKnown( obj
) )
240 return wxInvalidObjectID
;
242 return m_data
->m_writtenObjects
[obj
] ;
245 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
247 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
254 // convenience functions
256 void wxXmlAddContentToNode( wxXmlNode
* node
, const wxString
& data
)
258 node
->AddChild(new wxXmlNode(wxXML_TEXT_NODE
, "value", data
) );
261 wxString
wxXmlGetContentFromNode( wxXmlNode
*node
)
263 if ( node
->GetChildren() )
264 return node
->GetChildren()->GetContent() ;
266 return wxEmptyString
;
269 struct wxXmlWriter::wxXmlWriterInternal
272 wxXmlNode
*m_current
;
273 vector
< wxXmlNode
* > m_objectStack
;
275 void Push( wxXmlNode
*newCurrent
)
277 m_objectStack
.push_back( m_current
) ;
278 m_current
= newCurrent
;
283 m_current
= m_objectStack
.back() ;
284 m_objectStack
.pop_back() ;
288 wxXmlWriter::wxXmlWriter( wxXmlNode
* rootnode
)
290 m_data
= new wxXmlWriterInternal() ;
291 m_data
->m_root
= rootnode
;
292 m_data
->m_current
= rootnode
;
295 wxXmlWriter::~wxXmlWriter()
300 void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString
&name
)
303 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("entry"));
304 pnode
->AddProperty(wxString("name"), name
);
305 m_data
->m_current
->AddChild(pnode
) ;
306 m_data
->Push( pnode
) ;
309 void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString
&WXUNUSED(name
) )
314 void wxXmlWriter::DoBeginWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*classInfo
, int objectID
)
317 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
318 pnode
->AddProperty(wxT("class"), wxString(classInfo
->GetClassName()));
319 pnode
->AddProperty(wxT("id"), wxString::Format( "%d" , objectID
) );
321 m_data
->m_current
->AddChild(pnode
) ;
322 m_data
->Push( pnode
) ;
325 // end of writing the root object
326 void wxXmlWriter::DoEndWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*WXUNUSED(classInfo
), int WXUNUSED(objectID
) )
331 // writes a property in the stream format
332 void wxXmlWriter::DoWriteSimpleType( wxxVariant
&value
)
334 wxXmlAddContentToNode( m_data
->m_current
,value
.GetAsString() ) ;
337 void wxXmlWriter::DoBeginWriteElement()
340 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "element" );
341 m_data
->m_current
->AddChild(pnode
) ;
342 m_data
->Push( pnode
) ;
345 void wxXmlWriter::DoEndWriteElement()
350 void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo
*pi
)
353 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "prop" );
354 pnode
->AddProperty(wxT("name"), pi
->GetName() );
355 m_data
->m_current
->AddChild(pnode
) ;
356 m_data
->Push( pnode
) ;
359 void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo
*WXUNUSED(propInfo
) )
366 // insert an object reference to an already written object
367 void wxXmlWriter::DoWriteRepeatedObject( int objectID
)
370 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
371 pnode
->AddProperty(wxString("href"), wxString::Format( "%d" , objectID
) );
372 m_data
->m_current
->AddChild(pnode
) ;
375 // insert a null reference
376 void wxXmlWriter::DoWriteNullObject()
379 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
380 m_data
->m_current
->AddChild(pnode
) ;
383 // writes a delegate in the stream format
384 void wxXmlWriter::DoWriteDelegate( const wxObject
*WXUNUSED(object
), const wxClassInfo
* WXUNUSED(classInfo
) , const wxPropertyInfo
*pi
,
385 const wxObject
*eventSink
, int sinkObjectID
, const wxClassInfo
* WXUNUSED(eventSinkClassInfo
) , const wxHandlerInfo
* handlerInfo
)
387 if ( eventSink
!= NULL
&& handlerInfo
!= NULL
)
389 wxXmlAddContentToNode( m_data
->m_current
,wxString::Format(wxT("%d.%s"), sinkObjectID
, handlerInfo
->GetName()) ) ;
393 // ----------------------------------------------------------------------------
394 // reading objects in
395 // ----------------------------------------------------------------------------
397 struct wxReader::wxReaderInternal
399 map
<int,wxClassInfo
*> m_classInfos
;
404 m_data
= new wxReaderInternal
;
407 wxReader::~wxReader()
412 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
414 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
415 return m_data
->m_classInfos
[objectID
] ;
418 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
420 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
421 m_data
->m_classInfos
[objectID
] = classInfo
;
424 bool wxReader::HasObjectClassInfo( int objectID
)
426 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
430 // ----------------------------------------------------------------------------
432 // ----------------------------------------------------------------------------
435 Reading components has not to be extended for components
436 as properties are always sought by typeinfo over all levels
437 and create params are always toplevel class only
440 int wxXmlReader::ReadComponent(wxXmlNode
*node
, wxDepersister
*callbacks
)
443 wxClassInfo
*classInfo
;
445 wxxVariant
*createParams
;
446 int *createParamOids
;
447 const wxClassInfo
** createClassInfos
;
450 wxString ObjectIdString
;
452 children
= node
->GetChildren();
455 // check for a null object or href
456 if (node
->GetPropVal("href" , &ObjectIdString
) )
458 objectID
= atoi( ObjectIdString
.c_str() ) ;
459 wxASSERT_MSG( HasObjectClassInfo( objectID
) , wxT("Forward hrefs are not supported") ) ;
462 if ( !node
->GetPropVal("id" , &ObjectIdString
) )
464 return wxNullObjectID
;
467 if (!node
->GetPropVal("class", &className
))
469 // No class name. Eek. FIXME: error handling
470 return wxInvalidObjectID
;
472 classInfo
= wxClassInfo::FindClass(className
);
473 wxASSERT_MSG( classInfo
, wxString::Format(wxT("unknown class %s"),className
) ) ;
474 wxASSERT_MSG( !children
|| children
->GetType() != wxXML_TEXT_NODE
, wxT("objects cannot have XML Text Nodes") ) ;
475 if (!node
->GetPropVal("id", &ObjectIdString
))
477 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
478 // No object id. Eek. FIXME: error handling
479 return wxInvalidObjectID
;
481 objectID
= atoi( ObjectIdString
.c_str() ) ;
482 // is this object already has been streamed in, return it here
483 wxASSERT_MSG( !HasObjectClassInfo( objectID
) , wxString::Format(wxT("Doubly used id : %d"), objectID
) ) ;
485 // new object, start with allocation
486 // first make the object know to our internal registry
487 SetObjectClassInfo( objectID
, classInfo
) ;
489 callbacks
->AllocateObject(objectID
, classInfo
);
492 // stream back the Create parameters first
493 createParams
= new wxxVariant
[ classInfo
->GetCreateParamCount() ] ;
494 createParamOids
= new int[classInfo
->GetCreateParamCount() ] ;
495 createClassInfos
= new const wxClassInfo
*[classInfo
->GetCreateParamCount() ] ;
497 typedef map
<string
, wxXmlNode
*> PropertyNodes
;
498 typedef vector
<string
> PropertyNames
;
500 PropertyNodes propertyNodes
;
501 PropertyNames propertyNames
;
506 children
->GetPropVal( wxT("name") , &name
) ;
507 propertyNames
.push_back( name
.c_str() ) ;
508 propertyNodes
[name
.c_str()] = children
->GetChildren() ;
509 children
= children
->GetNext() ;
512 for ( int i
= 0 ; i
<classInfo
->GetCreateParamCount() ; ++i
)
514 const wxChar
* paramName
= classInfo
->GetCreateParamName(i
) ;
515 PropertyNodes::iterator propiter
= propertyNodes
.find( paramName
) ;
516 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( paramName
) ;
517 // if we don't have the value of a create param set in the xml
518 // we use the default value
519 if ( propiter
!= propertyNodes
.end() )
521 wxXmlNode
* prop
= propiter
->second
;
522 if ( pi
->GetTypeInfo()->IsObjectType() )
524 createParamOids
[i
] = ReadComponent( prop
, callbacks
) ;
525 createClassInfos
[i
] = dynamic_cast<const wxClassTypeInfo
*>(pi
->GetTypeInfo())->GetClassInfo() ;
529 createParamOids
[i
] = wxInvalidObjectID
;
530 createParams
[i
] = ReadValue( prop
, pi
->GetAccessor() ) ;
531 createClassInfos
[i
] = NULL
;
534 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
536 if ( propertyNames
[j
] == paramName
)
538 propertyNames
[j
] = "" ;
545 createParams
[i
] = pi
->GetDefaultValue() ;
549 // got the parameters. Call the Create method
550 callbacks
->CreateObject(objectID
, classInfo
,
551 classInfo
->GetCreateParamCount(),
552 createParams
, createParamOids
, createClassInfos
);
554 // now stream in the rest of the properties, in the sequence their properties were written in the xml
555 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
557 if ( propertyNames
[j
].length() )
559 PropertyNodes::iterator propiter
= propertyNodes
.find( propertyNames
[j
] ) ;
560 if ( propiter
!= propertyNodes
.end() )
562 wxXmlNode
* prop
= propiter
->second
;
563 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( propertyNames
[j
].c_str() ) ;
564 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
566 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
569 wxASSERT_MSG(prop
->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
570 wxXmlNode
* elementContent
= prop
->GetChildren() ;
571 wxASSERT_MSG(elementContent
, wxT("An element node cannot be empty")) ;
572 if ( elementType
->IsObjectType() )
574 int valueId
= ReadComponent( elementContent
, callbacks
) ;
577 if ( valueId
!= wxInvalidObjectID
)
580 callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ;
582 if ( elementType
->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
583 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
589 wxxVariant elementValue
= ReadValue( prop
, pi
->GetAccessor() ) ;
592 callbacks->SetProperty( objectID, classInfo ,pi , ) ;
595 prop
= prop
->GetNext() ;
598 else if ( pi
->GetTypeInfo()->IsObjectType() )
600 int valueId
= ReadComponent( prop
, callbacks
) ;
603 if ( valueId
!= wxInvalidObjectID
)
605 callbacks
->SetPropertyAsObject( objectID
, classInfo
, pi
, valueId
) ;
606 if ( pi
->GetTypeInfo()->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
607 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
) ;
623 callbacks
->SetConnect( objectID
, classInfo
, dynamic_cast<const wxDelegateTypeInfo
*>(pi
->GetTypeInfo()) , sinkClassInfo
,
624 sinkClassInfo
->FindHandlerInfo(handlerName
) , sinkOid
) ;
631 callbacks
->SetProperty( objectID
, classInfo
,pi
, ReadValue( prop
, pi
->GetAccessor() ) ) ;
637 delete[] createParams
;
638 delete[] createParamOids
;
639 delete[] createClassInfos
;
644 wxxVariant
wxXmlReader::ReadValue(wxXmlNode
*node
,
645 wxPropertyAccessor
*accessor
)
649 content
= node
->GetContent() ;
650 return accessor
->ReadValue(content
) ;
653 int wxXmlReader::ReadObject( const wxString
&name
, wxDepersister
*callbacks
)
655 wxXmlNode
*iter
= m_parent
->GetChildren() ;
659 if ( iter
->GetPropVal("name", &entryName
) )
661 if ( entryName
== name
)
662 return ReadComponent( iter
->GetChildren() , callbacks
) ;
664 iter
= iter
->GetNext() ;
666 return wxInvalidObjectID
;
669 // ----------------------------------------------------------------------------
670 // depersisting to memory
671 // ----------------------------------------------------------------------------
673 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
675 map
<int,wxObject
*> m_objects
;
677 void SetObject(int objectID
, wxObject
*obj
)
679 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
680 m_objects
[objectID
] = obj
;
682 wxObject
* GetObject( int objectID
)
684 if ( objectID
== wxNullObjectID
)
687 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
688 return m_objects
[objectID
] ;
692 wxRuntimeDepersister::wxRuntimeDepersister()
694 m_data
= new wxRuntimeDepersisterInternal() ;
697 wxRuntimeDepersister::~wxRuntimeDepersister()
702 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
705 O
= classInfo
->CreateObject();
706 m_data
->SetObject(objectID
, O
);
709 void wxRuntimeDepersister::CreateObject(int objectID
,
710 const wxClassInfo
*classInfo
,
714 const wxClassInfo
**objectClassInfos
)
717 o
= m_data
->GetObject(objectID
);
718 for ( int i
= 0 ; i
< paramCount
; ++i
)
720 if ( objectIdValues
[i
] != wxInvalidObjectID
)
723 o
= m_data
->GetObject(objectIdValues
[i
]);
724 // if this is a dynamic object and we are asked for another class
725 // than wxDynamicObject we cast it down manually.
726 wxDynamicObject
*dyno
= dynamic_cast< wxDynamicObject
* > (o
) ;
727 if ( dyno
!=NULL
&& (objectClassInfos
[i
] != dyno
->GetClassInfo()) )
729 o
= dyno
->GetSuperClassInstance() ;
731 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
734 classInfo
->Create(o
, paramCount
, params
);
737 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
740 o
= m_data
->GetObject(objectID
);
744 void wxRuntimeDepersister::SetProperty(int objectID
,
745 const wxClassInfo
*classInfo
,
746 const wxPropertyInfo
* propertyInfo
,
747 const wxxVariant
&value
)
750 o
= m_data
->GetObject(objectID
);
751 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
752 // propertyInfo->GetAccessor()->SetProperty( o , value ) ;
755 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
756 const wxClassInfo
*classInfo
,
757 const wxPropertyInfo
* propertyInfo
,
761 o
= m_data
->GetObject(objectID
);
762 valo
= m_data
->GetObject(valueObjectId
);
763 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(propertyInfo
->GetTypeInfo()))->GetClassInfo() ;
764 // if this is a dynamic object and we are asked for another class
765 // than wxDynamicObject we cast it down manually.
766 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
767 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
769 valo
= dynvalo
->GetSuperClassInstance() ;
772 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
773 // propertyInfo->GetAccessor()->SetProperty( o ,
774 // (dynamic_cast<const wxClassTypeInfo*>(propertyInfo->GetTypeInfo()))->GetClassInfo()->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
) ;
801 // ----------------------------------------------------------------------------
802 // depersisting to code
803 // ----------------------------------------------------------------------------
805 struct wxCodeDepersister::wxCodeDepersisterInternal
807 map
<int,string
> m_objectNames
;
809 void SetObjectName(int objectID
, const wxString
&name
)
811 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
812 m_objectNames
[objectID
] = (const char *)name
;
814 wxString
GetObjectName( int objectID
)
816 if ( objectID
== wxNullObjectID
)
819 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
820 return wxString( m_objectNames
[objectID
].c_str() ) ;
824 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
827 m_data
= new wxCodeDepersisterInternal
;
830 wxCodeDepersister::~wxCodeDepersister()
835 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
)
837 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
838 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
839 classInfo
->GetClassName(),
841 classInfo
->GetClassName()) );
842 m_data
->SetObjectName( objectID
, objectName
) ;
845 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
847 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
848 m_data
->GetObjectName( objectID
) ) );
851 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
854 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
855 if ( type
->GetKind() == wxT_CUSTOM
)
857 const wxCustomTypeInfo
* cti
= dynamic_cast<const wxCustomTypeInfo
*>(type
) ;
858 wxASSERT_MSG( cti
, wxT("Internal error, illegal wxCustomTypeInfo") ) ;
859 value
.Printf( "%s(%s)",cti
->GetTypeName(),param
.GetAsString() );
861 else if ( type
->GetKind() == wxT_STRING
)
863 value
.Printf( "\"%s\"",param
.GetAsString() );
867 value
.Printf( "%s", param
.GetAsString() );
872 void wxCodeDepersister::CreateObject(int objectID
,
873 const wxClassInfo
*WXUNUSED(classInfo
),
877 const wxClassInfo
**WXUNUSED(objectClassInfos
)
881 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
) ) );
882 for (i
= 0; i
< paramCount
; i
++)
884 if ( objectIDValues
[i
] != wxInvalidObjectID
)
885 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ) ) );
888 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]) ) );
890 if (i
< paramCount
- 1)
891 m_fp
->WriteString( ", ");
893 m_fp
->WriteString( ");\n");
896 void wxCodeDepersister::SetProperty(int objectID
,
897 const wxClassInfo
*WXUNUSED(classInfo
),
898 const wxPropertyInfo
* propertyInfo
,
899 const wxxVariant
&value
)
901 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
902 m_data
->GetObjectName(objectID
),
903 propertyInfo
->GetAccessor()->GetSetterName(),
904 ValueAsCode(value
)) );
907 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
908 const wxClassInfo
*WXUNUSED(classInfo
),
909 const wxPropertyInfo
* propertyInfo
,
912 if ( propertyInfo
->GetTypeInfo()->GetKind() == wxT_OBJECT
)
913 m_fp
->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
914 m_data
->GetObjectName(objectID
),
915 propertyInfo
->GetAccessor()->GetSetterName(),
916 m_data
->GetObjectName( valueObjectId
) ) );
918 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
919 m_data
->GetObjectName(objectID
),
920 propertyInfo
->GetAccessor()->GetSetterName(),
921 m_data
->GetObjectName( valueObjectId
) ) );
924 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
925 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
926 const wxDelegateTypeInfo
*delegateInfo
,
927 const wxClassInfo
*eventSinkClassInfo
,
928 const wxHandlerInfo
* handlerInfo
,
929 int eventSinkObjectID
)
931 wxString ehsource
= m_data
->GetObjectName( eventSourceObjectID
) ;
932 wxString ehsink
= m_data
->GetObjectName(eventSinkObjectID
) ;
933 wxString ehsinkClass
= eventSinkClassInfo
->GetClassName() ;
934 int eventType
= delegateInfo
->GetEventType() ;
935 wxString handlerName
= handlerInfo
->GetName() ;
937 m_fp
->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
938 ehsource
, ehsource
, eventType
, ehsinkClass
, handlerName
, ehsink
) );
941 #include <wx/arrimpl.cpp>
943 WX_DEFINE_OBJARRAY(wxxVariantArray
);