]> git.saurik.com Git - wxWidgets.git/blob - include/wx/xtitypes.h
adding new files for xti merge
[wxWidgets.git] / include / wx / xtitypes.h
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 // RCS-ID: $Id: xti.h 47299 2007-07-10 15:58:27Z FM $
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2003 Stefan Csomor
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifndef _XTITYPES_H_
14 #define _XTITYPES_H_
15
16 #include "wx/defs.h"
17
18 #if wxUSE_EXTENDED_RTTI
19
20 #include "wx/string.h"
21 #include "wx/hashmap.h"
22 #include "wx/arrstr.h"
23 #include "wx/flags.h"
24 #include "wx/intl.h"
25 #include "wx/log.h"
26 #include <typeinfo>
27
28 class WXDLLIMPEXP_BASE wxClassInfo;
29
30 // ----------------------------------------------------------------------------
31 // Enum Support
32 //
33 // In the header files XTI requires no change from pure c++ code, however in the
34 // implementation, an enum needs to be enumerated eg:
35 //
36 // wxBEGIN_ENUM( wxFlavor )
37 // wxENUM_MEMBER( Vanilla )
38 // wxENUM_MEMBER( Chocolate )
39 // wxENUM_MEMBER( Strawberry )
40 // wxEND_ENUM( wxFlavor )
41 // ----------------------------------------------------------------------------
42
43 struct WXDLLIMPEXP_BASE wxEnumMemberData
44 {
45 const wxChar* m_name;
46 int m_value;
47 };
48
49 class WXDLLIMPEXP_BASE wxEnumData
50 {
51 public:
52 wxEnumData( wxEnumMemberData* data );
53
54 // returns true if the member has been found and sets the int value
55 // pointed to accordingly (if ptr != null )
56 // if not found returns false, value left unchanged
57 bool HasEnumMemberValue( const wxChar *name, int *value = NULL ) const;
58
59 // returns the value of the member, if not found in debug mode an
60 // assert is issued, in release 0 is returned
61 int GetEnumMemberValue(const wxChar *name ) const;
62
63 // returns the name of the enum member having the passed in value
64 // returns an emtpy string if not found
65 const wxChar *GetEnumMemberName(int value) const;
66
67 // returns the number of members in this enum
68 int GetEnumCount() const { return m_count; }
69
70 // returns the value of the nth member
71 int GetEnumMemberValueByIndex( int n ) const;
72
73 // returns the value of the nth member
74 const wxChar *GetEnumMemberNameByIndex( int n ) const;
75
76 private:
77 wxEnumMemberData *m_members;
78 int m_count;
79 };
80
81 #define wxBEGIN_ENUM( e ) \
82 wxEnumMemberData s_enumDataMembers##e[] = {
83
84 #define wxENUM_MEMBER( v ) { wxT(#v), v },
85
86 #define wxEND_ENUM( e ) \
87 { NULL, 0 } }; \
88 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
89 wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \
90 template<> void wxStringReadValue(const wxString& s, e &data ) \
91 { data = (e) s_enumData##e.GetEnumMemberValue(s); } \
92 template<> void wxStringWriteValue(wxString &s, const e &data ) \
93 { s = s_enumData##e.GetEnumMemberName((int)data); } \
94 void FromLong##e( long data, wxVariantBase& result ) \
95 { result = wxVariantBase((e)data); } \
96 void ToLong##e( const wxVariantBase& data, long &result ) \
97 { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, e); } \
98 \
99 wxTO_STRING_IMP( e ) \
100 wxFROM_STRING_IMP( e ) \
101 wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \
102 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
103 &FromLong##e, typeid(e).name() );
104
105
106 // ----------------------------------------------------------------------------
107 // Set Support
108 //
109 // in the header :
110 //
111 // enum wxFlavor
112 // {
113 // Vanilla,
114 // Chocolate,
115 // Strawberry,
116 // };
117 //
118 // typedef wxBitset<wxFlavor> wxCoupe;
119 //
120 // in the implementation file :
121 //
122 // wxBEGIN_ENUM( wxFlavor )
123 // wxENUM_MEMBER( Vanilla )
124 // wxENUM_MEMBER( Chocolate )
125 // wxENUM_MEMBER( Strawberry )
126 // wxEND_ENUM( wxFlavor )
127 //
128 // wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
129 //
130 // implementation note: no partial specialization for streaming, but a delegation
131 // to a different class
132 //
133 // ----------------------------------------------------------------------------
134
135 // in order to remove dependancy on string tokenizer
136 void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array );
137
138 template<typename e>
139 void wxSetFromString(const wxString &s, wxBitset<e> &data )
140 {
141 wxEnumData* edata = wxGetEnumData((e) 0);
142 data.reset();
143
144 wxArrayString array;
145 wxSetStringToArray( s, array );
146 wxString flag;
147 for ( int i = 0; i < array.Count(); ++i )
148 {
149 flag = array[i];
150 int ivalue;
151 if ( edata->HasEnumMemberValue( flag, &ivalue ) )
152 {
153 data.set( (e) ivalue );
154 }
155 }
156 }
157
158 template<typename e>
159 void wxSetToString( wxString &s, const wxBitset<e> &data )
160 {
161 wxEnumData* edata = wxGetEnumData((e) 0);
162 int count = edata->GetEnumCount();
163 int i;
164 s.Clear();
165 for ( i = 0; i < count; i++ )
166 {
167 e value = (e) edata->GetEnumMemberValueByIndex(i);
168 if ( data.test( value ) )
169 {
170 // this could also be done by the templated calls
171 if ( !s.empty() )
172 s += wxT("|");
173 s += edata->GetEnumMemberNameByIndex(i);
174 }
175 }
176 }
177
178 #define wxIMPLEMENT_SET_STREAMING(SetName,e) \
179 template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \
180 { wxSetFromString( s, data ); } \
181 template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \
182 { wxSetToString( s, data ); } \
183 void FromLong##SetName( long data, wxVariantBase& result ) \
184 { result = wxVariantBase(SetName((unsigned long)data)); } \
185 void ToLong##SetName( const wxVariantBase& data, long &result ) \
186 { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, SetName).to_ulong(); } \
187 wxTO_STRING_IMP( SetName ) \
188 wxFROM_STRING_IMP( SetName ) \
189 wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \
190 &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \
191 &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() );
192
193 template<typename e>
194 void wxFlagsFromString(const wxString &s, e &data )
195 {
196 wxEnumData* edata = wxGetEnumData((e*) 0);
197 data.m_data = 0;
198
199 wxArrayString array;
200 wxSetStringToArray( s, array );
201 wxString flag;
202 for ( size_t i = 0; i < array.Count(); ++i )
203 {
204 flag = array[i];
205 int ivalue;
206 if ( edata->HasEnumMemberValue( flag, &ivalue ) )
207 {
208 data.m_data |= ivalue;
209 }
210 }
211 }
212
213 template<typename e>
214 void wxFlagsToString( wxString &s, const e& data )
215 {
216 wxEnumData* edata = wxGetEnumData((e*) 0);
217 int count = edata->GetEnumCount();
218 int i;
219 s.Clear();
220 long dataValue = data.m_data;
221 for ( i = 0; i < count; i++ )
222 {
223 int value = edata->GetEnumMemberValueByIndex(i);
224 // make this to allow for multi-bit constants to work
225 if ( value && ( dataValue & value ) == value )
226 {
227 // clear the flags we just set
228 dataValue &= ~value;
229 // this could also be done by the templated calls
230 if ( !s.empty() )
231 s +=wxT("|");
232 s += edata->GetEnumMemberNameByIndex(i);
233 }
234 }
235 }
236
237 #define wxBEGIN_FLAGS( e ) \
238 wxEnumMemberData s_enumDataMembers##e[] = {
239
240 #define wxFLAGS_MEMBER( v ) { wxT(#v), v },
241
242 #define wxEND_FLAGS( e ) \
243 { NULL, 0 } }; \
244 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
245 wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \
246 template<> void wxStringReadValue(const wxString &s, e &data ) \
247 { wxFlagsFromString<e>( s, data ); } \
248 template<> void wxStringWriteValue( wxString &s, const e& data ) \
249 { wxFlagsToString<e>( s, data ); } \
250 void FromLong##e( long data, wxVariantBase& result ) \
251 { result = wxVariantBase(e(data)); } \
252 void ToLong##e( const wxVariantBase& data, long &result ) \
253 { result = (long) data.wxTEMPLATED_MEMBER_CALL(Get, e).m_data; } \
254 wxTO_STRING_IMP( e ) \
255 wxFROM_STRING_IMP( e ) \
256 wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \
257 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
258 &FromLong##e, typeid(e).name() );
259
260 // ----------------------------------------------------------------------------
261 // Type Information
262 // ----------------------------------------------------------------------------
263
264 // All data exposed by the RTTI is characterized using the following classes.
265 // The first characterization is done by wxTypeKind. All enums up to and including
266 // wxT_CUSTOM represent so called simple types. These cannot be divided any further.
267 // They can be converted to and from wxStrings, that's all.
268 // Other wxTypeKinds can instead be splitted recursively into smaller parts until
269 // the simple types are reached.
270
271 enum wxTypeKind
272 {
273 wxT_VOID = 0, // unknown type
274 wxT_BOOL,
275 wxT_CHAR,
276 wxT_UCHAR,
277 wxT_INT,
278 wxT_UINT,
279 wxT_LONG,
280 wxT_ULONG,
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 wxVariantBase;
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 wxVariantBase& data, wxString &result );
308 typedef void (*wxString2VariantFnc)( const wxString& data, wxVariantBase &result );
309
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)
314 {
315 Register();
316 }
317 #if 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
328 virtual ~wxTypeInfo()
329 {
330 Unregister();
331 }
332
333 // return the kind of this type (wxT_... constants)
334 wxTypeKind GetKind() const { return m_kind; }
335
336 // returns the unique name of this type
337 const wxString& GetTypeName() const { return m_name; }
338
339 // is this type a delegate type
340 bool IsDelegateType() const { return m_kind == wxT_DELEGATE; }
341
342 // is this type a custom type
343 bool IsCustomType() const { return m_kind == wxT_CUSTOM; }
344
345 // is this type an object type
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 ?
349 bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; }
350
351 // convert a wxVariantBase holding data of this type into a string
352 void ConvertToString( const wxVariantBase& data, wxString &result ) const
353 {
354 if ( m_toString )
355 (*m_toString)( data, result );
356 else
357 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
358 }
359
360 // convert a string into a wxVariantBase holding the corresponding data in this type
361 void ConvertFromString( const wxString& data, wxVariantBase &result ) const
362 {
363 if( m_fromString )
364 (*m_fromString)( data, result );
365 else
366 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
367 }
368
369 // statics:
370
371 #if wxUSE_UNICODE
372 static wxTypeInfo *FindType(const char *typeName)
373 { return FindType( wxString::FromAscii(typeName) ); }
374 #endif
375 static wxTypeInfo *FindType(const wxChar *typeName);
376 static wxTypeInfo *FindType(const wxString& typeName)
377 {
378 #if wxUSE_UNICODE
379 return FindType( typeName.wchar_str() );
380 #else
381 return FindType( typeName.char_str() );
382 #endif
383 }
384
385 private:
386 void Register();
387 void Unregister();
388
389 wxVariant2StringFnc m_toString;
390 wxString2VariantFnc m_fromString;
391
392 wxTypeKind m_kind;
393 wxString m_name;
394
395 // the static list of all types we know about
396 static wxTypeInfoMap* ms_typeTable;
397 };
398
399 class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo
400 {
401 public:
402 wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL,
403 wxString2VariantFnc from = NULL,
404 const wxString &name = wxEmptyString ) :
405 wxTypeInfo( kind, to, from, name )
406 { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); }
407
408 #if wxUSE_UNICODE
409 wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to,
410 wxString2VariantFnc from , const char *name ) :
411 wxTypeInfo( kind, to, from, name )
412 { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); }
413 #endif
414 };
415
416 class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo
417 {
418 public:
419 wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to,
420 wxString2VariantFnc from ) :
421 wxTypeInfo( wxT_CUSTOM, to, from, name )
422 {}
423
424 #if wxUSE_UNICODE
425 wxCustomTypeInfo( const char *name , wxVariant2StringFnc to,
426 wxString2VariantFnc from ) :
427 wxTypeInfo( wxT_CUSTOM, to, from, name )
428 {}
429 #endif
430 };
431
432 class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo
433 {
434 public:
435 typedef void (*converterToLong_t)( const wxVariantBase& data, long &result );
436 typedef void (*converterFromLong_t)( long data, wxVariantBase &result );
437
438 wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to,
439 wxString2VariantFnc from, converterToLong_t toLong,
440 converterFromLong_t fromLong, const wxString &name ) :
441 wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong )
442 {
443 wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET,
444 wxT("Illegal Kind for Enum Type"));
445 m_enumInfo = enumInfo;
446 }
447
448 #if wxUSE_UNICODE
449 wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to,
450 wxString2VariantFnc from, converterToLong_t toLong,
451 converterFromLong_t fromLong, const char * name ) :
452 wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong )
453 {
454 wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET,
455 wxT("Illegal Kind for Enum Type"));
456 m_enumInfo = enumInfo;
457 }
458 #endif
459 const wxEnumData* GetEnumData() const { return m_enumInfo; }
460
461 // convert a wxVariantBase holding data of this type into a long
462 void ConvertToLong( const wxVariantBase& data, long &result ) const
463 {
464 if( m_toLong )
465 (*m_toLong)( data, result );
466 else
467 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
468 }
469
470 // convert a long into a wxVariantBase holding the corresponding data in this type
471 void ConvertFromLong( long data, wxVariantBase &result ) const
472 {
473 if( m_fromLong )
474 (*m_fromLong)( data, result );
475 else
476 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
477 }
478
479 private:
480 converterToLong_t m_toLong;
481 converterFromLong_t m_fromLong;
482
483 wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET
484 };
485
486 class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo
487 {
488 public:
489 wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
490 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
491 const wxString &name = wxEmptyString);
492
493 #if wxUSE_UNICODE
494 wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, wxVariant2StringFnc to,
495 wxString2VariantFnc from , const char *name );
496 #endif
497
498 const wxClassInfo *GetClassInfo() const { return m_classInfo; }
499
500 private:
501 wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL
502 };
503
504 class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo
505 {
506 public:
507 wxCollectionTypeInfo( const wxString &elementName, wxVariant2StringFnc to,
508 wxString2VariantFnc from , const wxString &name) :
509 wxTypeInfo( wxT_COLLECTION, to, from, name )
510 { m_elementTypeName = elementName; m_elementType = NULL; }
511
512 #if wxUSE_UNICODE
513 wxCollectionTypeInfo( const char *elementName, wxVariant2StringFnc to,
514 wxString2VariantFnc from , const char *name ) :
515 wxTypeInfo( wxT_COLLECTION, to, from, name )
516 { m_elementTypeName = wxString::FromAscii( elementName ); m_elementType = NULL; }
517 #endif
518
519 const wxTypeInfo* GetElementType() const
520 {
521 if ( m_elementType == NULL )
522 m_elementType = wxTypeInfo::FindType( m_elementTypeName );
523 return m_elementType;
524 }
525
526 private:
527 mutable wxTypeInfo * m_elementType;
528 wxString m_elementTypeName;
529 };
530
531 class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo
532 {
533 public:
534 wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass,
535 wxVariant2StringFnc to = NULL,
536 wxString2VariantFnc from = NULL );
537 wxEventSourceTypeInfo( int eventType, int lastEventType, wxClassInfo* eventClass,
538 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL );
539
540 int GetEventType() const { return m_eventType; }
541 int GetLastEventType() const { return m_lastEventType; }
542 const wxClassInfo* GetEventClass() const { return m_eventClass; }
543
544 private:
545 const wxClassInfo *m_eventClass; // (extended will merge into classinfo)
546 int m_eventType;
547 int m_lastEventType;
548 };
549
550 template<typename T> const wxTypeInfo* wxGetTypeInfo( T * ) \
551 { return wxTypeInfo::FindType(typeid(T).name()); }
552
553 // this macro is for usage with custom, non-object derived classes and structs,
554 // wxPoint is such a custom type
555
556 #if wxUSE_FUNC_TEMPLATE_POINTER
557 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
558 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
559 #else
560 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
561 void ToString##e( const wxVariantBase& data, wxString &result ) \
562 { toString(data, result); } \
563 void FromString##e( const wxString& data, wxVariantBase &result ) \
564 { fromString(data, result); } \
565 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
566 &ToString##e, &FromString##e);
567 #endif
568
569 #define wxCOLLECTION_TYPE_INFO( element, collection ) \
570 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
571 NULL, NULL, typeid(collection).name() );
572
573 // sometimes a compiler invents specializations that are nowhere called,
574 // use this macro to satisfy the refs, currently we don't have to play
575 // tricks, but if we will have to according to the compiler, we will use
576 // that macro for that
577
578 #define wxILLEGAL_TYPE_SPECIALIZATION( a )
579
580 #endif // wxUSE_EXTENDED_RTTI
581 #endif // _XTITYPES_H_