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