From: Stefan Csomor Date: Wed, 13 Aug 2003 16:59:46 +0000 (+0000) Subject: collection support for XTI X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/ab6e49136690b92c4879f8f964f7523a775dc7ee collection support for XTI git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@22807 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/xti.h b/include/wx/xti.h index f9b3050203..03274ef4f3 100644 --- a/include/wx/xti.h +++ b/include/wx/xti.h @@ -230,6 +230,13 @@ void wxSetToString( wxString &s , const wxSet &data ) // ---------------------------------------------------------------------------- // Type Information // ---------------------------------------------------------------------------- +// +// +// All data exposed by the RTTI is characterized using the following classes. +// The first characterization is done by wxTypeKind. All enums up to and including +// wxT_CUSTOM represent so called simple types. These cannot be divided any further. +// They can be converted to and from wxStrings, that's all. + enum wxTypeKind { @@ -246,11 +253,17 @@ enum wxTypeKind wxT_STRING, // must be wxString wxT_SET, // must be wxSet<> template wxT_ENUM, - wxT_OBJECT_PTR, // pointer to wxObject - wxT_OBJECT , // wxObject wxT_CUSTOM, // user defined type (e.g. wxPoint) + + wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM , + + wxT_OBJECT_PTR, // object reference + wxT_OBJECT , // embedded object + wxT_COLLECTION , // collection + wxT_DELEGATE , // for connecting against an event source - wxT_LAST_TYPE_KIND // sentinel for bad data, asserts, debugging + + wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging }; class WXDLLIMPEXP_BASE wxTypeInfo @@ -302,6 +315,17 @@ private : wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL } ; +class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo +{ +public : + wxCollectionTypeInfo( wxTypeInfo *elementType ) + { m_kind = wxT_COLLECTION , m_elementType = elementType ; } + + const wxTypeInfo* GetElementType() const { return m_elementType ; } +private : + wxTypeInfo * m_elementType ; +} ; + // a delegate is an exposed event source class WXDLLIMPEXP_BASE wxDelegateTypeInfo : public wxTypeInfo @@ -468,6 +492,10 @@ private : wxString m_name ; } ; +#include + +WX_DECLARE_OBJARRAY_WITH_DECL(wxxVariant, wxxVariantArray, class WXDLLIMPEXP_BASE); + // ---------------------------------------------------------------------------- // Property Support // @@ -487,19 +515,37 @@ public : class SetAndGetByRefRetBool ; class GetByRef ; #endif - wxPropertyAccessor() { m_setterName = NULL ; m_getterName = NULL ; } + wxPropertyAccessor() { m_setterName = NULL ; m_getterName = NULL ; m_adderName = NULL ;} virtual ~wxPropertyAccessor() {} + + // Setting a simple property (non-collection) virtual void SetProperty(wxObject *object, const wxxVariant &value) const = 0 ; + + // Getting a simple property (non-collection) virtual wxxVariant GetProperty(const wxObject *object) const = 0 ; + + // Adding an element to a collection property + virtual void AddToPropertyCollection(wxObject *object, const wxxVariant &value) const + { wxASSERT_MSG(0,wxT("Collection Operation called on non Collection Property")) ; } + + // Getting a collection property + virtual wxxVariantArray GetPropertyCollection( const wxObject *obj) const + { wxASSERT_MSG(0,wxT("Collection Operation called on non Collection Property")) ; return wxxVariantArray() ; } + virtual bool HasSetter() const = 0 ; virtual bool HasGetter() const = 0 ; + virtual bool HasAdder() const = 0 ; + const wxChar * GetGetterName() const { return m_setterName ; } const wxChar * GetSetterName() const { return m_getterName ; } + const wxChar * GetAdderName() const { return m_adderName ; } + virtual wxxVariant ReadValue( const wxString &value ) const = 0 ; virtual void WriteValue( wxString& value , const wxObject *o ) const = 0 ; protected : const wxChar *m_setterName ; const wxChar *m_getterName ; + const wxChar *m_adderName ; }; class WXDLLIMPEXP_BASE wxGenericPropertyAccessor : public wxPropertyAccessor @@ -509,8 +555,11 @@ public : ~wxGenericPropertyAccessor() ; virtual void SetProperty(wxObject *object, const wxxVariant &value) const ; virtual wxxVariant GetProperty(const wxObject *object) const ; + virtual bool HasSetter() const { return true ; } virtual bool HasGetter() const { return true ; } + virtual bool HasAdder() const { return false ; } + virtual wxxVariant ReadValue( const wxString &value ) const ; virtual void WriteValue( wxString& value , const wxObject *o ) const ; private : @@ -530,28 +579,28 @@ public: typedef T (Klass::*getter_t)() const; typedef const T& (Klass::*getter_ref_t)() const; - wxPropertyAccessorT(setter_t setter, getter_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(setter_t setter, getter_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( NULL ) , m_setter(setter), m_setter_ref(NULL), m_getter(getter) ,m_getter_ref(NULL) {m_setterName = s;m_getterName=g ;} wxPropertyAccessorT( getter_t getter, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( NULL ) , m_setter(NULL), m_setter_ref(NULL), m_getter(getter) ,m_getter_ref(NULL) {m_setterName = "";m_getterName=g ;} - wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetRetBool*,) setter_bool_t setter, getter_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetRetBool*,) setter_bool_t setter, getter_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( setter ) , m_setter_ref_bool( NULL ) , m_setter(NULL), m_setter_ref(NULL), m_getter(getter) , m_getter_ref(NULL){m_setterName = s;m_getterName=g ;} - wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetByRef*,) setter_ref_t setter, getter_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetByRef*,) setter_ref_t setter, getter_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( NULL ) , m_setter(NULL), m_setter_ref(setter), m_getter(getter) , m_getter_ref(NULL){m_setterName = s;m_getterName=g ;} - wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetByRefRetBool*,) setter_ref_bool_t setter, getter_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetByRefRetBool*,) setter_ref_bool_t setter, getter_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( setter ) , m_setter(NULL), m_setter_ref(NULL), m_getter(getter) , m_getter_ref(NULL){m_setterName = s;m_getterName=g ;} - wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetAndGetByRef*,) setter_ref_t setter, getter_ref_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetAndGetByRef*,) setter_ref_t setter, getter_ref_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( NULL ) , m_setter(NULL), m_setter_ref(setter), m_getter(NULL) , m_getter_ref(getter){m_setterName = s;m_getterName=g ;} - wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetAndGetByRefRetBool*,) setter_ref_bool_t setter, getter_ref_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(WX_XTI_PARAM_FIX(SetAndGetByRefRetBool*,) setter_ref_bool_t setter, getter_ref_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( setter ) , m_setter(NULL), m_setter_ref(NULL), m_getter(NULL) , m_getter_ref(getter){m_setterName = s;m_getterName=g ;} - wxPropertyAccessorT(WX_XTI_PARAM_FIX(GetByRef*,) setter_t setter, getter_ref_t getter, const wxChar *g, const wxChar *s) + wxPropertyAccessorT(WX_XTI_PARAM_FIX(GetByRef*,) setter_t setter, getter_ref_t getter, const wxChar *s, const wxChar *g) : m_setter_bool( NULL ) , m_setter_ref_bool( NULL ) , m_setter(NULL), m_setter(setter), m_getter(NULL) , m_getter_ref(getter){m_setterName = s;m_getterName=g ;} // returns true if this accessor has a setter @@ -560,6 +609,7 @@ public: // return true if this accessor has a getter bool HasGetter() const { return m_getter != NULL || m_getter_ref != NULL ; } + bool HasAdder() const { return true ; } // set the property this accessor is responsible for in an object void SetProperty(wxObject *o, const wxxVariant &v) const { @@ -624,31 +674,118 @@ private : getter_ref_t m_getter_ref ; }; +template +class WXDLLIMPEXP_BASE wxPropertyCollectionAccessorT : public wxPropertyAccessor +{ +public: + + typedef void (Klass::*adder_t)(AddedElementType value); + typedef const CollectionType& (Klass::*getter_t)() const ; + + wxPropertyCollectionAccessorT(adder_t adder, getter_t getter, const wxChar *a, const wxChar *g) + : m_getter(getter), m_adder(adder) { m_adderName = a;m_getterName=g ;} + + ~wxPropertyCollectionAccessorT() {} + + // returns true if this accessor has a setter + bool HasSetter() const { return false ;} + + // return true if this accessor has a getter + bool HasGetter() const { return m_getter != NULL ;} + + // return true if this accessor has a getter + bool HasAdder() const { return m_adder != NULL ;} + + // set the property this accessor is responsible for in an object + void AddToPropertyCollection(wxObject *o, const wxxVariant &v) const + { + Klass *obj = dynamic_cast(o); + AddedElementType value ; + + if ( wxGetTypeInfo((AddedElementType*)NULL)->GetKind() == wxT_OBJECT && v.GetTypeInfo()->GetKind() == wxT_OBJECT_PTR ) + value = *v.Get(); + else + value = v.Get(); + + if (m_adder) + (obj->*(m_adder))(value); + else + { + wxASSERT_MSG(0 , wxT("SetPropertyCalled without a valid Setter") ) ; + } + } + + // gets the property this accessor is responsible for from an object + wxxVariantArray GetPropertyCollection(const wxObject *o) const + { + const Klass *obj = dynamic_cast(o); + + wxxVariantArray result ; + CollectionType::compatibility_iterator current = (obj->*(m_getter))().GetFirst(); + while (current) + { + result.Add( new wxxVariant(current->GetData()) ) ; + current = current->GetNext(); + } + return result ; + } + + + // set the property this accessor is responsible for in an object + void SetProperty(wxObject *WXUNUSED(o), const wxxVariant &WXUNUSED(v)) const + { + wxASSERT_MSG(0,wxT("SetProperty called on Collection Property")) ; + } + + // gets the property this accessor is responsible for from an object + wxxVariant GetProperty(const wxObject *WXUNUSED(o)) const + { + wxASSERT_MSG(0,wxT("GetProperty called on Collection Property")) ; + return wxxVariant() ; + } + + // write the property this accessor is responsible for from an object into + // a string + void WriteValue( wxString& s , const wxObject *o ) const + { + wxASSERT_MSG(0,wxT("WriteValue called on Collection Property")) ; + } + + // read a wxxVariant having the correct type for the property this accessor + // is responsible for from a string + wxxVariant ReadValue( const wxString &value ) const + { + wxASSERT_MSG(0,wxT("ReadValue called on Collection Property")) ; + return wxxVariant() ; + } + +private : + getter_t m_getter; + adder_t m_adder; +}; + class WXDLLIMPEXP_BASE wxPropertyInfo { public : - wxPropertyInfo( wxPropertyInfo* &iter , const wxChar *name , const wxChar *typeName , const wxTypeInfo* typeInfo , wxPropertyAccessor *accessor , wxxVariant dv ) : - m_name( name ) , m_typeName(typeName) , m_typeInfo( typeInfo ) , m_accessor( accessor ) , m_defaultValue( dv ) + wxPropertyInfo( wxPropertyInfo* &iter , const wxChar *name , const wxTypeInfo* typeInfo , wxPropertyAccessor *accessor , wxxVariant dv ) : + m_name( name ) , m_typeInfo( typeInfo ) , m_accessor( accessor ) , m_defaultValue( dv ) , m_collectionElementTypeInfo(NULL) { - m_next = NULL ; - if ( iter == NULL ) - iter = this ; - else - { - wxPropertyInfo* i = iter ; - while( i->m_next ) - i = i->m_next ; + Insert(iter) ; + } - i->m_next = this ; - } + wxPropertyInfo( wxPropertyInfo* &iter , const wxChar *name , const wxTypeInfo* collTypeInfo , const wxTypeInfo* elemTypeInfo , wxPropertyAccessor *accessor ) : + m_name( name ) , m_typeInfo( collTypeInfo ) , m_accessor( accessor ) , m_collectionElementTypeInfo(elemTypeInfo) + { + Insert(iter) ; } + // return the name of this property const wxChar * GetName() const { return m_name ; } - // return the typename of this property - const wxChar * GetTypeName() const { return m_typeName ; } + // return the element type info of this property (for collections, otherwise NULL) + const wxTypeInfo * GetCollectionElementTypeInfo() const { return m_collectionElementTypeInfo ; } - // return the type info of this property + // return the type info of this property const wxTypeInfo * GetTypeInfo() const { return m_typeInfo ; } // return the accessor for this property @@ -660,9 +797,25 @@ public : // returns the default value of this property, its kind may be wxT_VOID if it is not valid wxxVariant GetDefaultValue() const { return m_defaultValue ; } private : + void Insert(wxPropertyInfo* &iter) + { + m_next = NULL ; + if ( iter == NULL ) + iter = this ; + else + { + wxPropertyInfo* i = iter ; + while( i->m_next ) + i = i->m_next ; + + i->m_next = this ; + } + } + const wxChar * m_name; const wxChar * m_typeName ; const wxTypeInfo* m_typeInfo ; + const wxTypeInfo* m_collectionElementTypeInfo ; wxPropertyAccessor* m_accessor ; wxxVariant m_defaultValue; // string representation of the default value @@ -685,29 +838,33 @@ private : #define WX_PROPERTY( name , type , setter , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( &setter , &getter , #setter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; #define WX_PROPERTY_SET_RET_BOOL( name , type , setter , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( (wxPropertyAccessor::SetRetBool*)NULL , &setter , &getter , #setter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; #define WX_PROPERTY_SET_BY_REF( name , type , setter , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( (wxPropertyAccessor::SetByRef*)NULL, &setter , &getter , #setter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; #define WX_PROPERTY_SET_BY_REF_RET_BOOL( name , type , setter , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( (wxPropertyAccessor::SetByRefRetBool*)NULL, &setter , &getter , #setter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; #define WX_PROPERTY_SET_AND_GET_BY_REF_RET_BOOL( name , type , setter , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( (wxPropertyAccessor::SetAndGetByRefRetBool*)NULL, &setter , &getter , #setter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; #else #define WX_PROPERTY( name , type , setter , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( &setter , &getter , #setter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + +#define WX_PROPERTY_COLLECTION( name , colltype , addelemtype , adder , getter ) \ + static wxPropertyCollectionAccessorT _accessor##name( &adder , &getter , #adder , #getter ) ; \ + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (colltype*) NULL ) ,wxGetTypeInfo( (addelemtype*) NULL ) ,&_accessor##name ) ; #define WX_PROPERTY_SET_RET_BOOL( name , type , setter , getter ,defaultValue ) \ WX_PROPERTY( name , type , setter , getter , defaultValue ) @@ -725,11 +882,11 @@ private : #define WX_READONLY_PROPERTY( name , type , getter ,defaultValue ) \ static wxPropertyAccessorT _accessor##name( &getter , #getter ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , #type , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; + static wxPropertyInfo _propertyInfo##name( first , #name , wxGetTypeInfo( (type*) NULL ) ,&_accessor##name , wxxVariant(defaultValue) ) ; #define WX_DELEGATE( name , eventType , eventClass ) \ static wxDelegateTypeInfo _typeInfo##name( eventType , CLASSINFO( eventClass ) ) ; \ - static wxPropertyInfo _propertyInfo##name( first , #name , NULL , &_typeInfo##name , NULL , wxxVariant() ) ; \ + static wxPropertyInfo _propertyInfo##name( first , #name , &_typeInfo##name , NULL , wxxVariant() ) ; \ // ---------------------------------------------------------------------------- // Handler Info @@ -1016,7 +1173,12 @@ public: virtual ~wxClassInfo() ; - virtual wxObject *CreateObject() const { return m_objectConstructor ? (*m_objectConstructor)() : 0; } + // allocates an instance of this class, this object does not have to be initialized or fully constructed + // as this call will be followed by a call to Create + virtual wxObject *AllocateObject() const { return m_objectConstructor ? (*m_objectConstructor)() : 0; } + + // 'old naming' for AllocateObject staying here for backward compatibility + wxObject *CreateObject() const { return AllocateObject() ; } const wxChar *GetClassName() const { return m_className; } const wxClassInfo **GetParents() const { return m_parents; } @@ -1060,7 +1222,8 @@ public: // returns the first handler const wxHandlerInfo* GetFirstHandler() const { return m_firstHandler ; } - // Call the Create method for a class + // Call the Create upon an instance of the class, in the end the object is fully + // initialized virtual void Create (wxObject *object, int ParamCount, wxxVariant *Params) const { wxASSERT_MSG( ParamCount == m_constructorPropertiesCount , wxT("Illegal Parameter Count for Create Method")) ; @@ -1070,12 +1233,16 @@ public: // get number of parameters for constructor virtual int GetCreateParamCount() const { return m_constructorPropertiesCount; } - // get i-th constructor parameter - virtual const wxChar* GetCreateParamName(int i) const { return m_constructorProperties[i] ; } + // get n-th constructor parameter + virtual const wxChar* GetCreateParamName(int n) const { return m_constructorProperties[n] ; } - // Runtime access to objects by property name, and variant data - virtual void SetProperty (wxObject *object, const wxChar *PropertyName, const wxxVariant &Value) const ; - virtual wxxVariant GetProperty (wxObject *object, const wxChar *PropertyName) const; + // Runtime access to objects for simple properties (get/set) by property name, and variant data + virtual void SetProperty (wxObject *object, const wxChar *propertyName, const wxxVariant &value) const ; + virtual wxxVariant GetProperty (wxObject *object, const wxChar *propertyName) const; + + // Runtime access to objects for collection properties by property name + virtual wxxVariantArray GetPropertyCollection(wxObject *object, const wxChar *propertyName) const ; + virtual void AddPropertyCollection(wxObject *object, const wxChar *propertyName , const wxxVariant& value) const ; // we must be able to cast variants to wxObject pointers, templates seem not to be suitable wxObject* VariantToInstance( wxxVariant &data ) const @@ -1157,7 +1324,7 @@ public : virtual ~wxDynamicClassInfo() ; // constructs a wxDynamicObject with an instance - virtual wxObject *CreateObject() const ; + virtual wxObject *AllocateObject() const ; // Call the Create method for a class virtual void Create (wxObject *object, int ParamCount, wxxVariant *Params) const ; diff --git a/include/wx/xtistrm.h b/include/wx/xtistrm.h index 2ac6ecf6fa..b12e0d2095 100644 --- a/include/wx/xtistrm.h +++ b/include/wx/xtistrm.h @@ -35,23 +35,43 @@ const int wxNullObjectID = -1 ; Main interfaces for streaming out objects. */ +// ---------------------------------------------------------------------------- +// wxPersister +// +// This class will be asked during the streaming-out process about every single +// property or object instance. It can veto streaming out by returning false +// or modify the value before it is streamed-out. +// ---------------------------------------------------------------------------- + +class wxWriter ; +class wxReader ; + class wxPersister { public : - // will be called before a toplevel object is written, may veto even that (eg for objects that cannot be supported) by returning false - virtual bool BeforeWriteObject( const wxObject *WXUNUSED(object) , const wxClassInfo *WXUNUSED(classInfo) , const wxString &WXUNUSED(name)) { return true ; } + // will be called before an object is written, may veto by returning false + virtual bool BeforeWriteObject( wxWriter *WXUNUSED(writer) , const wxObject *WXUNUSED(object) , const wxClassInfo *WXUNUSED(classInfo) ) { return true ; } + + // will be called after this object has been written, may be needed for adjusting stacks + virtual void AfterWriteObject( wxWriter *WXUNUSED(writer) , const wxObject *WXUNUSED(object) , const wxClassInfo *WXUNUSED(classInfo) ) {} // will be called before a property gets written, may change the value , eg replace a concrete wxSize by wxSize( -1 , -1 ) or veto // writing that property at all by returning false - virtual bool BeforeWriteProperty( const wxObject *WXUNUSED(object) , const wxClassInfo *WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(propInfo) , wxxVariant &WXUNUSED(value) ) { return true ; } + virtual bool BeforeWriteProperty( wxWriter *WXUNUSED(writer) , const wxPropertyInfo *WXUNUSED(propInfo) , wxxVariant &WXUNUSED(value) ) { return true ; } - // will be called before a property with an object value gets written, may change the value , eg replace the instance, void it or veto + // will be called before a property gets written, may change the value , eg replace a concrete wxSize by wxSize( -1 , -1 ) or veto // writing that property at all by returning false - virtual bool BeforeWritePropertyAsObject( const wxObject *WXUNUSED(object) , const wxClassInfo *WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(propInfo) , wxxVariant &WXUNUSED(value) ) { return true ; } + virtual bool BeforeWriteProperty( wxWriter *WXUNUSED(writer) , const wxPropertyInfo *WXUNUSED(propInfo) , wxxVariantArray &WXUNUSED(value) ) { return true ; } + + // will be called after a property has been written out, may be needed for adjusting stacks + virtual void AfterWriteProperty( wxWriter *WXUNUSED(writer) , const wxPropertyInfo *WXUNUSED(propInfo) ) {} + + // will be called before this delegate gets written + virtual bool BeforeWriteDelegate( wxWriter *WXUNUSED(writer) , const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(propInfo) , + const wxObject *&WXUNUSED(eventSink) , const wxHandlerInfo* &WXUNUSED(handlerInfo) ) { return true ; } - // will be called before a delegate property gets written, you may change all informations about the event sink - virtual bool BeforeWriteDelegate( const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(propInfo) , - const wxObject *&WXUNUSED(eventSink) , const wxHandlerInfo* &WXUNUSED(handlerInfo) ) { return true ; } + virtual void AfterWriteDelegate( wxWriter *WXUNUSED(writer) , const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *WXUNUSED(propInfo) , + const wxObject *&WXUNUSED(eventSink) , const wxHandlerInfo* &WXUNUSED(handlerInfo) ) { } } ; class wxWriter : public wxObject @@ -63,36 +83,53 @@ public : // with this call you start writing out a new top-level object void WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name ) ; + // + // Managing the object identity table a.k.a context + // + // these methods make sure that no object gets written twice, because sometimes multiple calls to the WriteObject will be + // made without wanting to have duplicate objects written, the object identity table will be reset manually + + virtual void ClearObjectContext() ; + + // gets the object Id for a passed in object in the context int GetObjectID(const wxObject *obj) ; - bool IsObjectKnown( const wxObject *obj ) ; + // returns true if this object has already been written in this context + bool IsObjectKnown( const wxObject *obj ) ; // // streaming callbacks // // these callbacks really write out the values in the stream format - // - // start of writing an toplevel object name param is used for unique identification within the container - virtual void DoBeginWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID , const wxString &name ) = 0 ; + // begins writing out a new toplevel entry which has the indicated unique name + virtual void DoBeginWriteTopLevelEntry( const wxString &name ) = 0 ; + + // ends writing out a new toplevel entry which has the indicated unique name + virtual void DoEndWriteTopLevelEntry( const wxString &name ) = 0 ; + + // start of writing an object having the passed in ID + virtual void DoBeginWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID ) = 0 ; // end of writing an toplevel object name param is used for unique identification within the container - virtual void DoEndWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID , const wxString &name ) = 0 ; + virtual void DoEndWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID ) = 0 ; + + // writes a simple property in the stream format + virtual void DoWriteSimpleType( wxxVariant &value ) = 0 ; - // start of writing an object used as param - virtual void DoBeginWriteParamAsObject(const wxObject *parentObject, const wxClassInfo *parentClassInfo, const wxObject *valueObject, - const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo ) = 0 ; + // start of writing a complex property into the stream ( + virtual void DoBeginWriteProperty( const wxPropertyInfo *propInfo ) = 0 ; - // end of writing an object used as param - virtual void DoEndWriteParamAsObject(const wxObject *parentObject, const wxClassInfo *parentClassInfo, const wxObject *valueObject, - const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo ) = 0 ; + // end of writing a complex property into the stream + virtual void DoEndWriteProperty( const wxPropertyInfo *propInfo ) = 0; - // insert an object reference to an already written object - virtual void DoWriteObjectReference(const wxObject *parentObject, const wxClassInfo *parentClassInfo, const wxObject *valueObject, - const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo ) = 0 ; + virtual void DoBeginWriteElement() = 0 ; + virtual void DoEndWriteElement() = 0 ; + // insert an object reference to an already written object + virtual void DoWriteRepeatedObject( int objectID ) = 0 ; - // writes a property in the stream format - virtual void DoWriteProperty( const wxObject *object, const wxClassInfo* classInfo , const wxPropertyInfo *propInfo , wxxVariant &value ) = 0 ; + // insert a null reference + virtual void DoWriteNullObject() = 0 ; // writes a delegate in the stream format virtual void DoWriteDelegate( const wxObject *object, const wxClassInfo* classInfo , const wxPropertyInfo *propInfo , @@ -105,6 +142,8 @@ private : struct wxWriterInternalPropertiesData ; void WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data ) ; + void WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded) ; + void FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) ; } ; class wxXmlWriter : public wxWriter @@ -120,30 +159,44 @@ public : // these callbacks really write out the values in the stream format // - // start of writing an toplevel object name param is used for unique identification within the container - virtual void DoBeginWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID , const wxString &name ) ; + // + // streaming callbacks + // + // these callbacks really write out the values in the stream format + + // begins writing out a new toplevel entry which has the indicated unique name + virtual void DoBeginWriteTopLevelEntry( const wxString &name ) ; + + // ends writing out a new toplevel entry which has the indicated unique name + virtual void DoEndWriteTopLevelEntry( const wxString &name ) ; + + // start of writing an object having the passed in ID + virtual void DoBeginWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID ) ; // end of writing an toplevel object name param is used for unique identification within the container - virtual void DoEndWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID , const wxString &name ) ; + virtual void DoEndWriteObject(const wxObject *object, const wxClassInfo *classInfo, int objectID ) ; + + // writes a simple property in the stream format + virtual void DoWriteSimpleType( wxxVariant &value ) ; + + // start of writing a complex property into the stream ( + virtual void DoBeginWriteProperty( const wxPropertyInfo *propInfo ) ; - // start of writing an object used as param - virtual void DoBeginWriteParamAsObject(const wxObject *parentObject, const wxClassInfo *parentClassInfo, const wxObject *valueObject, - const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo ) ; + // end of writing a complex property into the stream + virtual void DoEndWriteProperty( const wxPropertyInfo *propInfo ) ; - // end of writing an object used as param - virtual void DoEndWriteParamAsObject(const wxObject *parentObject, const wxClassInfo *parentClassInfo, const wxObject *valueObject, - const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo ) ; + virtual void DoBeginWriteElement() ; + virtual void DoEndWriteElement() ; - // insert an object reference to an already written object or to a null object - virtual void DoWriteObjectReference(const wxObject *parentObject, const wxClassInfo *parentClassInfo, const wxObject *valueObject, - const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo ) ; + // insert an object reference to an already written object + virtual void DoWriteRepeatedObject( int objectID ) ; - // writes a property in the stream format - virtual void DoWriteProperty( const wxObject *object, const wxClassInfo* classInfo , const wxPropertyInfo *propInfo , wxxVariant &value ) ; + // insert a null reference + virtual void DoWriteNullObject() ; // writes a delegate in the stream format virtual void DoWriteDelegate( const wxObject *object, const wxClassInfo* classInfo , const wxPropertyInfo *propInfo , - const wxObject *eventSink, int sinkObjectID , const wxClassInfo* eventSinkClassInfo , const wxHandlerInfo* handlerInfo ) ; + const wxObject *eventSink , int sinkObjectID , const wxClassInfo* eventSinkClassInfo , const wxHandlerInfo* handlerIndo ) ; private : struct wxXmlWriterInternal ; wxXmlWriterInternal* m_data ; @@ -174,7 +227,7 @@ public : // Reads the component the reader is pointed at from the underlying format. // The return value is the root object ID, which can // then be used to ask the depersister about that object - virtual int ReadObject( wxDepersister *depersist ) = 0 ; + virtual int ReadObject( const wxString &name , wxDepersister *depersist ) = 0 ; private : struct wxReaderInternal; @@ -194,7 +247,7 @@ public: // Reads a component from XML. The return value is the root object ID, which can // then be used to ask the depersister about that object - int ReadObject(wxDepersister *callbacks); + virtual int ReadObject( const wxString &name , wxDepersister *depersist ) ; private : int ReadComponent(wxXmlNode *parent, wxDepersister *callbacks); diff --git a/src/common/xti.cpp b/src/common/xti.cpp index 85d50e2eb8..23e5af6cf3 100644 --- a/src/common/xti.cpp +++ b/src/common/xti.cpp @@ -33,8 +33,10 @@ #if wxUSE_EXTENDED_RTTI +#include "wx/beforestd.h" #include #include +#include "wx/afterstd.h" using namespace std ; @@ -169,6 +171,12 @@ template<> const wxTypeInfo* wxGetTypeInfo( wxString * ) return &s_typeInfo ; } +template<> const wxTypeInfo* wxGetTypeInfo( wxWindowList * ) +{ + static wxCollectionTypeInfo s_typeInfo( (wxTypeInfo*) wxGetTypeInfo( (wxWindow **) NULL) ) ; + return &s_typeInfo ; +} + // this are compiler induced specialization which are never used anywhere WX_ILLEGAL_TYPE_SPECIALIZATION( char const * ) @@ -502,6 +510,24 @@ wxxVariant wxClassInfo::GetProperty(wxObject *object, const char *propertyName) return accessor->GetProperty(object); } +wxxVariantArray wxClassInfo::GetPropertyCollection(wxObject *object, const wxChar *propertyName) const +{ + const wxPropertyAccessor *accessor; + + accessor = FindAccessor(propertyName); + wxASSERT(accessor->HasGetter()); + return accessor->GetPropertyCollection(object); +} + +void wxClassInfo::AddPropertyCollection(wxObject *object, const wxChar *propertyName , const wxxVariant& value) const +{ + const wxPropertyAccessor *accessor; + + accessor = FindAccessor(propertyName); + wxASSERT(accessor->HasAdder()); + accessor->AddToPropertyCollection( object , value ) ; +} + /* VARIANT TO OBJECT */ @@ -570,9 +596,9 @@ wxDynamicClassInfo::~wxDynamicClassInfo() delete[] GetParents() ; } -wxObject *wxDynamicClassInfo::CreateObject() const +wxObject *wxDynamicClassInfo::AllocateObject() const { - wxObject* parent = GetParents()[0]->CreateObject() ; + wxObject* parent = GetParents()[0]->AllocateObject() ; return new wxDynamicObject( parent , this ) ; } @@ -617,7 +643,7 @@ wxxVariant wxDynamicClassInfo::GetProperty(wxObject *object, const char *propert void wxDynamicClassInfo::AddProperty( const wxChar *propertyName , const wxTypeInfo* typeInfo ) { - new wxPropertyInfo( m_firstProperty , propertyName , "" , typeInfo , new wxGenericPropertyAccessor( propertyName ) , wxxVariant() ) ; + new wxPropertyInfo( m_firstProperty , propertyName , typeInfo , new wxGenericPropertyAccessor( propertyName ) , wxxVariant() ) ; } void wxDynamicClassInfo::AddHandler( const wxChar *handlerName , wxObjectEventFunction address , const wxClassInfo* eventClassInfo ) diff --git a/src/common/xtistrm.cpp b/src/common/xtistrm.cpp index f94b2f6e9a..ccc44b4360 100644 --- a/src/common/xtistrm.cpp +++ b/src/common/xtistrm.cpp @@ -31,9 +31,12 @@ #include "wx/txtstrm.h" #if wxUSE_EXTENDED_RTTI + +#include "wx/beforestd.h" #include #include #include +#include "wx/afterstd.h" using namespace std ; @@ -59,76 +62,120 @@ struct wxWriter::wxWriterInternalPropertiesData map< string , int > m_writtenProperties ; } ; +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 ) { - if ( persister->BeforeWriteObject( object , classInfo , name ) ) + DoBeginWriteTopLevelEntry( name ) ; + WriteObject( object , classInfo , persister , false ) ; + DoEndWriteTopLevelEntry( name ) ; +} + +void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded) +{ + if ( persister->BeforeWriteObject( this , object , classInfo ) ) { - 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( object ) ; - if ( dynobj ) + if ( !isEmbedded && dynobj ) m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ; - DoBeginWriteObject( object , classInfo , oid , name ) ; + DoBeginWriteObject( object , classInfo , oid ) ; wxWriterInternalPropertiesData data ; WriteAllProperties( object , classInfo , persister , &data ) ; - DoEndWriteObject( object , classInfo , oid , name ) ; + DoEndWriteObject( object , classInfo , oid ) ; } + persister->AfterWriteObject( this ,object , classInfo ) ; } } +void wxWriter::FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) +{ + wxList *dynamicEvents = evSource->GetDynamicEventTable() ; + + 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(); + } + } +} void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data ) { const wxPropertyInfo *pi = ci->GetFirstProperty() ; while( pi ) { + // this property was not written yet in this object and we don't get a veto if ( data->m_writtenProperties.find( pi->GetName() ) == data->m_writtenProperties.end() ) { data->m_writtenProperties[ pi->GetName() ] = 1 ; - const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ; - if ( cti ) + DoBeginWriteProperty( pi ) ; + if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION ) { - const wxClassInfo* pci = cti->GetClassInfo() ; - wxxVariant value = pi->GetAccessor()->GetProperty(obj) ; - if ( persister->BeforeWritePropertyAsObject( obj , ci , pi , value ) ) + wxxVariantArray data = pi->GetAccessor()->GetPropertyCollection(obj) ; + const wxTypeInfo * elementType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() )->GetElementType() ; + for ( size_t i = 0 ; i < data.GetCount() ; ++i ) { - wxObject *vobj = pci->VariantToInstance( value ) ; - bool embeddedObject = cti->GetKind() == wxT_OBJECT ; - - if ( vobj == NULL || IsObjectKnown( vobj ) ) - { - DoWriteObjectReference( obj , ci , vobj , pci , GetObjectID(vobj) , pi ) ; - } - else + DoBeginWriteElement() ; + wxxVariant value = data[i] ; + if ( persister->BeforeWriteProperty( this , pi , value ) ) { - int oid = m_data->m_nextId++ ; - if ( !embeddedObject) + const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( elementType ) ; + if ( cti ) { - // 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( vobj ) ; - if ( dynobj ) - m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ; + const wxClassInfo* pci = cti->GetClassInfo() ; + wxObject *vobj = pci->VariantToInstance( value ) ; + WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT ) ; } - - DoBeginWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ; - if ( vobj != NULL ) - { - wxWriterInternalPropertiesData data ; - WriteAllProperties( vobj , pci , persister , &data ) ; + else + { + DoWriteSimpleType( value ) ; } - DoEndWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ; } + DoEndWriteElement() ; } } else @@ -138,46 +185,12 @@ void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci { const wxObject* sink = NULL ; const wxHandlerInfo *handler = NULL ; - + const wxWindow * evSource = dynamic_cast(obj) ; wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-Window) as Event Source") ) ; - wxList *dynamicEvents = evSource->GetDynamicEventTable() ; - - 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 ) ) + FindConnectEntry( evSource , dti , sink , handler ) ; + if ( persister->BeforeWriteDelegate( this , obj , ci , pi , sink , handler ) ) { if ( sink != NULL && handler != NULL ) { @@ -189,12 +202,23 @@ void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci else { wxxVariant value = pi->GetAccessor()->GetProperty(obj) ; - if ( persister->BeforeWriteProperty( obj , ci , pi , value ) ) + if ( persister->BeforeWriteProperty( this , pi , value ) ) { - DoWriteProperty( obj , ci , pi , value ) ; + const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ; + if ( cti ) + { + const wxClassInfo* pci = cti->GetClassInfo() ; + wxObject *vobj = pci->VariantToInstance( value ) ; + WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT ) ; + } + else + { + DoWriteSimpleType( value ) ; + } } } } + DoEndWriteProperty( pi ) ; } pi = pi->GetNext() ; } @@ -247,6 +271,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,74 +297,88 @@ 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 ) ; +} - m_data->m_current->AddChild(onode) ; - m_data->m_objectStack.push_back( m_data->m_current ) ; - m_data->m_current = onode ; +void wxXmlWriter::DoEndWriteTopLevelEntry( const wxString &WXUNUSED(name) ) +{ + m_data->Pop() ; +} + +void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID ) +{ + 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(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 , @@ -336,12 +386,7 @@ void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), const wxCl { 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()) ) ; } } @@ -402,32 +447,40 @@ 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 @@ -449,8 +502,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() ; } @@ -506,7 +561,41 @@ 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 ) + { + const wxTypeInfo * elementType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() )->GetElementType() ; + while( prop ) + { + wxASSERT_MSG(prop->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ; + wxXmlNode* elementContent = prop->GetChildren() ; + wxASSERT_MSG(elementContent, wxT("An element node cannot be empty")) ; + if ( elementType->IsObjectType() ) + { + int valueId = ReadComponent( elementContent , callbacks ) ; + if ( callbacks ) + { + if ( valueId != wxInvalidObjectID ) + { + /* + callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ; + */ + if ( elementType->GetKind() == wxT_OBJECT && valueId != wxNullObjectID ) + callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ; + } + } + } + else + { + wxxVariant elementValue = ReadValue( prop , pi->GetAccessor() ) ; + /* + if ( callbacks ) + callbacks->SetProperty( objectID, classInfo ,pi , ) ; + */ + } + prop = prop->GetNext() ; + } + } + else if ( pi->GetTypeInfo()->IsObjectType() ) { int valueId = ReadComponent( prop , callbacks ) ; if ( callbacks ) @@ -521,16 +610,19 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks) } 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) - callbacks->SetConnect( objectID , classInfo , dynamic_cast(pi->GetTypeInfo()) , sinkClassInfo , - sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ; + 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 ) ; + + if (callbacks) + callbacks->SetConnect( objectID , classInfo , dynamic_cast(pi->GetTypeInfo()) , sinkClassInfo , + sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ; + } } else @@ -552,12 +644,26 @@ int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks) wxxVariant wxXmlReader::ReadValue(wxXmlNode *node, wxPropertyAccessor *accessor ) { - return accessor->ReadValue(wxXmlGetContentFromNode( node ) ) ; + wxString content ; + if ( node ) + content = node->GetContent() ; + return accessor->ReadValue(content) ; } -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 ; } // ---------------------------------------------------------------------------- @@ -664,8 +770,8 @@ void wxRuntimeDepersister::SetPropertyAsObject(int objectID, } classInfo->SetProperty( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ; -// propertyInfo->GetAccessor()->SetProperty( o , -// (dynamic_cast(propertyInfo->GetTypeInfo()))->GetClassInfo()->InstanceToVariant(valo) ) ; + // propertyInfo->GetAccessor()->SetProperty( o , + // (dynamic_cast(propertyInfo->GetTypeInfo()))->GetClassInfo()->InstanceToVariant(valo) ) ; } void wxRuntimeDepersister::SetConnect(int eventSourceObjectID, @@ -832,4 +938,8 @@ void wxCodeDepersister::SetConnect(int eventSourceObjectID, ehsource , ehsource , eventType , ehsinkClass , handlerName , ehsink ) ); } +#include + +WX_DEFINE_OBJARRAY(wxxVariantArray); + #endif