-void WriteComponent(wxObject *Object, const wxClassInfo *classInfo, wxXmlNode *parent, const wxString& nodeName , int &nextId, bool embeddedObject, map< wxObject* , int > &writtenObjects ) ;
-
-void WriteComponentProperties( wxObject* obj , const wxClassInfo* ci , wxXmlNode *onode , int &nextId, map< wxObject* , int > &writtenObjects, map< string , int > &writtenProperties)
-{
- const wxPropertyInfo *pi = ci->GetFirstProperty() ;
- while( pi )
- {
- if ( writtenProperties.find( pi->GetName() ) == writtenProperties.end() )
- {
- writtenProperties[ pi->GetName() ] = 1 ;
- const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ;
- if ( cti )
- {
- const wxClassInfo* pci = cti->GetClassInfo() ;
- wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
- WriteComponent( pci->VariantToInstance( value ) , pci , onode , pi->GetName() , nextId ,
- ( cti->GetKind() == wxT_OBJECT ) , writtenObjects ) ;
- }
- else
- {
- const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ;
- if ( dti )
- {
- // in which form should we stream out these ?
- }
- else
- {
- wxXmlNode *pnode;
- pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
- pi->GetAccessor()->WriteValue(pnode, obj ) ;
- onode->AddChild(pnode);
- }
- }
- }
- pi = pi->GetNext() ;
- }
- const wxClassInfo** parents = ci->GetParents() ;
- for ( int i = 0 ; parents[i] ; ++ i )
- {
- WriteComponentProperties( obj , parents[i] , onode , nextId , writtenObjects , writtenProperties ) ;
- }
-}
-
-/*
- Writing Components does have to take inheritance into account, that's why we are iterating
- over our parents as well
- */
-
-void WriteComponent(wxObject *obj, const wxClassInfo *classInfo, wxXmlNode *parent, const wxString &nodeName)
-{
- int nextid = 0 ; // 0 is the root element
- map< wxObject* , int > writtenobjects ;
- WriteComponent( obj , classInfo, parent, nodeName , nextid , false , writtenobjects ) ;
-}
-
-void WriteComponent(wxObject *obj, const wxClassInfo *classInfo, wxXmlNode *parent, const wxString& nodeName , int &nextId, bool embeddedObject, map< wxObject* , int > &writtenObjects )
-{
- map< string , int > writtenProperties ;
- wxXmlNode *onode;
-
- onode = new wxXmlNode(wxXML_ELEMENT_NODE, nodeName);
-
- onode->AddProperty(wxString("class"), wxString(classInfo->GetClassName()));
- if ( obj == NULL )
- {
- wxXmlNode* nullnode = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, "null");
- onode->AddChild(nullnode);
- }
- else
- {
- // if we have already written this object, just insert an id
- // embedded objects have to be written out fully always, their address will be reused and is not a valid key
- if ( !embeddedObject && (writtenObjects.find( obj ) != writtenObjects.end()) )
- {
- onode->AddProperty(wxString("id"), wxString::Format( "%d" , writtenObjects[obj] ) );
- }
- else
- {
- int id = nextId++ ;
- if ( !embeddedObject )
- writtenObjects[obj] = id ;
- onode->AddProperty(wxString("id"), wxString::Format( "%d" , id ) );
- WriteComponentProperties( obj , classInfo , onode , nextId , writtenObjects, writtenProperties) ;
- }
- }
-
- parent->AddChild(onode);
+int wxWriter::GetObjectID(const wxObject *obj)
+{
+ if ( !IsObjectKnown( obj ) )
+ return wxInvalidObjectID ;
+
+ return m_data->m_writtenObjects[obj] ;
+}
+
+bool wxWriter::IsObjectKnown( const wxObject *obj )
+{
+ return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ;
+}
+
+//
+// XML Streaming
+//
+
+// convenience functions
+
+void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data )
+{
+ node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) );
+}
+
+wxString wxXmlGetContentFromNode( wxXmlNode *node )
+{
+ if ( node->GetChildren() )
+ return node->GetChildren()->GetContent() ;
+ else
+ return wxEmptyString ;
+}
+
+struct wxXmlWriter::wxXmlWriterInternal
+{
+ wxXmlNode *m_root ;
+ wxXmlNode *m_current ;
+ vector< wxXmlNode * > m_objectStack ;
+} ;
+
+wxXmlWriter::wxXmlWriter( wxXmlNode * rootnode )
+{
+ m_data = new wxXmlWriterInternal() ;
+ m_data->m_root = rootnode ;
+ m_data->m_current = rootnode ;
+}
+
+wxXmlWriter::~wxXmlWriter()
+{
+ delete m_data ;
+}
+
+// start of writing the root object
+void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID , const wxString &name )
+{
+ wxXmlNode *onode;
+ onode = new wxXmlNode(wxXML_ELEMENT_NODE, name);
+ onode->AddProperty(wxString("class"), wxString(classInfo->GetClassName()));
+ onode->AddProperty(wxString("id"), wxString::Format( "%d" , objectID ) );
+
+ m_data->m_current->AddChild(onode) ;
+ m_data->m_objectStack.push_back( m_data->m_current ) ;
+ m_data->m_current = onode ;
+}
+
+// end of writing the root object
+void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) , const wxString &WXUNUSED(name) )
+{
+ m_data->m_current = m_data->m_objectStack.back() ;
+ m_data->m_objectStack.pop_back() ;
+}
+
+// writes a property in the stream format
+void wxXmlWriter::DoWriteProperty( const wxObject *WXUNUSED(obj), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi , wxxVariant &value )
+{
+ wxXmlNode *pnode;
+ pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
+ wxXmlAddContentToNode( pnode ,value.GetAsString() ) ;
+ m_data->m_current->AddChild(pnode);
+}
+
+void wxXmlWriter::DoBeginWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject),
+ const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
+{
+ wxXmlNode *onode;
+ onode = new wxXmlNode(wxXML_ELEMENT_NODE, propInfo->GetName());
+ onode->AddProperty(wxString("class"), wxString(valueObjectClassInfo->GetClassName()));
+ onode->AddProperty(wxString("id"), wxString::Format( "%d" , valueObjectID ) );
+ m_data->m_current->AddChild(onode) ;
+ m_data->m_objectStack.push_back( m_data->m_current ) ;
+ m_data->m_current = onode ;
+}
+
+// insert an object reference to an already written object
+void wxXmlWriter::DoWriteObjectReference(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *valueObject,
+ const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
+{
+ wxXmlNode *onode;
+ onode = new wxXmlNode(wxXML_ELEMENT_NODE, propInfo->GetName());
+ onode->AddProperty(wxString("class"), wxString(valueObjectClassInfo->GetClassName()));
+ if ( valueObject == NULL )
+ {
+ wxXmlNode* nullnode = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, "null");
+ onode->AddChild(nullnode);
+ }
+ else
+ {
+ onode->AddProperty(wxString("id"), wxString::Format( "%d" , valueObjectID ) );
+ }
+
+ m_data->m_current->AddChild(onode) ;
+}
+
+void wxXmlWriter::DoEndWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject),
+ const wxClassInfo *WXUNUSED(valueObjectClassInfo), int WXUNUSED(valueObjectID) , const wxPropertyInfo *WXUNUSED(propInfo) )
+{
+ m_data->m_current = m_data->m_objectStack.back() ;
+ m_data->m_objectStack.pop_back() ;
+}
+
+
+// writes a delegate in the stream format
+void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi ,
+ const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo )
+{
+ if ( eventSink != NULL && handlerInfo != NULL )
+ {
+ wxXmlNode *pnode;
+ pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
+ wxString s ;
+ s.Printf(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName() ) ;
+ wxXmlAddContentToNode( pnode ,s ) ;
+ m_data->m_current->AddChild(pnode);
+ }