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
65 void wxWriter::ClearObjectContext()
68 m_data
= new wxWriterInternal() ;
69 m_data
->m_nextId
= 0 ;
72 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, const wxString
&name
, wxxVariantArray
&metadata
)
74 DoBeginWriteTopLevelEntry( name
) ;
75 WriteObject( object
, classInfo
, persister
, false , metadata
) ;
76 DoEndWriteTopLevelEntry( name
) ;
79 void wxWriter::WriteObject(const wxObject
*object
, const wxClassInfo
*classInfo
, wxPersister
*persister
, bool isEmbedded
, wxxVariantArray
&metadata
)
81 // hack to avoid writing out embedded windows, these are windows that are constructed as part of other windows, they would
82 // doubly constructed afterwards
84 const wxWindow
* win
= dynamic_cast<const wxWindow
*>(object
) ;
85 if ( win
&& win
->GetId() < 0 )
88 if ( persister
->BeforeWriteObject( this , object
, classInfo
, metadata
) )
92 else if ( IsObjectKnown( object
) )
93 DoWriteRepeatedObject( GetObjectID(object
) ) ;
96 int oid
= m_data
->m_nextId
++ ;
98 m_data
->m_writtenObjects
[object
] = oid
;
100 // in case this object is a wxDynamicObject we also have to insert is superclass
101 // instance with the same id, so that object relations are streamed out correctly
102 const wxDynamicObject
* dynobj
= dynamic_cast<const wxDynamicObject
*>( object
) ;
103 if ( !isEmbedded
&& dynobj
)
104 m_data
->m_writtenObjects
[dynobj
->GetSuperClassInstance()] = oid
;
106 DoBeginWriteObject( object
, classInfo
, oid
, metadata
) ;
107 wxWriterInternalPropertiesData data
;
108 WriteAllProperties( object
, classInfo
, persister
, &data
) ;
109 DoEndWriteObject( object
, classInfo
, oid
) ;
111 persister
->AfterWriteObject( this ,object
, classInfo
) ;
115 void wxWriter::FindConnectEntry(const wxWindow
* evSource
,const wxDelegateTypeInfo
* dti
, const wxObject
* &sink
, const wxHandlerInfo
*&handler
)
117 wxList
*dynamicEvents
= evSource
->GetDynamicEventTable() ;
121 wxList::compatibility_iterator node
= dynamicEvents
->GetFirst();
124 wxDynamicEventTableEntry
*entry
= (wxDynamicEventTableEntry
*)node
->GetData();
127 if ( entry
->m_fn
&& (dti
->GetEventType() == entry
->m_eventType
) &&
128 (entry
->m_id
== -1 ||
129 (entry
->m_lastId
== -1 && evSource
->GetId() == entry
->m_id
) ||
130 (entry
->m_lastId
!= -1 &&
131 (evSource
->GetId() >= entry
->m_id
&& evSource
->GetId() <= entry
->m_lastId
) ) ) &&
135 sink
= entry
->m_eventSink
;
136 const wxClassInfo
* sinkClassInfo
= sink
->GetClassInfo() ;
137 const wxHandlerInfo
* sinkHandler
= sinkClassInfo
->GetFirstHandler() ;
138 while ( sinkHandler
)
140 if ( sinkHandler
->GetEventFunction() == entry
->m_fn
)
142 handler
= sinkHandler
;
145 sinkHandler
= sinkHandler
->GetNext() ;
149 node
= node
->GetNext();
153 void wxWriter::WriteAllProperties( const wxObject
* obj
, const wxClassInfo
* ci
, wxPersister
*persister
, wxWriterInternalPropertiesData
* data
)
155 wxPropertyInfoMap map
;
156 ci
->GetProperties( map
) ;
157 for ( int i
= 0 ; i
< ci
->GetCreateParamCount() ; ++i
)
159 wxString name
= ci
->GetCreateParamName(i
) ;
160 const wxPropertyInfo
* prop
= map
.find(name
)->second
;
161 wxASSERT_MSG( prop
, wxT("Create Parameter not found in declared RTTI Parameters") ) ;
162 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
166 for( wxPropertyInfoMap::iterator iter
= map
.begin() ; iter
!= map
.end() ; ++iter
)
168 const wxPropertyInfo
* prop
= iter
->second
;
169 if ( prop
->GetFlags() & wxPROP_OBJECT_GRAPH
)
171 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
175 for( wxPropertyInfoMap::iterator iter
= map
.begin() ; iter
!= map
.end() ; ++iter
)
177 const wxPropertyInfo
* prop
= iter
->second
;
178 if ( !(prop
->GetFlags() & wxPROP_OBJECT_GRAPH
) )
180 WriteOneProperty( obj
, prop
->GetDeclaringClass() , prop
, persister
, data
) ;
185 void wxWriter::WriteOneProperty( const wxObject
*obj
, const wxClassInfo
* ci
, const wxPropertyInfo
* pi
, wxPersister
*persister
, wxWriterInternalPropertiesData
*data
)
187 // make sure that we are picking the correct object for accessing the property
188 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* > (obj
) ;
189 if ( dynobj
&& (dynamic_cast<const wxDynamicClassInfo
*>(ci
) == NULL
) )
190 obj
= dynobj
->GetSuperClassInstance() ;
192 DoBeginWriteProperty( pi
) ;
193 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
195 wxxVariantArray data
;
196 pi
->GetAccessor()->GetPropertyCollection(obj
, data
) ;
197 const wxTypeInfo
* elementType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() )->GetElementType() ;
198 for ( size_t i
= 0 ; i
< data
.GetCount() ; ++i
)
200 DoBeginWriteElement() ;
201 wxxVariant value
= data
[i
] ;
202 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
204 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( elementType
) ;
207 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
208 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
210 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
214 DoWriteSimpleType( value
) ;
217 DoEndWriteElement() ;
222 const wxDelegateTypeInfo
* dti
= dynamic_cast< const wxDelegateTypeInfo
* > ( pi
->GetTypeInfo() ) ;
225 const wxObject
* sink
= NULL
;
226 const wxHandlerInfo
*handler
= NULL
;
228 const wxWindow
* evSource
= dynamic_cast<const wxWindow
*>(obj
) ;
229 wxASSERT_MSG( evSource
, wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
231 FindConnectEntry( evSource
, dti
, sink
, handler
) ;
232 if ( persister
->BeforeWriteDelegate( this , obj
, ci
, pi
, sink
, handler
) )
234 if ( sink
!= NULL
&& handler
!= NULL
)
236 wxASSERT_MSG( IsObjectKnown( sink
) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
237 DoWriteDelegate( obj
, ci
, pi
, sink
, GetObjectID( sink
) , sink
->GetClassInfo() , handler
) ;
244 pi
->GetAccessor()->GetProperty(obj
, value
) ;
245 if ( persister
->BeforeWriteProperty( this , pi
, value
) )
247 const wxClassTypeInfo
* cti
= dynamic_cast< const wxClassTypeInfo
* > ( pi
->GetTypeInfo() ) ;
250 const wxClassInfo
* pci
= cti
->GetClassInfo() ;
251 wxObject
*vobj
= pci
->VariantToInstance( value
) ;
253 WriteObject( vobj
, (vobj
? vobj
->GetClassInfo() : pci
) , persister
, cti
->GetKind()== wxT_OBJECT
, md
) ;
257 if ( pi
->GetFlags() & wxPROP_ENUM_STORE_LONG
)
259 const wxEnumTypeInfo
*eti
= dynamic_cast<const wxEnumTypeInfo
*>( pi
->GetTypeInfo() ) ;
260 wxASSERT_MSG( eti
, wxT("Type must have enum - long conversion") ) ;
261 eti
->ConvertFromLong( value
.Get
<long>() , value
) ;
263 DoWriteSimpleType( value
) ;
268 DoEndWriteProperty( pi
) ;
271 int wxWriter::GetObjectID(const wxObject
*obj
)
273 if ( !IsObjectKnown( obj
) )
274 return wxInvalidObjectID
;
276 return m_data
->m_writtenObjects
[obj
] ;
279 bool wxWriter::IsObjectKnown( const wxObject
*obj
)
281 return m_data
->m_writtenObjects
.find( obj
) != m_data
->m_writtenObjects
.end() ;
288 // convenience functions
290 void wxXmlAddContentToNode( wxXmlNode
* node
, const wxString
& data
)
292 node
->AddChild(new wxXmlNode(wxXML_TEXT_NODE
, "value", data
) );
295 wxString
wxXmlGetContentFromNode( wxXmlNode
*node
)
297 if ( node
->GetChildren() )
298 return node
->GetChildren()->GetContent() ;
300 return wxEmptyString
;
303 struct wxXmlWriter::wxXmlWriterInternal
306 wxXmlNode
*m_current
;
307 vector
< wxXmlNode
* > m_objectStack
;
309 void Push( wxXmlNode
*newCurrent
)
311 m_objectStack
.push_back( m_current
) ;
312 m_current
= newCurrent
;
317 m_current
= m_objectStack
.back() ;
318 m_objectStack
.pop_back() ;
322 wxXmlWriter::wxXmlWriter( wxXmlNode
* rootnode
)
324 m_data
= new wxXmlWriterInternal() ;
325 m_data
->m_root
= rootnode
;
326 m_data
->m_current
= rootnode
;
329 wxXmlWriter::~wxXmlWriter()
334 void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString
&name
)
337 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("entry"));
338 pnode
->AddProperty(wxString("name"), name
);
339 m_data
->m_current
->AddChild(pnode
) ;
340 m_data
->Push( pnode
) ;
343 void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString
&WXUNUSED(name
) )
348 void wxXmlWriter::DoBeginWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*classInfo
, int objectID
, wxxVariantArray
&metadata
)
351 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
352 pnode
->AddProperty(wxT("class"), wxString(classInfo
->GetClassName()));
353 pnode
->AddProperty(wxT("id"), wxString::Format( "%d" , objectID
) );
355 for ( size_t i
= 0 ; i
< metadata
.GetCount() ; ++i
)
357 pnode
->AddProperty( metadata
[i
].GetName() , metadata
[i
].GetAsString() ) ;
359 m_data
->m_current
->AddChild(pnode
) ;
360 m_data
->Push( pnode
) ;
363 // end of writing the root object
364 void wxXmlWriter::DoEndWriteObject(const wxObject
*WXUNUSED(object
), const wxClassInfo
*WXUNUSED(classInfo
), int WXUNUSED(objectID
) )
369 // writes a property in the stream format
370 void wxXmlWriter::DoWriteSimpleType( wxxVariant
&value
)
372 wxXmlAddContentToNode( m_data
->m_current
,value
.GetAsString() ) ;
375 void wxXmlWriter::DoBeginWriteElement()
378 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "element" );
379 m_data
->m_current
->AddChild(pnode
) ;
380 m_data
->Push( pnode
) ;
383 void wxXmlWriter::DoEndWriteElement()
388 void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo
*pi
)
391 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, "prop" );
392 pnode
->AddProperty(wxT("name"), pi
->GetName() );
393 m_data
->m_current
->AddChild(pnode
) ;
394 m_data
->Push( pnode
) ;
397 void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo
*WXUNUSED(propInfo
) )
404 // insert an object reference to an already written object
405 void wxXmlWriter::DoWriteRepeatedObject( int objectID
)
408 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
409 pnode
->AddProperty(wxString("href"), wxString::Format( "%d" , objectID
) );
410 m_data
->m_current
->AddChild(pnode
) ;
413 // insert a null reference
414 void wxXmlWriter::DoWriteNullObject()
417 pnode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("object"));
418 m_data
->m_current
->AddChild(pnode
) ;
421 // writes a delegate in the stream format
422 void wxXmlWriter::DoWriteDelegate( const wxObject
*WXUNUSED(object
), const wxClassInfo
* WXUNUSED(classInfo
) , const wxPropertyInfo
*WXUNUSED(pi
) ,
423 const wxObject
*eventSink
, int sinkObjectID
, const wxClassInfo
* WXUNUSED(eventSinkClassInfo
) , const wxHandlerInfo
* handlerInfo
)
425 if ( eventSink
!= NULL
&& handlerInfo
!= NULL
)
427 wxXmlAddContentToNode( m_data
->m_current
,wxString::Format(wxT("%d.%s"), sinkObjectID
, handlerInfo
->GetName()) ) ;
431 // ----------------------------------------------------------------------------
432 // reading objects in
433 // ----------------------------------------------------------------------------
435 struct wxReader::wxReaderInternal
437 map
<int,wxClassInfo
*> m_classInfos
;
442 m_data
= new wxReaderInternal
;
445 wxReader::~wxReader()
450 wxClassInfo
* wxReader::GetObjectClassInfo(int objectID
)
452 assert( m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() );
453 return m_data
->m_classInfos
[objectID
] ;
456 void wxReader::SetObjectClassInfo(int objectID
, wxClassInfo
*classInfo
)
458 assert( m_data
->m_classInfos
.find(objectID
) == m_data
->m_classInfos
.end() ) ;
459 m_data
->m_classInfos
[objectID
] = classInfo
;
462 bool wxReader::HasObjectClassInfo( int objectID
)
464 return m_data
->m_classInfos
.find(objectID
) != m_data
->m_classInfos
.end() ;
468 // ----------------------------------------------------------------------------
470 // ----------------------------------------------------------------------------
473 Reading components has not to be extended for components
474 as properties are always sought by typeinfo over all levels
475 and create params are always toplevel class only
478 int wxXmlReader::ReadComponent(wxXmlNode
*node
, wxDepersister
*callbacks
)
480 wxASSERT_MSG( callbacks
, wxT("Does not support reading without a Depersistor") ) ;
482 wxClassInfo
*classInfo
;
484 wxxVariant
*createParams
;
485 int *createParamOids
;
486 const wxClassInfo
** createClassInfos
;
489 wxString ObjectIdString
;
491 children
= node
->GetChildren();
494 // check for a null object or href
495 if (node
->GetPropVal("href" , &ObjectIdString
) )
497 objectID
= atoi( ObjectIdString
.c_str() ) ;
498 wxASSERT_MSG( HasObjectClassInfo( objectID
) , wxT("Forward hrefs are not supported") ) ;
501 if ( !node
->GetPropVal("id" , &ObjectIdString
) )
503 return wxNullObjectID
;
506 if (!node
->GetPropVal("class", &className
))
508 // No class name. Eek. FIXME: error handling
509 return wxInvalidObjectID
;
511 classInfo
= wxClassInfo::FindClass(className
);
512 wxASSERT_MSG( classInfo
, wxString::Format(wxT("unknown class %s"),className
) ) ;
513 wxASSERT_MSG( !children
|| children
->GetType() != wxXML_TEXT_NODE
, wxT("objects cannot have XML Text Nodes") ) ;
514 if (!node
->GetPropVal("id", &ObjectIdString
))
516 wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
517 // No object id. Eek. FIXME: error handling
518 return wxInvalidObjectID
;
520 objectID
= atoi( ObjectIdString
.c_str() ) ;
521 // is this object already has been streamed in, return it here
522 wxASSERT_MSG( !HasObjectClassInfo( objectID
) , wxString::Format(wxT("Doubly used id : %d"), objectID
) ) ;
524 // new object, start with allocation
525 // first make the object know to our internal registry
526 SetObjectClassInfo( objectID
, classInfo
) ;
528 wxxVariantArray metadata
;
529 wxXmlProperty
*xp
= node
->GetProperties() ;
532 if ( xp
->GetName() != wxString("class") && xp
->GetName() != wxString("id") )
534 metadata
.Add( new wxxVariant( xp
->GetValue() , xp
->GetName() ) ) ;
538 callbacks
->AllocateObject(objectID
, classInfo
, metadata
);
541 // stream back the Create parameters first
542 createParams
= new wxxVariant
[ classInfo
->GetCreateParamCount() ] ;
543 createParamOids
= new int[classInfo
->GetCreateParamCount() ] ;
544 createClassInfos
= new const wxClassInfo
*[classInfo
->GetCreateParamCount() ] ;
546 typedef map
<string
, wxXmlNode
*> PropertyNodes
;
547 typedef vector
<string
> PropertyNames
;
549 PropertyNodes propertyNodes
;
550 PropertyNames propertyNames
;
555 children
->GetPropVal( wxT("name") , &name
) ;
556 propertyNames
.push_back( name
.c_str() ) ;
557 propertyNodes
[name
.c_str()] = children
->GetChildren() ;
558 children
= children
->GetNext() ;
561 for ( int i
= 0 ; i
<classInfo
->GetCreateParamCount() ; ++i
)
563 const wxChar
* paramName
= classInfo
->GetCreateParamName(i
) ;
564 PropertyNodes::iterator propiter
= propertyNodes
.find( paramName
) ;
565 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( paramName
) ;
566 wxASSERT_MSG(pi
,wxString::Format("Unkown Property %s",paramName
) ) ;
567 // if we don't have the value of a create param set in the xml
568 // we use the default value
569 if ( propiter
!= propertyNodes
.end() )
571 wxXmlNode
* prop
= propiter
->second
;
572 if ( pi
->GetTypeInfo()->IsObjectType() )
574 createParamOids
[i
] = ReadComponent( prop
, callbacks
) ;
575 createClassInfos
[i
] = dynamic_cast<const wxClassTypeInfo
*>(pi
->GetTypeInfo())->GetClassInfo() ;
579 createParamOids
[i
] = wxInvalidObjectID
;
580 createParams
[i
] = ReadValue( prop
, pi
->GetTypeInfo() ) ;
581 if( pi
->GetFlags() & wxPROP_ENUM_STORE_LONG
)
583 const wxEnumTypeInfo
*eti
= dynamic_cast<const wxEnumTypeInfo
*>( pi
->GetTypeInfo() ) ;
584 wxASSERT_MSG( eti
, wxT("Type must have enum - long conversion") ) ;
587 eti
->ConvertToLong( createParams
[i
] , realval
) ;
588 createParams
[i
] = wxxVariant( realval
) ;
590 createClassInfos
[i
] = NULL
;
593 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
595 if ( propertyNames
[j
] == paramName
)
597 propertyNames
[j
] = "" ;
604 createParams
[i
] = pi
->GetDefaultValue() ;
608 // got the parameters. Call the Create method
609 callbacks
->CreateObject(objectID
, classInfo
,
610 classInfo
->GetCreateParamCount(),
611 createParams
, createParamOids
, createClassInfos
, metadata
);
613 // now stream in the rest of the properties, in the sequence their properties were written in the xml
614 for ( size_t j
= 0 ; j
< propertyNames
.size() ; ++j
)
616 if ( propertyNames
[j
].length() )
618 PropertyNodes::iterator propiter
= propertyNodes
.find( propertyNames
[j
] ) ;
619 if ( propiter
!= propertyNodes
.end() )
621 wxXmlNode
* prop
= propiter
->second
;
622 const wxPropertyInfo
* pi
= classInfo
->FindPropertyInfo( propertyNames
[j
].c_str() ) ;
623 if ( pi
->GetTypeInfo()->GetKind() == wxT_COLLECTION
)
625 const wxCollectionTypeInfo
* collType
= dynamic_cast< const wxCollectionTypeInfo
* >( pi
->GetTypeInfo() ) ;
626 const wxTypeInfo
* elementType
= collType
->GetElementType() ;
629 wxASSERT_MSG(prop
->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
630 wxXmlNode
* elementContent
= prop
->GetChildren() ;
631 if ( elementContent
)
633 // we skip empty elements
634 if ( elementType
->IsObjectType() )
636 int valueId
= ReadComponent( elementContent
, callbacks
) ;
637 if ( valueId
!= wxInvalidObjectID
)
639 if ( pi
->GetAccessor()->HasAdder() )
640 callbacks
->AddToPropertyCollectionAsObject( objectID
, classInfo
, pi
, valueId
) ;
641 // TODO for collections we must have a notation on taking over ownership or not
642 if ( elementType
->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
643 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
648 wxxVariant elementValue
= ReadValue( elementContent
, elementType
) ;
649 if ( pi
->GetAccessor()->HasAdder() )
650 callbacks
->AddToPropertyCollection( objectID
, classInfo
,pi
, elementValue
) ;
653 prop
= prop
->GetNext() ;
656 else if ( pi
->GetTypeInfo()->IsObjectType() )
658 int valueId
= ReadComponent( prop
, callbacks
) ;
659 if ( valueId
!= wxInvalidObjectID
)
661 callbacks
->SetPropertyAsObject( objectID
, classInfo
, pi
, valueId
) ;
662 if ( pi
->GetTypeInfo()->GetKind() == wxT_OBJECT
&& valueId
!= wxNullObjectID
)
663 callbacks
->DestroyObject( valueId
, GetObjectClassInfo( valueId
) ) ;
666 else if ( pi
->GetTypeInfo()->IsDelegateType() )
670 wxString resstring
= prop
->GetContent() ;
671 wxInt32 pos
= resstring
.Find('.') ;
672 assert( pos
!= wxNOT_FOUND
) ;
673 int sinkOid
= atol(resstring
.Left(pos
)) ;
674 wxString handlerName
= resstring
.Mid(pos
+1) ;
675 wxClassInfo
* sinkClassInfo
= GetObjectClassInfo( sinkOid
) ;
677 callbacks
->SetConnect( objectID
, classInfo
, dynamic_cast<const wxDelegateTypeInfo
*>(pi
->GetTypeInfo()) , sinkClassInfo
,
678 sinkClassInfo
->FindHandlerInfo(handlerName
) , sinkOid
) ;
685 callbacks
->SetProperty( objectID
, classInfo
,pi
, ReadValue( prop
, pi
->GetTypeInfo() ) ) ;
691 delete[] createParams
;
692 delete[] createParamOids
;
693 delete[] createClassInfos
;
698 wxxVariant
wxXmlReader::ReadValue(wxXmlNode
*node
,
699 const wxTypeInfo
*type
)
703 content
= node
->GetContent() ;
705 type
->ConvertFromString( content
, result
) ;
709 int wxXmlReader::ReadObject( const wxString
&name
, wxDepersister
*callbacks
)
711 wxXmlNode
*iter
= m_parent
->GetChildren() ;
715 if ( iter
->GetPropVal("name", &entryName
) )
717 if ( entryName
== name
)
718 return ReadComponent( iter
->GetChildren() , callbacks
) ;
720 iter
= iter
->GetNext() ;
722 return wxInvalidObjectID
;
725 // ----------------------------------------------------------------------------
726 // depersisting to memory
727 // ----------------------------------------------------------------------------
729 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
731 map
<int,wxObject
*> m_objects
;
733 void SetObject(int objectID
, wxObject
*obj
)
735 assert( m_objects
.find(objectID
) == m_objects
.end() ) ;
736 m_objects
[objectID
] = obj
;
738 wxObject
* GetObject( int objectID
)
740 if ( objectID
== wxNullObjectID
)
743 assert( m_objects
.find(objectID
) != m_objects
.end() ) ;
744 return m_objects
[objectID
] ;
748 wxRuntimeDepersister::wxRuntimeDepersister()
750 m_data
= new wxRuntimeDepersisterInternal() ;
753 wxRuntimeDepersister::~wxRuntimeDepersister()
758 void wxRuntimeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
759 wxxVariantArray
&metadata
)
762 O
= classInfo
->CreateObject();
763 m_data
->SetObject(objectID
, O
);
766 void wxRuntimeDepersister::CreateObject(int objectID
,
767 const wxClassInfo
*classInfo
,
771 const wxClassInfo
**objectClassInfos
,
772 wxxVariantArray
&metadata
)
775 o
= m_data
->GetObject(objectID
);
776 for ( int i
= 0 ; i
< paramCount
; ++i
)
778 if ( objectIdValues
[i
] != wxInvalidObjectID
)
781 o
= m_data
->GetObject(objectIdValues
[i
]);
782 // if this is a dynamic object and we are asked for another class
783 // than wxDynamicObject we cast it down manually.
784 wxDynamicObject
*dyno
= dynamic_cast< wxDynamicObject
* > (o
) ;
785 if ( dyno
!=NULL
&& (objectClassInfos
[i
] != dyno
->GetClassInfo()) )
787 o
= dyno
->GetSuperClassInstance() ;
789 params
[i
] = objectClassInfos
[i
]->InstanceToVariant(o
) ;
792 classInfo
->Create(o
, paramCount
, params
);
795 void wxRuntimeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
798 o
= m_data
->GetObject(objectID
);
802 void wxRuntimeDepersister::SetProperty(int objectID
,
803 const wxClassInfo
*classInfo
,
804 const wxPropertyInfo
* propertyInfo
,
805 const wxxVariant
&value
)
808 o
= m_data
->GetObject(objectID
);
809 classInfo
->SetProperty( o
, propertyInfo
->GetName() , value
) ;
812 void wxRuntimeDepersister::SetPropertyAsObject(int objectID
,
813 const wxClassInfo
*classInfo
,
814 const wxPropertyInfo
* propertyInfo
,
818 o
= m_data
->GetObject(objectID
);
819 valo
= m_data
->GetObject(valueObjectId
);
820 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(propertyInfo
->GetTypeInfo()))->GetClassInfo() ;
821 // if this is a dynamic object and we are asked for another class
822 // than wxDynamicObject we cast it down manually.
823 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
824 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
826 valo
= dynvalo
->GetSuperClassInstance() ;
829 classInfo
->SetProperty( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
832 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID
,
833 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
834 const wxDelegateTypeInfo
*delegateInfo
,
835 const wxClassInfo
*WXUNUSED(eventSinkClassInfo
) ,
836 const wxHandlerInfo
* handlerInfo
,
837 int eventSinkObjectID
)
839 wxWindow
*ehsource
= dynamic_cast< wxWindow
* >( m_data
->GetObject( eventSourceObjectID
) ) ;
840 wxEvtHandler
*ehsink
= dynamic_cast< wxEvtHandler
*>(m_data
->GetObject(eventSinkObjectID
) ) ;
842 if ( ehsource
&& ehsink
)
844 ehsource
->Connect( ehsource
->GetId() , delegateInfo
->GetEventType() ,
845 handlerInfo
->GetEventFunction() , NULL
/*user data*/ ,
850 wxObject
*wxRuntimeDepersister::GetObject(int objectID
)
852 return m_data
->GetObject( objectID
) ;
855 // adds an element to a property collection
856 void wxRuntimeDepersister::AddToPropertyCollection( int objectID
,
857 const wxClassInfo
*classInfo
,
858 const wxPropertyInfo
* propertyInfo
,
859 const wxxVariant
&value
)
862 o
= m_data
->GetObject(objectID
);
863 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , value
) ;
866 // sets the corresponding property (value is an object)
867 void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID
,
868 const wxClassInfo
*classInfo
,
869 const wxPropertyInfo
* propertyInfo
,
873 o
= m_data
->GetObject(objectID
);
874 valo
= m_data
->GetObject(valueObjectId
);
875 const wxCollectionTypeInfo
* collectionTypeInfo
= dynamic_cast< const wxCollectionTypeInfo
* >(propertyInfo
->GetTypeInfo() ) ;
876 const wxClassInfo
* valClassInfo
= (dynamic_cast<const wxClassTypeInfo
*>(collectionTypeInfo
->GetElementType()))->GetClassInfo() ;
877 // if this is a dynamic object and we are asked for another class
878 // than wxDynamicObject we cast it down manually.
879 wxDynamicObject
*dynvalo
= dynamic_cast< wxDynamicObject
* > (valo
) ;
880 if ( dynvalo
!=NULL
&& (valClassInfo
!= dynvalo
->GetClassInfo()) )
882 valo
= dynvalo
->GetSuperClassInstance() ;
885 classInfo
->AddToPropertyCollection( o
, propertyInfo
->GetName() , valClassInfo
->InstanceToVariant(valo
) ) ;
888 // ----------------------------------------------------------------------------
889 // depersisting to code
890 // ----------------------------------------------------------------------------
892 struct wxCodeDepersister::wxCodeDepersisterInternal
894 map
<int,string
> m_objectNames
;
896 void SetObjectName(int objectID
, const wxString
&name
)
898 assert( m_objectNames
.find(objectID
) == m_objectNames
.end() ) ;
899 m_objectNames
[objectID
] = (const char *)name
;
901 wxString
GetObjectName( int objectID
)
903 if ( objectID
== wxNullObjectID
)
906 assert( m_objectNames
.find(objectID
) != m_objectNames
.end() ) ;
907 return wxString( m_objectNames
[objectID
].c_str() ) ;
911 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream
*out
)
914 m_data
= new wxCodeDepersisterInternal
;
917 wxCodeDepersister::~wxCodeDepersister()
922 void wxCodeDepersister::AllocateObject(int objectID
, wxClassInfo
*classInfo
,
923 wxxVariantArray
&metadata
)
925 wxString objectName
= wxString::Format( "LocalObject_%d" , objectID
) ;
926 m_fp
->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
927 classInfo
->GetClassName(),
929 classInfo
->GetClassName()) );
930 m_data
->SetObjectName( objectID
, objectName
) ;
933 void wxCodeDepersister::DestroyObject(int objectID
, wxClassInfo
*WXUNUSED(classInfo
))
935 m_fp
->WriteString( wxString::Format( "\tdelete %s;\n",
936 m_data
->GetObjectName( objectID
) ) );
939 wxString
wxCodeDepersister::ValueAsCode( const wxxVariant
¶m
)
942 const wxTypeInfo
* type
= param
.GetTypeInfo() ;
943 if ( type
->GetKind() == wxT_CUSTOM
)
945 const wxCustomTypeInfo
* cti
= dynamic_cast<const wxCustomTypeInfo
*>(type
) ;
946 wxASSERT_MSG( cti
, wxT("Internal error, illegal wxCustomTypeInfo") ) ;
947 value
.Printf( "%s(%s)",cti
->GetTypeName(),param
.GetAsString() );
949 else if ( type
->GetKind() == wxT_STRING
)
951 value
.Printf( "\"%s\"",param
.GetAsString() );
955 value
.Printf( "%s", param
.GetAsString() );
960 void wxCodeDepersister::CreateObject(int objectID
,
961 const wxClassInfo
*WXUNUSED(classInfo
),
965 const wxClassInfo
**WXUNUSED(objectClassInfos
) ,
966 wxxVariantArray
&metadata
970 m_fp
->WriteString( wxString::Format( "\t%s->Create(", m_data
->GetObjectName(objectID
) ) );
971 for (i
= 0; i
< paramCount
; i
++)
973 if ( objectIDValues
[i
] != wxInvalidObjectID
)
974 m_fp
->WriteString( wxString::Format( "%s", m_data
->GetObjectName( objectIDValues
[i
] ) ) );
977 m_fp
->WriteString( wxString::Format( "%s", ValueAsCode(params
[i
]) ) );
979 if (i
< paramCount
- 1)
980 m_fp
->WriteString( ", ");
982 m_fp
->WriteString( ");\n");
985 void wxCodeDepersister::SetProperty(int objectID
,
986 const wxClassInfo
*WXUNUSED(classInfo
),
987 const wxPropertyInfo
* propertyInfo
,
988 const wxxVariant
&value
)
990 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
991 m_data
->GetObjectName(objectID
),
992 propertyInfo
->GetAccessor()->GetSetterName(),
993 ValueAsCode(value
)) );
996 void wxCodeDepersister::SetPropertyAsObject(int objectID
,
997 const wxClassInfo
*WXUNUSED(classInfo
),
998 const wxPropertyInfo
* propertyInfo
,
1001 if ( propertyInfo
->GetTypeInfo()->GetKind() == wxT_OBJECT
)
1002 m_fp
->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
1003 m_data
->GetObjectName(objectID
),
1004 propertyInfo
->GetAccessor()->GetSetterName(),
1005 m_data
->GetObjectName( valueObjectId
) ) );
1007 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
1008 m_data
->GetObjectName(objectID
),
1009 propertyInfo
->GetAccessor()->GetSetterName(),
1010 m_data
->GetObjectName( valueObjectId
) ) );
1013 void wxCodeDepersister::AddToPropertyCollection( int objectID
,
1014 const wxClassInfo
*classInfo
,
1015 const wxPropertyInfo
* propertyInfo
,
1016 const wxxVariant
&value
)
1018 m_fp
->WriteString( wxString::Format( "\t%s->%s(%s);\n",
1019 m_data
->GetObjectName(objectID
),
1020 propertyInfo
->GetAccessor()->GetAdderName(),
1021 ValueAsCode(value
)) );
1024 // sets the corresponding property (value is an object)
1025 void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID
,
1026 const wxClassInfo
*classInfo
,
1027 const wxPropertyInfo
* propertyInfo
,
1033 void wxCodeDepersister::SetConnect(int eventSourceObjectID
,
1034 const wxClassInfo
*WXUNUSED(eventSourceClassInfo
),
1035 const wxDelegateTypeInfo
*delegateInfo
,
1036 const wxClassInfo
*eventSinkClassInfo
,
1037 const wxHandlerInfo
* handlerInfo
,
1038 int eventSinkObjectID
)
1040 wxString ehsource
= m_data
->GetObjectName( eventSourceObjectID
) ;
1041 wxString ehsink
= m_data
->GetObjectName(eventSinkObjectID
) ;
1042 wxString ehsinkClass
= eventSinkClassInfo
->GetClassName() ;
1043 int eventType
= delegateInfo
->GetEventType() ;
1044 wxString handlerName
= handlerInfo
->GetName() ;
1046 m_fp
->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
1047 ehsource
, ehsource
, eventType
, ehsinkClass
, handlerName
, ehsink
) );
1050 #include <wx/arrimpl.cpp>
1052 WX_DEFINE_OBJARRAY(wxxVariantArray
);