]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/xtistrm.cpp
fixes for new lib dirs for wxMSW
[wxWidgets.git] / src / common / xtistrm.cpp
index f94b2f6e9ad49704e4a2d71642e5f3faed2b8728..372602c3760db7218b9bcbd24ee719bebf550ec1 100644 (file)
 #include "wx/txtstrm.h"
 
 #if wxUSE_EXTENDED_RTTI
+
+#include "wx/beforestd.h"
 #include <map>
 #include <vector>
 #include <string>
+#include "wx/afterstd.h"
 
 using namespace std ;
 
@@ -56,158 +59,213 @@ wxWriter::~wxWriter()
 
 struct wxWriter::wxWriterInternalPropertiesData
 {
-    map< string , int > m_writtenProperties ;
+    char nothing ;
 } ;
 
-void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name )
+void wxWriter::ClearObjectContext()
+{
+    delete m_data ;
+    m_data = new wxWriterInternal() ;
+    m_data->m_nextId = 0 ;
+}
+
+void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name , wxxVariantArray &metadata )
 {
-    if ( persister->BeforeWriteObject( object , classInfo , name ) )
+    DoBeginWriteTopLevelEntry( name ) ;
+    WriteObject( object , classInfo , persister , false , metadata) ;
+    DoEndWriteTopLevelEntry( name ) ;
+}
+
+void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded, wxxVariantArray &metadata )
+{
+    // hack to avoid writing out embedded windows, these are windows that are constructed as part of other windows, they would
+    // doubly constructed afterwards
+
+    const wxWindow * win = dynamic_cast<const wxWindow*>(object) ;
+    if ( win && win->GetId() < 0 )
+        return ;
+
+    if ( persister->BeforeWriteObject( this , object , classInfo , metadata) )
     {
-        if ( object == NULL || IsObjectKnown( object ) )
-        {
-            DoWriteObjectReference( NULL , NULL , object , classInfo , GetObjectID(object) , NULL ) ;
-        }
+        if ( object == NULL )
+            DoWriteNullObject() ;
+        else if ( IsObjectKnown( object ) )
+            DoWriteRepeatedObject( GetObjectID(object) ) ;
         else
         {
             int oid = m_data->m_nextId++ ;
-            m_data->m_writtenObjects[object] = oid ;
+            if ( !isEmbedded )
+                m_data->m_writtenObjects[object] = oid ;
+
             // in case this object is a wxDynamicObject we also have to insert is superclass
             // instance with the same id, so that object relations are streamed out correctly
             const wxDynamicObject* dynobj = dynamic_cast<const wxDynamicObject *>( object ) ;
-            if ( dynobj )
+            if ( !isEmbedded && dynobj )
                 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
 
-            DoBeginWriteObject( object , classInfo , oid , name ) ;
+            DoBeginWriteObject( object , classInfo , oid , metadata ) ;
             wxWriterInternalPropertiesData data ;
             WriteAllProperties( object , classInfo , persister , &data ) ;
-            DoEndWriteObject( object , classInfo , oid , name  ) ;
+            DoEndWriteObject( object , classInfo , oid  ) ;
         }
+        persister->AfterWriteObject( this ,object , classInfo ) ;
     }
 }
 
