From: Stefan Csomor Date: Sat, 23 Aug 2003 19:40:04 +0000 (+0000) Subject: redistribution of code for different library parts X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/9c8046dded47cbd3e9b9c83051ba0530ac3b9491 redistribution of code for different library parts git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23142 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/flags.h b/include/wx/flags.h index ec14d2c2b9..94c1e265d5 100644 --- a/include/wx/flags.h +++ b/include/wx/flags.h @@ -16,101 +16,147 @@ #pragma interface "flags.h" #endif +#include + // wxFlags should be applied to an enum, then this can be used like // bitwise operators but keeps the type safety and information, the // enums must be in a sequence , their value determines the bit position // that they represent +// The api is made as close as possible to template class wxFlags { friend class wxEnumData ; public: - wxFlags(long val) { m_data = val ; } + // creates a wxFlags<> object with all flags initialized to 0 wxFlags() { m_data = 0; } + + // created a wxFlags<> object initialized according to the bits of the + // integral value val + wxFlags(unsigned long val) { m_data = val ; } + + // copies the content in the new wxFlags<> object from another one wxFlags(const wxFlags &src) { m_data = src.m_data; } + + // creates a wxFlags<> object that has the specific flag set wxFlags(const T el) { m_data |= 1 << el; } - operator long() const { return m_data ; } + // returns the integral value that the bits of this object represent + unsigned long to_ulong() const { return m_data ; } + // assignment wxFlags &operator =(const wxFlags &rhs) { m_data = rhs.m_data; return *this; } - wxFlags &operator +=(const wxFlags &rhs) // union + + // bitwise or operator, sets all bits that are in rhs and leaves + // the rest unchanged + wxFlags &operator |=(const wxFlags &rhs) { m_data |= rhs.m_data; return *this; } - wxFlags &operator -=(const wxFlags &rhs) // difference + + // bitwsie exclusive-or operator, toggles the value of all bits + // that are set in bits and leaves all others unchanged + wxFlags &operator ^=(const wxFlags &rhs) // difference { m_data ^= rhs.m_data; return *this; } - wxFlags &operator *=(const wxFlags &rhs) // intersection + // bitwise and operator, resets all bits that are not in rhs and leaves + // all others unchanged + wxFlags &operator &=(const wxFlags &rhs) // intersection { m_data &= rhs.m_data; return *this; } - wxFlags operator +(const wxFlags &rhs) const // union + // bitwise or operator, returns a new bitset that has all bits set that set are in + // bitset2 or in this bitset + wxFlags operator |(const wxFlags &bitset2) const // union { wxFlags s; - s.m_data = m_data | rhs.m_data; + s.m_data = m_data | bitset2.m_data; return s; } - wxFlags operator -(const wxFlags &rhs) const // difference + + // bitwise exclusive-or operator, returns a new bitset that has all bits set that are set either in + // bitset2 or in this bitset but not in both + wxFlags operator ^(const wxFlags &bitset2) const // difference { wxFlags s; - s.m_data = m_data ^ rhs.m_data; + s.m_data = m_data ^ bitset2.m_data; return s; } - wxFlags operator *(const wxFlags &rhs) const // intersection + + // bitwise and operator, returns a new bitset that has all bits set that are set both in + // bitset2 and in this bitset + wxFlags operator &(const wxFlags &bitset2) const // intersection { wxFlags s; - s.m_data = m_data & rhs.m_data; + s.m_data = m_data & bitset2.m_data; return s; } - wxFlags& Set(const T el) //Add element + // sets appropriate the bit to true + wxFlags& set(const T el) //Add element { m_data |= 1 << el; return *this; } - wxFlags& Clear(const T el) //remove element + + // clears the appropriate flag to false + wxFlags& reset(const T el) //remove element { m_data &= ~(1 << el); return *this; } - bool Contains(const T el) const + // clear all flags + wxFlags& reset() { - return (m_data & (1 << el)) ? true : false; + m_data = 0; + return *this; } - wxFlags &Clear() + // true if this flag is set + bool test(const T el) const { - m_data = 0; - return *this; + return (m_data & (1 << el)) ? true : false; } - bool Empty() const + // true if no flag is set + bool none() const { return m_data == 0; } + // true if any flag is set + bool any() const + { + return m_data != 0; + } + + // true if both have the same flags bool operator ==(const wxFlags &rhs) const { return m_data == rhs.m_data; } + // true if both differ in their flags set bool operator !=(const wxFlags &rhs) const { return !operator==(rhs); } + + bool operator[] (const T el) const { return test(el) ; } + private : - int m_data; + unsigned long m_data; }; diff --git a/include/wx/xti.h b/include/wx/xti.h index 558b77c389..0477ea5f64 100644 --- a/include/wx/xti.h +++ b/include/wx/xti.h @@ -167,7 +167,7 @@ template void wxSetFromString(const wxString &s , wxFlags &data ) { wxEnumData* edata = wxGetEnumData((e) 0) ; - data.Clear() ; + data.reset() ; wxArrayString array ; wxSetStringToArray( s , array ) ; @@ -178,7 +178,7 @@ void wxSetFromString(const wxString &s , wxFlags &data ) int ivalue ; if ( edata->HasEnumMemberValue( flag , &ivalue ) ) { - data.Set( (e) ivalue ) ; + data.set( (e) ivalue ) ; } } } @@ -193,7 +193,7 @@ void wxSetToString( wxString &s , const wxFlags &data ) for ( i = 0 ; i < count ; i++ ) { e value = (e) edata->GetEnumMemberValueByIndex(i) ; - if ( data.Contains( value ) ) + if ( data.test( value ) ) { // this could also be done by the templated calls if ( !s.IsEmpty() ) @@ -215,8 +215,8 @@ void wxSetToString( wxString &s , const wxFlags &data ) { \ wxSetToString( s , data ) ; \ } \ - void FromLong##SetName( long data , wxxVariant& result ) { result = wxxVariant(SetName(data)) ;} \ - void ToLong##SetName( const wxxVariant& data , long &result ) { result = (long) data.Get() ;} \ + void FromLong##SetName( long data , wxxVariant& result ) { result = wxxVariant(SetName((unsigned long)data)) ;} \ + void ToLong##SetName( const wxxVariant& data , long &result ) { result = (long) data.Get().to_ulong() ;} \ template<> const wxTypeInfo* wxGetTypeInfo( SetName * ) \ { \ static wxEnumTypeInfo s_typeInfo(wxT_SET , &s_enumData##e , &wxToStringConverter , &wxFromStringConverter , &ToLong##SetName , &FromLong##SetName, #SetName ) ; return &s_typeInfo ; \ @@ -749,6 +749,8 @@ enum { wxPROP_OBJECT_GRAPH = 0x00000002 , // this will only be streamed out and in as enum/set, the internal representation is still a long wxPROP_ENUM_STORE_LONG = 0x00000004 , + // don't stream out this property, needed eg to avoid streaming out children that are always created by their parents + wxPROP_DONT_STREAM = 0x00000008 , } ; class WXDLLIMPEXP_BASE wxPropertyInfo @@ -838,7 +840,8 @@ WX_DECLARE_EXPORTED_STRING_HASH_MAP( wxPropertyInfo* , wxPropertyInfoMap ) ; #define WX_END_PROPERTIES_TABLE() \ return first ; } - +#define WX_HIDE_PROPERTY( name ) \ + static wxPropertyInfo _propertyInfo##name( first , class_t::GetClassInfoStatic() , #name , wxGetTypeInfo( (void*) NULL ) ,NULL , wxxVariant() , wxPROP_DONT_STREAM , wxEmptyString , wxEmptyString ) ; #define WX_PROPERTY( name , type , setter , getter ,defaultValue , flags , help , group) \ WX_SETTER( name , class_t , type , setter ) \ @@ -1192,6 +1195,9 @@ struct wxConstructorBridge_8 : public wxConstructorBridge typedef wxObject *(*wxObjectConstructorFn)(void); typedef wxObject* (*wxVariantToObjectConverter)( wxxVariant &data ) ; typedef wxxVariant (*wxObjectToVariantConverter)( wxObject* ) ; +class wxWriter ; +class wxPersister ; +typedef bool (*wxObjectStreamingCallback) ( const wxObject *, wxWriter * , wxPersister * , wxxVariantArray & ) ; class WXDLLIMPEXP_BASE wxClassInfo { @@ -1208,11 +1214,13 @@ public: const int _ConstructorPropertiesCount , wxVariantToObjectConverter _PtrConverter1 , wxVariantToObjectConverter _Converter2 , - wxObjectToVariantConverter _Converter3 + wxObjectToVariantConverter _Converter3 , + wxObjectStreamingCallback _streamingCallback = NULL ) : m_parents(_Parents) , m_unitName(_UnitName) ,m_className(_ClassName), m_objectSize(size), m_objectConstructor(ctor) , m_firstProperty(_Props ) , m_firstHandler(_Handlers ) , m_constructor( _Constructor ) , m_constructorProperties(_ConstructorProperties) , m_constructorPropertiesCount(_ConstructorPropertiesCount), - m_variantOfPtrToObjectConverter( _PtrConverter1 ) , m_variantToObjectConverter( _Converter2 ) , m_objectToVariantConverter( _Converter3 ) , m_next(sm_first) + m_variantOfPtrToObjectConverter( _PtrConverter1 ) , m_variantToObjectConverter( _Converter2 ) , m_objectToVariantConverter( _Converter3 ) , + m_next(sm_first) , m_streamingCallback( _streamingCallback ) { sm_first = this; Register() ; @@ -1221,7 +1229,8 @@ public: wxClassInfo(const wxChar *_UnitName, const wxChar *_ClassName, const wxClassInfo **_Parents) : m_parents(_Parents) , m_unitName(_UnitName) ,m_className(_ClassName), m_objectSize(0), m_objectConstructor(NULL) , m_firstProperty(NULL ) , m_firstHandler(NULL ) , m_constructor( NULL ) , m_constructorProperties(NULL) , m_constructorPropertiesCount(NULL), - m_variantOfPtrToObjectConverter( NULL ) , m_variantToObjectConverter( NULL ) , m_objectToVariantConverter( NULL ) , m_next(sm_first) + m_variantOfPtrToObjectConverter( NULL ) , m_variantToObjectConverter( NULL ) , m_objectToVariantConverter( NULL ) , m_next(sm_first) , + m_streamingCallback( NULL ) { sm_first = this; Register() ; @@ -1237,6 +1246,7 @@ public: wxObject *CreateObject() const { return AllocateObject() ; } const wxChar *GetClassName() const { return m_className; } + const wxChar *GetIncludeName() const { return m_unitName ; } const wxClassInfo **GetParents() const { return m_parents; } int GetSize() const { return m_objectSize; } @@ -1264,6 +1274,15 @@ public: return false ; } + // if there is a callback registered with that class it will be called before this + // object will be written to disk, it can veto streaming out this object by returning + // false, if this class has not registered a callback, the search will go up the inheritance tree + // if no callback has been registered true will be returned by default + bool BeforeWriteObject( const wxObject *obj, wxWriter *streamer , wxPersister *persister , wxxVariantArray &metadata) const ; + + // gets the streaming callback from this class or any superclass + wxObjectStreamingCallback GetStreamingCallback() const ; + #ifdef WXWIN_COMPATIBILITY_2_4 // Initializes parent pointers and hash table for fast searching. wxDEPRECATED( static void InitializeClasses() ); @@ -1353,7 +1372,7 @@ private: wxVariantToObjectConverter m_variantOfPtrToObjectConverter ; wxVariantToObjectConverter m_variantToObjectConverter ; wxObjectToVariantConverter m_objectToVariantConverter ; - + wxObjectStreamingCallback m_streamingCallback ; const wxPropertyAccessor *FindAccessor (const wxChar *propertyName) const ; @@ -1441,7 +1460,7 @@ public : // Single inheritance with one base class -#define _IMPLEMENT_DYNAMIC_CLASS(name, basename, unit) \ +#define _IMPLEMENT_DYNAMIC_CLASS(name, basename, unit , callback) \ wxObject* wxConstructorFor##name() \ { return new name; } \ const wxClassInfo* name::sm_classParents##name[] = { &basename::sm_class##basename ,NULL } ; \ @@ -1451,7 +1470,7 @@ public : (int) sizeof(name), \ (wxObjectConstructorFn) wxConstructorFor##name , \ name::GetPropertiesStatic(),name::GetHandlersStatic(),name::sm_constructor##name , name::sm_constructorProperties##name , \ - name::sm_constructorPropertiesCount##name , wxVariantOfPtrToObjectConverter##name , NULL , wxObjectToVariantConverter##name); \ + name::sm_constructorPropertiesCount##name , wxVariantOfPtrToObjectConverter##name , NULL , wxObjectToVariantConverter##name , callback); \ template<> void wxStringReadValue(const wxString & , name & ){wxASSERT_MSG( 0 , wxT("Illegal Spezialication Called") ) ;}\ template<> void wxStringWriteValue(wxString & , name const & ){wxASSERT_MSG( 0 , wxT("Illegal Spezialication Called") );}\ template<> void wxStringReadValue(const wxString & , name * & ){wxASSERT_MSG( 0 , wxT("Illegal Spezialication Called") ) ;}\ @@ -1462,7 +1481,7 @@ public : template<> const wxTypeInfo* wxGetTypeInfo( name * ){ static wxClassTypeInfo s_typeInfo(wxT_OBJECT , &name::sm_class##name) ; return &s_typeInfo ; } \ template<> const wxTypeInfo* wxGetTypeInfo( name ** ){ static wxClassTypeInfo s_typeInfo(wxT_OBJECT_PTR , &name::sm_class##name) ; return &s_typeInfo ; } -#define _IMPLEMENT_DYNAMIC_CLASS_WITH_COPY(name, basename, unit) \ +#define _IMPLEMENT_DYNAMIC_CLASS_WITH_COPY(name, basename, unit, callback ) \ wxObject* wxConstructorFor##name() \ { return new name; } \ const wxClassInfo* name::sm_classParents##name[] = { &basename::sm_class##basename ,NULL } ; \ @@ -1473,7 +1492,7 @@ public : (int) sizeof(name), \ (wxObjectConstructorFn) wxConstructorFor##name , \ name::GetPropertiesStatic(),name::GetHandlersStatic(),name::sm_constructor##name , name::sm_constructorProperties##name , \ - name::sm_constructorPropertiesCount##name , wxVariantOfPtrToObjectConverter##name , wxVariantToObjectConverter##name , wxObjectToVariantConverter##name); \ + name::sm_constructorPropertiesCount##name , wxVariantOfPtrToObjectConverter##name , wxVariantToObjectConverter##name , wxObjectToVariantConverter##name, callback); \ template<> void wxStringReadValue(const wxString & , name & ){wxASSERT_MSG( 0 , wxT("Illegal Spezialication Called") ) ;}\ template<> void wxStringWriteValue(wxString & , name const & ){wxASSERT_MSG( 0 , wxT("Illegal Spezialication Called") );}\ template<> void wxStringReadValue(const wxString & , name * & ){wxASSERT_MSG( 0 , wxT("Illegal Spezialication Called") ) ;}\ @@ -1485,22 +1504,25 @@ public : template<> const wxTypeInfo* wxGetTypeInfo( name ** ){ static wxClassTypeInfo s_typeInfo(wxT_OBJECT_PTR , &name::sm_class##name) ; return &s_typeInfo ; } #define IMPLEMENT_DYNAMIC_CLASS_WITH_COPY( name , basename ) \ - _IMPLEMENT_DYNAMIC_CLASS_WITH_COPY( name , basename , "" ) \ + _IMPLEMENT_DYNAMIC_CLASS_WITH_COPY( name , basename , "" , NULL ) \ const wxPropertyInfo *name::GetPropertiesStatic() { return (wxPropertyInfo*) NULL ; } \ const wxHandlerInfo *name::GetHandlersStatic() { return (wxHandlerInfo*) NULL ; } \ WX_CONSTRUCTOR_DUMMY( name ) #define IMPLEMENT_DYNAMIC_CLASS( name , basename ) \ - _IMPLEMENT_DYNAMIC_CLASS( name , basename , "" ) \ + _IMPLEMENT_DYNAMIC_CLASS( name , basename , "" , NULL ) \ wxPropertyInfo *name::GetPropertiesStatic() { return (wxPropertyInfo*) NULL ; } \ wxHandlerInfo *name::GetHandlersStatic() { return (wxHandlerInfo*) NULL ; } \ WX_CONSTRUCTOR_DUMMY( name ) #define IMPLEMENT_DYNAMIC_CLASS_XTI( name , basename , unit ) \ - _IMPLEMENT_DYNAMIC_CLASS( name , basename , unit ) + _IMPLEMENT_DYNAMIC_CLASS( name , basename , unit , NULL ) + +#define IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK( name , basename , unit , callback ) \ + _IMPLEMENT_DYNAMIC_CLASS( name , basename , unit , &callback ) #define IMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI( name , basename , unit ) \ - _IMPLEMENT_DYNAMIC_CLASS_WITH_COPY( name , basename , unit ) + _IMPLEMENT_DYNAMIC_CLASS_WITH_COPY( name , basename , unit , NULL ) // this is for classes that do not derive from wxobject, there are no creators for these diff --git a/include/wx/xtistrm.h b/include/wx/xtistrm.h index b2dd547658..876f6ab0c4 100644 --- a/include/wx/xtistrm.h +++ b/include/wx/xtistrm.h @@ -144,64 +144,9 @@ private : void WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data ) ; void WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , const wxPropertyInfo* pi , wxPersister *persister , wxWriterInternalPropertiesData *data ) ; void WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded, wxxVariantArray &metadata ) ; - void FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) ; + void FindConnectEntry(const wxEvtHandler * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) ; } ; -class wxXmlWriter : public wxWriter -{ -public : - - wxXmlWriter( wxXmlNode * parent ) ; - ~wxXmlWriter() ; - - // - // streaming callbacks - // - // these callbacks really write out the values in the stream format - // - - // - // 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 , wxxVariantArray &metadata ) ; - - // 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 ) ; - - // 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 ) ; - - // end of writing a complex property into the stream - virtual void DoEndWriteProperty( const wxPropertyInfo *propInfo ) ; - - virtual void DoBeginWriteElement() ; - virtual void DoEndWriteElement() ; - - // insert an object reference to an already written object - virtual void DoWriteRepeatedObject( int objectID ) ; - - // 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* handlerIndo ) ; -private : - struct wxXmlWriterInternal ; - wxXmlWriterInternal* m_data ; -} ; /* Streaming callbacks for depersisting XML to code, or running objects @@ -235,31 +180,6 @@ private : wxReaderInternal *m_data; } ; -/* -wxXmlReader handles streaming in a class from XML -*/ - -class wxXmlReader : public wxReader -{ -public: - wxXmlReader(wxXmlNode *parent) { m_parent = parent ; } - ~wxXmlReader() {} - - // 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 - - virtual int ReadObject( const wxString &name , wxDepersister *depersist ) ; - -private : - int ReadComponent(wxXmlNode *parent, wxDepersister *callbacks); - - // read the content of this node (simple type) and return the corresponding value - wxxVariant ReadValue(wxXmlNode *Node, - const wxTypeInfo *type ); - - wxXmlNode * m_parent ; -}; - // This abstract class matches the allocate-init/create model of creation of objects. // At runtime, these will create actual instances, and manipulate them. // When generating code, these will just create statements of C++ diff --git a/include/wx/xtixml.h b/include/wx/xtixml.h new file mode 100644 index 0000000000..a61129dfcb --- /dev/null +++ b/include/wx/xtixml.h @@ -0,0 +1,110 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/xtixml.h +// Purpose: xml streaming runtime metadata information (extended class info) +// Author: Stefan Csomor +// Modified by: +// Created: 27/07/03 +// RCS-ID: $Id$ +// Copyright: (c) 2003 Stefan Csomor +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_XTIXMLH__ +#define _WX_XTIXMLH__ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) +#pragma interface "xtixml.h" +#endif + +#include "wx/wx.h" + +#if wxUSE_EXTENDED_RTTI + +#include "wx/xtistrm.h" + +class wxXmlNode ; + +class wxXmlWriter : public wxWriter +{ +public : + + wxXmlWriter( wxXmlNode * parent ) ; + ~wxXmlWriter() ; + + // + // streaming callbacks + // + // these callbacks really write out the values in the stream format + // + + // + // 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 , wxxVariantArray &metadata ) ; + + // 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 ) ; + + // 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 ) ; + + // end of writing a complex property into the stream + virtual void DoEndWriteProperty( const wxPropertyInfo *propInfo ) ; + + virtual void DoBeginWriteElement() ; + virtual void DoEndWriteElement() ; + + // insert an object reference to an already written object + virtual void DoWriteRepeatedObject( int objectID ) ; + + // 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* handlerIndo ) ; +private : + struct wxXmlWriterInternal ; + wxXmlWriterInternal* m_data ; +} ; + +/* +wxXmlReader handles streaming in a class from XML +*/ + +class wxXmlReader : public wxReader +{ +public: + wxXmlReader(wxXmlNode *parent) { m_parent = parent ; } + ~wxXmlReader() {} + + // 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 + + virtual int ReadObject( const wxString &name , wxDepersister *depersist ) ; + +private : + int ReadComponent(wxXmlNode *parent, wxDepersister *callbacks); + + // read the content of this node (simple type) and return the corresponding value + wxxVariant ReadValue(wxXmlNode *Node, + const wxTypeInfo *type ); + + wxXmlNode * m_parent ; +}; + +#endif // wxUSE_EXTENDED_RTTI + +#endif diff --git a/src/common/xti.cpp b/src/common/xti.cpp index 0b188a042e..aacc0dbb35 100644 --- a/src/common/xti.cpp +++ b/src/common/xti.cpp @@ -316,10 +316,6 @@ WX_ILLEGAL_TYPE_SPECIALIZATION( bool * ) WX_ILLEGAL_TYPE_SPECIALIZATION( long * ) WX_ILLEGAL_TYPE_SPECIALIZATION( wxString * ) -// - -// make wxWindowList known - WX_COLLECTION_TYPE_INFO( wxString , wxArrayString ) ; template<> void wxCollectionToVariantArray( wxArrayString const &theArray, wxxVariantArray &value) @@ -445,6 +441,28 @@ const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const char *PropertyName) con return 0; } +wxObjectStreamingCallback wxClassInfo::GetStreamingCallback() const +{ + if ( m_streamingCallback ) + return m_streamingCallback ; + + wxObjectStreamingCallback retval = NULL ; + const wxClassInfo** parents = GetParents() ; + for ( int i = 0 ; parents[i] && retval == NULL ; ++ i ) + { + retval = parents[i]->GetStreamingCallback() ; + } + return retval ; +} + +bool wxClassInfo::BeforeWriteObject( const wxObject *obj, wxWriter *streamer , wxPersister *persister , wxxVariantArray &metadata) const +{ + wxObjectStreamingCallback sb = GetStreamingCallback() ; + if ( sb ) + return (*sb)(obj , streamer , persister , metadata ) ; + + return true ; +} void wxClassInfo::SetProperty(wxObject *object, const char *propertyName, const wxxVariant &value) const { diff --git a/src/common/xtistrm.cpp b/src/common/xtistrm.cpp index 372602c376..bdd76724bd 100644 --- a/src/common/xtistrm.cpp +++ b/src/common/xtistrm.cpp @@ -25,10 +25,10 @@ #include "wx/object.h" #endif -#include "wx/xml/xml.h" #include "wx/tokenzr.h" #include "wx/xtistrm.h" #include "wx/txtstrm.h" +#include "wx/event.h" #if wxUSE_EXTENDED_RTTI @@ -78,11 +78,7 @@ void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo 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(object) ; - if ( win && win->GetId() < 0 ) + if ( !classInfo->BeforeWriteObject( object , this , persister , metadata) ) return ; if ( persister->BeforeWriteObject( this , object , classInfo , metadata) ) @@ -112,7 +108,7 @@ void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo } } -void wxWriter::FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) +void wxWriter::FindConnectEntry(const wxEvtHandler * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) { wxList *dynamicEvents = evSource->GetDynamicEventTable() ; @@ -124,13 +120,10 @@ void wxWriter::FindConnectEntry(const wxWindow * evSource,const wxDelegateTypeIn 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 - ) + if ( entry->m_fn && + (dti->GetEventType() == entry->m_eventType) && + (entry->m_id == -1 ) && + (entry->m_eventSink != NULL ) ) { sink = entry->m_eventSink ; const wxClassInfo* sinkClassInfo = sink->GetClassInfo() ; @@ -182,8 +175,11 @@ void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci } } -void wxWriter::WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , const wxPropertyInfo* pi , wxPersister *persister , wxWriterInternalPropertiesData *data ) +void wxWriter::WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , const wxPropertyInfo* pi , wxPersister *persister , wxWriterInternalPropertiesData *WXUNUSED(data) ) { + if ( pi->GetFlags() & wxPROP_DONT_STREAM ) + return ; + // 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(ci) == NULL) ) @@ -225,8 +221,8 @@ void wxWriter::WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , c 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") ) ; + const wxEvtHandler * evSource = dynamic_cast(obj) ; + wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-wxEvtHandler) as Event Source") ) ; FindConnectEntry( evSource , dti , sink , handler ) ; if ( persister->BeforeWriteDelegate( this , obj , ci , pi , sink , handler ) ) @@ -281,152 +277,6 @@ bool wxWriter::IsObjectKnown( const wxObject *obj ) return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ; } -// -// XML Streaming -// - -// convenience functions - -void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data ) -{ - node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) ); -} - -wxString wxXmlGetContentFromNode( wxXmlNode *node ) -{ - if ( node->GetChildren() ) - return node->GetChildren()->GetContent() ; - else - return wxEmptyString ; -} - -struct wxXmlWriter::wxXmlWriterInternal -{ - wxXmlNode *m_root ; - wxXmlNode *m_current ; - vector< wxXmlNode * > m_objectStack ; - - 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 ) -{ - m_data = new wxXmlWriterInternal() ; - m_data->m_root = rootnode ; - m_data->m_current = rootnode ; -} - -wxXmlWriter::~wxXmlWriter() -{ - delete m_data ; -} - -void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString &name ) -{ - 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 ) ); - - 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) ) -{ - m_data->Pop() ; -} - -// writes a property in the stream format -void wxXmlWriter::DoWriteSimpleType( wxxVariant &value ) -{ - wxXmlAddContentToNode( m_data->m_current ,value.GetAsString() ) ; -} - -void wxXmlWriter::DoBeginWriteElement() -{ - wxXmlNode *pnode; - pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "element" ); - m_data->m_current->AddChild(pnode) ; - m_data->Push( pnode ) ; -} - -void wxXmlWriter::DoEndWriteElement() -{ - m_data->Pop() ; -} - -void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo *pi ) -{ - 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 ) ; -} - -void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo *WXUNUSED(propInfo) ) -{ - m_data->Pop() ; -} - - - -// insert an object reference to an already written object -void wxXmlWriter::DoWriteRepeatedObject( int objectID ) -{ - 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 *WXUNUSED(pi) , - const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo ) -{ - if ( eventSink != NULL && handlerInfo != NULL ) - { - wxXmlAddContentToNode( m_data->m_current ,wxString::Format(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName()) ) ; - } -} // ---------------------------------------------------------------------------- // reading objects in @@ -475,252 +325,6 @@ as properties are always sought by typeinfo over all levels 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; - - wxxVariant *createParams ; - int *createParamOids ; - 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); - 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 - 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 ) ; - - 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 - createParams = new wxxVariant[ classInfo->GetCreateParamCount() ] ; - createParamOids = new int[classInfo->GetCreateParamCount() ] ; - createClassInfos = new const wxClassInfo*[classInfo->GetCreateParamCount() ] ; - - typedef map PropertyNodes ; - typedef vector PropertyNames ; - - PropertyNodes propertyNodes ; - PropertyNames propertyNames ; - - while( children ) - { - wxString name ; - children->GetPropVal( wxT("name") , &name ) ; - propertyNames.push_back( name.c_str() ) ; - propertyNodes[name.c_str()] = children->GetChildren() ; - children = children->GetNext() ; - } - - for ( int i = 0 ; i GetCreateParamCount() ; ++i ) - { - 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() ) - { - wxXmlNode* prop = propiter->second ; - if ( pi->GetTypeInfo()->IsObjectType() ) - { - createParamOids[i] = ReadComponent( prop , callbacks ) ; - createClassInfos[i] = dynamic_cast(pi->GetTypeInfo())->GetClassInfo() ; - } - else - { - createParamOids[i] = wxInvalidObjectID ; - createParams[i] = ReadValue( prop , pi->GetTypeInfo() ) ; - if( pi->GetFlags() & wxPROP_ENUM_STORE_LONG ) - { - const wxEnumTypeInfo *eti = dynamic_cast( 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 ; - } - - for ( size_t j = 0 ; j < propertyNames.size() ; ++j ) - { - if ( propertyNames[j] == paramName ) - { - propertyNames[j] = "" ; - break ; - } - } - } - else - { - createParams[i] = pi->GetDefaultValue() ; - } - } - - // got the parameters. Call the Create method - callbacks->CreateObject(objectID, classInfo, - classInfo->GetCreateParamCount(), - 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 ) - { - if ( propertyNames[j].length() ) - { - PropertyNodes::iterator propiter = propertyNodes.find( propertyNames[j] ) ; - if ( propiter != propertyNodes.end() ) - { - wxXmlNode* prop = propiter->second ; - const wxPropertyInfo* pi = classInfo->FindPropertyInfo( propertyNames[j].c_str() ) ; - if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION ) - { - const wxCollectionTypeInfo* collType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() ) ; - const wxTypeInfo * elementType = collType->GetElementType() ; - while( prop ) - { - wxASSERT_MSG(prop->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ; - wxXmlNode* elementContent = prop->GetChildren() ; - if ( elementContent ) - { - // 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() ) - { - 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(pi->GetTypeInfo()) , sinkClassInfo , - sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ; - } - - } - else - { - wxxVariant nodeval ; - callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetTypeInfo() ) ) ; - } - } - } - } - - delete[] createParams ; - delete[] createParamOids ; - delete[] createClassInfos ; - - return objectID; -} - -wxxVariant wxXmlReader::ReadValue(wxXmlNode *node, - const wxTypeInfo *type ) -{ - wxString content ; - if ( node ) - content = node->GetContent() ; - wxxVariant result ; - type->ConvertFromString( content , result ) ; - return result ; -} - -int wxXmlReader::ReadObject( const wxString &name , wxDepersister *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 ; -} // ---------------------------------------------------------------------------- // depersisting to memory @@ -756,7 +360,7 @@ wxRuntimeDepersister::~wxRuntimeDepersister() } void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo , - wxxVariantArray &metadata) + wxxVariantArray &WXUNUSED(metadata)) { wxObject *O; O = classInfo->CreateObject(); @@ -769,7 +373,7 @@ void wxRuntimeDepersister::CreateObject(int objectID, wxxVariant *params, int *objectIdValues, const wxClassInfo **objectClassInfos , - wxxVariantArray &metadata) + wxxVariantArray &WXUNUSED(metadata)) { wxObject *o; o = m_data->GetObject(objectID); @@ -836,12 +440,12 @@ void wxRuntimeDepersister::SetConnect(int eventSourceObjectID, const wxHandlerInfo* handlerInfo , int eventSinkObjectID ) { - wxWindow *ehsource = dynamic_cast< wxWindow* >( m_data->GetObject( eventSourceObjectID ) ) ; + wxEvtHandler *ehsource = dynamic_cast< wxEvtHandler* >( m_data->GetObject( eventSourceObjectID ) ) ; wxEvtHandler *ehsink = dynamic_cast< wxEvtHandler *>(m_data->GetObject(eventSinkObjectID) ) ; if ( ehsource && ehsink ) { - ehsource->Connect( ehsource->GetId() , delegateInfo->GetEventType() , + ehsource->Connect( -1 , delegateInfo->GetEventType() , handlerInfo->GetEventFunction() , NULL /*user data*/ , ehsink ) ; } @@ -920,7 +524,7 @@ wxCodeDepersister::~wxCodeDepersister() } void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo , - wxxVariantArray &metadata) + wxxVariantArray &WXUNUSED(metadata)) { wxString objectName = wxString::Format( "LocalObject_%d" , objectID ) ; m_fp->WriteString( wxString::Format( "\t%s *%s = new %s;\n", @@ -963,7 +567,7 @@ void wxCodeDepersister::CreateObject(int objectID, wxxVariant *params, int *objectIDValues, const wxClassInfo **WXUNUSED(objectClassInfos) , - wxxVariantArray &metadata + wxxVariantArray &WXUNUSED(metadata) ) { int i; @@ -1011,7 +615,7 @@ void wxCodeDepersister::SetPropertyAsObject(int objectID, } void wxCodeDepersister::AddToPropertyCollection( int objectID , - const wxClassInfo *classInfo, + const wxClassInfo *WXUNUSED(classInfo), const wxPropertyInfo* propertyInfo , const wxxVariant &value) { @@ -1022,10 +626,10 @@ void wxCodeDepersister::AddToPropertyCollection( int objectID , } // sets the corresponding property (value is an object) -void wxCodeDepersister::AddToPropertyCollectionAsObject(int objectID, - const wxClassInfo *classInfo, - const wxPropertyInfo* propertyInfo , - int valueObjectId) +void wxCodeDepersister::AddToPropertyCollectionAsObject(int WXUNUSED(objectID), + const wxClassInfo *WXUNUSED(classInfo), + const wxPropertyInfo* WXUNUSED(propertyInfo) , + int WXUNUSED(valueObjectId)) { // TODO } diff --git a/src/common/xtixml.cpp b/src/common/xtixml.cpp new file mode 100644 index 0000000000..94dcc08ebe --- /dev/null +++ b/src/common/xtixml.cpp @@ -0,0 +1,455 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: src/common/xtistrm.cpp +// Purpose: streaming runtime metadata information +// Author: Stefan Csomor +// Modified by: +// Created: 27/07/03 +// RCS-ID: $Id$ +// Copyright: (c) 2003 Stefan Csomor +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) +#pragma implementation "xtistrm.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/hash.h" +#include "wx/object.h" +#endif + +#include "wx/xml/xml.h" +#include "wx/tokenzr.h" +#include "wx/xtistrm.h" +#include "wx/xtixml.h" +#include "wx/txtstrm.h" +#include "wx/event.h" + +#if wxUSE_EXTENDED_RTTI + +#include "wx/beforestd.h" +#include +#include +#include +#include "wx/afterstd.h" + +using namespace std ; + +// +// XML Streaming +// + +// convenience functions + +void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data ) +{ + node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) ); +} + +wxString wxXmlGetContentFromNode( wxXmlNode *node ) +{ + if ( node->GetChildren() ) + return node->GetChildren()->GetContent() ; + else + return wxEmptyString ; +} + +struct wxXmlWriter::wxXmlWriterInternal +{ + wxXmlNode *m_root ; + wxXmlNode *m_current ; + vector< wxXmlNode * > m_objectStack ; + + 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 ) +{ + m_data = new wxXmlWriterInternal() ; + m_data->m_root = rootnode ; + m_data->m_current = rootnode ; +} + +wxXmlWriter::~wxXmlWriter() +{ + delete m_data ; +} + +void wxXmlWriter::DoBeginWriteTopLevelEntry( const wxString &name ) +{ + 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 ) ); + + 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) ) +{ + m_data->Pop() ; +} + +// writes a property in the stream format +void wxXmlWriter::DoWriteSimpleType( wxxVariant &value ) +{ + wxXmlAddContentToNode( m_data->m_current ,value.GetAsString() ) ; +} + +void wxXmlWriter::DoBeginWriteElement() +{ + wxXmlNode *pnode; + pnode = new wxXmlNode(wxXML_ELEMENT_NODE, "element" ); + m_data->m_current->AddChild(pnode) ; + m_data->Push( pnode ) ; +} + +void wxXmlWriter::DoEndWriteElement() +{ + m_data->Pop() ; +} + +void wxXmlWriter::DoBeginWriteProperty(const wxPropertyInfo *pi ) +{ + 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 ) ; +} + +void wxXmlWriter::DoEndWriteProperty(const wxPropertyInfo *WXUNUSED(propInfo) ) +{ + m_data->Pop() ; +} + + + +// insert an object reference to an already written object +void wxXmlWriter::DoWriteRepeatedObject( int objectID ) +{ + 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 *WXUNUSED(pi) , + const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo ) +{ + if ( eventSink != NULL && handlerInfo != NULL ) + { + wxXmlAddContentToNode( m_data->m_current ,wxString::Format(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName()) ) ; + } +} + +// ---------------------------------------------------------------------------- +// reading objects in +// ---------------------------------------------------------------------------- + + + +// ---------------------------------------------------------------------------- +// reading xml in +// ---------------------------------------------------------------------------- + +/* +Reading components has not to be extended for components +as properties are always sought by typeinfo over all levels +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; + + wxxVariant *createParams ; + int *createParamOids ; + 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); + 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 + 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 ) ; + + 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 + createParams = new wxxVariant[ classInfo->GetCreateParamCount() ] ; + createParamOids = new int[classInfo->GetCreateParamCount() ] ; + createClassInfos = new const wxClassInfo*[classInfo->GetCreateParamCount() ] ; + + typedef map PropertyNodes ; + typedef vector PropertyNames ; + + PropertyNodes propertyNodes ; + PropertyNames propertyNames ; + + while( children ) + { + wxString name ; + children->GetPropVal( wxT("name") , &name ) ; + propertyNames.push_back( name.c_str() ) ; + propertyNodes[name.c_str()] = children->GetChildren() ; + children = children->GetNext() ; + } + + for ( int i = 0 ; i GetCreateParamCount() ; ++i ) + { + 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() ) + { + wxXmlNode* prop = propiter->second ; + if ( pi->GetTypeInfo()->IsObjectType() ) + { + createParamOids[i] = ReadComponent( prop , callbacks ) ; + createClassInfos[i] = dynamic_cast(pi->GetTypeInfo())->GetClassInfo() ; + } + else + { + createParamOids[i] = wxInvalidObjectID ; + createParams[i] = ReadValue( prop , pi->GetTypeInfo() ) ; + if( pi->GetFlags() & wxPROP_ENUM_STORE_LONG ) + { + const wxEnumTypeInfo *eti = dynamic_cast( 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 ; + } + + for ( size_t j = 0 ; j < propertyNames.size() ; ++j ) + { + if ( propertyNames[j] == paramName ) + { + propertyNames[j] = "" ; + break ; + } + } + } + else + { + createParams[i] = pi->GetDefaultValue() ; + } + } + + // got the parameters. Call the Create method + callbacks->CreateObject(objectID, classInfo, + classInfo->GetCreateParamCount(), + 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 ) + { + if ( propertyNames[j].length() ) + { + PropertyNodes::iterator propiter = propertyNodes.find( propertyNames[j] ) ; + if ( propiter != propertyNodes.end() ) + { + wxXmlNode* prop = propiter->second ; + const wxPropertyInfo* pi = classInfo->FindPropertyInfo( propertyNames[j].c_str() ) ; + if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION ) + { + const wxCollectionTypeInfo* collType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() ) ; + const wxTypeInfo * elementType = collType->GetElementType() ; + while( prop ) + { + wxASSERT_MSG(prop->GetName() == wxT("element") , wxT("A non empty collection must consist of 'element' nodes")) ; + wxXmlNode* elementContent = prop->GetChildren() ; + if ( elementContent ) + { + // 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() ) + { + 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(pi->GetTypeInfo()) , sinkClassInfo , + sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ; + } + + } + else + { + wxxVariant nodeval ; + callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetTypeInfo() ) ) ; + } + } + } + } + + delete[] createParams ; + delete[] createParamOids ; + delete[] createClassInfos ; + + return objectID; +} + +wxxVariant wxXmlReader::ReadValue(wxXmlNode *node, + const wxTypeInfo *type ) +{ + wxString content ; + if ( node ) + content = node->GetContent() ; + wxxVariant result ; + type->ConvertFromString( content , result ) ; + return result ; +} + +int wxXmlReader::ReadObject( const wxString &name , wxDepersister *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 ; +} + +#endif