X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cc3977bf132d40cb66c6b488890ef67a396d4a0a..508bd1654f3eb44327fb84ecd2e2181959dac13b:/include/wx/xtitypes.h diff --git a/include/wx/xtitypes.h b/include/wx/xtitypes.h index 81331a885a..d3fd1432f8 100644 --- a/include/wx/xtitypes.h +++ b/include/wx/xtitypes.h @@ -1,581 +1,533 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wx/xtitypes.h -// Purpose: enum, set, basic types support -// Author: Stefan Csomor -// Modified by: Francesco Montorsi -// Created: 27/07/03 -// RCS-ID: $Id: xti.h 47299 2007-07-10 15:58:27Z FM $ -// Copyright: (c) 1997 Julian Smart -// (c) 2003 Stefan Csomor -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _XTITYPES_H_ -#define _XTITYPES_H_ - -#include "wx/defs.h" - -#if wxUSE_EXTENDED_RTTI - -#include "wx/string.h" -#include "wx/hashmap.h" -#include "wx/arrstr.h" -#include "wx/flags.h" -#include "wx/intl.h" -#include "wx/log.h" -#include - -class WXDLLIMPEXP_BASE wxClassInfo; - -// ---------------------------------------------------------------------------- -// Enum Support -// -// In the header files XTI requires no change from pure c++ code, however in the -// implementation, an enum needs to be enumerated eg: -// -// wxBEGIN_ENUM( wxFlavor ) -// wxENUM_MEMBER( Vanilla ) -// wxENUM_MEMBER( Chocolate ) -// wxENUM_MEMBER( Strawberry ) -// wxEND_ENUM( wxFlavor ) -// ---------------------------------------------------------------------------- - -struct WXDLLIMPEXP_BASE wxEnumMemberData -{ - const wxChar* m_name; - int m_value; -}; - -class WXDLLIMPEXP_BASE wxEnumData -{ -public: - wxEnumData( wxEnumMemberData* data ); - - // returns true if the member has been found and sets the int value - // pointed to accordingly (if ptr != null ) - // if not found returns false, value left unchanged - bool HasEnumMemberValue( const wxChar *name, int *value = NULL ) const; - - // returns the value of the member, if not found in debug mode an - // assert is issued, in release 0 is returned - int GetEnumMemberValue(const wxChar *name ) const; - - // returns the name of the enum member having the passed in value - // returns an emtpy string if not found - const wxChar *GetEnumMemberName(int value) const; - - // returns the number of members in this enum - int GetEnumCount() const { return m_count; } - - // returns the value of the nth member - int GetEnumMemberValueByIndex( int n ) const; - - // returns the value of the nth member - const wxChar *GetEnumMemberNameByIndex( int n ) const; - -private: - wxEnumMemberData *m_members; - int m_count; -}; - -#define wxBEGIN_ENUM( e ) \ - wxEnumMemberData s_enumDataMembers##e[] = { - -#define wxENUM_MEMBER( v ) { wxT(#v), v }, - -#define wxEND_ENUM( e ) \ - { NULL, 0 } }; \ - wxEnumData s_enumData##e( s_enumDataMembers##e ); \ - wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \ - template<> void wxStringReadValue(const wxString& s, e &data ) \ - { data = (e) s_enumData##e.GetEnumMemberValue(s); } \ - template<> void wxStringWriteValue(wxString &s, const e &data ) \ - { s = s_enumData##e.GetEnumMemberName((int)data); } \ - void FromLong##e( long data, wxVariantBase& result ) \ - { result = wxVariantBase((e)data); } \ - void ToLong##e( const wxVariantBase& data, long &result ) \ - { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, e); } \ - \ - wxTO_STRING_IMP( e ) \ - wxFROM_STRING_IMP( e ) \ - wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \ - &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \ - &FromLong##e, typeid(e).name() ); - - -// ---------------------------------------------------------------------------- -// Set Support -// -// in the header : -// -// enum wxFlavor -// { -// Vanilla, -// Chocolate, -// Strawberry, -// }; -// -// typedef wxBitset wxCoupe; -// -// in the implementation file : -// -// wxBEGIN_ENUM( wxFlavor ) -// wxENUM_MEMBER( Vanilla ) -// wxENUM_MEMBER( Chocolate ) -// wxENUM_MEMBER( Strawberry ) -// wxEND_ENUM( wxFlavor ) -// -// wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor ) -// -// implementation note: no partial specialization for streaming, but a delegation -// to a different class -// -// ---------------------------------------------------------------------------- - -// in order to remove dependancy on string tokenizer -void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array ); - -template -void wxSetFromString(const wxString &s, wxBitset &data ) -{ - wxEnumData* edata = wxGetEnumData((e) 0); - data.reset(); - - wxArrayString array; - wxSetStringToArray( s, array ); - wxString flag; - for ( int i = 0; i < array.Count(); ++i ) - { - flag = array[i]; - int ivalue; - if ( edata->HasEnumMemberValue( flag, &ivalue ) ) - { - data.set( (e) ivalue ); - } - } -} - -template -void wxSetToString( wxString &s, const wxBitset &data ) -{ - wxEnumData* edata = wxGetEnumData((e) 0); - int count = edata->GetEnumCount(); - int i; - s.Clear(); - for ( i = 0; i < count; i++ ) - { - e value = (e) edata->GetEnumMemberValueByIndex(i); - if ( data.test( value ) ) - { - // this could also be done by the templated calls - if ( !s.empty() ) - s += wxT("|"); - s += edata->GetEnumMemberNameByIndex(i); - } - } -} - -#define wxIMPLEMENT_SET_STREAMING(SetName,e) \ - template<> void wxStringReadValue(const wxString &s, wxBitset &data ) \ - { wxSetFromString( s, data ); } \ - template<> void wxStringWriteValue( wxString &s, const wxBitset &data ) \ - { wxSetToString( s, data ); } \ - void FromLong##SetName( long data, wxVariantBase& result ) \ - { result = wxVariantBase(SetName((unsigned long)data)); } \ - void ToLong##SetName( const wxVariantBase& data, long &result ) \ - { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, SetName).to_ulong(); } \ - wxTO_STRING_IMP( SetName ) \ - wxFROM_STRING_IMP( SetName ) \ - wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \ - &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \ - &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() ); - -template -void wxFlagsFromString(const wxString &s, e &data ) -{ - wxEnumData* edata = wxGetEnumData((e*) 0); - data.m_data = 0; - - wxArrayString array; - wxSetStringToArray( s, array ); - wxString flag; - for ( size_t i = 0; i < array.Count(); ++i ) - { - flag = array[i]; - int ivalue; - if ( edata->HasEnumMemberValue( flag, &ivalue ) ) - { - data.m_data |= ivalue; - } - } -} - -template -void wxFlagsToString( wxString &s, const e& data ) -{ - wxEnumData* edata = wxGetEnumData((e*) 0); - int count = edata->GetEnumCount(); - int i; - s.Clear(); - long dataValue = data.m_data; - for ( i = 0; i < count; i++ ) - { - int value = edata->GetEnumMemberValueByIndex(i); - // make this to allow for multi-bit constants to work - if ( value && ( dataValue & value ) == value ) - { - // clear the flags we just set - dataValue &= ~value; - // this could also be done by the templated calls - if ( !s.empty() ) - s +=wxT("|"); - s += edata->GetEnumMemberNameByIndex(i); - } - } -} - -#define wxBEGIN_FLAGS( e ) \ - wxEnumMemberData s_enumDataMembers##e[] = { - -#define wxFLAGS_MEMBER( v ) { wxT(#v), v }, - -#define wxEND_FLAGS( e ) \ - { NULL, 0 } }; \ - wxEnumData s_enumData##e( s_enumDataMembers##e ); \ - wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \ - template<> void wxStringReadValue(const wxString &s, e &data ) \ - { wxFlagsFromString( s, data ); } \ - template<> void wxStringWriteValue( wxString &s, const e& data ) \ - { wxFlagsToString( s, data ); } \ - void FromLong##e( long data, wxVariantBase& result ) \ - { result = wxVariantBase(e(data)); } \ - void ToLong##e( const wxVariantBase& data, long &result ) \ - { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, e).m_data; } \ - wxTO_STRING_IMP( e ) \ - wxFROM_STRING_IMP( e ) \ - wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \ - &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \ - &FromLong##e, typeid(e).name() ); - -// ---------------------------------------------------------------------------- -// Type Information -// ---------------------------------------------------------------------------- - -// All data exposed by the RTTI is characterized using the following classes. -// The first characterization is done by wxTypeKind. All enums up to and including -// wxT_CUSTOM represent so called simple types. These cannot be divided any further. -// They can be converted to and from wxStrings, that's all. -// Other wxTypeKinds can instead be splitted recursively into smaller parts until -// the simple types are reached. - -enum wxTypeKind -{ - wxT_VOID = 0, // unknown type - wxT_BOOL, - wxT_CHAR, - wxT_UCHAR, - wxT_INT, - wxT_UINT, - wxT_LONG, - wxT_ULONG, - wxT_FLOAT, - wxT_DOUBLE, - wxT_STRING, // must be wxString - wxT_SET, // must be wxBitset<> template - wxT_ENUM, - wxT_CUSTOM, // user defined type (e.g. wxPoint) - - wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM, - - wxT_OBJECT_PTR, // object reference - wxT_OBJECT, // embedded object - wxT_COLLECTION, // collection - - wxT_DELEGATE, // for connecting against an event source - - wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging -}; - -class WXDLLIMPEXP_BASE wxVariantBase; -class WXDLLIMPEXP_BASE wxTypeInfo; - -WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE ); - -class WXDLLIMPEXP_BASE wxTypeInfo -{ -public: - typedef void (*wxVariant2StringFnc)( const wxVariantBase& data, wxString &result ); - typedef void (*wxString2VariantFnc)( const wxString& data, wxVariantBase &result ); - - wxTypeInfo(wxTypeKind kind, - wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL, - const wxString &name = wxEmptyString): - m_toString(to), m_fromString(from), m_kind(kind), m_name(name) - { - Register(); - } -#if wxUSE_UNICODE - wxTypeInfo(wxTypeKind kind, - wxVariant2StringFnc to, wxString2VariantFnc from, - const char *name): - m_toString(to), m_fromString(from), m_kind(kind), - m_name(wxString::FromAscii(name)) - { - Register(); - } -#endif - - virtual ~wxTypeInfo() - { - Unregister(); - } - - // return the kind of this type (wxT_... constants) - wxTypeKind GetKind() const { return m_kind; } - - // returns the unique name of this type - const wxString& GetTypeName() const { return m_name; } - - // is this type a delegate type - bool IsDelegateType() const { return m_kind == wxT_DELEGATE; } - - // is this type a custom type - bool IsCustomType() const { return m_kind == wxT_CUSTOM; } - - // is this type an object type - bool IsObjectType() const { return m_kind == wxT_OBJECT || m_kind == wxT_OBJECT_PTR; } - - // can the content of this type be converted to and from strings ? - bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; } - - // convert a wxVariantBase holding data of this type into a string - void ConvertToString( const wxVariantBase& data, wxString &result ) const - { - if ( m_toString ) - (*m_toString)( data, result ); - else - wxLogError( wxGetTranslation(_T("String conversions not supported")) ); - } - - // convert a string into a wxVariantBase holding the corresponding data in this type - void ConvertFromString( const wxString& data, wxVariantBase &result ) const - { - if( m_fromString ) - (*m_fromString)( data, result ); - else - wxLogError( wxGetTranslation(_T("String conversions not supported")) ); - } - - // statics: - -#if wxUSE_UNICODE - static wxTypeInfo *FindType(const char *typeName) - { return FindType( wxString::FromAscii(typeName) ); } -#endif - static wxTypeInfo *FindType(const wxChar *typeName); - static wxTypeInfo *FindType(const wxString& typeName) - { -#if wxUSE_UNICODE - return FindType( typeName.wchar_str() ); -#else - return FindType( typeName.char_str() ); -#endif - } - -private: - void Register(); - void Unregister(); - - wxVariant2StringFnc m_toString; - wxString2VariantFnc m_fromString; - - wxTypeKind m_kind; - wxString m_name; - - // the static list of all types we know about - static wxTypeInfoMap* ms_typeTable; -}; - -class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo -{ -public: - wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL, - wxString2VariantFnc from = NULL, - const wxString &name = wxEmptyString ) : - wxTypeInfo( kind, to, from, name ) - { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); } - -#if wxUSE_UNICODE - wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to, - wxString2VariantFnc from , const char *name ) : - wxTypeInfo( kind, to, from, name ) - { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); } -#endif -}; - -class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo -{ -public: - wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to, - wxString2VariantFnc from ) : - wxTypeInfo( wxT_CUSTOM, to, from, name ) - {} - -#if wxUSE_UNICODE - wxCustomTypeInfo( const char *name , wxVariant2StringFnc to, - wxString2VariantFnc from ) : - wxTypeInfo( wxT_CUSTOM, to, from, name ) - {} -#endif -}; - -class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo -{ -public: - typedef void (*converterToLong_t)( const wxVariantBase& data, long &result ); - typedef void (*converterFromLong_t)( long data, wxVariantBase &result ); - - wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to, - wxString2VariantFnc from, converterToLong_t toLong, - converterFromLong_t fromLong, const wxString &name ) : - wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong ) - { - wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET, - wxT("Illegal Kind for Enum Type")); - m_enumInfo = enumInfo; - } - -#if wxUSE_UNICODE - wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to, - wxString2VariantFnc from, converterToLong_t toLong, - converterFromLong_t fromLong, const char * name ) : - wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong ) - { - wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET, - wxT("Illegal Kind for Enum Type")); - m_enumInfo = enumInfo; - } -#endif - const wxEnumData* GetEnumData() const { return m_enumInfo; } - - // convert a wxVariantBase holding data of this type into a long - void ConvertToLong( const wxVariantBase& data, long &result ) const - { - if( m_toLong ) - (*m_toLong)( data, result ); - else - wxLogError( wxGetTranslation(_T("Long Conversions not supported")) ); - } - - // convert a long into a wxVariantBase holding the corresponding data in this type - void ConvertFromLong( long data, wxVariantBase &result ) const - { - if( m_fromLong ) - (*m_fromLong)( data, result ); - else - wxLogError( wxGetTranslation(_T("Long Conversions not supported")) ); - } - -private: - converterToLong_t m_toLong; - converterFromLong_t m_fromLong; - - wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET -}; - -class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo -{ -public: - wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, - wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL, - const wxString &name = wxEmptyString); - -#if wxUSE_UNICODE - wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, wxVariant2StringFnc to, - wxString2VariantFnc from , const char *name ); -#endif - - const wxClassInfo *GetClassInfo() const { return m_classInfo; } - -private: - wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL -}; - -class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo -{ -public: - wxCollectionTypeInfo( const wxString &elementName, wxVariant2StringFnc to, - wxString2VariantFnc from , const wxString &name) : - wxTypeInfo( wxT_COLLECTION, to, from, name ) - { m_elementTypeName = elementName; m_elementType = NULL; } - -#if wxUSE_UNICODE - wxCollectionTypeInfo( const char *elementName, wxVariant2StringFnc to, - wxString2VariantFnc from , const char *name ) : - wxTypeInfo( wxT_COLLECTION, to, from, name ) - { m_elementTypeName = wxString::FromAscii( elementName ); m_elementType = NULL; } -#endif - - const wxTypeInfo* GetElementType() const - { - if ( m_elementType == NULL ) - m_elementType = wxTypeInfo::FindType( m_elementTypeName ); - return m_elementType; - } - -private: - mutable wxTypeInfo * m_elementType; - wxString m_elementTypeName; -}; - -class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo -{ -public: - wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass, - wxVariant2StringFnc to = NULL, - wxString2VariantFnc from = NULL ); - wxEventSourceTypeInfo( int eventType, int lastEventType, wxClassInfo* eventClass, - wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL ); - - int GetEventType() const { return m_eventType; } - int GetLastEventType() const { return m_lastEventType; } - const wxClassInfo* GetEventClass() const { return m_eventClass; } - -private: - const wxClassInfo *m_eventClass; // (extended will merge into classinfo) - int m_eventType; - int m_lastEventType; -}; - -template const wxTypeInfo* wxGetTypeInfo( T * ) \ - { return wxTypeInfo::FindType(typeid(T).name()); } - -// this macro is for usage with custom, non-object derived classes and structs, -// wxPoint is such a custom type - -#if wxUSE_FUNC_TEMPLATE_POINTER - #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \ - wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString); -#else - #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \ - void ToString##e( const wxVariantBase& data, wxString &result ) \ - { toString(data, result); } \ - void FromString##e( const wxString& data, wxVariantBase &result ) \ - { fromString(data, result); } \ - wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \ - &ToString##e, &FromString##e); -#endif - -#define wxCOLLECTION_TYPE_INFO( element, collection ) \ - wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \ - NULL, NULL, typeid(collection).name() ); - -// sometimes a compiler invents specializations that are nowhere called, -// use this macro to satisfy the refs, currently we don't have to play -// tricks, but if we will have to according to the compiler, we will use -// that macro for that - -#define wxILLEGAL_TYPE_SPECIALIZATION( a ) - -#endif // wxUSE_EXTENDED_RTTI -#endif // _XTITYPES_H_ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/xtitypes.h +// Purpose: enum, set, basic types support +// Author: Stefan Csomor +// Modified by: Francesco Montorsi +// Created: 27/07/03 +// RCS-ID: $Id$ +// Copyright: (c) 1997 Julian Smart +// (c) 2003 Stefan Csomor +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _XTITYPES_H_ +#define _XTITYPES_H_ + +#include "wx/defs.h" + +#if wxUSE_EXTENDED_RTTI + +#include "wx/string.h" +#include "wx/hashmap.h" +#include "wx/arrstr.h" +#include "wx/flags.h" +#include "wx/intl.h" +#include "wx/log.h" +#include + +class WXDLLIMPEXP_BASE wxClassInfo; + +// ---------------------------------------------------------------------------- +// Enum Support +// +// In the header files XTI requires no change from pure c++ code, however in the +// implementation, an enum needs to be enumerated eg: +// +// wxBEGIN_ENUM( wxFlavor ) +// wxENUM_MEMBER( Vanilla ) +// wxENUM_MEMBER( Chocolate ) +// wxENUM_MEMBER( Strawberry ) +// wxEND_ENUM( wxFlavor ) +// ---------------------------------------------------------------------------- + +struct WXDLLIMPEXP_BASE wxEnumMemberData +{ + const wxChar* m_name; + int m_value; +}; + +class WXDLLIMPEXP_BASE wxEnumData +{ +public: + wxEnumData( wxEnumMemberData* data ); + + // returns true if the member has been found and sets the int value + // pointed to accordingly (if ptr != null ) + // if not found returns false, value left unchanged + bool HasEnumMemberValue( const wxChar *name, int *value = NULL ) const; + + // returns the value of the member, if not found in debug mode an + // assert is issued, in release 0 is returned + int GetEnumMemberValue(const wxChar *name ) const; + + // returns the name of the enum member having the passed in value + // returns an emtpy string if not found + const wxChar *GetEnumMemberName(int value) const; + + // returns the number of members in this enum + int GetEnumCount() const { return m_count; } + + // returns the value of the nth member + int GetEnumMemberValueByIndex( int n ) const; + + // returns the value of the nth member + const wxChar *GetEnumMemberNameByIndex( int n ) const; + +private: + wxEnumMemberData *m_members; + int m_count; +}; + +#define wxBEGIN_ENUM( e ) \ + wxEnumMemberData s_enumDataMembers##e[] = { + +#define wxENUM_MEMBER( v ) { wxT(#v), v }, + +#define wxEND_ENUM( e ) \ + { NULL, 0 } }; \ + wxEnumData s_enumData##e( s_enumDataMembers##e ); \ + wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \ + template<> void wxStringReadValue(const wxString& s, e &data ) \ + { data = (e) s_enumData##e.GetEnumMemberValue(s.c_str()); } \ + template<> void wxStringWriteValue(wxString &s, const e &data ) \ + { s = s_enumData##e.GetEnumMemberName((int)data); } \ + void FromLong##e( long data, wxAny& result ) \ + { result = wxAny((e)data); } \ + void ToLong##e( const wxAny& data, long &result ) \ + { result = (long) (data).As(static_cast(NULL)); } \ + \ + wxTO_STRING_IMP( e ) \ + wxFROM_STRING_IMP( e ) \ + wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \ + &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \ + &FromLong##e, typeid(e).name() ); + + +// ---------------------------------------------------------------------------- +// Set Support +// +// in the header : +// +// enum wxFlavor +// { +// Vanilla, +// Chocolate, +// Strawberry, +// }; +// +// typedef wxBitset wxCoupe; +// +// in the implementation file : +// +// wxBEGIN_ENUM( wxFlavor ) +// wxENUM_MEMBER( Vanilla ) +// wxENUM_MEMBER( Chocolate ) +// wxENUM_MEMBER( Strawberry ) +// wxEND_ENUM( wxFlavor ) +// +// wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor ) +// +// implementation note: no partial specialization for streaming, but a delegation +// to a different class +// +// ---------------------------------------------------------------------------- + +void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array ); + +template +void wxSetFromString(const wxString &s, wxBitset &data ) +{ + wxEnumData* edata = wxGetEnumData((e) 0); + data.reset(); + + wxArrayString array; + wxSetStringToArray( s, array ); + wxString flag; + for ( int i = 0; i < array.Count(); ++i ) + { + flag = array[i]; + int ivalue; + if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) ) + { + data.set( (e) ivalue ); + } + } +} + +template +void wxSetToString( wxString &s, const wxBitset &data ) +{ + wxEnumData* edata = wxGetEnumData((e) 0); + int count = edata->GetEnumCount(); + int i; + s.Clear(); + for ( i = 0; i < count; i++ ) + { + e value = (e) edata->GetEnumMemberValueByIndex(i); + if ( data.test( value ) ) + { + // this could also be done by the templated calls + if ( !s.empty() ) + s += wxT("|"); + s += edata->GetEnumMemberNameByIndex(i); + } + } +} + +#define wxIMPLEMENT_SET_STREAMING(SetName,e) \ + template<> void wxStringReadValue(const wxString &s, wxBitset &data ) \ + { wxSetFromString( s, data ); } \ + template<> void wxStringWriteValue( wxString &s, const wxBitset &data ) \ + { wxSetToString( s, data ); } \ + void FromLong##SetName( long data, wxAny& result ) \ + { result = wxAny(SetName((unsigned long)data)); } \ + void ToLong##SetName( const wxAny& data, long &result ) \ + { result = (long) (data).As(static_cast(NULL)).to_ulong(); } \ + wxTO_STRING_IMP( SetName ) \ + wxFROM_STRING_IMP( SetName ) \ + wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \ + &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \ + &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() ); + +template +void wxFlagsFromString(const wxString &s, e &data ) +{ + wxEnumData* edata = wxGetEnumData((e*) 0); + data.m_data = 0; + + wxArrayString array; + wxSetStringToArray( s, array ); + wxString flag; + for ( size_t i = 0; i < array.Count(); ++i ) + { + flag = array[i]; + int ivalue; + if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) ) + { + data.m_data |= ivalue; + } + } +} + +template +void wxFlagsToString( wxString &s, const e& data ) +{ + wxEnumData* edata = wxGetEnumData((e*) 0); + int count = edata->GetEnumCount(); + int i; + s.Clear(); + long dataValue = data.m_data; + for ( i = 0; i < count; i++ ) + { + int value = edata->GetEnumMemberValueByIndex(i); + // make this to allow for multi-bit constants to work + if ( value && ( dataValue & value ) == value ) + { + // clear the flags we just set + dataValue &= ~value; + // this could also be done by the templated calls + if ( !s.empty() ) + s +=wxT("|"); + s += edata->GetEnumMemberNameByIndex(i); + } + } +} + +#define wxBEGIN_FLAGS( e ) \ + wxEnumMemberData s_enumDataMembers##e[] = { + +#define wxFLAGS_MEMBER( v ) { wxT(#v), static_cast(v) }, + +#define wxEND_FLAGS( e ) \ + { NULL, 0 } }; \ + wxEnumData s_enumData##e( s_enumDataMembers##e ); \ + wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \ + template<> void wxStringReadValue(const wxString &s, e &data ) \ + { wxFlagsFromString( s, data ); } \ + template<> void wxStringWriteValue( wxString &s, const e& data ) \ + { wxFlagsToString( s, data ); } \ + void FromLong##e( long data, wxAny& result ) \ + { result = wxAny(e(data)); } \ + void ToLong##e( const wxAny& data, long &result ) \ + { result = (long) (data).As(static_cast(NULL)).m_data; } \ + wxTO_STRING_IMP( e ) \ + wxFROM_STRING_IMP( e ) \ + wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \ + &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \ + &FromLong##e, typeid(e).name() ); + +// ---------------------------------------------------------------------------- +// Type Information +// ---------------------------------------------------------------------------- + +// All data exposed by the RTTI is characterized using the following classes. +// The first characterization is done by wxTypeKind. All enums up to and including +// wxT_CUSTOM represent so called simple types. These cannot be divided any further. +// They can be converted to and from wxStrings, that's all. +// Other wxTypeKinds can instead be splitted recursively into smaller parts until +// the simple types are reached. + +enum wxTypeKind +{ + wxT_VOID = 0, // unknown type + wxT_BOOL, + wxT_CHAR, + wxT_UCHAR, + wxT_INT, + wxT_UINT, + wxT_LONG, + wxT_ULONG, + wxT_LONGLONG, + wxT_ULONGLONG, + wxT_FLOAT, + wxT_DOUBLE, + wxT_STRING, // must be wxString + wxT_SET, // must be wxBitset<> template + wxT_ENUM, + wxT_CUSTOM, // user defined type (e.g. wxPoint) + + wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM, + + wxT_OBJECT_PTR, // object reference + wxT_OBJECT, // embedded object + wxT_COLLECTION, // collection + + wxT_DELEGATE, // for connecting against an event source + + wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging +}; + +class WXDLLIMPEXP_BASE wxAny; +class WXDLLIMPEXP_BASE wxTypeInfo; + +WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE ); + +class WXDLLIMPEXP_BASE wxTypeInfo +{ +public: + typedef void (*wxVariant2StringFnc)( const wxAny& data, wxString &result ); + typedef void (*wxString2VariantFnc)( const wxString& data, wxAny &result ); + + wxTypeInfo(wxTypeKind kind, + wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL, + const wxString &name = wxEmptyString): + m_toString(to), m_fromString(from), m_kind(kind), m_name(name) + { + Register(); + } +#if 0 // wxUSE_UNICODE + wxTypeInfo(wxTypeKind kind, + wxVariant2StringFnc to, wxString2VariantFnc from, + const char *name): + m_toString(to), m_fromString(from), m_kind(kind), + m_name(wxString::FromAscii(name)) + { + Register(); + } +#endif + + virtual ~wxTypeInfo() + { + Unregister(); + } + + // return the kind of this type (wxT_... constants) + wxTypeKind GetKind() const { return m_kind; } + + // returns the unique name of this type + const wxString& GetTypeName() const { return m_name; } + + // is this type a delegate type + bool IsDelegateType() const { return m_kind == wxT_DELEGATE; } + + // is this type a custom type + bool IsCustomType() const { return m_kind == wxT_CUSTOM; } + + // is this type an object type + bool IsObjectType() const { return m_kind == wxT_OBJECT || m_kind == wxT_OBJECT_PTR; } + + // can the content of this type be converted to and from strings ? + bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; } + + // convert a wxAny holding data of this type into a string + void ConvertToString( const wxAny& data, wxString &result ) const + { + if ( m_toString ) + (*m_toString)( data, result ); + else + wxLogError( wxGetTranslation(wxT("String conversions not supported")) ); + } + + // convert a string into a wxAny holding the corresponding data in this type + void ConvertFromString( const wxString& data, wxAny &result ) const + { + if( m_fromString ) + (*m_fromString)( data, result ); + else + wxLogError( wxGetTranslation(wxT("String conversions not supported")) ); + } + + // statics: + + // looks for the corresponding type, will return NULL if not found + static wxTypeInfo *FindType( const wxString& typeName ); +private: + void Register(); + void Unregister(); + + wxVariant2StringFnc m_toString; + wxString2VariantFnc m_fromString; + + wxTypeKind m_kind; + wxString m_name; + + // the static list of all types we know about + static wxTypeInfoMap* ms_typeTable; +}; + +class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo +{ +public: + wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL, + wxString2VariantFnc from = NULL, + const wxString &name = wxEmptyString ) : + wxTypeInfo( kind, to, from, name ) + { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); } +}; + +class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo +{ +public: + wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to, + wxString2VariantFnc from ) : + wxTypeInfo( wxT_CUSTOM, to, from, name ) + {} +}; + +class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo +{ +public: + typedef void (*converterToLong_t)( const wxAny& data, long &result ); + typedef void (*converterFromLong_t)( long data, wxAny &result ); + + wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to, + wxString2VariantFnc from, converterToLong_t toLong, + converterFromLong_t fromLong, const wxString &name ) : + wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong ) + { + wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET, + wxT("Illegal Kind for Enum Type")); + m_enumInfo = enumInfo; + } + + const wxEnumData* GetEnumData() const { return m_enumInfo; } + + // convert a wxAny holding data of this type into a long + void ConvertToLong( const wxAny& data, long &result ) const + { + if( m_toLong ) + (*m_toLong)( data, result ); + else + wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) ); + } + + // convert a long into a wxAny holding the corresponding data in this type + void ConvertFromLong( long data, wxAny &result ) const + { + if( m_fromLong ) + (*m_fromLong)( data, result ); + else + wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) ); + } + +private: + converterToLong_t m_toLong; + converterFromLong_t m_fromLong; + + wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET +}; + +class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo +{ +public: + wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, + wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL, + const wxString &name = wxEmptyString); + + const wxClassInfo *GetClassInfo() const { return m_classInfo; } + +private: + wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL +}; + +class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo +{ +public: + wxCollectionTypeInfo( const wxString &elementName, wxVariant2StringFnc to, + wxString2VariantFnc from , const wxString &name) : + wxTypeInfo( wxT_COLLECTION, to, from, name ) + { m_elementTypeName = elementName; m_elementType = NULL; } + + const wxTypeInfo* GetElementType() const + { + if ( m_elementType == NULL ) + m_elementType = wxTypeInfo::FindType( m_elementTypeName ); + return m_elementType; + } + +private: + mutable wxTypeInfo * m_elementType; + wxString m_elementTypeName; +}; + +class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo +{ +public: + wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass, + wxVariant2StringFnc to = NULL, + wxString2VariantFnc from = NULL ); + wxEventSourceTypeInfo( int eventType, int lastEventType, wxClassInfo* eventClass, + wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL ); + + int GetEventType() const { return m_eventType; } + int GetLastEventType() const { return m_lastEventType; } + const wxClassInfo* GetEventClass() const { return m_eventClass; } + +private: + const wxClassInfo *m_eventClass; // (extended will merge into classinfo) + int m_eventType; + int m_lastEventType; +}; + +template const wxTypeInfo* wxGetTypeInfo( T * ) + { return wxTypeInfo::FindType(typeid(T).name()); } + +// this macro is for usage with custom, non-object derived classes and structs, +// wxPoint is such a custom type + +#if wxUSE_FUNC_TEMPLATE_POINTER + #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \ + wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString); +#else + #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \ + void ToString##e( const wxAny& data, wxString &result ) \ + { toString(data, result); } \ + void FromString##e( const wxString& data, wxAny &result ) \ + { fromString(data, result); } \ + wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \ + &ToString##e, &FromString##e); +#endif + +#define wxCOLLECTION_TYPE_INFO( element, collection ) \ + wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \ + NULL, NULL, typeid(collection).name() ); + +// sometimes a compiler invents specializations that are nowhere called, +// use this macro to satisfy the refs, currently we don't have to play +// tricks, but if we will have to according to the compiler, we will use +// that macro for that + +#define wxILLEGAL_TYPE_SPECIALIZATION( a ) + +#endif // wxUSE_EXTENDED_RTTI +#endif // _XTITYPES_H_