]> git.saurik.com Git - wxWidgets.git/blame - include/wx/xtitypes.h
update docs after r66615
[wxWidgets.git] / include / wx / xtitypes.h
CommitLineData
e1d3601a
PC
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$
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
28class 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
43struct WXDLLIMPEXP_BASE wxEnumMemberData
44{
45 const wxChar* m_name;
46 int m_value;
47};
48
49class WXDLLIMPEXP_BASE wxEnumData
50{
51public:
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
76private:
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
6c887dde
SC
86/*
87WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e>) \
88WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e*>) \
89*/
90
e1d3601a
PC
91#define wxEND_ENUM( e ) \
92 { NULL, 0 } }; \
93 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
94 wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \
95 template<> void wxStringReadValue(const wxString& s, e &data ) \
96 { data = (e) s_enumData##e.GetEnumMemberValue(s); } \
97 template<> void wxStringWriteValue(wxString &s, const e &data ) \
98 { s = s_enumData##e.GetEnumMemberName((int)data); } \
6c887dde
SC
99 void FromLong##e( long data, wxAny& result ) \
100 { result = wxAny((e)data); } \
101 void ToLong##e( const wxAny& data, long &result ) \
102 { result = (long) (data).As(static_cast<e*>(NULL)); } \
e1d3601a
PC
103 \
104 wxTO_STRING_IMP( e ) \
105 wxFROM_STRING_IMP( e ) \
106 wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \
107 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
108 &FromLong##e, typeid(e).name() );
109
110
111// ----------------------------------------------------------------------------
112// Set Support
113//
114// in the header :
115//
116// enum wxFlavor
117// {
118// Vanilla,
119// Chocolate,
120// Strawberry,
121// };
122//
123// typedef wxBitset<wxFlavor> wxCoupe;
124//
125// in the implementation file :
126//
127// wxBEGIN_ENUM( wxFlavor )
128// wxENUM_MEMBER( Vanilla )
129// wxENUM_MEMBER( Chocolate )
130// wxENUM_MEMBER( Strawberry )
131// wxEND_ENUM( wxFlavor )
132//
133// wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor )
134//
135// implementation note: no partial specialization for streaming, but a delegation
136// to a different class
137//
138// ----------------------------------------------------------------------------
139
140// in order to remove dependancy on string tokenizer
141void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array );
142
143template<typename e>
144void wxSetFromString(const wxString &s, wxBitset<e> &data )
145{
146 wxEnumData* edata = wxGetEnumData((e) 0);
147 data.reset();
148
149 wxArrayString array;
150 wxSetStringToArray( s, array );
151 wxString flag;
152 for ( int i = 0; i < array.Count(); ++i )
153 {
154 flag = array[i];
155 int ivalue;
156 if ( edata->HasEnumMemberValue( flag, &ivalue ) )
157 {
158 data.set( (e) ivalue );
159 }
160 }
161}
162
163template<typename e>
164void wxSetToString( wxString &s, const wxBitset<e> &data )
165{
166 wxEnumData* edata = wxGetEnumData((e) 0);
167 int count = edata->GetEnumCount();
168 int i;
169 s.Clear();
170 for ( i = 0; i < count; i++ )
171 {
172 e value = (e) edata->GetEnumMemberValueByIndex(i);
173 if ( data.test( value ) )
174 {
175 // this could also be done by the templated calls
176 if ( !s.empty() )
177 s += wxT("|");
178 s += edata->GetEnumMemberNameByIndex(i);
179 }
180 }
181}
182
183#define wxIMPLEMENT_SET_STREAMING(SetName,e) \
184 template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \
185 { wxSetFromString( s, data ); } \
186 template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \
187 { wxSetToString( s, data ); } \
6c887dde
SC
188 void FromLong##SetName( long data, wxAny& result ) \
189 { result = wxAny(SetName((unsigned long)data)); } \
190 void ToLong##SetName( const wxAny& data, long &result ) \
191 { result = (long) (data).As(static_cast<SetName*>(NULL)).to_ulong(); } \
e1d3601a
PC
192 wxTO_STRING_IMP( SetName ) \
193 wxFROM_STRING_IMP( SetName ) \
194 wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \
195 &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \
196 &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() );
197
198template<typename e>
199void wxFlagsFromString(const wxString &s, e &data )
200{
201 wxEnumData* edata = wxGetEnumData((e*) 0);
202 data.m_data = 0;
203
204 wxArrayString array;
205 wxSetStringToArray( s, array );
206 wxString flag;
207 for ( size_t i = 0; i < array.Count(); ++i )
208 {
209 flag = array[i];
210 int ivalue;
211 if ( edata->HasEnumMemberValue( flag, &ivalue ) )
212 {
213 data.m_data |= ivalue;
214 }
215 }
216}
217
218template<typename e>
219void wxFlagsToString( wxString &s, const e& data )
220{
221 wxEnumData* edata = wxGetEnumData((e*) 0);
222 int count = edata->GetEnumCount();
223 int i;
224 s.Clear();
225 long dataValue = data.m_data;
226 for ( i = 0; i < count; i++ )
227 {
228 int value = edata->GetEnumMemberValueByIndex(i);
229 // make this to allow for multi-bit constants to work
230 if ( value && ( dataValue & value ) == value )
231 {
232 // clear the flags we just set
233 dataValue &= ~value;
234 // this could also be done by the templated calls
235 if ( !s.empty() )
236 s +=wxT("|");
237 s += edata->GetEnumMemberNameByIndex(i);
238 }
239 }
240}
241
242#define wxBEGIN_FLAGS( e ) \
243 wxEnumMemberData s_enumDataMembers##e[] = {
244
245#define wxFLAGS_MEMBER( v ) { wxT(#v), v },
246
6c887dde
SC
247/*
248WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e>) \
249WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<e*>) \
250*/
251
e1d3601a
PC
252#define wxEND_FLAGS( e ) \
253 { NULL, 0 } }; \
254 wxEnumData s_enumData##e( s_enumDataMembers##e ); \
255 wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \
256 template<> void wxStringReadValue(const wxString &s, e &data ) \
257 { wxFlagsFromString<e>( s, data ); } \
258 template<> void wxStringWriteValue( wxString &s, const e& data ) \
259 { wxFlagsToString<e>( s, data ); } \
6c887dde
SC
260 void FromLong##e( long data, wxAny& result ) \
261 { result = wxAny(e(data)); } \
262 void ToLong##e( const wxAny& data, long &result ) \
263 { result = (long) (data).As(static_cast<e*>(NULL)).m_data; } \
e1d3601a
PC
264 wxTO_STRING_IMP( e ) \
265 wxFROM_STRING_IMP( e ) \
266 wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \
267 &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \
268 &FromLong##e, typeid(e).name() );
269
270// ----------------------------------------------------------------------------
271// Type Information
272// ----------------------------------------------------------------------------
273
274// All data exposed by the RTTI is characterized using the following classes.
275// The first characterization is done by wxTypeKind. All enums up to and including
276// wxT_CUSTOM represent so called simple types. These cannot be divided any further.
277// They can be converted to and from wxStrings, that's all.
278// Other wxTypeKinds can instead be splitted recursively into smaller parts until
279// the simple types are reached.
280
281enum wxTypeKind
282{
283 wxT_VOID = 0, // unknown type
284 wxT_BOOL,
285 wxT_CHAR,
286 wxT_UCHAR,
287 wxT_INT,
288 wxT_UINT,
289 wxT_LONG,
290 wxT_ULONG,
6c887dde
SC
291 wxT_LONGLONG,
292 wxT_ULONGLONG,
e1d3601a
PC
293 wxT_FLOAT,
294 wxT_DOUBLE,
295 wxT_STRING, // must be wxString
296 wxT_SET, // must be wxBitset<> template
297 wxT_ENUM,
298 wxT_CUSTOM, // user defined type (e.g. wxPoint)
299
300 wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM,
301
302 wxT_OBJECT_PTR, // object reference
303 wxT_OBJECT, // embedded object
304 wxT_COLLECTION, // collection
305
306 wxT_DELEGATE, // for connecting against an event source
307
308 wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging
309};
310
6c887dde 311class WXDLLIMPEXP_BASE wxAny;
e1d3601a
PC
312class WXDLLIMPEXP_BASE wxTypeInfo;
313
314WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE );
315
316class WXDLLIMPEXP_BASE wxTypeInfo
317{
318public:
6c887dde
SC
319 typedef void (*wxVariant2StringFnc)( const wxAny& data, wxString &result );
320 typedef void (*wxString2VariantFnc)( const wxString& data, wxAny &result );
e1d3601a
PC
321
322 wxTypeInfo(wxTypeKind kind,
323 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
324 const wxString &name = wxEmptyString):
325 m_toString(to), m_fromString(from), m_kind(kind), m_name(name)
326 {
327 Register();
328 }
329#if wxUSE_UNICODE
330 wxTypeInfo(wxTypeKind kind,
331 wxVariant2StringFnc to, wxString2VariantFnc from,
332 const char *name):
333 m_toString(to), m_fromString(from), m_kind(kind),
334 m_name(wxString::FromAscii(name))
335 {
336 Register();
337 }
338#endif
339
340 virtual ~wxTypeInfo()
341 {
342 Unregister();
343 }
344
345 // return the kind of this type (wxT_... constants)
346 wxTypeKind GetKind() const { return m_kind; }
347
348 // returns the unique name of this type
349 const wxString& GetTypeName() const { return m_name; }
350
351 // is this type a delegate type
352 bool IsDelegateType() const { return m_kind == wxT_DELEGATE; }
353
354 // is this type a custom type
355 bool IsCustomType() const { return m_kind == wxT_CUSTOM; }
356
357 // is this type an object type
358 bool IsObjectType() const { return m_kind == wxT_OBJECT || m_kind == wxT_OBJECT_PTR; }
359
360 // can the content of this type be converted to and from strings ?
361 bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; }
362
6c887dde
SC
363 // convert a wxAny holding data of this type into a string
364 void ConvertToString( const wxAny& data, wxString &result ) const
e1d3601a
PC
365 {
366 if ( m_toString )
367 (*m_toString)( data, result );
368 else
369 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
370 }
371
6c887dde
SC
372 // convert a string into a wxAny holding the corresponding data in this type
373 void ConvertFromString( const wxString& data, wxAny &result ) const
e1d3601a
PC
374 {
375 if( m_fromString )
376 (*m_fromString)( data, result );
377 else
378 wxLogError( wxGetTranslation(_T("String conversions not supported")) );
379 }
380
381 // statics:
382
6c887dde
SC
383 static wxTypeInfo *FindType( const wxString& typeName );
384#if 0 // TODO
e1d3601a
PC
385#if wxUSE_UNICODE
386 static wxTypeInfo *FindType(const char *typeName)
387 { return FindType( wxString::FromAscii(typeName) ); }
388#endif
389 static wxTypeInfo *FindType(const wxChar *typeName);
390 static wxTypeInfo *FindType(const wxString& typeName)
391 {
392#if wxUSE_UNICODE
393 return FindType( typeName.wchar_str() );
394#else
395 return FindType( typeName.char_str() );
396#endif
397 }
6c887dde 398#endif
e1d3601a
PC
399private:
400 void Register();
401 void Unregister();
402
403 wxVariant2StringFnc m_toString;
404 wxString2VariantFnc m_fromString;
405
406 wxTypeKind m_kind;
407 wxString m_name;
408
409 // the static list of all types we know about
410 static wxTypeInfoMap* ms_typeTable;
411};
412
413class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo
414{
415public:
416 wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL,
417 wxString2VariantFnc from = NULL,
418 const wxString &name = wxEmptyString ) :
419 wxTypeInfo( kind, to, from, name )
420 { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); }
421
422#if wxUSE_UNICODE
423 wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to,
424 wxString2VariantFnc from , const char *name ) :
425 wxTypeInfo( kind, to, from, name )
426 { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); }
427#endif
428};
429
430class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo
431{
432public:
433 wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to,
434 wxString2VariantFnc from ) :
435 wxTypeInfo( wxT_CUSTOM, to, from, name )
436 {}
437
438#if wxUSE_UNICODE
439 wxCustomTypeInfo( const char *name , wxVariant2StringFnc to,
440 wxString2VariantFnc from ) :
441 wxTypeInfo( wxT_CUSTOM, to, from, name )
442 {}
443#endif
444};
445
446class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo
447{
448public:
6c887dde
SC
449 typedef void (*converterToLong_t)( const wxAny& data, long &result );
450 typedef void (*converterFromLong_t)( long data, wxAny &result );
e1d3601a
PC
451
452 wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to,
453 wxString2VariantFnc from, converterToLong_t toLong,
454 converterFromLong_t fromLong, const wxString &name ) :
455 wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong )
456 {
457 wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET,
458 wxT("Illegal Kind for Enum Type"));
459 m_enumInfo = enumInfo;
460 }
461
462#if wxUSE_UNICODE
463 wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to,
464 wxString2VariantFnc from, converterToLong_t toLong,
465 converterFromLong_t fromLong, const char * name ) :
466 wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong )
467 {
468 wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET,
469 wxT("Illegal Kind for Enum Type"));
470 m_enumInfo = enumInfo;
471 }
472#endif
473 const wxEnumData* GetEnumData() const { return m_enumInfo; }
474
6c887dde
SC
475 // convert a wxAny holding data of this type into a long
476 void ConvertToLong( const wxAny& data, long &result ) const
e1d3601a
PC
477 {
478 if( m_toLong )
479 (*m_toLong)( data, result );
480 else
481 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
482 }
483
6c887dde
SC
484 // convert a long into a wxAny holding the corresponding data in this type
485 void ConvertFromLong( long data, wxAny &result ) const
e1d3601a
PC
486 {
487 if( m_fromLong )
488 (*m_fromLong)( data, result );
489 else
490 wxLogError( wxGetTranslation(_T("Long Conversions not supported")) );
491 }
492
493private:
494 converterToLong_t m_toLong;
495 converterFromLong_t m_fromLong;
496
497 wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET
498};
499
500class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo
501{
502public:
503 wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
504 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
505 const wxString &name = wxEmptyString);
506
507#if wxUSE_UNICODE
508 wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, wxVariant2StringFnc to,
509 wxString2VariantFnc from , const char *name );
510#endif
511
512 const wxClassInfo *GetClassInfo() const { return m_classInfo; }
513
514private:
515 wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL
516};
517
518class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo
519{
520public:
521 wxCollectionTypeInfo( const wxString &elementName, wxVariant2StringFnc to,
522 wxString2VariantFnc from , const wxString &name) :
523 wxTypeInfo( wxT_COLLECTION, to, from, name )
524 { m_elementTypeName = elementName; m_elementType = NULL; }
525
526#if wxUSE_UNICODE
527 wxCollectionTypeInfo( const char *elementName, wxVariant2StringFnc to,
528 wxString2VariantFnc from , const char *name ) :
529 wxTypeInfo( wxT_COLLECTION, to, from, name )
530 { m_elementTypeName = wxString::FromAscii( elementName ); m_elementType = NULL; }
531#endif
532
533 const wxTypeInfo* GetElementType() const
534 {
535 if ( m_elementType == NULL )
536 m_elementType = wxTypeInfo::FindType( m_elementTypeName );
537 return m_elementType;
538 }
539
540private:
541 mutable wxTypeInfo * m_elementType;
542 wxString m_elementTypeName;
543};
544
545class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo
546{
547public:
548 wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass,
549 wxVariant2StringFnc to = NULL,
550 wxString2VariantFnc from = NULL );
551 wxEventSourceTypeInfo( int eventType, int lastEventType, wxClassInfo* eventClass,
552 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL );
553
554 int GetEventType() const { return m_eventType; }
555 int GetLastEventType() const { return m_lastEventType; }
556 const wxClassInfo* GetEventClass() const { return m_eventClass; }
557
558private:
559 const wxClassInfo *m_eventClass; // (extended will merge into classinfo)
560 int m_eventType;
561 int m_lastEventType;
562};
563
6c887dde 564template<typename T> const wxTypeInfo* wxGetTypeInfo( T * )
e1d3601a
PC
565 { return wxTypeInfo::FindType(typeid(T).name()); }
566
567// this macro is for usage with custom, non-object derived classes and structs,
568// wxPoint is such a custom type
569
570#if wxUSE_FUNC_TEMPLATE_POINTER
571 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
572 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString);
573#else
574 #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \
6c887dde 575 void ToString##e( const wxAny& data, wxString &result ) \
e1d3601a 576 { toString(data, result); } \
6c887dde 577 void FromString##e( const wxString& data, wxAny &result ) \
e1d3601a
PC
578 { fromString(data, result); } \
579 wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \
580 &ToString##e, &FromString##e);
581#endif
582
583#define wxCOLLECTION_TYPE_INFO( element, collection ) \
584 wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \
585 NULL, NULL, typeid(collection).name() );
586
587// sometimes a compiler invents specializations that are nowhere called,
588// use this macro to satisfy the refs, currently we don't have to play
589// tricks, but if we will have to according to the compiler, we will use
590// that macro for that
591
592#define wxILLEGAL_TYPE_SPECIALIZATION( a )
593
594#endif // wxUSE_EXTENDED_RTTI
595#endif // _XTITYPES_H_