-void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
+void wxWriter::FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler)
 {
-    const wxPropertyInfo *pi = ci->GetFirstProperty() ;
-    while( pi ) 
+    wxList *dynamicEvents = evSource->GetDynamicEventTable() ;
+
+    if ( dynamicEvents )
     {
-        if ( data->m_writtenProperties.find( pi->GetName() ) == data->m_writtenProperties.end() )
+        wxList::compatibility_iterator node = dynamicEvents->GetFirst();
+        while (node)
         {
-            data->m_writtenProperties[ pi->GetName() ] = 1 ;
-            const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ;
-            if ( cti )
+            wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
+
+            // find the match
+            if ( entry->m_fn && (dti->GetEventType() == entry->m_eventType) &&
+                (entry->m_id == -1 ||
+                (entry->m_lastId == -1 && evSource->GetId() == entry->m_id) ||
+                (entry->m_lastId != -1 &&
+                (evSource->GetId()  >= entry->m_id && evSource->GetId() <= entry->m_lastId) ) ) &&
+                entry->m_eventSink
+                )
             {
-                const wxClassInfo* pci = cti->GetClassInfo() ;
-                wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
-                if ( persister->BeforeWritePropertyAsObject( obj , ci , pi , value ) )
+                sink = entry->m_eventSink ;
+                const wxClassInfo* sinkClassInfo = sink->GetClassInfo() ;
+                const wxHandlerInfo* sinkHandler = sinkClassInfo->GetFirstHandler() ;
+                while ( sinkHandler )
                 {
-                    wxObject *vobj = pci->VariantToInstance( value ) ;
-                    bool embeddedObject = cti->GetKind() == wxT_OBJECT ;
-
-                    if ( vobj == NULL || IsObjectKnown( vobj ) )
+                    if ( sinkHandler->GetEventFunction() == entry->m_fn )
                     {
-                        DoWriteObjectReference( obj , ci , vobj , pci , GetObjectID(vobj) , pi ) ;
-                    }
-                    else
-                    {
-                        int oid = m_data->m_nextId++ ;
-                        if ( !embeddedObject)
-                        {
-                            // insert this object and its id
-                            m_data->m_writtenObjects[vobj] = oid ;
-                            // in case this object is a wxDynamicObject we also have to insert is superclass
-                            // instance with the same id, so that object relations are streamed out correctly
-                            const wxDynamicObject* dynobj = dynamic_cast<const wxDynamicObject *>( vobj ) ;
-                            if ( dynobj )
-                                m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
-                        }
-
-                        DoBeginWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ;
-                        if ( vobj != NULL )
-                        {
-                            wxWriterInternalPropertiesData data ;
-                            WriteAllProperties( vobj , pci , persister , &data ) ;
-                        }
-                        DoEndWriteParamAsObject( obj , ci , vobj , pci , oid , pi   ) ;
+                        handler = sinkHandler ;
+                        break ;
                     }
+                    sinkHandler = sinkHandler->GetNext() ;
                 }
+                break ;
             }
-            else
+            node = node->GetNext();
+        }
+    }
+}
+void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
+{
+    wxPropertyInfoMap map ;
+    ci->GetProperties( map ) ;
+    for ( int i = 0 ; i < ci->GetCreateParamCount() ; ++i )
+    {
+        wxString name = ci->GetCreateParamName(i) ;
+        const wxPropertyInfo* prop = map.find(name)->second ;
+        wxASSERT_MSG( prop , wxT("Create Parameter not found in declared RTTI Parameters") ) ;
+        WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ;
+        map.erase( name ) ;
+    }
+
+    for( wxPropertyInfoMap::iterator iter = map.begin() ; iter != map.end() ; ++iter )
+    {
+        const wxPropertyInfo* prop = iter->second ;
+        if ( prop->GetFlags() & wxPROP_OBJECT_GRAPH )
+        {
+            WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ;
+        }
+    }
+
+    for( wxPropertyInfoMap::iterator iter = map.begin() ; iter != map.end() ; ++iter )
+    {
+        const wxPropertyInfo* prop = iter->second ;
+        if ( !(prop->GetFlags() & wxPROP_OBJECT_GRAPH) )
+        {
+            WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ;
+        }
+    }
+}
+
+void wxWriter::WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , const wxPropertyInfo* pi , wxPersister *persister , wxWriterInternalPropertiesData *data ) 
+{
+    // make sure that we are picking the correct object for accessing the property
+    const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject* > (obj ) ;
+    if ( dynobj && (dynamic_cast<const wxDynamicClassInfo*>(ci) == NULL) )
+        obj = dynobj->GetSuperClassInstance() ;
+
+    DoBeginWriteProperty( pi ) ;
+    if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
+    {
+        wxxVariantArray data ;
+        pi->GetAccessor()->GetPropertyCollection(obj, data) ;
+        const wxTypeInfo * elementType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() )->GetElementType() ;
+        for ( size_t i = 0 ; i < data.GetCount() ; ++i )
+        {
+            DoBeginWriteElement() ;
+            wxxVariant value = data[i] ;
+            if ( persister->BeforeWriteProperty( this , pi , value ) )
             {
-                const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ;
-                if ( dti )
+                const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( elementType ) ;
+                if ( cti )
+                {
+                    const wxClassInfo* pci = cti->GetClassInfo() ;
+                    wxObject *vobj = pci->VariantToInstance( value ) ;
+                    wxxVariantArray md ;
+                    WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT , md ) ;
+                }
+                else
                 {
-                    const wxObject* sink = NULL ;
-                    const wxHandlerInfo *handler = NULL ;
-                    
-                    const wxWindow * evSource = dynamic_cast<const wxWindow *>(obj) ;
-                    wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
+                     DoWriteSimpleType( value ) ;
+                }
+            }
+            DoEndWriteElement() ;
+        }
+    }
+    else
+    {
+        const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ;
+        if ( dti )
+        {
+            const wxObject* sink = NULL ;
+            const wxHandlerInfo *handler = NULL ;
 
-                    wxList *dynamicEvents = evSource->GetDynamicEventTable() ;
+            const wxWindow * evSource = dynamic_cast<const wxWindow *>(obj) ;
+            wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
 
-                    if ( dynamicEvents )
-                    {
-                        wxList::compatibility_iterator node = dynamicEvents->GetFirst();
-                        while (node)
-                        {
-                            wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
-
-                            // find the match
-                            if ( entry->m_fn && (dti->GetEventType() == entry->m_eventType) &&
-                                (entry->m_id == -1 ||
-                                (entry->m_lastId == -1 && evSource->GetId() == entry->m_id) ||
-                                (entry->m_lastId != -1 &&
-                                (evSource->GetId()  >= entry->m_id && evSource->GetId() <= entry->m_lastId) ) ) &&
-                                entry->m_eventSink
-                                )
-                            {
-                                sink = entry->m_eventSink ;
-                                const wxClassInfo* sinkClassInfo = sink->GetClassInfo() ;
-                                const wxHandlerInfo* sinkHandler = sinkClassInfo->GetFirstHandler() ;
-                                while ( sinkHandler )
-                                {
-                                    if ( sinkHandler->GetEventFunction() == entry->m_fn )
-                                    {
-                                        handler = sinkHandler ;
-                                        break ;
-                                    }
-                                    sinkHandler = sinkHandler->GetNext() ;
-                                }
-                                break ;
-                            }
-                            node = node->GetNext();
-                        }
-                        }
-                    if ( persister->BeforeWriteDelegate( obj , ci , pi , sink , handler ) )
-                    {
-                        if ( sink != NULL && handler != NULL )
-                        {
-                            wxASSERT_MSG( IsObjectKnown( sink ) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
-                            DoWriteDelegate( obj , ci , pi , sink , GetObjectID( sink ) , sink->GetClassInfo() , handler ) ;
-                        }
-                    }
+            FindConnectEntry( evSource , dti , sink , handler ) ;
+            if ( persister->BeforeWriteDelegate( this , obj , ci , pi , sink , handler ) )
+            {
+                if ( sink != NULL && handler != NULL )
+                {
+                    wxASSERT_MSG( IsObjectKnown( sink ) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
+                    DoWriteDelegate( obj , ci , pi , sink , GetObjectID( sink ) , sink->GetClassInfo() , handler ) ;
                 }
-                else
+            }
+        }
+        else
+        {
+            wxxVariant value ;
+            pi->GetAccessor()->GetProperty(obj, value) ;
+            if ( persister->BeforeWriteProperty( this , pi , value ) )
+            {
+                const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ;
+                if ( cti )
                 {
-                    wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
-                    if ( persister->BeforeWriteProperty( obj , ci , pi , value ) )
+                    const wxClassInfo* pci = cti->GetClassInfo() ;
+                    wxObject *vobj = pci->VariantToInstance( value ) ;
+                    wxxVariantArray md ;
+                    WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT , md) ;
+                }
+                else
+                {                        
+                    if ( pi->GetFlags() & wxPROP_ENUM_STORE_LONG )
                     {
-                        DoWriteProperty( obj , ci , pi , value ) ;
+                        const wxEnumTypeInfo *eti = dynamic_cast<const wxEnumTypeInfo*>( pi->GetTypeInfo() ) ;
+                        wxASSERT_MSG( eti , wxT("Type must have enum - long conversion") ) ;
+                        eti->ConvertFromLong( value.Get<long>() , value ) ;
                     }
+                    DoWriteSimpleType( value ) ;
                 }
             }
         }
-        pi = pi->GetNext() ;
-    }
-    // in case this object is wxDynamic object we have to hand over the streaming
-    // of the properties of the superclasses to the real super class instance
-    const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject* > (obj ) ;
-    if ( dynobj )
-        obj = dynobj->GetSuperClassInstance() ;
-    const wxClassInfo** parents = ci->GetParents() ;
-    for ( int i = 0 ; parents[i] ; ++ i )
-    {
-        WriteAllProperties( obj , parents[i] , persister , data ) ;
     }
+    DoEndWriteProperty( pi ) ;
 }
 
 int wxWriter::GetObjectID(const wxObject *obj) 
