]>
Commit | Line | Data |
---|---|---|
a095505c SC |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/common/xti.cpp | |
13830d6f | 3 | // Purpose: runtime metadata information (extended class info) |
a095505c | 4 | // Author: Stefan Csomor |
30fd71e6 | 5 | // Modified by: |
a095505c | 6 | // Created: 27/07/03 |
a095505c SC |
7 | // Copyright: (c) 1997 Julian Smart |
8 | // (c) 2003 Stefan Csomor | |
65571936 | 9 | // Licence: wxWindows licence |
a095505c SC |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
a095505c SC |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
8e3f3880 | 16 | #pragma hdrstop |
a095505c SC |
17 | #endif |
18 | ||
8e3f3880 WS |
19 | #if wxUSE_EXTENDED_RTTI |
20 | ||
a095505c | 21 | #ifndef WX_PRECOMP |
8e3f3880 | 22 | #include "wx/object.h" |
8ecff181 | 23 | #include "wx/list.h" |
8e3f3880 | 24 | #include "wx/hash.h" |
a095505c SC |
25 | #endif |
26 | ||
53b74313 | 27 | #include "wx/xti.h" |
a095505c SC |
28 | #include "wx/xml/xml.h" |
29 | #include "wx/tokenzr.h" | |
e765d7ee SC |
30 | #include "wx/range.h" |
31 | ||
a095505c SC |
32 | #include <string.h> |
33 | ||
ab6e4913 | 34 | #include "wx/beforestd.h" |
2d51f067 SC |
35 | #include <map> |
36 | #include <string> | |
8f2b1cfd | 37 | #include <list> |
ab6e4913 | 38 | #include "wx/afterstd.h" |
2d51f067 | 39 | |
13830d6f | 40 | using namespace std; |
2d51f067 | 41 | |
a095505c | 42 | // ---------------------------------------------------------------------------- |
13830d6f | 43 | // wxEnumData |
a095505c SC |
44 | // ---------------------------------------------------------------------------- |
45 | ||
30fd71e6 | 46 | wxEnumData::wxEnumData( wxEnumMemberData* data ) |
a095505c | 47 | { |
13830d6f SC |
48 | m_members = data; |
49 | for ( m_count = 0; m_members[m_count].m_name; m_count++) | |
50 | {}; | |
a095505c SC |
51 | } |
52 | ||
9a75ecf6 | 53 | bool wxEnumData::HasEnumMemberValue(const wxChar *name, int *value) const |
a095505c SC |
54 | { |
55 | int i; | |
13830d6f | 56 | for (i = 0; m_members[i].m_name; i++ ) |
2abce515 | 57 | { |
9dc6871e | 58 | if (!wxStrcmp(name, m_members[i].m_name)) |
2abce515 SC |
59 | { |
60 | if ( value ) | |
61 | *value = m_members[i].m_value; | |
13830d6f | 62 | return true; |
2abce515 SC |
63 | } |
64 | } | |
13830d6f | 65 | return false; |
a095505c SC |
66 | } |
67 | ||
9a75ecf6 | 68 | int wxEnumData::GetEnumMemberValue(const wxChar *name) const |
a095505c SC |
69 | { |
70 | int i; | |
13830d6f | 71 | for (i = 0; m_members[i].m_name; i++ ) |
2abce515 | 72 | { |
9dc6871e | 73 | if (!wxStrcmp(name, m_members[i].m_name)) |
2abce515 SC |
74 | { |
75 | return m_members[i].m_value; | |
76 | } | |
77 | } | |
13830d6f | 78 | return 0; |
a095505c SC |
79 | } |
80 | ||
9a75ecf6 | 81 | const wxChar *wxEnumData::GetEnumMemberName(int value) const |
a095505c SC |
82 | { |
83 | int i; | |
13830d6f | 84 | for (i = 0; m_members[i].m_name; i++) |
2abce515 SC |
85 | if (value == m_members[i].m_value) |
86 | return m_members[i].m_name; | |
a095505c | 87 | |
13830d6f | 88 | return wxEmptyString; |
a095505c SC |
89 | } |
90 | ||
9a75ecf6 | 91 | int wxEnumData::GetEnumMemberValueByIndex( int idx ) const |
a095505c | 92 | { |
2abce515 | 93 | // we should cache the count in order to avoid out-of-bounds errors |
13830d6f | 94 | return m_members[idx].m_value; |
a095505c SC |
95 | } |
96 | ||
9a75ecf6 | 97 | const wxChar * wxEnumData::GetEnumMemberNameByIndex( int idx ) const |
a095505c | 98 | { |
2abce515 | 99 | // we should cache the count in order to avoid out-of-bounds errors |
13830d6f | 100 | return m_members[idx].m_name; |
a095505c SC |
101 | } |
102 | ||
103 | // ---------------------------------------------------------------------------- | |
104 | // Type Information | |
105 | // ---------------------------------------------------------------------------- | |
13830d6f | 106 | |
a095505c | 107 | // ---------------------------------------------------------------------------- |
30fd71e6 | 108 | // value streaming |
a095505c SC |
109 | // ---------------------------------------------------------------------------- |
110 | ||
a095505c | 111 | // streamer specializations |
45212047 | 112 | // for all built-in types |
a095505c | 113 | |
45212047 | 114 | // bool |
a095505c | 115 | |
13830d6f | 116 | template<> void wxStringReadValue(const wxString &s, bool &data ) |
45212047 | 117 | { |
13830d6f | 118 | int intdata; |
ebd98179 | 119 | wxSscanf(s, wxT("%d"), &intdata ); |
13830d6f | 120 | data = (bool)(intdata != 0); |
45212047 | 121 | } |
a095505c | 122 | |
13830d6f | 123 | template<> void wxStringWriteValue(wxString &s, const bool &data ) |
a095505c | 124 | { |
ebd98179 | 125 | s = wxString::Format(wxT("%d"), data ); |
a095505c SC |
126 | } |
127 | ||
45212047 SC |
128 | // char |
129 | ||
13830d6f | 130 | template<> void wxStringReadValue(const wxString &s, char &data ) |
a095505c | 131 | { |
13830d6f | 132 | int intdata; |
ebd98179 | 133 | wxSscanf(s, wxT("%d"), &intdata ); |
13830d6f | 134 | data = char(intdata); |
45212047 SC |
135 | } |
136 | ||
13830d6f | 137 | template<> void wxStringWriteValue(wxString &s, const char &data ) |
45212047 | 138 | { |
ebd98179 | 139 | s = wxString::Format(wxT("%d"), data ); |
45212047 SC |
140 | } |
141 | ||
142 | // unsigned char | |
143 | ||
13830d6f | 144 | template<> void wxStringReadValue(const wxString &s, unsigned char &data ) |
45212047 | 145 | { |
13830d6f | 146 | int intdata; |
ebd98179 | 147 | wxSscanf(s, wxT("%d"), &intdata ); |
13830d6f | 148 | data = (unsigned char)(intdata); |
45212047 SC |
149 | } |
150 | ||
13830d6f | 151 | template<> void wxStringWriteValue(wxString &s, const unsigned char &data ) |
45212047 | 152 | { |
ebd98179 | 153 | s = wxString::Format(wxT("%d"), data ); |
a095505c SC |
154 | } |
155 | ||
30fd71e6 | 156 | // int |
a095505c | 157 | |
13830d6f | 158 | template<> void wxStringReadValue(const wxString &s, int &data ) |
a095505c | 159 | { |
ebd98179 | 160 | wxSscanf(s, wxT("%d"), &data ); |
a095505c SC |
161 | } |
162 | ||
13830d6f | 163 | template<> void wxStringWriteValue(wxString &s, const int &data ) |
a095505c | 164 | { |
ebd98179 | 165 | s = wxString::Format(wxT("%d"), data ); |
a095505c SC |
166 | } |
167 | ||
45212047 SC |
168 | // unsigned int |
169 | ||
13830d6f | 170 | template<> void wxStringReadValue(const wxString &s, unsigned int &data ) |
45212047 | 171 | { |
ebd98179 | 172 | wxSscanf(s, wxT("%d"), &data ); |
45212047 SC |
173 | } |
174 | ||
13830d6f | 175 | template<> void wxStringWriteValue(wxString &s, const unsigned int &data ) |
45212047 | 176 | { |
ebd98179 | 177 | s = wxString::Format(wxT("%d"), data ); |
45212047 SC |
178 | } |
179 | ||
180 | // long | |
181 | ||
13830d6f | 182 | template<> void wxStringReadValue(const wxString &s, long &data ) |
45212047 | 183 | { |
ebd98179 | 184 | wxSscanf(s, wxT("%ld"), &data ); |
45212047 SC |
185 | } |
186 | ||
13830d6f | 187 | template<> void wxStringWriteValue(wxString &s, const long &data ) |
45212047 | 188 | { |
ebd98179 | 189 | s = wxString::Format(wxT("%ld"), data ); |
45212047 SC |
190 | } |
191 | ||
192 | // unsigned long | |
193 | ||
13830d6f | 194 | template<> void wxStringReadValue(const wxString &s, unsigned long &data ) |
45212047 | 195 | { |
ebd98179 | 196 | wxSscanf(s, wxT("%ld"), &data ); |
45212047 SC |
197 | } |
198 | ||
13830d6f | 199 | template<> void wxStringWriteValue(wxString &s, const unsigned long &data ) |
45212047 | 200 | { |
ebd98179 | 201 | s = wxString::Format(wxT("%ld"), data ); |
45212047 SC |
202 | } |
203 | ||
e765d7ee SC |
204 | #ifdef wxLongLong_t |
205 | template<> void wxStringReadValue(const wxString &s, wxLongLong_t &data ) | |
206 | { | |
ebd98179 | 207 | wxSscanf(s, wxT("%lld"), &data ); |
e765d7ee SC |
208 | } |
209 | ||
210 | template<> void wxStringWriteValue(wxString &s, const wxLongLong_t &data ) | |
211 | { | |
ebd98179 | 212 | s = wxString::Format(wxT("%lld"), data ); |
e765d7ee SC |
213 | } |
214 | ||
215 | template<> void wxStringReadValue(const wxString &s, wxULongLong_t &data ) | |
216 | { | |
ebd98179 | 217 | wxSscanf(s, wxT("%lld"), &data ); |
e765d7ee SC |
218 | } |
219 | ||
220 | template<> void wxStringWriteValue(wxString &s, const wxULongLong_t &data ) | |
221 | { | |
ebd98179 | 222 | s = wxString::Format(wxT("%lld"), data ); |
e765d7ee SC |
223 | } |
224 | #endif | |
45212047 SC |
225 | // float |
226 | ||
13830d6f | 227 | template<> void wxStringReadValue(const wxString &s, float &data ) |
45212047 | 228 | { |
ebd98179 | 229 | wxSscanf(s, wxT("%f"), &data ); |
45212047 SC |
230 | } |
231 | ||
13830d6f | 232 | template<> void wxStringWriteValue(wxString &s, const float &data ) |
45212047 | 233 | { |
ebd98179 | 234 | s = wxString::Format(wxT("%f"), data ); |
45212047 SC |
235 | } |
236 | ||
237 | // double | |
238 | ||
13830d6f | 239 | template<> void wxStringReadValue(const wxString &s, double &data ) |
45212047 | 240 | { |
ebd98179 | 241 | wxSscanf(s, wxT("%lf"), &data ); |
45212047 SC |
242 | } |
243 | ||
13830d6f | 244 | template<> void wxStringWriteValue(wxString &s, const double &data ) |
45212047 | 245 | { |
ebd98179 | 246 | s = wxString::Format(wxT("%lf"), data ); |
45212047 SC |
247 | } |
248 | ||
a095505c SC |
249 | // wxString |
250 | ||
13830d6f | 251 | template<> void wxStringReadValue(const wxString &s, wxString &data ) |
a095505c | 252 | { |
13830d6f | 253 | data = s; |
a095505c SC |
254 | } |
255 | ||
13830d6f | 256 | template<> void wxStringWriteValue(wxString &s, const wxString &data ) |
a095505c | 257 | { |
13830d6f | 258 | s = data; |
a095505c SC |
259 | } |
260 | ||
13830d6f | 261 | |
c1d6d0f9 SC |
262 | // built-ins |
263 | // | |
b8d5be01 | 264 | |
af498247 | 265 | #if wxUSE_FUNC_TEMPLATE_POINTER |
13830d6f SC |
266 | #define wxBUILTIN_TYPE_INFO( element, type ) \ |
267 | wxBuiltInTypeInfo \ | |
268 | s_typeInfo##type(element, &wxToStringConverter<type>, \ | |
269 | &wxFromStringConverter<type>, typeid(type).name()); | |
af498247 | 270 | #else |
13830d6f | 271 | #define wxBUILTIN_TYPE_INFO( element, type ) \ |
e765d7ee | 272 | void _toString##element( const wxAny& data, wxString &result ) \ |
13830d6f | 273 | { wxToStringConverter<type, data, result); } \ |
e765d7ee | 274 | void _fromString##element( const wxString& data, wxAny &result ) \ |
13830d6f SC |
275 | { wxFromStringConverter<type, data, result); } \ |
276 | wxBuiltInTypeInfo s_typeInfo##type(element, &_toString##element, \ | |
277 | &_fromString##element, typeid(type).name()); | |
af498247 VZ |
278 | #endif |
279 | ||
280 | typedef unsigned char unsigned_char; | |
281 | typedef unsigned int unsigned_int; | |
282 | typedef unsigned long unsigned_long; | |
283 | ||
13830d6f SC |
284 | wxBuiltInTypeInfo s_typeInfovoid( wxT_VOID, NULL, NULL, typeid(void).name()); |
285 | wxBUILTIN_TYPE_INFO( wxT_BOOL, bool); | |
286 | wxBUILTIN_TYPE_INFO( wxT_CHAR, char); | |
287 | wxBUILTIN_TYPE_INFO( wxT_UCHAR, unsigned_char); | |
288 | wxBUILTIN_TYPE_INFO( wxT_INT, int); | |
289 | wxBUILTIN_TYPE_INFO( wxT_UINT, unsigned_int); | |
290 | wxBUILTIN_TYPE_INFO( wxT_LONG, long); | |
291 | wxBUILTIN_TYPE_INFO( wxT_ULONG, unsigned_long); | |
292 | wxBUILTIN_TYPE_INFO( wxT_FLOAT, float); | |
293 | wxBUILTIN_TYPE_INFO( wxT_DOUBLE, double); | |
294 | wxBUILTIN_TYPE_INFO( wxT_STRING, wxString); | |
af498247 | 295 | |
e765d7ee SC |
296 | #ifdef wxLongLong_t |
297 | wxBUILTIN_TYPE_INFO(wxT_LONGLONG, wxLongLong_t) | |
298 | wxBUILTIN_TYPE_INFO(wxT_ULONGLONG, wxULongLong_t) | |
299 | #endif | |
b8d5be01 SC |
300 | |
301 | // this are compiler induced specialization which are never used anywhere | |
302 | ||
8805dbab SC |
303 | wxILLEGAL_TYPE_SPECIALIZATION( char const * ) |
304 | wxILLEGAL_TYPE_SPECIALIZATION( char * ) | |
305 | wxILLEGAL_TYPE_SPECIALIZATION( unsigned char * ) | |
306 | wxILLEGAL_TYPE_SPECIALIZATION( int * ) | |
307 | wxILLEGAL_TYPE_SPECIALIZATION( bool * ) | |
308 | wxILLEGAL_TYPE_SPECIALIZATION( long * ) | |
309 | wxILLEGAL_TYPE_SPECIALIZATION( wxString * ) | |
b8d5be01 | 310 | |
e765d7ee SC |
311 | // wxRange |
312 | ||
313 | template<> void wxStringReadValue(const wxString &s , wxRange &data) | |
314 | { | |
315 | int minValue, maxValue; | |
316 | wxSscanf(s, wxT("%d,%d"), &minValue , &maxValue); | |
317 | data = wxRange(minValue, maxValue); | |
318 | } | |
319 | ||
320 | template<> void wxStringWriteValue(wxString &s , const wxRange &data) | |
321 | { | |
322 | s = wxString::Format(wxT("%d,%d"), data.GetMin() , data.GetMax()); | |
323 | } | |
324 | ||
325 | wxCUSTOM_TYPE_INFO(wxRange, wxToStringConverter<wxRange> , wxFromStringConverter<wxRange>) | |
326 | ||
327 | // other types | |
328 | ||
13830d6f | 329 | wxCOLLECTION_TYPE_INFO( wxString, wxArrayString ); |
b8d5be01 | 330 | |
13830d6f | 331 | template<> void wxCollectionToVariantArray( wxArrayString const &theArray, |
e765d7ee | 332 | wxAnyList &value) |
b8d5be01 | 333 | { |
13830d6f | 334 | wxArrayCollectionToVariantArray( theArray, value ); |
b8d5be01 SC |
335 | } |
336 | ||
13830d6f | 337 | wxTypeInfoMap *wxTypeInfo::ms_typeTable = NULL; |
b8d5be01 | 338 | |
e765d7ee | 339 | wxTypeInfo *wxTypeInfo::FindType(const wxString& typeName) |
cb73e600 | 340 | { |
13830d6f SC |
341 | wxTypeInfoMap::iterator iter = ms_typeTable->find(typeName); |
342 | ||
13830d6f SC |
343 | if (iter == ms_typeTable->end()) |
344 | return NULL; | |
345 | ||
499a9a62 | 346 | return (wxTypeInfo *)iter->second; |
cb73e600 | 347 | } |
b8d5be01 | 348 | |
13830d6f SC |
349 | wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, |
350 | wxVariant2StringFnc to, | |
351 | wxString2VariantFnc from, | |
352 | const wxString &name) : | |
353 | wxTypeInfo( kind, to, from, name) | |
354 | { | |
355 | wxASSERT_MSG( kind == wxT_OBJECT_PTR || kind == wxT_OBJECT, | |
356 | wxT("Illegal Kind for Enum Type")); m_classInfo = classInfo; | |
357 | } | |
358 | ||
359 | wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass, | |
360 | wxVariant2StringFnc to, | |
361 | wxString2VariantFnc from ) : | |
362 | wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString ) | |
363 | { | |
364 | m_eventClass = eventClass; | |
365 | m_eventType = eventType; | |
366 | m_lastEventType = -1; | |
367 | } | |
368 | ||
369 | wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, int lastEventType, | |
370 | wxClassInfo* eventClass, | |
371 | wxVariant2StringFnc to, | |
372 | wxString2VariantFnc from ) : | |
373 | wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString ) | |
374 | { | |
375 | m_eventClass = eventClass; | |
376 | m_eventType = eventType; | |
377 | m_lastEventType = lastEventType; | |
378 | } | |
45212047 | 379 | |
cb73e600 | 380 | void wxTypeInfo::Register() |
cab1a605 | 381 | { |
05fa251a | 382 | if ( ms_typeTable == NULL ) |
13830d6f | 383 | ms_typeTable = new wxTypeInfoMap(); |
45212047 | 384 | |
525d8583 | 385 | if( !m_name.empty() ) |
13830d6f | 386 | (*ms_typeTable)[m_name] = this; |
45212047 SC |
387 | } |
388 | ||
cb73e600 SC |
389 | void wxTypeInfo::Unregister() |
390 | { | |
525d8583 | 391 | if( !m_name.empty() ) |
05fa251a | 392 | ms_typeTable->erase(m_name); |
2abce515 | 393 | } |
45212047 | 394 | |
37424888 | 395 | // removing header dependency on string tokenizer |
a095505c | 396 | |
13830d6f | 397 | void wxSetStringToArray( const wxString &s, wxArrayString &array ) |
a095505c SC |
398 | { |
399 | wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK); | |
400 | wxString flag; | |
13830d6f | 401 | array.Clear(); |
a095505c SC |
402 | while (tokenizer.HasMoreTokens()) |
403 | { | |
13830d6f | 404 | array.Add(tokenizer.GetNextToken()); |
2abce515 | 405 | } |
a095505c SC |
406 | } |
407 | ||
408 | // ---------------------------------------------------------------------------- | |
13830d6f | 409 | // wxPropertyInfo |
a095505c SC |
410 | // ---------------------------------------------------------------------------- |
411 | ||
13830d6f SC |
412 | void wxPropertyInfo::Insert(wxPropertyInfo* &iter) |
413 | { | |
414 | m_next = NULL; | |
415 | if ( iter == NULL ) | |
416 | iter = this; | |
417 | else | |
418 | { | |
419 | wxPropertyInfo* i = iter; | |
420 | while( i->m_next ) | |
421 | i = i->m_next; | |
422 | ||
423 | i->m_next = this; | |
424 | } | |
425 | } | |
426 | ||
427 | void wxPropertyInfo::Remove() | |
499a9a62 SC |
428 | { |
429 | if ( this == m_itsClass->m_firstProperty ) | |
430 | { | |
431 | m_itsClass->m_firstProperty = m_next; | |
432 | } | |
433 | else | |
434 | { | |
435 | wxPropertyInfo *info = m_itsClass->m_firstProperty; | |
436 | while (info) | |
437 | { | |
438 | if ( info->m_next == this ) | |
439 | { | |
440 | info->m_next = m_next; | |
441 | break; | |
442 | } | |
443 | ||
444 | info = info->m_next; | |
445 | } | |
446 | } | |
e765d7ee | 447 | |
499a9a62 SC |
448 | } |
449 | ||
13830d6f SC |
450 | // ---------------------------------------------------------------------------- |
451 | // wxHandlerInfo | |
452 | // ---------------------------------------------------------------------------- | |
453 | ||
454 | void wxHandlerInfo::Insert(wxHandlerInfo* &iter) | |
455 | { | |
456 | m_next = NULL; | |
457 | if ( iter == NULL ) | |
458 | iter = this; | |
459 | else | |
460 | { | |
461 | wxHandlerInfo* i = iter; | |
462 | while( i->m_next ) | |
463 | i = i->m_next; | |
464 | ||
465 | i->m_next = this; | |
466 | } | |
467 | } | |
468 | ||
469 | void wxHandlerInfo::Remove() | |
499a9a62 SC |
470 | { |
471 | if ( this == m_itsClass->m_firstHandler ) | |
472 | { | |
473 | m_itsClass->m_firstHandler = m_next; | |
474 | } | |
475 | else | |
476 | { | |
477 | wxHandlerInfo *info = m_itsClass->m_firstHandler; | |
478 | while (info) | |
479 | { | |
480 | if ( info->m_next == this ) | |
481 | { | |
482 | info->m_next = m_next; | |
483 | break; | |
484 | } | |
485 | ||
486 | info = info->m_next; | |
487 | } | |
488 | } | |
489 | } | |
490 | ||
13830d6f SC |
491 | |
492 | // ---------------------------------------------------------------------------- | |
493 | // wxClassInfo | |
494 | // ---------------------------------------------------------------------------- | |
495 | ||
e765d7ee | 496 | bool wxClassInfo::Create(wxObject *object, int ParamCount, wxAny *Params) const |
13830d6f SC |
497 | { |
498 | if ( ParamCount != m_constructorPropertiesCount ) | |
499 | { | |
500 | // FIXME: shouldn't we just return false and let the caller handle it? | |
501 | wxLogError( _("Illegal Parameter Count for Create Method") ); | |
502 | return false; | |
503 | } | |
504 | ||
505 | return m_constructor->Create( object, Params ); | |
506 | } | |
507 | ||
e765d7ee | 508 | wxObject *wxClassInfo::ConstructObject(int ParamCount, wxAny *Params) const |
13830d6f SC |
509 | { |
510 | if ( ParamCount != m_constructorPropertiesCount ) | |
511 | { | |
512 | // FIXME: shouldn't we just return NULL and let the caller handle this case? | |
513 | wxLogError( _("Illegal Parameter Count for ConstructObject Method") ); | |
514 | return NULL; | |
515 | } | |
516 | ||
517 | wxObject *object = NULL; | |
518 | if (!m_constructor->Create( object, Params )) | |
519 | return NULL; | |
520 | return object; | |
521 | } | |
522 | ||
523 | bool wxClassInfo::IsKindOf(const wxClassInfo *info) const | |
524 | { | |
525 | if ( info != 0 ) | |
526 | { | |
527 | if ( info == this ) | |
528 | return true; | |
529 | ||
530 | for ( int i = 0; m_parents[i]; ++ i ) | |
531 | { | |
532 | if ( m_parents[i]->IsKindOf( info ) ) | |
533 | return true; | |
534 | } | |
535 | } | |
536 | return false; | |
537 | } | |
538 | ||
9dc6871e | 539 | const wxPropertyAccessor *wxClassInfo::FindAccessor(const wxChar *PropertyName) const |
a095505c | 540 | { |
13830d6f | 541 | const wxPropertyInfo* info = FindPropertyInfo( PropertyName ); |
30fd71e6 | 542 | |
2abce515 | 543 | if ( info ) |
13830d6f | 544 | return info->GetAccessor(); |
a095505c | 545 | |
13830d6f | 546 | return NULL; |
a095505c SC |
547 | } |
548 | ||
9dc6871e | 549 | wxPropertyInfo *wxClassInfo::FindPropertyInfoInThisClass (const wxChar *PropertyName) const |
a095505c | 550 | { |
e765d7ee | 551 | wxPropertyInfo* info = GetFirstProperty(); |
a095505c | 552 | |
2abce515 SC |
553 | while( info ) |
554 | { | |
13830d6f SC |
555 | if ( wxStrcmp( info->GetName(), PropertyName ) == 0 ) |
556 | return info; | |
557 | info = info->GetNext(); | |
2abce515 | 558 | } |
a095505c | 559 | |
2d51f067 SC |
560 | return 0; |
561 | } | |
562 | ||
9dc6871e | 563 | const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const wxChar *PropertyName) const |
2d51f067 | 564 | { |
13830d6f | 565 | const wxPropertyInfo* info = FindPropertyInfoInThisClass( PropertyName ); |
2d51f067 | 566 | if ( info ) |
13830d6f | 567 | return info; |
2d51f067 | 568 | |
13830d6f SC |
569 | const wxClassInfo** parents = GetParents(); |
570 | for ( int i = 0; parents[i]; ++ i ) | |
2abce515 SC |
571 | { |
572 | if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL ) | |
13830d6f | 573 | return info; |
2abce515 | 574 | } |
a095505c SC |
575 | |
576 | return 0; | |
577 | } | |
578 | ||
9dc6871e | 579 | wxHandlerInfo *wxClassInfo::FindHandlerInfoInThisClass (const wxChar *PropertyName) const |
fbbdc52c | 580 | { |
e765d7ee | 581 | wxHandlerInfo* info = GetFirstHandler(); |
fbbdc52c | 582 | |
2abce515 SC |
583 | while( info ) |
584 | { | |
13830d6f SC |
585 | if ( wxStrcmp( info->GetName(), PropertyName ) == 0 ) |
586 | return info; | |
587 | info = info->GetNext(); | |
2abce515 | 588 | } |
fbbdc52c | 589 | |
2d51f067 SC |
590 | return 0; |
591 | } | |
592 | ||
9dc6871e | 593 | const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const wxChar *PropertyName) const |
2d51f067 | 594 | { |
13830d6f | 595 | const wxHandlerInfo* info = FindHandlerInfoInThisClass( PropertyName ); |
2d51f067 SC |
596 | |
597 | if ( info ) | |
13830d6f | 598 | return info; |
2d51f067 | 599 | |
13830d6f SC |
600 | const wxClassInfo** parents = GetParents(); |
601 | for ( int i = 0; parents[i]; ++ i ) | |
2abce515 SC |
602 | { |
603 | if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL ) | |
13830d6f | 604 | return info; |
2abce515 | 605 | } |
fbbdc52c SC |
606 | |
607 | return 0; | |
608 | } | |
609 | ||
9c8046dd SC |
610 | wxObjectStreamingCallback wxClassInfo::GetStreamingCallback() const |
611 | { | |
612 | if ( m_streamingCallback ) | |
13830d6f | 613 | return m_streamingCallback; |
9c8046dd | 614 | |
13830d6f SC |
615 | wxObjectStreamingCallback retval = NULL; |
616 | const wxClassInfo** parents = GetParents(); | |
617 | for ( int i = 0; parents[i] && retval == NULL; ++ i ) | |
2abce515 | 618 | { |
13830d6f | 619 | retval = parents[i]->GetStreamingCallback(); |
2abce515 | 620 | } |
13830d6f | 621 | return retval; |
9c8046dd SC |
622 | } |
623 | ||
13830d6f | 624 | bool wxClassInfo::BeforeWriteObject( const wxObject *obj, wxObjectWriter *streamer, |
e765d7ee | 625 | wxObjectWriterCallback *writercallback, const wxStringToAnyHashMap &metadata) const |
9c8046dd | 626 | { |
13830d6f | 627 | wxObjectStreamingCallback sb = GetStreamingCallback(); |
9c8046dd | 628 | if ( sb ) |
e765d7ee | 629 | return (*sb)(obj, streamer, writercallback, metadata ); |
9c8046dd | 630 | |
13830d6f | 631 | return true; |
9c8046dd | 632 | } |
fbbdc52c | 633 | |
13830d6f | 634 | void wxClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, |
e765d7ee | 635 | const wxAny &value) const |
a095505c SC |
636 | { |
637 | const wxPropertyAccessor *accessor; | |
638 | ||
639 | accessor = FindAccessor(propertyName); | |
640 | wxASSERT(accessor->HasSetter()); | |
13830d6f | 641 | accessor->SetProperty( object, value ); |
a095505c SC |
642 | } |
643 | ||
e765d7ee | 644 | wxAny wxClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const |
a095505c SC |
645 | { |
646 | const wxPropertyAccessor *accessor; | |
647 | ||
648 | accessor = FindAccessor(propertyName); | |
649 | wxASSERT(accessor->HasGetter()); | |
e765d7ee | 650 | wxAny result; |
b8d5be01 | 651 | accessor->GetProperty(object,result); |
13830d6f | 652 | return result; |
a095505c SC |
653 | } |
654 | ||
e765d7ee | 655 | wxAnyList wxClassInfo::GetPropertyCollection(wxObject *object, |
13830d6f | 656 | const wxChar *propertyName) const |
ab6e4913 SC |
657 | { |
658 | const wxPropertyAccessor *accessor; | |
659 | ||
660 | accessor = FindAccessor(propertyName); | |
661 | wxASSERT(accessor->HasGetter()); | |
e765d7ee | 662 | wxAnyList result; |
b8d5be01 | 663 | accessor->GetPropertyCollection(object,result); |
13830d6f | 664 | return result; |
ab6e4913 SC |
665 | } |
666 | ||
13830d6f | 667 | void wxClassInfo::AddToPropertyCollection(wxObject *object, const wxChar *propertyName, |
e765d7ee | 668 | const wxAny& value) const |
ab6e4913 SC |
669 | { |
670 | const wxPropertyAccessor *accessor; | |
671 | ||
672 | accessor = FindAccessor(propertyName); | |
673 | wxASSERT(accessor->HasAdder()); | |
13830d6f | 674 | accessor->AddToPropertyCollection( object, value ); |
ab6e4913 SC |
675 | } |
676 | ||
cab1a605 | 677 | // void wxClassInfo::GetProperties( wxPropertyInfoMap &map ) const |
af498247 VZ |
678 | // The map parameter (the name map that is) seems something special |
679 | // to MSVC and so we use a other name. | |
cab1a605 | 680 | void wxClassInfo::GetProperties( wxPropertyInfoMap &infomap ) const |
cb73e600 | 681 | { |
13830d6f | 682 | const wxPropertyInfo *pi = GetFirstProperty(); |
cab1a605 | 683 | while( pi ) |
cb73e600 | 684 | { |
af498247 | 685 | if ( infomap.find( pi->GetName() ) == infomap.end() ) |
13830d6f | 686 | infomap[pi->GetName()] = (wxPropertyInfo*) pi; |
cb73e600 | 687 | |
13830d6f | 688 | pi = pi->GetNext(); |
cb73e600 SC |
689 | } |
690 | ||
13830d6f SC |
691 | const wxClassInfo** parents = GetParents(); |
692 | for ( int i = 0; parents[i]; ++ i ) | |
cb73e600 | 693 | { |
13830d6f | 694 | parents[i]->GetProperties( infomap ); |
cb73e600 SC |
695 | } |
696 | } | |
697 | ||
e765d7ee SC |
698 | wxObject* wxClassInfo::AnyToObjectPtr( const wxAny &data) const |
699 | { | |
700 | return m_variantOfPtrToObjectConverter(data); | |
701 | } | |
702 | ||
703 | void wxClassInfo::CallOnAny( const wxAny &data, wxObjectFunctor* functor ) const | |
704 | { | |
705 | if ( data.GetTypeInfo()->GetKind() == wxT_OBJECT ) | |
706 | return m_variantToObjectConverter(data, functor); | |
707 | else | |
708 | return (*functor)(m_variantOfPtrToObjectConverter(data)); | |
709 | } | |
710 | ||
711 | wxAny wxClassInfo::ObjectPtrToAny( wxObject* obj) const | |
712 | { | |
713 | return m_objectToVariantConverter(obj); | |
714 | } | |
a095505c | 715 | |
bca6bd38 SC |
716 | bool wxClassInfo::NeedsDirectConstruction() const |
717 | { | |
718 | return wx_dynamic_cast(wxObjectAllocator*, m_constructor) != NULL; | |
719 | } | |
720 | ||
2d51f067 SC |
721 | // ---------------------------------------------------------------------------- |
722 | // wxDynamicObject support | |
723 | // ---------------------------------------------------------------------------- | |
13830d6f | 724 | |
2d51f067 SC |
725 | // Dynamic Objects are objects that have a real superclass instance and carry their |
726 | // own attributes in a hash map. Like this it is possible to create the objects and | |
727 | // stream them, as if their class information was already available from compiled data | |
728 | ||
729 | struct wxDynamicObject::wxDynamicObjectInternal | |
730 | { | |
8f2b1cfd SC |
731 | wxDynamicObjectInternal() {} |
732 | ||
e765d7ee | 733 | wxStringToAnyHashMap m_properties; |
13830d6f | 734 | }; |
8f2b1cfd | 735 | |
13830d6f | 736 | typedef list< wxDynamicObject* > wxDynamicObjectList; |
8f2b1cfd SC |
737 | |
738 | struct wxDynamicClassInfo::wxDynamicClassInfoInternal | |
739 | { | |
13830d6f SC |
740 | wxDynamicObjectList m_dynamicObjects; |
741 | }; | |
2d51f067 SC |
742 | |
743 | // instantiates this object with an instance of its superclass | |
b8d5be01 | 744 | wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info) |
2d51f067 | 745 | { |
13830d6f SC |
746 | m_superClassInstance = superClassInstance; |
747 | m_classInfo = info; | |
748 | m_data = new wxDynamicObjectInternal; | |
2d51f067 SC |
749 | } |
750 | ||
751 | wxDynamicObject::~wxDynamicObject() | |
752 | { | |
13830d6f SC |
753 | wx_dynamic_cast(const wxDynamicClassInfo*, m_classInfo)-> |
754 | m_data->m_dynamicObjects.remove( this ); | |
755 | delete m_data; | |
756 | delete m_superClassInstance; | |
2d51f067 SC |
757 | } |
758 | ||
e765d7ee | 759 | void wxDynamicObject::SetProperty (const wxChar *propertyName, const wxAny &value) |
2d51f067 | 760 | { |
13830d6f SC |
761 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), |
762 | wxT("Accessing Unknown Property in a Dynamic Object") ); | |
763 | m_data->m_properties[propertyName] = value; | |
2d51f067 SC |
764 | } |
765 | ||
e765d7ee | 766 | wxAny wxDynamicObject::GetProperty (const wxChar *propertyName) const |
2d51f067 | 767 | { |
13830d6f SC |
768 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), |
769 | wxT("Accessing Unknown Property in a Dynamic Object") ); | |
770 | return m_data->m_properties[propertyName]; | |
8f2b1cfd SC |
771 | } |
772 | ||
cab1a605 | 773 | void wxDynamicObject::RemoveProperty( const wxChar *propertyName ) |
8f2b1cfd | 774 | { |
13830d6f SC |
775 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), |
776 | wxT("Removing Unknown Property in a Dynamic Object") ); | |
777 | m_data->m_properties.erase( propertyName ); | |
2d51f067 SC |
778 | } |
779 | ||
13830d6f SC |
780 | void wxDynamicObject::RenameProperty( const wxChar *oldPropertyName, |
781 | const wxChar *newPropertyName ) | |
8f2b1cfd | 782 | { |
13830d6f SC |
783 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(oldPropertyName), |
784 | wxT("Renaming Unknown Property in a Dynamic Object") ); | |
785 | ||
e765d7ee | 786 | wxAny value = m_data->m_properties[oldPropertyName]; |
13830d6f SC |
787 | m_data->m_properties.erase( oldPropertyName ); |
788 | m_data->m_properties[newPropertyName] = value; | |
8f2b1cfd SC |
789 | } |
790 | ||
791 | ||
2d51f067 | 792 | // ---------------------------------------------------------------------------- |
13830d6f | 793 | // wxDynamicClassInfo |
2d51f067 SC |
794 | // ---------------------------------------------------------------------------- |
795 | ||
13830d6f SC |
796 | wxDynamicClassInfo::wxDynamicClassInfo( const wxChar *unitName, |
797 | const wxChar *className, | |
798 | const wxClassInfo* superClass ) : | |
799 | wxClassInfo( unitName, className, new const wxClassInfo*[2]) | |
2d51f067 | 800 | { |
13830d6f SC |
801 | GetParents()[0] = superClass; |
802 | GetParents()[1] = NULL; | |
803 | m_data = new wxDynamicClassInfoInternal; | |
2d51f067 SC |
804 | } |
805 | ||
806 | wxDynamicClassInfo::~wxDynamicClassInfo() | |
807 | { | |
13830d6f SC |
808 | delete[] GetParents(); |
809 | delete m_data; | |
2d51f067 SC |
810 | } |
811 | ||
b8d5be01 | 812 | wxObject *wxDynamicClassInfo::AllocateObject() const |
2d51f067 | 813 | { |
13830d6f SC |
814 | wxObject* parent = GetParents()[0]->AllocateObject(); |
815 | wxDynamicObject *obj = new wxDynamicObject( parent, this ); | |
816 | m_data->m_dynamicObjects.push_back( obj ); | |
817 | return obj; | |
2d51f067 SC |
818 | } |
819 | ||
e765d7ee | 820 | bool wxDynamicClassInfo::Create (wxObject *object, int paramCount, wxAny *params) const |
2d51f067 | 821 | { |
13830d6f SC |
822 | wxDynamicObject *dynobj = wx_dynamic_cast( wxDynamicObject *, object ); |
823 | wxASSERT_MSG( dynobj, | |
824 | wxT("cannot call wxDynamicClassInfo::Create on ") | |
825 | wxT("an object other than wxDynamicObject") ); | |
826 | ||
827 | return GetParents()[0]->Create( dynobj->GetSuperClassInstance(), paramCount, params ); | |
2d51f067 SC |
828 | } |
829 | ||
830 | // get number of parameters for constructor | |
b8d5be01 | 831 | int wxDynamicClassInfo::GetCreateParamCount() const |
2d51f067 | 832 | { |
13830d6f | 833 | return GetParents()[0]->GetCreateParamCount(); |
2d51f067 SC |
834 | } |
835 | ||
836 | // get i-th constructor parameter | |
b8d5be01 | 837 | const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const |
2d51f067 | 838 | { |
13830d6f | 839 | return GetParents()[0]->GetCreateParamName( i ); |
2d51f067 SC |
840 | } |
841 | ||
e765d7ee | 842 | void wxDynamicClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, const wxAny &value) const |
2d51f067 | 843 | { |
13830d6f SC |
844 | wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); |
845 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
2d51f067 | 846 | if ( FindPropertyInfoInThisClass(propertyName) ) |
13830d6f | 847 | dynobj->SetProperty( propertyName, value ); |
2d51f067 | 848 | else |
13830d6f | 849 | GetParents()[0]->SetProperty( dynobj->GetSuperClassInstance(), propertyName, value ); |
2d51f067 SC |
850 | } |
851 | ||
e765d7ee | 852 | wxAny wxDynamicClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const |
2d51f067 | 853 | { |
13830d6f SC |
854 | wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); |
855 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
2d51f067 | 856 | if ( FindPropertyInfoInThisClass(propertyName) ) |
13830d6f | 857 | return dynobj->GetProperty( propertyName ); |
2d51f067 | 858 | else |
13830d6f | 859 | return GetParents()[0]->GetProperty( dynobj->GetSuperClassInstance(), propertyName ); |
2d51f067 SC |
860 | } |
861 | ||
13830d6f | 862 | void wxDynamicClassInfo::AddProperty( const wxChar *propertyName, const wxTypeInfo* typeInfo ) |
2d51f067 | 863 | { |
e765d7ee SC |
864 | EnsureInfosInited(); |
865 | new wxPropertyInfo( m_firstProperty, this, propertyName, typeInfo->GetTypeName(), new wxGenericPropertyAccessor( propertyName ), wxAny() ); | |
2d51f067 SC |
866 | } |
867 | ||
13830d6f | 868 | void wxDynamicClassInfo::AddHandler( const wxChar *handlerName, wxObjectEventFunction address, const wxClassInfo* eventClassInfo ) |
2d51f067 | 869 | { |
e765d7ee | 870 | EnsureInfosInited(); |
13830d6f | 871 | new wxHandlerInfo( m_firstHandler, this, handlerName, address, eventClassInfo ); |
2d51f067 SC |
872 | } |
873 | ||
2abce515 | 874 | // removes an existing runtime-property |
cab1a605 | 875 | void wxDynamicClassInfo::RemoveProperty( const wxChar *propertyName ) |
2abce515 | 876 | { |
13830d6f SC |
877 | for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter ) |
878 | (*iter)->RemoveProperty( propertyName ); | |
879 | delete FindPropertyInfoInThisClass(propertyName); | |
2abce515 SC |
880 | } |
881 | ||
882 | // removes an existing runtime-handler | |
cab1a605 | 883 | void wxDynamicClassInfo::RemoveHandler( const wxChar *handlerName ) |
2abce515 | 884 | { |
13830d6f | 885 | delete FindHandlerInfoInThisClass(handlerName); |
499a9a62 SC |
886 | } |
887 | ||
888 | // renames an existing runtime-property | |
13830d6f | 889 | void wxDynamicClassInfo::RenameProperty( const wxChar *oldPropertyName, const wxChar *newPropertyName ) |
499a9a62 | 890 | { |
13830d6f SC |
891 | wxPropertyInfo* pi = FindPropertyInfoInThisClass(oldPropertyName); |
892 | wxASSERT_MSG( pi,wxT("not existing property") ); | |
893 | pi->m_name = newPropertyName; | |
894 | wx_dynamic_cast(wxGenericPropertyAccessor*, pi->GetAccessor())->RenameProperty( oldPropertyName, newPropertyName ); | |
895 | for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter ) | |
896 | (*iter)->RenameProperty( oldPropertyName, newPropertyName ); | |
499a9a62 SC |
897 | } |
898 | ||
899 | // renames an existing runtime-handler | |
13830d6f | 900 | void wxDynamicClassInfo::RenameHandler( const wxChar *oldHandlerName, const wxChar *newHandlerName ) |
499a9a62 | 901 | { |
13830d6f SC |
902 | wxASSERT_MSG(FindHandlerInfoInThisClass(oldHandlerName),wxT("not existing handler") ); |
903 | FindHandlerInfoInThisClass(oldHandlerName)->m_name = newHandlerName; | |
2abce515 SC |
904 | } |
905 | ||
2d51f067 SC |
906 | // ---------------------------------------------------------------------------- |
907 | // wxGenericPropertyAccessor | |
908 | // ---------------------------------------------------------------------------- | |
909 | ||
910 | struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal | |
911 | { | |
13830d6f SC |
912 | char filler; |
913 | }; | |
2d51f067 | 914 | |
b8d5be01 | 915 | wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString& propertyName ) |
13830d6f | 916 | : wxPropertyAccessor( NULL, NULL, NULL, NULL ) |
2d51f067 | 917 | { |
13830d6f SC |
918 | m_data = new wxGenericPropertyAccessorInternal; |
919 | m_propertyName = propertyName; | |
920 | m_getterName = wxT("Get")+propertyName; | |
921 | m_setterName = wxT("Set")+propertyName; | |
2d51f067 SC |
922 | } |
923 | ||
924 | wxGenericPropertyAccessor::~wxGenericPropertyAccessor() | |
925 | { | |
13830d6f | 926 | delete m_data; |
2d51f067 | 927 | } |
13830d6f | 928 | |
e765d7ee | 929 | void wxGenericPropertyAccessor::SetProperty(wxObject *object, const wxAny &value) const |
2d51f067 | 930 | { |
13830d6f SC |
931 | wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); |
932 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
44a00712 | 933 | dynobj->SetProperty(m_propertyName.c_str(), value ); |
2d51f067 SC |
934 | } |
935 | ||
e765d7ee | 936 | void wxGenericPropertyAccessor::GetProperty(const wxObject *object, wxAny& value) const |
2d51f067 | 937 | { |
13830d6f SC |
938 | const wxDynamicObject* dynobj = wx_dynamic_cast( const wxDynamicObject * , object ); |
939 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
44a00712 | 940 | value = dynobj->GetProperty( m_propertyName.c_str() ); |
2d51f067 | 941 | } |
8e3f3880 | 942 | |
e765d7ee SC |
943 | // ---------------------------------------------------------------------------- |
944 | // wxGenericPropertyAccessor | |
945 | // ---------------------------------------------------------------------------- | |
946 | ||
947 | wxString wxAnyGetAsString( const wxAny& data) | |
948 | { | |
949 | if ( data.IsNull() || data.GetTypeInfo()==NULL ) | |
950 | return wxEmptyString; | |
951 | ||
952 | wxString s; | |
953 | data.GetTypeInfo()->ConvertToString(data,s); | |
954 | return s; | |
955 | } | |
956 | ||
957 | const wxObject* wxAnyGetAsObjectPtr( const wxAny& data) | |
958 | { | |
959 | if ( !data.IsNull() ) | |
960 | { | |
961 | const wxClassTypeInfo* ti = wx_dynamic_cast(const wxClassTypeInfo*, data.GetTypeInfo()); | |
962 | if( ti ) | |
963 | return ti->GetClassInfo()->AnyToObjectPtr(data); | |
964 | } | |
965 | return NULL; | |
966 | } | |
967 | ||
968 | wxObjectFunctor::~wxObjectFunctor() | |
969 | {}; | |
970 | ||
8e3f3880 | 971 | #endif // wxUSE_EXTENDED_RTTI |