1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/xtitypes.h
3 // Purpose:     enum, set, basic types support
4 // Author:      Stefan Csomor
5 // Modified by: Francesco Montorsi
6 // Created:     27/07/03
7 // Copyright:   (c) 1997 Julian Smart
8 //              (c) 2003 Stefan Csomor
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef _XTITYPES_H_
13 #define _XTITYPES_H_
14 
15 #include "wx/defs.h"
16 
17 #if wxUSE_EXTENDED_RTTI
18 
19 #include "wx/string.h"
20 #include "wx/hashmap.h"
21 #include "wx/arrstr.h"
22 #include "wx/flags.h"
23 #include "wx/intl.h"
24 #include "wx/log.h"
25 #include <typeinfo>
26 
27 class WXDLLIMPEXP_BASE wxClassInfo;
28 
29 // ----------------------------------------------------------------------------
30 // Enum Support
31 //
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:
34 //
35 // wxBEGIN_ENUM( wxFlavor )
36 //   wxENUM_MEMBER( Vanilla )
37 //   wxENUM_MEMBER( Chocolate )
38 //   wxENUM_MEMBER( Strawberry )
39 // wxEND_ENUM( wxFlavor )
40 // ----------------------------------------------------------------------------
41 
42 struct WXDLLIMPEXP_BASE wxEnumMemberData
43 {
44     const wxChar*   m_name;
45     int             m_value;
46 };
47 
48 class WXDLLIMPEXP_BASE wxEnumData
49 {
50 public:
51     wxEnumData( wxEnumMemberData* data );
52 
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;
57 
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;
61 
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;
65 
66     // returns the number of members in this enum
GetEnumCount()67     int GetEnumCount() const { return m_count; }
68 
69     // returns the value of the nth member
70     int GetEnumMemberValueByIndex( int n ) const;
71 
72     // returns the value of the nth member
73     const wxChar *GetEnumMemberNameByIndex( int n ) const;
74 
75 private:
76     wxEnumMemberData *m_members;
77     int m_count;
78 };
79 
80 #define wxBEGIN_ENUM( e ) \
81     wxEnumMemberData s_enumDataMembers##e[] = {
82 
83 #define wxENUM_MEMBER( v ) { wxT(#v), v },
84 
85 #define wxEND_ENUM( e )                                                 \
86         { NULL, 0 } };                                                 \
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)); }      \
97                                                                         \
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() );
103 
104 
105 // ----------------------------------------------------------------------------
106 // Set Support
107 //
108 // in the header :
109 //
110 // enum wxFlavor
111 // {
112 //  Vanilla,
113 //  Chocolate,
114 //  Strawberry,
115 // };
116 //
117 // typedef wxBitset<wxFlavor> wxCoupe;
118 //
119 // in the implementation file :
120 //
121 // wxBEGIN_ENUM( wxFlavor )
122 //  wxENUM_MEMBER( Vanilla )
123 //  wxENUM_MEMBER( Chocolate )
124 //  wxENUM_MEMBER( Strawberry )
125 // wxEND_ENUM( wxFlavor )
126 //
127 // wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
128 //
129 // implementation note: no partial specialization for streaming, but a delegation
130 //                      to a different class
131 //
132 // ----------------------------------------------------------------------------
133 
134 void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array );
135 
136 template<typename e>
wxSetFromString(const wxString & s,wxBitset<e> & data)137 void wxSetFromString(const wxString &s, wxBitset<e> &data )
138 {
139     wxEnumData* edata = wxGetEnumData((e) 0);
140     data.reset();
141 
142     wxArrayString array;
143     wxSetStringToArray( s, array );
144     wxString flag;
145     for ( int i = 0; i < array.Count(); ++i )
146     {
147         flag = array[i];
148         int ivalue;
149         if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) )
150         {
151             data.set( (e) ivalue );
152         }
153     }
154 }
155 
156 template<typename e>
wxSetToString(wxString & s,const wxBitset<e> & data)157 void wxSetToString( wxString &s, const wxBitset<e> &data )
158 {
159     wxEnumData* edata = wxGetEnumData((e) 0);
160     int count = edata->GetEnumCount();
161     int i;
162     s.Clear();
163     for ( i = 0; i < count; i++ )
164     {
165         e value = (e) edata->GetEnumMemberValueByIndex(i);
166         if ( data.test( value ) )
167         {
168             // this could also be done by the templated calls
169             if ( !s.empty() )
170                 s += wxT("|");
171             s += edata->GetEnumMemberNameByIndex(i);
172         }
173     }
174 }
175 
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() );
190 
191 template<typename e>
wxFlagsFromString(const wxString & s,e & data)192 void wxFlagsFromString(const wxString &s, e &data )
193 {
194     wxEnumData* edata = wxGetEnumData((e*) 0);
195     data.m_data = 0;
196 
197     wxArrayString array;
198     wxSetStringToArray( s, array );
199     wxString flag;
200     for ( size_t i = 0; i < array.Count(); ++i )
201     {
202         flag = array[i];
203         int ivalue;
204         if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) )
205         {
206             data.m_data |= ivalue;
207         }
208     }
209 }
210 
211 template<typename e>
wxFlagsToString(wxString & s,const e & data)212 void wxFlagsToString( wxString &s, const e& data )
213 {
214     wxEnumData* edata = wxGetEnumData((e*) 0);
215     int count = edata->GetEnumCount();
216     int i;
217     s.Clear();
218     long dataValue = data.m_data;
219     for ( i = 0; i < count; i++ )
220     {
221         int value = edata->GetEnumMemberValueByIndex(i);
222         // make this to allow for multi-bit constants to work
223         if ( value && ( dataValue & value ) == value )
224         {
225             // clear the flags we just set
226             dataValue &= ~value;
227             // this could also be done by the templated calls
228             if ( !s.empty() )
229                 s +=wxT("|");
230             s += edata->GetEnumMemberNameByIndex(i);
231         }
232     }
233 }
234 
235 #define wxBEGIN_FLAGS( e ) \
236     wxEnumMemberData s_enumDataMembers##e[] = {
237 
238 #define wxFLAGS_MEMBER( v ) { wxT(#v), static_cast<int>(v) },
239 
240 #define wxEND_FLAGS( e )                                                \
241         { NULL, 0 } };                                                 \
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() );
257 
258 // ----------------------------------------------------------------------------
259 // Type Information
260 // ----------------------------------------------------------------------------
261 
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.
268 
269 enum wxTypeKind
270 {
271     wxT_VOID = 0,   // unknown type
272     wxT_BOOL,
273     wxT_CHAR,
274     wxT_UCHAR,
275     wxT_INT,
276     wxT_UINT,
277     wxT_LONG,
278     wxT_ULONG,
279     wxT_LONGLONG,
280     wxT_ULONGLONG,
281     wxT_FLOAT,
282     wxT_DOUBLE,
283     wxT_STRING,     // must be wxString
284     wxT_SET,        // must be wxBitset<> template
285     wxT_ENUM,
286     wxT_CUSTOM,     // user defined type (e.g. wxPoint)
287 
288     wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM,
289 
290     wxT_OBJECT_PTR, // object reference
291     wxT_OBJECT,     // embedded object
292     wxT_COLLECTION, // collection
293 
294     wxT_DELEGATE,   // for connecting against an event source
295 
296     wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging
297 };
298 
299 class WXDLLIMPEXP_BASE wxAny;
300 class WXDLLIMPEXP_BASE wxTypeInfo;
301 
302 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE );
303 
304 class WXDLLIMPEXP_BASE wxTypeInfo
305 {
306 public:
307     typedef void (*wxVariant2StringFnc)( const wxAny& data, wxString &result );
308     typedef void (*wxString2VariantFnc)( const wxString& data, wxAny &result );
309 
310     wxTypeInfo(wxTypeKind kind,
311                wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
312                const wxString &name = wxEmptyString):
m_toString(to)313             m_toString(to), m_fromString(from), m_kind(kind), m_name(name)
314     {
315         Register();
316     }
317 #if 0 // wxUSE_UNICODE
318     wxTypeInfo(wxTypeKind kind,
319                wxVariant2StringFnc to, wxString2VariantFnc from,
320                const char *name):
321             m_toString(to), m_fromString(from), m_kind(kind),
322             m_name(wxString::FromAscii(name))
323     {
324         Register();
325     }
326 #endif
327 
~wxTypeInfo()328     virtual ~wxTypeInfo()
329     {
330         Unregister();
331     }
332 
333     // return the kind of this type (wxT_... constants)
GetKind()334     wxTypeKind GetKind() const { return m_kind; }
335 
336     // returns the unique name of this type
GetTypeName()337     const wxString& GetTypeName() const { return m_name; }
338 
339     // is this type a delegate type
IsDelegateType()340     bool IsDelegateType() const { return m_kind == wxT_DELEGATE; }
341 
342     // is this type a custom type
IsCustomType()343     bool IsCustomType() const { return m_kind == wxT_CUSTOM; }
344 
345     // is this type an object type
IsObjectType()346     bool IsObjectType() const { return m_kind == wxT_OBJECT || m_kind == wxT_OBJECT_PTR; }
347 
348     // can the content of this type be converted to and from strings ?
HasStringConverters()349     bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; }
350 
351     // convert a wxAny holding data of this type into a string
ConvertToString(const wxAny & data,wxString & result)352     void ConvertToString( const wxAny& data, wxString &result ) const
353     {
354         if ( m_toString )
355             (*m_toString)( data, result );
356         else
357             wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
358     }
359 
360     // convert a string into a wxAny holding the corresponding data in this type
ConvertFromString(const wxString & data,wxAny & result)361     void ConvertFromString( const wxString& data, wxAny &result ) const
362     {
363         if( m_fromString )
364             (*m_fromString)( data, result );
365         else
366             wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
367     }
368 
369     // statics:
370 
371     // looks for the corresponding type, will return NULL if not found
372     static wxTypeInfo *FindType( const wxString& typeName );
373 private:
374     void Register();
375     void Unregister();
376 
377     wxVariant2StringFnc m_toString;
378     wxString2VariantFnc m_fromString;
379 
380     wxTypeKind m_kind;
381     wxString m_name;
382 
383     // the static list of all types we know about
384     static wxTypeInfoMap* ms_typeTable;
385 };
386 
387 class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo
388 {
389 public:
390     wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL,
391                        wxString2VariantFnc from = NULL,
392                        const wxString &name = wxEmptyString ) :
wxTypeInfo(kind,to,from,name)393             wxTypeInfo( kind, to, from, name )
394        { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); }
395 };
396 
397 class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo
398 {
399 public:
wxCustomTypeInfo(const wxString & name,wxVariant2StringFnc to,wxString2VariantFnc from)400     wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to,
401                       wxString2VariantFnc from ) :
402             wxTypeInfo( wxT_CUSTOM, to, from, name )
403        {}
404 };
405 
406 class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo
407 {
408 public:
409     typedef void (*converterToLong_t)( const wxAny& data, long &result );
410     typedef void (*converterFromLong_t)( long data, wxAny &result );
411 
wxEnumTypeInfo(wxTypeKind kind,wxEnumData * enumInfo,wxVariant2StringFnc to,wxString2VariantFnc from,converterToLong_t toLong,converterFromLong_t fromLong,const wxString & name)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 )
416     {
417         wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET,
418                       wxT("Illegal Kind for Enum Type"));
419         m_enumInfo = enumInfo;
420     }
421 
GetEnumData()422     const wxEnumData* GetEnumData() const { return m_enumInfo; }
423 
424     // convert a wxAny holding data of this type into a long
ConvertToLong(const wxAny & data,long & result)425     void ConvertToLong( const wxAny& data, long &result ) const
426     {
427         if( m_toLong )
428             (*m_toLong)( data, result );
429         else
430             wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
431     }
432 
433     // convert a long into a wxAny holding the corresponding data in this type
ConvertFromLong(long data,wxAny & result)434     void ConvertFromLong( long data, wxAny &result ) const
435     {
436         if( m_fromLong )
437             (*m_fromLong)( data, result );
438         else
439             wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
440     }
441 
442 private:
443     converterToLong_t m_toLong;
444     converterFromLong_t m_fromLong;
445 
446     wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET
447 };
448 
449 class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo
450 {
451 public:
452     wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
453                      wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
454                      const wxString &name = wxEmptyString);
455 
GetClassInfo()456     const wxClassInfo *GetClassInfo() const { return m_classInfo; }
457 
458 private:
459     wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL
460 };
461 
462 class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo
463 {
464 public:
wxCollectionTypeInfo(const wxString & elementName,wxVariant2StringFnc to,wxString2VariantFnc from,const wxString & name)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; }
469 
GetElementType()470     const wxTypeInfo* GetElementType() const
471     {
472         if ( m_elementType == NULL )
473             m_elementType = wxTypeInfo::FindType( m_elementTypeName );
474         return m_elementType;
475     }
476 
477 private:
478     mutable wxTypeInfo * m_elementType;
479     wxString    m_elementTypeName;
480 };
481 
482 class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo
483 {
484 public:
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 );
490 
GetEventType()491     int GetEventType() const { return m_eventType; }
GetLastEventType()492     int GetLastEventType() const { return m_lastEventType; }
GetEventClass()493     const wxClassInfo* GetEventClass() const { return m_eventClass; }
494 
495 private:
496     const wxClassInfo *m_eventClass; // (extended will merge into classinfo)
497     int m_eventType;
498     int m_lastEventType;
499 };
500 
wxGetTypeInfo(T *)501 template<typename T> const wxTypeInfo* wxGetTypeInfo( T * )
502     { return wxTypeInfo::FindType(typeid(T).name()); }
503 
504 // this macro is for usage with custom, non-object derived classes and structs,
505 // wxPoint is such a custom type
506 
507 #if wxUSE_FUNC_TEMPLATE_POINTER
508     #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
509         wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
510 #else
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);
518 #endif
519 
520 #define wxCOLLECTION_TYPE_INFO( element, collection )                      \
521     wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(),   \
522                                 NULL, NULL, typeid(collection).name() );
523 
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
528 
529 #define wxILLEGAL_TYPE_SPECIALIZATION( a )
530 
531 #endif      // wxUSE_EXTENDED_RTTI
532 #endif      // _XTITYPES_H_
533