@@ -247,6 +305,18 @@ struct wxXmlWriter::wxXmlWriterInternal
     wxXmlNode *m_root ;
     wxXmlNode *m_current ;
     vector< wxXmlNode * > m_objectStack ;
+
+    void Push( wxXmlNode *newCurrent )
+    {
+        m_objectStack.push_back( m_current ) ;
+        m_current = newCurrent ;
+    }
+
+    void Pop()
+    {
+        m_current = m_objectStack.back() ;
+        m_objectStack.pop_back() ;
+    }
 } ;
 
 wxXmlWriter::wxXmlWriter( wxXmlNode * rootnode ) 
@@ -261,87 +331,100 @@ 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  ) 
+void wxXmlWriter::DoBeginWriteTopLevelEntry( 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 ) );
+    wxXmlNode *pnode;
+    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("entry"));
+    pnode->AddProperty(wxString("name"), name);
+    m_data->m_current->AddChild(pnode) ;
+    m_data->Push( pnode ) ;
+}
+
+void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString &WXUNUSED(name) )
+{
+    m_data->Pop() ;
+}
+
+void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID , wxxVariantArray &metadata   ) 
+{
+    wxXmlNode *pnode;
+    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object"));
+    pnode->AddProperty(wxT("class"), wxString(classInfo->GetClassName()));
+    pnode->AddProperty(wxT("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 ;
+    for ( size_t i = 0 ; i < metadata.GetCount() ; ++i )
+    {
+        pnode->AddProperty( metadata[i].GetName() , metadata[i].GetAsString() ) ;
+    }
+    m_data->m_current->AddChild(pnode) ;
+    m_data->Push( pnode ) ;
 }
 
 // end of writing the root object
-void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) , const wxString &WXUNUSED(name) 
+void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) ) 
 {
-    m_data->m_current = m_data->m_objectStack.back() ;
-    m_data->m_objectStack.pop_back() ;
+    m_data->Pop() ;
 }
 
 // writes a property in the stream format
