]> git.saurik.com Git - wxWidgets.git/blame - include/wx/xtitypes.h
Use wxGetTranslation() instead of _() in the public headers.
[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
e1d3601a
PC
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
27class 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
42struct WXDLLIMPEXP_BASE wxEnumMemberData
43{
44 const wxChar* m_name;
45 int m_value;
46};
47
48class WXDLLIMPEXP_BASE wxEnumData
49{
50public:
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
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
75private:
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 ) \
44a00712 90 { data = (e) s_enumData##e.GetEnumMemberValue(s.c_str()); } \
e1d3601a
PC
91 template<> void wxStringWriteValue(wxString &s, const e &data ) \
92 { s = s_enumData##e.GetEnumMemberName((int)data); } \
6c887dde
SC
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)); } \
e1d3601a
PC
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
e1d3601a
PC
134void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array );
135
136template<typename e>
137void 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;
31ba1c7e 149 if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) )
e1d3601a
PC
150 {
151 data.set( (e) ivalue );
152 }
153 }
154}
155
156template<typename e>
157void 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 ); } \
6c887dde
SC
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(); } \
e1d3601a
PC
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
191template<typename e>
192void 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;
44a00712 204 if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) )
e1d3601a
PC
205 {
206 data.m_data |= ivalue;
207 }
208 }
209}
210
211template<typename e>
212void 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
29a1e530 238#define wxFLAGS_MEMBER( v ) { wxT(#v), static_cast<int>(v) },
e1d3601a
PC
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 ); } \
6c887dde
SC
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; } \
e1d3601a
PC
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
269enum 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,
6c887dde
SC
279 wxT_LONGLONG,
280 wxT_ULONGLONG,
e1d3601a
PC
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
6c887dde 299class WXDLLIMPEXP_BASE wxAny;
e1d3601a
PC
300class WXDLLIMPEXP_BASE wxTypeInfo;
301
302WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE );
303
304class WXDLLIMPEXP_BASE wxTypeInfo
305{
306public:
6c887dde
SC
307 typedef void (*wxVariant2StringFnc)( const wxAny& data, wxString &result );
308 typedef void (*wxString2VariantFnc)( const wxString& data, wxAny &result );
e1d3601a
PC
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 }
f06d6937 317#if 0 // wxUSE_UNICODE
e1d3601a
PC
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
6c887dde
SC
351 // convert a wxAny holding data of this type into a string
352 void ConvertToString( const wxAny& data, wxString &result ) const
e1d3601a
PC
353 {
354 if ( m_toString )
355 (*m_toString)( data, result );
356 else
ebd98179 357 wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
e1d3601a
PC
358 }
359
6c887dde
SC
360 // convert a string into a wxAny holding the corresponding data in this type
361 void ConvertFromString( const wxString& data, wxAny &result ) const
e1d3601a
PC
362 {
363 if( m_fromString )
364 (*m_fromString)( data, result );
365 else
ebd98179 366 wxLogError( wxGetTranslation(wxT("String conversions not supported")) );
e1d3601a
PC
367 }
368
369 // statics:
370
c294641f 371 // looks for the corresponding type, will return NULL if not found
6c887dde 372 static wxTypeInfo *FindType( const wxString& typeName );
e1d3601a
PC
373private:
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
387class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo
388{
389public:
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") ); }
e1d3601a
PC
395};
396
397class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo
398{
399public:
400 wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to,
401 wxString2VariantFnc from ) :
402 wxTypeInfo( wxT_CUSTOM, to, from, name )
403 {}
e1d3601a
PC
404};
405
406class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo
407{
408public:
6c887dde
SC
409 typedef void (*converterToLong_t)( const wxAny& data, long &result );
410 typedef void (*converterFromLong_t)( long data, wxAny &result );
e1d3601a
PC
411
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
e1d3601a
PC
422 const wxEnumData* GetEnumData() const { return m_enumInfo; }
423
6c887dde
SC
424 // convert a wxAny holding data of this type into a long
425 void ConvertToLong( const wxAny& data, long &result ) const
e1d3601a
PC
426 {
427 if( m_toLong )
428 (*m_toLong)( data, result );
429 else
ebd98179 430 wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
e1d3601a
PC
431 }
432
6c887dde
SC
433 // convert a long into a wxAny holding the corresponding data in this type
434 void ConvertFromLong( long data, wxAny &result ) const
e1d3601a
PC
435 {
436 if( m_fromLong )
437 (*m_fromLong)( data, result );
438 else
ebd98179 439 wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) );
e1d3601a
PC
440 }
441
442private:
443 converterToLong_t m_toLong;
444 converterFromLong_t m_fromLong;
445
446 wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET
447};
448
449class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo
450{
451public:
452 wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
453 wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL,
454 const wxString &name = wxEmptyString);
455
e1d3601a
PC
456 const wxClassInfo *GetClassInfo() const { return m_classInfo; }
457
458private:
459 wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL
460};
461
462class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo
463{
464public:
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
e1d3601a
PC
470 const wxTypeInfo* GetElementType() const
471 {
472 if ( m_elementType == NULL )
473 m_elementType = wxTypeInfo::FindType( m_elementTypeName );
474 return m_elementType;
475 }
476
477private:
478 mutable wxTypeInfo * m_elementType;
479 wxString m_elementTypeName;
480};
481
482class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo
483{
484public:
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
491 int GetEventType() const { return m_eventType; }
492 int GetLastEventType() const { return m_lastEventType; }
493 const wxClassInfo* GetEventClass() const { return m_eventClass; }
494
495private:
496 const wxClassInfo *m_eventClass; // (extended will merge into classinfo)
497 int m_eventType;
498 int m_lastEventType;
499};
500
6c887dde 501template<typename T> const wxTypeInfo* wxGetTypeInfo( T * )
e1d3601a
PC
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 ) \
6c887dde 512 void ToString##e( const wxAny& data, wxString &result ) \
e1d3601a 513 { toString(data, result); } \
6c887dde 514 void FromString##e( const wxString& data, wxAny &result ) \
e1d3601a
PC
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_