1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: enum, set, basic types support
4 // Author: Stefan Csomor
5 // Modified by: Francesco Montorsi
7 // Copyright: (c) 1997 Julian Smart
8 // (c) 2003 Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
17 #if wxUSE_EXTENDED_RTTI
19 #include "wx/string.h"
20 #include "wx/hashmap.h"
21 #include "wx/arrstr.h"
27 class WXDLLIMPEXP_BASE wxClassInfo
;
29 // ----------------------------------------------------------------------------
32 // In the header files XTI requires no change from pure c++ code, however in the
33 // implementation, an enum needs to be enumerated eg:
35 // wxBEGIN_ENUM( wxFlavor )
36 // wxENUM_MEMBER( Vanilla )
37 // wxENUM_MEMBER( Chocolate )
38 // wxENUM_MEMBER( Strawberry )
39 // wxEND_ENUM( wxFlavor )
40 // ----------------------------------------------------------------------------
42 struct WXDLLIMPEXP_BASE wxEnumMemberData
48 class WXDLLIMPEXP_BASE wxEnumData
51 wxEnumData( wxEnumMemberData
* data
);
53 // returns true if the member has been found and sets the int value
54 // pointed to accordingly (if ptr != null )
55 // if not found returns false, value left unchanged
56 bool HasEnumMemberValue( const wxChar
*name
, int *value
= NULL
) const;
58 // returns the value of the member, if not found in debug mode an
59 // assert is issued, in release 0 is returned
60 int GetEnumMemberValue(const wxChar
*name
) const;
62 // returns the name of the enum member having the passed in value
63 // returns an emtpy string if not found
64 const wxChar
*GetEnumMemberName(int value
) const;
66 // returns the number of members in this enum
67 int GetEnumCount() const { return m_count
; }
69 // returns the value of the nth member
70 int GetEnumMemberValueByIndex( int n
) const;
72 // returns the value of the nth member
73 const wxChar
*GetEnumMemberNameByIndex( int n
) const;
76 wxEnumMemberData
*m_members
;
80 #define wxBEGIN_ENUM( e ) \
81 wxEnumMemberData s_enumDataMembers##e[] = {
83 #define wxENUM_MEMBER( v ) { wxT(#v), v },
85 #define wxEND_ENUM( e ) \
87 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
88 wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \
89 template<> void wxStringReadValue(const wxString& s, e &data ) \
90 { data = (e) s_enumData##e.GetEnumMemberValue(s.c_str()); } \
91 template<> void wxStringWriteValue(wxString &s, const e &data ) \
92 { s = s_enumData##e.GetEnumMemberName((int)data); } \
93 void FromLong##e( long data, wxAny& result ) \
94 { result = wxAny((e)data); } \
95 void ToLong##e( const wxAny& data, long &result ) \
96 { result = (long) (data).As(static_cast<e*>(NULL)); } \
98 wxTO_STRING_IMP( e ) \
99 wxFROM_STRING_IMP( e ) \
100 wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \
101 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
102 &FromLong##e, typeid(e).name() );
105 // ----------------------------------------------------------------------------
117 // typedef wxBitset<wxFlavor> wxCoupe;
119 // in the implementation file :
121 // wxBEGIN_ENUM( wxFlavor )
122 // wxENUM_MEMBER( Vanilla )
123 // wxENUM_MEMBER( Chocolate )
124 // wxENUM_MEMBER( Strawberry )
125 // wxEND_ENUM( wxFlavor )
127 // wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
129 // implementation note: no partial specialization for streaming, but a delegation
130 // to a different class
132 // ----------------------------------------------------------------------------
134 void WXDLLIMPEXP_BASE
wxSetStringToArray( const wxString
&s
, wxArrayString
&array
);
137 void wxSetFromString(const wxString
&s
, wxBitset
<e
> &data
)
139 wxEnumData
* edata
= wxGetEnumData((e
) 0);
143 wxSetStringToArray( s
, array
);
145 for ( int i
= 0; i
< array
.Count(); ++i
)
149 if ( edata
->HasEnumMemberValue( flag
.c_str(), &ivalue
) )
151 data
.set( (e
) ivalue
);
157 void wxSetToString( wxString
&s
, const wxBitset
<e
> &data
)
159 wxEnumData
* edata
= wxGetEnumData((e
) 0);
160 int count
= edata
->GetEnumCount();
163 for ( i
= 0; i
< count
; i
++ )
165 e value
= (e
) edata
->GetEnumMemberValueByIndex(i
);
166 if ( data
.test( value
) )
168 // this could also be done by the templated calls
171 s
+= edata
->GetEnumMemberNameByIndex(i
);
176 #define wxIMPLEMENT_SET_STREAMING(SetName,e) \
177 template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \
178 { wxSetFromString( s, data ); } \
179 template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \
180 { wxSetToString( s, data ); } \
181 void FromLong##SetName( long data, wxAny& result ) \
182 { result = wxAny(SetName((unsigned long)data)); } \
183 void ToLong##SetName( const wxAny& data, long &result ) \
184 { result = (long) (data).As(static_cast<SetName*>(NULL)).to_ulong(); } \
185 wxTO_STRING_IMP( SetName ) \
186 wxFROM_STRING_IMP( SetName ) \
187 wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \
188 &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \
189 &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() );
192 void wxFlagsFromString(const wxString
&s
, e
&data
)
194 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
198 wxSetStringToArray( s
, array
);
200 for ( size_t i
= 0; i
< array
.Count(); ++i
)
204 if ( edata
->HasEnumMemberValue( flag
.c_str(), &ivalue
) )
206 data
.m_data
|= ivalue
;
212 void wxFlagsToString( wxString
&s
, const e
& data
)
214 wxEnumData
* edata
= wxGetEnumData((e
*) 0);
215 int count
= edata
->GetEnumCount();
218 long dataValue
= data
.m_data
;
219 for ( i
= 0; i
< count
; i
++ )
221 int value
= edata
->GetEnumMemberValueByIndex(i
);
222 // make this to allow for multi-bit constants to work
223 if ( value
&& ( dataValue
& value
) == value
)
225 // clear the flags we just set
227 // this could also be done by the templated calls
230 s
+= edata
->GetEnumMemberNameByIndex(i
);
235 #define wxBEGIN_FLAGS( e ) \
236 wxEnumMemberData s_enumDataMembers##e[] = {
238 #define wxFLAGS_MEMBER( v ) { wxT(#v), static_cast<int>(v) },
240 #define wxEND_FLAGS( e ) \
242 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
243 wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \
244 template<> void wxStringReadValue(const wxString &s, e &data ) \
245 { wxFlagsFromString<e>( s, data ); } \
246 template<> void wxStringWriteValue( wxString &s, const e& data ) \
247 { wxFlagsToString<e>( s, data ); } \
248 void FromLong##e( long data, wxAny& result ) \
249 { result = wxAny(e(data)); } \
250 void ToLong##e( const wxAny& data, long &result ) \
251 { result = (long) (data).As(static_cast<e*>(NULL)).m_data; } \
252 wxTO_STRING_IMP( e ) \
253 wxFROM_STRING_IMP( e ) \
254 wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \
255 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
256 &FromLong##e, typeid(e).name() );
258 // ----------------------------------------------------------------------------
260 // ----------------------------------------------------------------------------
262 // All data exposed by the RTTI is characterized using the following classes.
263 // The first characterization is done by wxTypeKind. All enums up to and including
264 // wxT_CUSTOM represent so called simple types. These cannot be divided any further.
265 // They can be converted to and from wxStrings, that's all.
266 // Other wxTypeKinds can instead be splitted recursively into smaller parts until
267 // the simple types are reached.
271 wxT_VOID
= 0, // unknown type
283 wxT_STRING
, // must be wxString
284 wxT_SET
, // must be wxBitset<> template
286 wxT_CUSTOM
, // user defined type (e.g. wxPoint)
288 wxT_LAST_SIMPLE_TYPE_KIND
= wxT_CUSTOM
,
290 wxT_OBJECT_PTR
, // object reference
291 wxT_OBJECT
, // embedded object
292 wxT_COLLECTION
, // collection
294 wxT_DELEGATE
, // for connecting against an event source
296 wxT_LAST_TYPE_KIND
= wxT_DELEGATE
// sentinel for bad data, asserts, debugging
299 class WXDLLIMPEXP_BASE wxAny
;
300 class WXDLLIMPEXP_BASE wxTypeInfo
;
302 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo
*, wxTypeInfoMap
, class WXDLLIMPEXP_BASE
);
304 class WXDLLIMPEXP_BASE wxTypeInfo
307 typedef void (*wxVariant2StringFnc
)( const wxAny
& data
, wxString
&result
);
308 typedef void (*wxString2VariantFnc
)( const wxString
& data
, wxAny
&result
);
310 wxTypeInfo(wxTypeKind kind
,
311 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
312 const wxString
&name
= wxEmptyString
):
313 m_toString(to
), m_fromString(from
), m_kind(kind
), m_name(name
)
317 #if 0 // wxUSE_UNICODE
318 wxTypeInfo(wxTypeKind kind
,
319 wxVariant2StringFnc to
, wxString2VariantFnc from
,
321 m_toString(to
), m_fromString(from
), m_kind(kind
),
322 m_name(wxString::FromAscii(name
))
328 virtual ~wxTypeInfo()
333 // return the kind of this type (wxT_... constants)
334 wxTypeKind
GetKind() const { return m_kind
; }
336 // returns the unique name of this type
337 const wxString
& GetTypeName() const { return m_name
; }
339 // is this type a delegate type
340 bool IsDelegateType() const { return m_kind
== wxT_DELEGATE
; }
342 // is this type a custom type
343 bool IsCustomType() const { return m_kind
== wxT_CUSTOM
; }
345 // is this type an object type
346 bool IsObjectType() const { return m_kind
== wxT_OBJECT
|| m_kind
== wxT_OBJECT_PTR
; }
348 // can the content of this type be converted to and from strings ?
349 bool HasStringConverters() const { return m_toString
!= NULL
&& m_fromString
!= NULL
; }
351 // convert a wxAny holding data of this type into a string
352 void ConvertToString( const wxAny
& data
, wxString
&result
) const
355 (*m_toString
)( data
, result
);
357 wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
360 // convert a string into a wxAny holding the corresponding data in this type
361 void ConvertFromString( const wxString
& data
, wxAny
&result
) const
364 (*m_fromString
)( data
, result
);
366 wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
371 // looks for the corresponding type, will return NULL if not found
372 static wxTypeInfo
*FindType( const wxString
& typeName
);
377 wxVariant2StringFnc m_toString
;
378 wxString2VariantFnc m_fromString
;
383 // the static list of all types we know about
384 static wxTypeInfoMap
* ms_typeTable
;
387 class WXDLLIMPEXP_BASE wxBuiltInTypeInfo
: public wxTypeInfo
390 wxBuiltInTypeInfo( wxTypeKind kind
, wxVariant2StringFnc to
= NULL
,
391 wxString2VariantFnc from
= NULL
,
392 const wxString
&name
= wxEmptyString
) :
393 wxTypeInfo( kind
, to
, from
, name
)
394 { wxASSERT_MSG( GetKind() < wxT_SET
, wxT("Illegal Kind for Base Type") ); }
397 class WXDLLIMPEXP_BASE wxCustomTypeInfo
: public wxTypeInfo
400 wxCustomTypeInfo( const wxString
&name
, wxVariant2StringFnc to
,
401 wxString2VariantFnc from
) :
402 wxTypeInfo( wxT_CUSTOM
, to
, from
, name
)
406 class WXDLLIMPEXP_BASE wxEnumTypeInfo
: public wxTypeInfo
409 typedef void (*converterToLong_t
)( const wxAny
& data
, long &result
);
410 typedef void (*converterFromLong_t
)( long data
, wxAny
&result
);
412 wxEnumTypeInfo( wxTypeKind kind
, wxEnumData
* enumInfo
, wxVariant2StringFnc to
,
413 wxString2VariantFnc from
, converterToLong_t toLong
,
414 converterFromLong_t fromLong
, const wxString
&name
) :
415 wxTypeInfo( kind
, to
, from
, name
), m_toLong( toLong
), m_fromLong( fromLong
)
417 wxASSERT_MSG( kind
== wxT_ENUM
|| kind
== wxT_SET
,
418 wxT("Illegal Kind for Enum Type"));
419 m_enumInfo
= enumInfo
;
422 const wxEnumData
* GetEnumData() const { return m_enumInfo
; }
424 // convert a wxAny holding data of this type into a long
425 void ConvertToLong( const wxAny
& data
, long &result
) const
428 (*m_toLong
)( data
, result
);
430 wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
433 // convert a long into a wxAny holding the corresponding data in this type
434 void ConvertFromLong( long data
, wxAny
&result
) const
437 (*m_fromLong
)( data
, result
);
439 wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
443 converterToLong_t m_toLong
;
444 converterFromLong_t m_fromLong
;
446 wxEnumData
*m_enumInfo
; // Kind == wxT_ENUM or Kind == wxT_SET
449 class WXDLLIMPEXP_BASE wxClassTypeInfo
: public wxTypeInfo
452 wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
,
453 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
,
454 const wxString
&name
= wxEmptyString
);
456 const wxClassInfo
*GetClassInfo() const { return m_classInfo
; }
459 wxClassInfo
*m_classInfo
; // Kind == wxT_OBJECT - could be NULL
462 class WXDLLIMPEXP_BASE wxCollectionTypeInfo
: public wxTypeInfo
465 wxCollectionTypeInfo( const wxString
&elementName
, wxVariant2StringFnc to
,
466 wxString2VariantFnc from
, const wxString
&name
) :
467 wxTypeInfo( wxT_COLLECTION
, to
, from
, name
)
468 { m_elementTypeName
= elementName
; m_elementType
= NULL
; }
470 const wxTypeInfo
* GetElementType() const
472 if ( m_elementType
== NULL
)
473 m_elementType
= wxTypeInfo::FindType( m_elementTypeName
);
474 return m_elementType
;
478 mutable wxTypeInfo
* m_elementType
;
479 wxString m_elementTypeName
;
482 class WXDLLIMPEXP_BASE wxEventSourceTypeInfo
: public wxTypeInfo
485 wxEventSourceTypeInfo( int eventType
, wxClassInfo
* eventClass
,
486 wxVariant2StringFnc to
= NULL
,
487 wxString2VariantFnc from
= NULL
);
488 wxEventSourceTypeInfo( int eventType
, int lastEventType
, wxClassInfo
* eventClass
,
489 wxVariant2StringFnc to
= NULL
, wxString2VariantFnc from
= NULL
);
491 int GetEventType() const { return m_eventType
; }
492 int GetLastEventType() const { return m_lastEventType
; }
493 const wxClassInfo
* GetEventClass() const { return m_eventClass
; }
496 const wxClassInfo
*m_eventClass
; // (extended will merge into classinfo)
501 template<typename T
> const wxTypeInfo
* wxGetTypeInfo( T
* )
502 { return wxTypeInfo::FindType(typeid(T
).name()); }
504 // this macro is for usage with custom, non-object derived classes and structs,
505 // wxPoint is such a custom type
507 #if wxUSE_FUNC_TEMPLATE_POINTER
508 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
509 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
511 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
512 void ToString##e( const wxAny& data, wxString &result ) \
513 { toString(data, result); } \
514 void FromString##e( const wxString& data, wxAny &result ) \
515 { fromString(data, result); } \
516 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
517 &ToString##e, &FromString##e);
520 #define wxCOLLECTION_TYPE_INFO( element, collection ) \
521 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
522 NULL, NULL, typeid(collection).name() );
524 // sometimes a compiler invents specializations that are nowhere called,
525 // use this macro to satisfy the refs, currently we don't have to play
526 // tricks, but if we will have to according to the compiler, we will use
527 // that macro for that
529 #define wxILLEGAL_TYPE_SPECIALIZATION( a )
531 #endif // wxUSE_EXTENDED_RTTI
532 #endif // _XTITYPES_H_