-void wxXmlWriter::DoWriteProperty( const wxObject *WXUNUSED(obj), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi , wxxVariant &value ) 
+void wxXmlWriter::DoWriteSimpleType( wxxVariant &value ) 
+{
+    wxXmlAddContentToNode( m_data->m_current ,value.GetAsString() ) ;
+}
+
+void wxXmlWriter::DoBeginWriteElement() 
 {
     wxXmlNode *pnode;
-    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
-    wxXmlAddContentToNode( pnode ,value.GetAsString() ) ;
-    m_data->m_current->AddChild(pnode);
+    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "element" );
+    m_data->m_current->AddChild(pnode) ;
+    m_data->Push( pnode ) ;
 }
 
-void wxXmlWriter::DoBeginWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject), 
-                                            const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
+void wxXmlWriter::DoEndWriteElement() 
 {
-    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 ;
+    m_data->Pop() ;
 }
 
-// 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 ) 
+void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo *pi )
 {
-    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 ) );
-    }
+    wxXmlNode *pnode;
+    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "prop" );
+    pnode->AddProperty(wxT("name"), pi->GetName() );
+    m_data->m_current->AddChild(pnode) ;
+    m_data->Push( pnode ) ;
+}
 
-    m_data->m_current->AddChild(onode) ;
+void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo *WXUNUSED(propInfo) )
+{
+    m_data->Pop() ;
 }
 
