X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f0b7eadf889c2882e81470ec8e629d831858acb1..ad653fa23069c5d9378247084f03c9a718c3ad62:/src/common/xti.cpp diff --git a/src/common/xti.cpp b/src/common/xti.cpp index acaa9b56a9..ab4796ff3f 100644 --- a/src/common/xti.cpp +++ b/src/common/xti.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/common/xti.cpp -// Purpose: runtime metadata information (extended class info +// Purpose: runtime metadata information (extended class info) // Author: Stefan Csomor // Modified by: // Created: 27/07/03 @@ -10,645 +10,963 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "xti.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif +#if wxUSE_EXTENDED_RTTI + #ifndef WX_PRECOMP - #include "wx/hash.h" #include "wx/object.h" + #include "wx/list.h" + #include "wx/hash.h" #endif +#include "wx/xti.h" #include "wx/xml/xml.h" #include "wx/tokenzr.h" +#include "wx/range.h" #include -#if wxUSE_EXTENDED_RTTI +#include "wx/beforestd.h" +#include +#include +#include +#include "wx/afterstd.h" + +using namespace std; // ---------------------------------------------------------------------------- -// Enum Support +// wxEnumData // ---------------------------------------------------------------------------- wxEnumData::wxEnumData( wxEnumMemberData* data ) { - m_members = data ; - for ( m_count = 0; m_members[m_count].m_name ; m_count++) - {} ; + m_members = data; + for ( m_count = 0; m_members[m_count].m_name; m_count++) + {}; } -bool wxEnumData::HasEnumMemberValue(const wxChar *name, int *value) +bool wxEnumData::HasEnumMemberValue(const wxChar *name, int *value) const { int i; - for (i = 0; m_members[i].m_name ; i++ ) - { - if (!strcmp(name, m_members[i].m_name)) - { - if ( value ) - *value = m_members[i].m_value; - return true ; - } - } - return false ; + for (i = 0; m_members[i].m_name; i++ ) + { + if (!wxStrcmp(name, m_members[i].m_name)) + { + if ( value ) + *value = m_members[i].m_value; + return true; + } + } + return false; } -int wxEnumData::GetEnumMemberValue(const wxChar *name) +int wxEnumData::GetEnumMemberValue(const wxChar *name) const { int i; - for (i = 0; m_members[i].m_name ; i++ ) - { - if (!strcmp(name, m_members[i].m_name)) - { - return m_members[i].m_value; - } - } - return 0 ; + for (i = 0; m_members[i].m_name; i++ ) + { + if (!wxStrcmp(name, m_members[i].m_name)) + { + return m_members[i].m_value; + } + } + return 0; } -const wxChar *wxEnumData::GetEnumMemberName(int value) +const wxChar *wxEnumData::GetEnumMemberName(int value) const { int i; - for (i = 0; m_members[i].m_name ; i++) - if (value == m_members[i].m_value) - return m_members[i].m_name; + for (i = 0; m_members[i].m_name; i++) + if (value == m_members[i].m_value) + return m_members[i].m_name; - return wxT("") ; + return wxEmptyString; } -int wxEnumData::GetEnumMemberValueByIndex( int idx ) +int wxEnumData::GetEnumMemberValueByIndex( int idx ) const { - // we should cache the count in order to avoid out-of-bounds errors - return m_members[idx].m_value ; + // we should cache the count in order to avoid out-of-bounds errors + return m_members[idx].m_value; } -const char * wxEnumData::GetEnumMemberNameByIndex( int idx ) +const wxChar * wxEnumData::GetEnumMemberNameByIndex( int idx ) const { - // we should cache the count in order to avoid out-of-bounds errors - return m_members[idx].m_name ; + // we should cache the count in order to avoid out-of-bounds errors + return m_members[idx].m_name; } // ---------------------------------------------------------------------------- // Type Information // ---------------------------------------------------------------------------- -template<> const wxTypeInfo* wxGetTypeInfo( void * ) +// ---------------------------------------------------------------------------- +// value streaming +// ---------------------------------------------------------------------------- + +// streamer specializations +// for all built-in types + +// bool + +template<> void wxStringReadValue(const wxString &s, bool &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + int intdata; + wxSscanf(s, wxT("%d"), &intdata ); + data = (bool)(intdata != 0); } -template<> const wxTypeInfo* wxGetTypeInfo( bool * ) +template<> void wxStringWriteValue(wxString &s, const bool &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_BOOL ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%d"), data ); } -template<> const wxTypeInfo* wxGetTypeInfo( char * ) +// char + +template<> void wxStringReadValue(const wxString &s, char &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_CHAR ) ; - return &s_typeInfo ; + int intdata; + wxSscanf(s, wxT("%d"), &intdata ); + data = char(intdata); } -template<> const wxTypeInfo* wxGetTypeInfo( unsigned char * ) +template<> void wxStringWriteValue(wxString &s, const char &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_UCHAR ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%d"), data ); } -template<> const wxTypeInfo* wxGetTypeInfo( int * ) +// unsigned char + +template<> void wxStringReadValue(const wxString &s, unsigned char &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_CHAR ) ; - return &s_typeInfo ; + int intdata; + wxSscanf(s, wxT("%d"), &intdata ); + data = (unsigned char)(intdata); } -template<> const wxTypeInfo* wxGetTypeInfo( unsigned int * ) +template<> void wxStringWriteValue(wxString &s, const unsigned char &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_UCHAR ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%d"), data ); } -template<> const wxTypeInfo* wxGetTypeInfo( long * ) +// int + +template<> void wxStringReadValue(const wxString &s, int &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_CHAR ) ; - return &s_typeInfo ; + wxSscanf(s, wxT("%d"), &data ); } -template<> const wxTypeInfo* wxGetTypeInfo( unsigned long * ) +template<> void wxStringWriteValue(wxString &s, const int &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_UCHAR ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%d"), data ); } -template<> const wxTypeInfo* wxGetTypeInfo( float * ) +// unsigned int + +template<> void wxStringReadValue(const wxString &s, unsigned int &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_FLOAT ) ; - return &s_typeInfo ; + wxSscanf(s, wxT("%d"), &data ); } -template<> const wxTypeInfo* wxGetTypeInfo( double * ) +template<> void wxStringWriteValue(wxString &s, const unsigned int &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_DOUBLE ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%d"), data ); } -template<> const wxTypeInfo* wxGetTypeInfo( wxString * ) +// long + +template<> void wxStringReadValue(const wxString &s, long &data ) { - static wxBuiltInTypeInfo s_typeInfo( wxT_STRING ) ; - return &s_typeInfo ; + wxSscanf(s, wxT("%ld"), &data ); } -// this are compiler induced specialization which are never used anywhere +template<> void wxStringWriteValue(wxString &s, const long &data ) +{ + s = wxString::Format(wxT("%ld"), data ); +} -// char const * +// unsigned long -template<> const wxTypeInfo* wxGetTypeInfo( char const ** ) +template<> void wxStringReadValue(const wxString &s, unsigned long &data ) { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + wxSscanf(s, wxT("%ld"), &data ); } -template<> void wxStringReadValue(const wxString & , const char* & ) +template<> void wxStringWriteValue(wxString &s, const unsigned long &data ) { - assert(0) ; + s = wxString::Format(wxT("%ld"), data ); } -template<> void wxStringWriteValue(wxString & , char const * const & ) +#ifdef wxLongLong_t +template<> void wxStringReadValue(const wxString &s, wxLongLong_t &data ) { - assert(0) ; + wxSscanf(s, wxT("%lld"), &data ); } -// char * - -template<> const wxTypeInfo* wxGetTypeInfo( char ** ) +template<> void wxStringWriteValue(wxString &s, const wxLongLong_t &data ) { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%lld"), data ); } -template<> void wxStringReadValue(const wxString & , char* & ) +template<> void wxStringReadValue(const wxString &s, wxULongLong_t &data ) { - assert(0) ; + wxSscanf(s, wxT("%lld"), &data ); } -template<> void wxStringWriteValue(wxString & , char * const & ) +template<> void wxStringWriteValue(wxString &s, const wxULongLong_t &data ) { - assert(0) ; + s = wxString::Format(wxT("%lld"), data ); } +#endif +// float -// unsigned char * - -template<> const wxTypeInfo* wxGetTypeInfo( unsigned char ** ) +template<> void wxStringReadValue(const wxString &s, float &data ) { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + wxSscanf(s, wxT("%f"), &data ); } -template<> void wxStringReadValue(const wxString & , unsigned char* & ) +template<> void wxStringWriteValue(wxString &s, const float &data ) { - assert(0) ; + s = wxString::Format(wxT("%f"), data ); } -template<> void wxStringWriteValue(wxString & , unsigned char * const & ) +// double + +template<> void wxStringReadValue(const wxString &s, double &data ) { - assert(0) ; + wxSscanf(s, wxT("%lf"), &data ); } -// int * - -template<> const wxTypeInfo* wxGetTypeInfo( int ** ) +template<> void wxStringWriteValue(wxString &s, const double &data ) { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + s = wxString::Format(wxT("%lf"), data ); } -template<> void wxStringReadValue(const wxString & , int* & ) +// wxString + +template<> void wxStringReadValue(const wxString &s, wxString &data ) { - assert(0) ; + data = s; } -template<> void wxStringWriteValue(wxString & , int * const & ) +template<> void wxStringWriteValue(wxString &s, const wxString &data ) { - assert(0) ; + s = data; } -// bool * -template<> const wxTypeInfo* wxGetTypeInfo( bool ** ) +// built-ins +// + +#if wxUSE_FUNC_TEMPLATE_POINTER + #define wxBUILTIN_TYPE_INFO( element, type ) \ + wxBuiltInTypeInfo \ + s_typeInfo##type(element, &wxToStringConverter, \ + &wxFromStringConverter, typeid(type).name()); +#else + #define wxBUILTIN_TYPE_INFO( element, type ) \ + void _toString##element( const wxAny& data, wxString &result ) \ + { wxToStringConverter void wxStringReadValue(const wxString &s , wxRange &data) { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + int minValue, maxValue; + wxSscanf(s, wxT("%d,%d"), &minValue , &maxValue); + data = wxRange(minValue, maxValue); } -template<> void wxStringReadValue(const wxString & , bool* & ) +template<> void wxStringWriteValue(wxString &s , const wxRange &data) { - assert(0) ; + s = wxString::Format(wxT("%d,%d"), data.GetMin() , data.GetMax()); } -template<> void wxStringWriteValue(wxString & , bool * const & ) +wxCUSTOM_TYPE_INFO(wxRange, wxToStringConverter , wxFromStringConverter) + +// other types + +wxCOLLECTION_TYPE_INFO( wxString, wxArrayString ); + +template<> void wxCollectionToVariantArray( wxArrayString const &theArray, + wxAnyList &value) { - assert(0) ; + wxArrayCollectionToVariantArray( theArray, value ); } -// long * +wxTypeInfoMap *wxTypeInfo::ms_typeTable = NULL; -template<> const wxTypeInfo* wxGetTypeInfo( long ** ) +wxTypeInfo *wxTypeInfo::FindType(const wxString& typeName) { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + wxTypeInfoMap::iterator iter = ms_typeTable->find(typeName); + + if (iter == ms_typeTable->end()) + return NULL; + + return (wxTypeInfo *)iter->second; } -template<> void wxStringReadValue(const wxString & , long* & ) -{ - assert(0) ; +wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, + wxVariant2StringFnc to, + wxString2VariantFnc from, + const wxString &name) : + wxTypeInfo( kind, to, from, name) +{ + wxASSERT_MSG( kind == wxT_OBJECT_PTR || kind == wxT_OBJECT, + wxT("Illegal Kind for Enum Type")); m_classInfo = classInfo; } -template<> void wxStringWriteValue(wxString & , long * const & ) -{ - assert(0) ; +wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass, + wxVariant2StringFnc to, + wxString2VariantFnc from ) : + wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString ) +{ + m_eventClass = eventClass; + m_eventType = eventType; + m_lastEventType = -1; } -// wxString * +wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, int lastEventType, + wxClassInfo* eventClass, + wxVariant2StringFnc to, + wxString2VariantFnc from ) : + wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString ) +{ + m_eventClass = eventClass; + m_eventType = eventType; + m_lastEventType = lastEventType; +} -template<> const wxTypeInfo* wxGetTypeInfo( wxString ** ) +void wxTypeInfo::Register() { - assert(0) ; - static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ; - return &s_typeInfo ; + if ( ms_typeTable == NULL ) + ms_typeTable = new wxTypeInfoMap(); + + if( !m_name.empty() ) + (*ms_typeTable)[m_name] = this; } -template<> void wxStringReadValue(const wxString & , wxString* & ) +void wxTypeInfo::Unregister() { - assert(0) ; + if( !m_name.empty() ) + ms_typeTable->erase(m_name); } -template<> void wxStringWriteValue(wxString & , wxString * const & ) +// removing header dependency on string tokenizer + +void wxSetStringToArray( const wxString &s, wxArrayString &array ) { - assert(0) ; + wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK); + wxString flag; + array.Clear(); + while (tokenizer.HasMoreTokens()) + { + array.Add(tokenizer.GetNextToken()); + } } - // ---------------------------------------------------------------------------- -// value streaming +// wxPropertyInfo // ---------------------------------------------------------------------------- -// convenience function (avoids including xml headers in users code) - -void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data ) +void wxPropertyInfo::Insert(wxPropertyInfo* &iter) { - node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) ); + m_next = NULL; + if ( iter == NULL ) + iter = this; + else + { + wxPropertyInfo* i = iter; + while( i->m_next ) + i = i->m_next; + + i->m_next = this; + } } -wxString wxXmlGetContentFromNode( wxXmlNode *node ) +void wxPropertyInfo::Remove() { - if ( node->GetChildren() ) - return node->GetChildren()->GetContent() ; - else - return wxEmptyString ; -} + if ( this == m_itsClass->m_firstProperty ) + { + m_itsClass->m_firstProperty = m_next; + } + else + { + wxPropertyInfo *info = m_itsClass->m_firstProperty; + while (info) + { + if ( info->m_next == this ) + { + info->m_next = m_next; + break; + } + + info = info->m_next; + } + } -// streamer specializations -// for all built-in types +} -// bool +// ---------------------------------------------------------------------------- +// wxHandlerInfo +// ---------------------------------------------------------------------------- -template<> void wxStringReadValue(const wxString &s , bool &data ) +void wxHandlerInfo::Insert(wxHandlerInfo* &iter) { - int intdata ; - wxSscanf(s, _T("%d"), &intdata ) ; - data = bool(intdata) ; + m_next = NULL; + if ( iter == NULL ) + iter = this; + else + { + wxHandlerInfo* i = iter; + while( i->m_next ) + i = i->m_next; + + i->m_next = this; + } } -template<> void wxStringWriteValue(wxString &s , const bool &data ) +void wxHandlerInfo::Remove() { - s = wxString::Format("%d", data ) ; + if ( this == m_itsClass->m_firstHandler ) + { + m_itsClass->m_firstHandler = m_next; + } + else + { + wxHandlerInfo *info = m_itsClass->m_firstHandler; + while (info) + { + if ( info->m_next == this ) + { + info->m_next = m_next; + break; + } + + info = info->m_next; + } + } } -// char -template<> void wxStringReadValue(const wxString &s , char &data ) +// ---------------------------------------------------------------------------- +// wxClassInfo +// ---------------------------------------------------------------------------- + +bool wxClassInfo::Create(wxObject *object, int ParamCount, wxAny *Params) const { - int intdata ; - wxSscanf(s, _T("%d"), &intdata ) ; - data = char(intdata) ; + if ( ParamCount != m_constructorPropertiesCount ) + { + // FIXME: shouldn't we just return false and let the caller handle it? + wxLogError( _("Illegal Parameter Count for Create Method") ); + return false; + } + + return m_constructor->Create( object, Params ); } -template<> void wxStringWriteValue(wxString &s , const char &data ) +wxObject *wxClassInfo::ConstructObject(int ParamCount, wxAny *Params) const { - s = wxString::Format("%d", data ) ; -} + if ( ParamCount != m_constructorPropertiesCount ) + { + // FIXME: shouldn't we just return NULL and let the caller handle this case? + wxLogError( _("Illegal Parameter Count for ConstructObject Method") ); + return NULL; + } -// unsigned char + wxObject *object = NULL; + if (!m_constructor->Create( object, Params )) + return NULL; + return object; +} -template<> void wxStringReadValue(const wxString &s , unsigned char &data ) +bool wxClassInfo::IsKindOf(const wxClassInfo *info) const { - int intdata ; - wxSscanf(s, _T("%d"), &intdata ) ; - data = (unsigned char)(intdata) ; + if ( info != 0 ) + { + if ( info == this ) + return true; + + for ( int i = 0; m_parents[i]; ++ i ) + { + if ( m_parents[i]->IsKindOf( info ) ) + return true; + } + } + return false; } -template<> void wxStringWriteValue(wxString &s , const unsigned char &data ) +const wxPropertyAccessor *wxClassInfo::FindAccessor(const wxChar *PropertyName) const { - s = wxString::Format("%d", data ) ; -} + const wxPropertyInfo* info = FindPropertyInfo( PropertyName ); -// int + if ( info ) + return info->GetAccessor(); -template<> void wxStringReadValue(const wxString &s , int &data ) -{ - wxSscanf(s, _T("%d"), &data ) ; + return NULL; } -template<> void wxStringWriteValue(wxString &s , const int &data ) +wxPropertyInfo *wxClassInfo::FindPropertyInfoInThisClass (const wxChar *PropertyName) const { - s = wxString::Format("%d", data ) ; -} + wxPropertyInfo* info = GetFirstProperty(); -// unsigned int + while( info ) + { + if ( wxStrcmp( info->GetName(), PropertyName ) == 0 ) + return info; + info = info->GetNext(); + } -template<> void wxStringReadValue(const wxString &s , unsigned int &data ) -{ - wxSscanf(s, _T("%d"), &data ) ; + return 0; } -template<> void wxStringWriteValue(wxString &s , const unsigned int &data ) +const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const wxChar *PropertyName) const { - s = wxString::Format("%d", data ) ; -} + const wxPropertyInfo* info = FindPropertyInfoInThisClass( PropertyName ); + if ( info ) + return info; -// long + const wxClassInfo** parents = GetParents(); + for ( int i = 0; parents[i]; ++ i ) + { + if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL ) + return info; + } -template<> void wxStringReadValue(const wxString &s , long &data ) -{ - wxSscanf(s, _T("%ld"), &data ) ; + return 0; } -template<> void wxStringWriteValue(wxString &s , const long &data ) +wxHandlerInfo *wxClassInfo::FindHandlerInfoInThisClass (const wxChar *PropertyName) const { - s = wxString::Format("%ld", data ) ; -} + wxHandlerInfo* info = GetFirstHandler(); -// unsigned long + while( info ) + { + if ( wxStrcmp( info->GetName(), PropertyName ) == 0 ) + return info; + info = info->GetNext(); + } -template<> void wxStringReadValue(const wxString &s , unsigned long &data ) + return 0; +} + +const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const wxChar *PropertyName) const { - wxSscanf(s, _T("%ld"), &data ) ; + const wxHandlerInfo* info = FindHandlerInfoInThisClass( PropertyName ); + + if ( info ) + return info; + + const wxClassInfo** parents = GetParents(); + for ( int i = 0; parents[i]; ++ i ) + { + if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL ) + return info; + } + + return 0; } -template<> void wxStringWriteValue(wxString &s , const unsigned long &data ) +wxObjectStreamingCallback wxClassInfo::GetStreamingCallback() const { - s = wxString::Format("%ld", data ) ; + 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; } -// float +bool wxClassInfo::BeforeWriteObject( const wxObject *obj, wxObjectWriter *streamer, + wxObjectWriterCallback *writercallback, const wxStringToAnyHashMap &metadata) const +{ + wxObjectStreamingCallback sb = GetStreamingCallback(); + if ( sb ) + return (*sb)(obj, streamer, writercallback, metadata ); -template<> void wxStringReadValue(const wxString &s , float &data ) + return true; +} + +void wxClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, + const wxAny &value) const { - wxSscanf(s, _T("%f"), &data ) ; + const wxPropertyAccessor *accessor; + + accessor = FindAccessor(propertyName); + wxASSERT(accessor->HasSetter()); + accessor->SetProperty( object, value ); } -template<> void wxStringWriteValue(wxString &s , const float &data ) +wxAny wxClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const { - s = wxString::Format("%f", data ) ; + const wxPropertyAccessor *accessor; + + accessor = FindAccessor(propertyName); + wxASSERT(accessor->HasGetter()); + wxAny result; + accessor->GetProperty(object,result); + return result; } -// double +wxAnyList wxClassInfo::GetPropertyCollection(wxObject *object, + const wxChar *propertyName) const +{ + const wxPropertyAccessor *accessor; -template<> void wxStringReadValue(const wxString &s , double &data ) + accessor = FindAccessor(propertyName); + wxASSERT(accessor->HasGetter()); + wxAnyList result; + accessor->GetPropertyCollection(object,result); + return result; +} + +void wxClassInfo::AddToPropertyCollection(wxObject *object, const wxChar *propertyName, + const wxAny& value) const { - wxSscanf(s, _T("%lf"), &data ) ; + const wxPropertyAccessor *accessor; + + accessor = FindAccessor(propertyName); + wxASSERT(accessor->HasAdder()); + accessor->AddToPropertyCollection( object, value ); } -template<> void wxStringWriteValue(wxString &s , const double &data ) +// void wxClassInfo::GetProperties( wxPropertyInfoMap &map ) const +// The map parameter (the name map that is) seems something special +// to MSVC and so we use a other name. +void wxClassInfo::GetProperties( wxPropertyInfoMap &infomap ) const { - s = wxString::Format("%lf", data ) ; + const wxPropertyInfo *pi = GetFirstProperty(); + while( pi ) + { + if ( infomap.find( pi->GetName() ) == infomap.end() ) + infomap[pi->GetName()] = (wxPropertyInfo*) pi; + + pi = pi->GetNext(); + } + + const wxClassInfo** parents = GetParents(); + for ( int i = 0; parents[i]; ++ i ) + { + parents[i]->GetProperties( infomap ); + } } -// wxString +wxObject* wxClassInfo::AnyToObjectPtr( const wxAny &data) const +{ + return m_variantOfPtrToObjectConverter(data); +} -template<> void wxStringReadValue(const wxString &s , wxString &data ) +void wxClassInfo::CallOnAny( const wxAny &data, wxObjectFunctor* functor ) const { - data = s ; + if ( data.GetTypeInfo()->GetKind() == wxT_OBJECT ) + return m_variantToObjectConverter(data, functor); + else + return (*functor)(m_variantOfPtrToObjectConverter(data)); } -template<> void wxStringWriteValue(wxString &s , const wxString &data ) +wxAny wxClassInfo::ObjectPtrToAny( wxObject* obj) const { - s = data ; + return m_objectToVariantConverter(obj); } -/* - Custom Data Streaming / Type Infos - we will have to add this for all wx non object types, but it is also an example - for custom data structures -*/ +bool wxClassInfo::NeedsDirectConstruction() const +{ + return wx_dynamic_cast(wxObjectAllocator*, m_constructor) != NULL; +} + +// ---------------------------------------------------------------------------- +// wxDynamicObject support +// ---------------------------------------------------------------------------- -// wxPoint +// Dynamic Objects are objects that have a real superclass instance and carry their +// own attributes in a hash map. Like this it is possible to create the objects and +// stream them, as if their class information was already available from compiled data -template<> void wxStringReadValue(const wxString &s , wxPoint &data ) +struct wxDynamicObject::wxDynamicObjectInternal { - wxSscanf(s, _T("%d,%d"), &data.x , &data.y ) ; -} + wxDynamicObjectInternal() {} + + wxStringToAnyHashMap m_properties; +}; -template<> void wxStringWriteValue(wxString &s , const wxPoint &data ) +typedef list< wxDynamicObject* > wxDynamicObjectList; + +struct wxDynamicClassInfo::wxDynamicClassInfoInternal { - s = wxString::Format("%d,%d", data.x , data.y ) ; -} + wxDynamicObjectList m_dynamicObjects; +}; -template<> void wxStringReadValue(const wxString & , wxPoint* & ) +// instantiates this object with an instance of its superclass +wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info) { - assert(0) ; + m_superClassInstance = superClassInstance; + m_classInfo = info; + m_data = new wxDynamicObjectInternal; } -template<> void wxStringWriteValue(wxString & , wxPoint* const & ) +wxDynamicObject::~wxDynamicObject() { - assert(0) ; + wx_dynamic_cast(const wxDynamicClassInfo*, m_classInfo)-> + m_data->m_dynamicObjects.remove( this ); + delete m_data; + delete m_superClassInstance; } -WX_CUSTOM_TYPE_INFO(wxPoint) - -template<> void wxStringReadValue(const wxString &s , wxSize &data ) +void wxDynamicObject::SetProperty (const wxChar *propertyName, const wxAny &value) { - wxSscanf(s, _T("%d,%d"), &data.x , &data.y ) ; + wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), + wxT("Accessing Unknown Property in a Dynamic Object") ); + m_data->m_properties[propertyName] = value; } -template<> void wxStringWriteValue(wxString &s , const wxSize &data ) +wxAny wxDynamicObject::GetProperty (const wxChar *propertyName) const { - s = wxString::Format("%d,%d", data.x , data.y ) ; + wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), + wxT("Accessing Unknown Property in a Dynamic Object") ); + return m_data->m_properties[propertyName]; } -template<> void wxStringReadValue(const wxString & , wxSize* & ) +void wxDynamicObject::RemoveProperty( const wxChar *propertyName ) { - assert(0) ; + wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), + wxT("Removing Unknown Property in a Dynamic Object") ); + m_data->m_properties.erase( propertyName ); } -template<> void wxStringWriteValue(wxString & , wxSize * const & ) +void wxDynamicObject::RenameProperty( const wxChar *oldPropertyName, + const wxChar *newPropertyName ) { - assert(0) ; + wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(oldPropertyName), + wxT("Renaming Unknown Property in a Dynamic Object") ); + + wxAny value = m_data->m_properties[oldPropertyName]; + m_data->m_properties.erase( oldPropertyName ); + m_data->m_properties[newPropertyName] = value; } -WX_CUSTOM_TYPE_INFO(wxSize) -/* +// ---------------------------------------------------------------------------- +// wxDynamicClassInfo +// ---------------------------------------------------------------------------- -template<> void wxStringReadValue(const wxString &s , wxColour &data ) +wxDynamicClassInfo::wxDynamicClassInfo( const wxChar *unitName, + const wxChar *className, + const wxClassInfo* superClass ) : + wxClassInfo( unitName, className, new const wxClassInfo*[2]) { - // copied from VS xrc - unsigned long tmp = 0; - - if (s.Length() != 7 || s[0u] != wxT('#') || - wxSscanf(s.c_str(), wxT("#%lX"), &tmp) != 1) - { - wxLogError(_("String To Colour : Incorrect colour specification : %s"), - s.c_str() ); - data = wxNullColour; - } - else - { - data = wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) , - (unsigned char) ((tmp & 0x00FF00) >> 8), - (unsigned char) ((tmp & 0x0000FF))); - } + GetParents()[0] = superClass; + GetParents()[1] = NULL; + m_data = new wxDynamicClassInfoInternal; } -template<> void wxStringWriteValue(wxString &s , const wxColour &data ) +wxDynamicClassInfo::~wxDynamicClassInfo() { - s = wxString::Format("#%2X%2X%2X", data.Red() , data.Green() , data.Blue() ) ; + delete[] GetParents(); + delete m_data; } -WX_CUSTOM_TYPE_INFO(wxColour) - -*/ - -// removing header dependancy on string tokenizer - -void wxSetStringToArray( const wxString &s , wxArrayString &array ) +wxObject *wxDynamicClassInfo::AllocateObject() const { - wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK); - wxString flag; - array.Clear() ; - while (tokenizer.HasMoreTokens()) - { - array.Add(tokenizer.GetNextToken()) ; - } + wxObject* parent = GetParents()[0]->AllocateObject(); + wxDynamicObject *obj = new wxDynamicObject( parent, this ); + m_data->m_dynamicObjects.push_back( obj ); + return obj; } -// ---------------------------------------------------------------------------- -// wxClassInfo -// ---------------------------------------------------------------------------- +bool wxDynamicClassInfo::Create (wxObject *object, int paramCount, wxAny *params) const +{ + wxDynamicObject *dynobj = wx_dynamic_cast( wxDynamicObject *, object ); + wxASSERT_MSG( dynobj, + wxT("cannot call wxDynamicClassInfo::Create on ") + wxT("an object other than wxDynamicObject") ); + return GetParents()[0]->Create( dynobj->GetSuperClassInstance(), paramCount, params ); +} -void wxClassInfo::Register(const char *WXUNUSED(name), wxClassInfo *WXUNUSED(info)) +// get number of parameters for constructor +int wxDynamicClassInfo::GetCreateParamCount() const { - /* - if (!ExtendedTypeMap) - ExtendedTypeMap = new ClassMap; - (*ExtendedTypeMap)[string(Name)] = Info; - */ + return GetParents()[0]->GetCreateParamCount(); } -void wxClassInfo::Unregister(const char *WXUNUSED(name)) +// get i-th constructor parameter +const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const { - /* - assert(ExtendedTypeMap); - ExtendedTypeMap->erase(Name); - */ + return GetParents()[0]->GetCreateParamName( i ); } -const wxPropertyAccessor *wxClassInfo::FindAccessor(const char *PropertyName) +void wxDynamicClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, const wxAny &value) const { - const wxPropertyInfo* info = FindPropertyInfo( PropertyName ) ; + wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); + wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); + if ( FindPropertyInfoInThisClass(propertyName) ) + dynobj->SetProperty( propertyName, value ); + else + GetParents()[0]->SetProperty( dynobj->GetSuperClassInstance(), propertyName, value ); +} - if ( info ) - return info->GetAccessor() ; +wxAny wxDynamicClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const +{ + wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); + wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); + if ( FindPropertyInfoInThisClass(propertyName) ) + return dynobj->GetProperty( propertyName ); + else + return GetParents()[0]->GetProperty( dynobj->GetSuperClassInstance(), propertyName ); +} - return NULL ; +void wxDynamicClassInfo::AddProperty( const wxChar *propertyName, const wxTypeInfo* typeInfo ) +{ + EnsureInfosInited(); + new wxPropertyInfo( m_firstProperty, this, propertyName, typeInfo->GetTypeName(), new wxGenericPropertyAccessor( propertyName ), wxAny() ); } -const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const char *PropertyName) const +void wxDynamicClassInfo::AddHandler( const wxChar *handlerName, wxObjectEventFunction address, const wxClassInfo* eventClassInfo ) { - const wxPropertyInfo* info = GetFirstProperty() ; + EnsureInfosInited(); + new wxHandlerInfo( m_firstHandler, this, handlerName, address, eventClassInfo ); +} - while( info ) - { - if ( strcmp( info->GetName() , PropertyName ) == 0 ) - return info ; - info = info->GetNext() ; - } +// removes an existing runtime-property +void wxDynamicClassInfo::RemoveProperty( const wxChar *propertyName ) +{ + for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter ) + (*iter)->RemoveProperty( propertyName ); + delete FindPropertyInfoInThisClass(propertyName); +} - const wxClassInfo** parents = GetParents() ; - for ( int i = 0 ; parents[i] ; ++ i ) - { - if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL ) - return info ; - } +// removes an existing runtime-handler +void wxDynamicClassInfo::RemoveHandler( const wxChar *handlerName ) +{ + delete FindHandlerInfoInThisClass(handlerName); +} - return 0; +// renames an existing runtime-property +void wxDynamicClassInfo::RenameProperty( const wxChar *oldPropertyName, const wxChar *newPropertyName ) +{ + wxPropertyInfo* pi = FindPropertyInfoInThisClass(oldPropertyName); + wxASSERT_MSG( pi,wxT("not existing property") ); + pi->m_name = newPropertyName; + wx_dynamic_cast(wxGenericPropertyAccessor*, pi->GetAccessor())->RenameProperty( oldPropertyName, newPropertyName ); + for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter ) + (*iter)->RenameProperty( oldPropertyName, newPropertyName ); } -const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const char *PropertyName) const +// renames an existing runtime-handler +void wxDynamicClassInfo::RenameHandler( const wxChar *oldHandlerName, const wxChar *newHandlerName ) { - const wxHandlerInfo* info = GetFirstHandler() ; + wxASSERT_MSG(FindHandlerInfoInThisClass(oldHandlerName),wxT("not existing handler") ); + FindHandlerInfoInThisClass(oldHandlerName)->m_name = newHandlerName; +} - while( info ) - { - if ( strcmp( info->GetName() , PropertyName ) == 0 ) - return info ; - info = info->GetNext() ; - } +// ---------------------------------------------------------------------------- +// wxGenericPropertyAccessor +// ---------------------------------------------------------------------------- - const wxClassInfo** parents = GetParents() ; - for ( int i = 0 ; parents[i] ; ++ i ) - { - if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL ) - return info ; - } +struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal +{ + char filler; +}; - return 0; +wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString& propertyName ) +: wxPropertyAccessor( NULL, NULL, NULL, NULL ) +{ + m_data = new wxGenericPropertyAccessorInternal; + m_propertyName = propertyName; + m_getterName = wxT("Get")+propertyName; + m_setterName = wxT("Set")+propertyName; } +wxGenericPropertyAccessor::~wxGenericPropertyAccessor() +{ + delete m_data; +} -void wxClassInfo::SetProperty(wxObject *object, const char *propertyName, const wxxVariant &value) +void wxGenericPropertyAccessor::SetProperty(wxObject *object, const wxAny &value) const { - const wxPropertyAccessor *accessor; + wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); + wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); + dynobj->SetProperty(m_propertyName.c_str(), value ); +} - accessor = FindAccessor(propertyName); - wxASSERT(accessor->HasSetter()); - accessor->SetProperty( object , value ) ; +void wxGenericPropertyAccessor::GetProperty(const wxObject *object, wxAny& value) const +{ + const wxDynamicObject* dynobj = wx_dynamic_cast( const wxDynamicObject * , object ); + wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); + value = dynobj->GetProperty( m_propertyName.c_str() ); } -wxxVariant wxClassInfo::GetProperty(wxObject *object, const char *propertyName) +// ---------------------------------------------------------------------------- +// wxGenericPropertyAccessor +// ---------------------------------------------------------------------------- + +wxString wxAnyGetAsString( const wxAny& data) { - const wxPropertyAccessor *accessor; + if ( data.IsNull() || data.GetTypeInfo()==NULL ) + return wxEmptyString; - accessor = FindAccessor(propertyName); - wxASSERT(accessor->HasGetter()); - return accessor->GetProperty(object); + wxString s; + data.GetTypeInfo()->ConvertToString(data,s); + return s; } -/* -VARIANT TO OBJECT -*/ - -wxObject* wxxVariant::GetAsObject() +const wxObject* wxAnyGetAsObjectPtr( const wxAny& data) { - const wxClassTypeInfo *ti = dynamic_cast( m_data->GetTypeInfo() ) ; - if ( ti ) - return ti->GetClassInfo()->VariantToInstance(*this) ; - else - return NULL ; + if ( !data.IsNull() ) + { + const wxClassTypeInfo* ti = wx_dynamic_cast(const wxClassTypeInfo*, data.GetTypeInfo()); + if( ti ) + return ti->GetClassInfo()->AnyToObjectPtr(data); + } + return NULL; } +wxObjectFunctor::~wxObjectFunctor() +{}; -#endif +#endif // wxUSE_EXTENDED_RTTI