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