-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) )
+
+
+// insert an object reference to an already written object
+void wxXmlWriter::DoWriteRepeatedObject( int objectID ) 
 {
-    m_data->m_current = m_data->m_objectStack.back() ;
-    m_data->m_objectStack.pop_back() ;
+    wxXmlNode *pnode;
+    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object"));
+    pnode->AddProperty(wxString("href"), wxString::Format( "%d" , objectID ) );
+    m_data->m_current->AddChild(pnode) ;
 }
 
+// insert a null reference
+void wxXmlWriter::DoWriteNullObject() 
+{
+    wxXmlNode *pnode;
+    pnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object"));
+    m_data->m_current->AddChild(pnode) ;
+}
 
 // writes a delegate in the stream format
-void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object),  const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi , 
+void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object),  const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(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);
+        wxXmlAddContentToNode( m_data->m_current ,wxString::Format(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName()) ) ;
     }
 }
 
@@ -394,6 +477,7 @@ and create params are always toplevel class only
 
 int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
 {
+    wxASSERT_MSG( callbacks , wxT("Does not support reading without a Depersistor") ) ;
     wxString className;
     wxClassInfo *classInfo;
 
@@ -402,38 +486,56 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
     const wxClassInfo** createClassInfos ;
     wxXmlNode *children;
     int objectID;
+    wxString ObjectIdString ;
 
     children = node->GetChildren();
+    if (!children)
+    {
+        // check for a null object or href
+        if (node->GetPropVal("href" , &ObjectIdString ) )
+        {
+            objectID = atoi( ObjectIdString.c_str() ) ;
+            wxASSERT_MSG( HasObjectClassInfo( objectID ) , wxT("Forward hrefs are not supported") ) ;
+            return objectID ;
+        }
+        if ( !node->GetPropVal("id" , &ObjectIdString ) )
+        {
+            return wxNullObjectID;
+        }
+    }
     if (!node->GetPropVal("class", &className))
     {
         // No class name.  Eek. FIXME: error handling
         return wxInvalidObjectID;
     }
     classInfo = wxClassInfo::FindClass(className);
-    if (children && children->GetType() == wxXML_TEXT_NODE)
-    {
-        assert( wxXmlGetContentFromNode(node) == "null" ) ;
-        // this must be a NULL component reference.  We just bail out
-        return wxNullObjectID;
-    }
-
-    wxString ObjectIdString ;
+    wxASSERT_MSG( classInfo , wxString::Format(wxT("unknown class %s"),className ) ) ;
+    wxASSERT_MSG( !children || children->GetType() != wxXML_TEXT_NODE , wxT("objects cannot have XML Text Nodes") ) ;
     if (!node->GetPropVal("id", &ObjectIdString))
     {
+        wxASSERT_MSG(0,wxT("Objects must have an id attribute") ) ;
         // No object id.  Eek. FIXME: error handling
         return wxInvalidObjectID;
     }
-
     objectID = atoi( ObjectIdString.c_str() ) ;
     // is this object already has been streamed in, return it here
-    if ( HasObjectClassInfo( objectID ) )
-        return objectID ;
+    wxASSERT_MSG( !HasObjectClassInfo( objectID ) , wxString::Format(wxT("Doubly used id : %d"), objectID ) ) ;
 
     // new object, start with allocation
     // first make the object know to our internal registry
     SetObjectClassInfo( objectID , classInfo ) ;
 
-    callbacks->AllocateObject(objectID, classInfo);
+    wxxVariantArray metadata ;
+    wxXmlProperty *xp = node->GetProperties() ;
+    while ( xp )
+    {
+        if ( xp->GetName() != wxString("class") && xp->GetName() != wxString("id") )
+        {
+            metadata.Add( new wxxVariant( xp->GetValue() , xp->GetName() ) ) ;
+        }
+        xp = xp->GetNext() ;
+    }
+    callbacks->AllocateObject(objectID, classInfo, metadata);
 
     // 
     // stream back the Create parameters first
@@ -449,8 +551,10 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
 
     while( children )
     {
-        propertyNames.push_back( children->GetName().c_str() ) ;
-        propertyNodes[children->GetName().c_str()] = children ;
+        wxString name ;
+        children->GetPropVal( wxT("name") , &name ) ;
+        propertyNames.push_back( name.c_str() ) ;
+        propertyNodes[name.c_str()] = children->GetChildren() ;
         children = children->GetNext() ;
     }
 
@@ -459,6 +563,7 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
         const wxChar* paramName = classInfo->GetCreateParamName(i) ;
         PropertyNodes::iterator propiter = propertyNodes.find( paramName ) ;
         const wxPropertyInfo* pi = classInfo->FindPropertyInfo( paramName ) ;
+        wxASSERT_MSG(pi,wxString::Format("Unkown Property %s",paramName) ) ;
         // if we don't have the value of a create param set in the xml
         // we use the default value
         if ( propiter != propertyNodes.end() )
@@ -472,7 +577,16 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
             else
             {
                 createParamOids[i] = wxInvalidObjectID ;
-                createParams[i] = ReadValue( prop , pi->GetAccessor() ) ;
+                createParams[i] = ReadValue( prop , pi->GetTypeInfo() ) ;
+                if( pi->GetFlags() & wxPROP_ENUM_STORE_LONG )
+                {
+                    const wxEnumTypeInfo *eti = dynamic_cast<const wxEnumTypeInfo*>( pi->GetTypeInfo() ) ;
+                    wxASSERT_MSG( eti , wxT("Type must have enum - long conversion") ) ;
+
+                    long realval ;
+                    eti->ConvertToLong( createParams[i]  , realval ) ;
+                    createParams[i] = wxxVariant( realval ) ;
+                }
                 createClassInfos[i] = NULL ;
             }
 
@@ -494,7 +608,7 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
     // got the parameters.  Call the Create method
     callbacks->CreateObject(objectID, classInfo,
         classInfo->GetCreateParamCount(),
-        createParams, createParamOids, createClassInfos);
+        createParams, createParamOids, createClassInfos, metadata );
 
     // now stream in the rest of the properties, in the sequence their properties were written in the xml
     for ( size_t j = 0 ; j < propertyNames.size() ; ++j )
@@ -506,37 +620,69 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
             {
                 wxXmlNode* prop = propiter->second ;
                 const wxPropertyInfo* pi = classInfo->FindPropertyInfo( propertyNames[j].c_str() ) ;
-                if ( pi->GetTypeInfo()->IsObjectType() )
+                if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
                 {
-                    int valueId = ReadComponent( prop , callbacks ) ;
-                    if ( callbacks )
+                    const wxCollectionTypeInfo* collType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() ) ;
+                    const wxTypeInfo * elementType = collType->GetElementType() ;
+                    while( prop )
                     {
-                        if ( valueId != wxInvalidObjectID )
+                        wxASSERT_MSG(prop->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ;
+                        wxXmlNode* elementContent = prop->GetChildren() ;
+                        if ( elementContent )
                         {
-                            callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ;
-                            if ( pi->GetTypeInfo()->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
-                                callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
+                            // we skip empty elements
+                            if ( elementType->IsObjectType() )
+                            {
+                                int valueId = ReadComponent( elementContent , callbacks ) ;
+                                if ( valueId != wxInvalidObjectID )
+                                {
+                                    if ( pi->GetAccessor()->HasAdder() )
+                                        callbacks->AddToPropertyCollectionAsObject( objectID , classInfo , pi , valueId ) ;
+                                    // TODO for collections we must have a notation on taking over ownership or not 
+                                    if ( elementType->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
+                                        callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
+                                }
+                            }
+                            else
+                            {
+                                wxxVariant elementValue = ReadValue( elementContent , elementType ) ;
+                                if ( pi->GetAccessor()->HasAdder() )
+                                    callbacks->AddToPropertyCollection( objectID , classInfo ,pi , elementValue ) ;
+                            }
                         }
+                        prop = prop->GetNext() ;
+                    }
+                }
+                else if ( pi->GetTypeInfo()->IsObjectType() )
+                {
+                    int valueId = ReadComponent( prop , callbacks ) ;
+                    if ( valueId != wxInvalidObjectID )
+                    {
+                        callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ;
+                        if ( pi->GetTypeInfo()->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
+                            callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
                     }
                 }
                 else if ( pi->GetTypeInfo()->IsDelegateType() )
                 {
-                    wxString resstring = wxXmlGetContentFromNode(prop) ;
-                    wxInt32 pos = resstring.Find('.') ;
-                    assert( pos != wxNOT_FOUND ) ;
-                    int sinkOid = atol(resstring.Left(pos)) ;
-                    wxString handlerName = resstring.Mid(pos+1) ;
-                    wxClassInfo* sinkClassInfo = GetObjectClassInfo( sinkOid ) ;
-
-                    if (callbacks)
+                    if ( prop )
+                    {
+                        wxString resstring = prop->GetContent() ;
+                        wxInt32 pos = resstring.Find('.') ;
+                        assert( pos != wxNOT_FOUND ) ;
+                        int sinkOid = atol(resstring.Left(pos)) ;
+                        wxString handlerName = resstring.Mid(pos+1) ;
+                        wxClassInfo* sinkClassInfo = GetObjectClassInfo( sinkOid ) ;
+
                         callbacks->SetConnect( objectID , classInfo , dynamic_cast<const wxDelegateTypeInfo*>(pi->GetTypeInfo()) , sinkClassInfo ,
-                        sinkClassInfo->FindHandlerInfo(handlerName) ,  sinkOid ) ;
+                            sinkClassInfo->FindHandlerInfo(handlerName) ,  sinkOid ) ;
+                    }
 
                 }
                 else
                 {
-                    if ( callbacks )
-                        callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetAccessor() ) ) ;
+                    wxxVariant nodeval ;
+                    callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetTypeInfo() ) ) ;
                 }
             }
         }
@@ -550,14 +696,30 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
 }
 
 wxxVariant wxXmlReader::ReadValue(wxXmlNode *node,
-                                  wxPropertyAccessor *accessor )
+                                  const wxTypeInfo *type )
 {
-    return accessor->ReadValue(wxXmlGetContentFromNode( node ) ) ;
+    wxString content ;
+    if ( node )
+        content = node->GetContent() ;
+    wxxVariant result ;
+    type->ConvertFromString( content , result ) ;
+    return result ;
 }
 
-int wxXmlReader::ReadObject(wxDepersister *callbacks)
+int wxXmlReader::ReadObject( const wxString &name , wxDepersister *callbacks)
 {
-    return ReadComponent( m_parent , callbacks ) ;
+    wxXmlNode *iter = m_parent->GetChildren() ;
+    while ( iter )
+    {
+        wxString entryName ;
+        if ( iter->GetPropVal("name", &entryName) )
+        {
+            if ( entryName == name )
+                return ReadComponent( iter->GetChildren() , callbacks ) ;
+        }
+        iter = iter->GetNext() ;
+    }
+    return wxInvalidObjectID ;
 }
 
 // ----------------------------------------------------------------------------
@@ -593,7 +755,8 @@ wxRuntimeDepersister::~wxRuntimeDepersister()
     delete m_data ;
 }
 
-void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo)
+void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo ,
+                                          wxxVariantArray &metadata)
 {
     wxObject *O;
     O = classInfo->CreateObject();
@@ -605,7 +768,8 @@ void wxRuntimeDepersister::CreateObject(int objectID,
                                         int paramCount,
                                         wxxVariant *params,
                                         int *objectIdValues,
-                                        const wxClassInfo **objectClassInfos)
+                                        const wxClassInfo **objectClassInfos ,
+                                        wxxVariantArray &metadata)
 {
     wxObject *o;
     o = m_data->GetObject(objectID);
@@ -643,7 +807,6 @@ void wxRuntimeDepersister::SetProperty(int objectID,
     wxObject *o;
     o = m_data->GetObject(objectID);
     classInfo->SetProperty( o , propertyInfo->GetName() , value ) ;
-    // propertyInfo->GetAccessor()->SetProperty( o , value ) ;
 }
 
 void wxRuntimeDepersister::SetPropertyAsObject(int objectID,
@@ -664,8 +827,6 @@ void wxRuntimeDepersister::SetPropertyAsObject(int objectID,
     }
 
     classInfo->SetProperty( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ;
-//    propertyInfo->GetAccessor()->SetProperty( o , 
-//        (dynamic_cast<const wxClassTypeInfo*>(propertyInfo->GetTypeInfo()))->GetClassInfo()->InstanceToVariant(valo) ) ;
 }
 
 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID,
@@ -691,6 +852,38 @@ wxObject *wxRuntimeDepersister::GetObject(int objectID)
     return m_data->GetObject( objectID ) ;
 }
 
+// adds an element to a property collection
+void wxRuntimeDepersister::AddToPropertyCollection( int objectID ,
+                                                   const wxClassInfo *classInfo,
+                                                   const wxPropertyInfo* propertyInfo ,
+                                                   const wxxVariant &value) 
+{
+    wxObject *o;
+    o = m_data->GetObject(objectID);
+    classInfo->AddToPropertyCollection( o , propertyInfo->GetName() , value ) ;
+}
+
+// sets the corresponding property (value is an object)
+void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID,
+                                                           const wxClassInfo *classInfo,
+                                                           const wxPropertyInfo* propertyInfo ,
+                                                           int valueObjectId) 
+{
+    wxObject *o, *valo;
+    o = m_data->GetObject(objectID);
+    valo = m_data->GetObject(valueObjectId);
+    const wxCollectionTypeInfo * collectionTypeInfo = dynamic_cast< const wxCollectionTypeInfo * >(propertyInfo->GetTypeInfo() ) ;
+    const wxClassInfo* valClassInfo = (dynamic_cast<const wxClassTypeInfo*>(collectionTypeInfo->GetElementType()))->GetClassInfo() ;
+    // if this is a dynamic object and we are asked for another class
+    // than wxDynamicObject we cast it down manually.
+    wxDynamicObject *dynvalo = dynamic_cast< wxDynamicObject * > (valo) ;
+    if ( dynvalo!=NULL  && (valClassInfo != dynvalo->GetClassInfo()) )
+    {
+        valo = dynvalo->GetSuperClassInstance() ;
+    }
+
+    classInfo->AddToPropertyCollection( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ;
+}
 
 // ----------------------------------------------------------------------------
 // depersisting to code 
@@ -726,7 +919,8 @@ wxCodeDepersister::~wxCodeDepersister()
     delete m_data ;
 }
 
-void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo)
+void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo ,
+                                       wxxVariantArray &metadata)
 {
     wxString objectName = wxString::Format( "LocalObject_%d" , objectID ) ;
     m_fp->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
@@ -768,7 +962,8 @@ void wxCodeDepersister::CreateObject(int objectID,
                                      int paramCount,
                                      wxxVariant *params,
                                      int *objectIDValues,
-                                     const wxClassInfo **WXUNUSED(objectClassInfos)
+                                     const wxClassInfo **WXUNUSED(objectClassInfos) ,
+                                     wxxVariantArray &metadata
                                      )
 {
     int i;
@@ -815,6 +1010,26 @@ void wxCodeDepersister::SetPropertyAsObject(int objectID,
         m_data->GetObjectName( valueObjectId) ) );
 }
 
+void wxCodeDepersister::AddToPropertyCollection( int objectID ,
+                                                const wxClassInfo *classInfo,
+                                                const wxPropertyInfo* propertyInfo ,
+                                                const wxxVariant &value) 
+{
+    m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
+        m_data->GetObjectName(objectID),
+        propertyInfo->GetAccessor()->GetAdderName(),
+        ValueAsCode(value)) );
+}
+
+// sets the corresponding property (value is an object)
+void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID,
+                                                        const wxClassInfo *classInfo,
+                                                        const wxPropertyInfo* propertyInfo ,
+                                                        int valueObjectId) 
+{
+    // TODO
+}
+
 void wxCodeDepersister::SetConnect(int eventSourceObjectID,
                                    const wxClassInfo *WXUNUSED(eventSourceClassInfo),
                                    const wxDelegateTypeInfo *delegateInfo ,
@@ -832,4 +1047,8 @@ void wxCodeDepersister::SetConnect(int eventSourceObjectID,
         ehsource , ehsource , eventType , ehsinkClass , handlerName , ehsink ) );
 }
 
+#include <wx/arrimpl.cpp>
+
+WX_DEFINE_OBJARRAY(wxxVariantArray);
+
 #endif