]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: src/common/xti.cpp | |
3 | // Purpose: runtime metadata information (extended class info) | |
4 | // Author: Stefan Csomor | |
5 | // Modified by: | |
6 | // Created: 27/07/03 | |
7 | // Copyright: (c) 1997 Julian Smart | |
8 | // (c) 2003 Stefan Csomor | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // For compilers that support precompilation, includes "wx.h". | |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #if wxUSE_EXTENDED_RTTI | |
20 | ||
21 | #ifndef WX_PRECOMP | |
22 | #include "wx/object.h" | |
23 | #include "wx/list.h" | |
24 | #include "wx/hash.h" | |
25 | #endif | |
26 | ||
27 | #include "wx/xti.h" | |
28 | #include "wx/xml/xml.h" | |
29 | #include "wx/tokenzr.h" | |
30 | #include "wx/range.h" | |
31 | ||
32 | #include <string.h> | |
33 | ||
34 | #include "wx/beforestd.h" | |
35 | #include <map> | |
36 | #include <string> | |
37 | #include <list> | |
38 | #include "wx/afterstd.h" | |
39 | ||
40 | using namespace std; | |
41 | ||
42 | // ---------------------------------------------------------------------------- | |
43 | // wxEnumData | |
44 | // ---------------------------------------------------------------------------- | |
45 | ||
46 | wxEnumData::wxEnumData( wxEnumMemberData* data ) | |
47 | { | |
48 | m_members = data; | |
49 | for ( m_count = 0; m_members[m_count].m_name; m_count++) | |
50 | {}; | |
51 | } | |
52 | ||
53 | bool wxEnumData::HasEnumMemberValue(const wxChar *name, int *value) const | |
54 | { | |
55 | int i; | |
56 | for (i = 0; m_members[i].m_name; i++ ) | |
57 | { | |
58 | if (!wxStrcmp(name, m_members[i].m_name)) | |
59 | { | |
60 | if ( value ) | |
61 | *value = m_members[i].m_value; | |
62 | return true; | |
63 | } | |
64 | } | |
65 | return false; | |
66 | } | |
67 | ||
68 | int wxEnumData::GetEnumMemberValue(const wxChar *name) const | |
69 | { | |
70 | int i; | |
71 | for (i = 0; m_members[i].m_name; i++ ) | |
72 | { | |
73 | if (!wxStrcmp(name, m_members[i].m_name)) | |
74 | { | |
75 | return m_members[i].m_value; | |
76 | } | |
77 | } | |
78 | return 0; | |
79 | } | |
80 | ||
81 | const wxChar *wxEnumData::GetEnumMemberName(int value) const | |
82 | { | |
83 | int i; | |
84 | for (i = 0; m_members[i].m_name; i++) | |
85 | if (value == m_members[i].m_value) | |
86 | return m_members[i].m_name; | |
87 | ||
88 | return wxEmptyString; | |
89 | } | |
90 | ||
91 | int wxEnumData::GetEnumMemberValueByIndex( int idx ) const | |
92 | { | |
93 | // we should cache the count in order to avoid out-of-bounds errors | |
94 | return m_members[idx].m_value; | |
95 | } | |
96 | ||
97 | const wxChar * wxEnumData::GetEnumMemberNameByIndex( int idx ) const | |
98 | { | |
99 | // we should cache the count in order to avoid out-of-bounds errors | |
100 | return m_members[idx].m_name; | |
101 | } | |
102 | ||
103 | // ---------------------------------------------------------------------------- | |
104 | // Type Information | |
105 | // ---------------------------------------------------------------------------- | |
106 | ||
107 | // ---------------------------------------------------------------------------- | |
108 | // value streaming | |
109 | // ---------------------------------------------------------------------------- | |
110 | ||
111 | // streamer specializations | |
112 | // for all built-in types | |
113 | ||
114 | // bool | |
115 | ||
116 | template<> void wxStringReadValue(const wxString &s, bool &data ) | |
117 | { | |
118 | int intdata; | |
119 | wxSscanf(s, wxT("%d"), &intdata ); | |
120 | data = (bool)(intdata != 0); | |
121 | } | |
122 | ||
123 | template<> void wxStringWriteValue(wxString &s, const bool &data ) | |
124 | { | |
125 | s = wxString::Format(wxT("%d"), data ); | |
126 | } | |
127 | ||
128 | // char | |
129 | ||
130 | template<> void wxStringReadValue(const wxString &s, char &data ) | |
131 | { | |
132 | int intdata; | |
133 | wxSscanf(s, wxT("%d"), &intdata ); | |
134 | data = char(intdata); | |
135 | } | |
136 | ||
137 | template<> void wxStringWriteValue(wxString &s, const char &data ) | |
138 | { | |
139 | s = wxString::Format(wxT("%d"), data ); | |
140 | } | |
141 | ||
142 | // unsigned char | |
143 | ||
144 | template<> void wxStringReadValue(const wxString &s, unsigned char &data ) | |
145 | { | |
146 | int intdata; | |
147 | wxSscanf(s, wxT("%d"), &intdata ); | |
148 | data = (unsigned char)(intdata); | |
149 | } | |
150 | ||
151 | template<> void wxStringWriteValue(wxString &s, const unsigned char &data ) | |
152 | { | |
153 | s = wxString::Format(wxT("%d"), data ); | |
154 | } | |
155 | ||
156 | // int | |
157 | ||
158 | template<> void wxStringReadValue(const wxString &s, int &data ) | |
159 | { | |
160 | wxSscanf(s, wxT("%d"), &data ); | |
161 | } | |
162 | ||
163 | template<> void wxStringWriteValue(wxString &s, const int &data ) | |
164 | { | |
165 | s = wxString::Format(wxT("%d"), data ); | |
166 | } | |
167 | ||
168 | // unsigned int | |
169 | ||
170 | template<> void wxStringReadValue(const wxString &s, unsigned int &data ) | |
171 | { | |
172 | wxSscanf(s, wxT("%d"), &data ); | |
173 | } | |
174 | ||
175 | template<> void wxStringWriteValue(wxString &s, const unsigned int &data ) | |
176 | { | |
177 | s = wxString::Format(wxT("%d"), data ); | |
178 | } | |
179 | ||
180 | // long | |
181 | ||
182 | template<> void wxStringReadValue(const wxString &s, long &data ) | |
183 | { | |
184 | wxSscanf(s, wxT("%ld"), &data ); | |
185 | } | |
186 | ||
187 | template<> void wxStringWriteValue(wxString &s, const long &data ) | |
188 | { | |
189 | s = wxString::Format(wxT("%ld"), data ); | |
190 | } | |
191 | ||
192 | // unsigned long | |
193 | ||
194 | template<> void wxStringReadValue(const wxString &s, unsigned long &data ) | |
195 | { | |
196 | wxSscanf(s, wxT("%ld"), &data ); | |
197 | } | |
198 | ||
199 | template<> void wxStringWriteValue(wxString &s, const unsigned long &data ) | |
200 | { | |
201 | s = wxString::Format(wxT("%ld"), data ); | |
202 | } | |
203 | ||
204 | #ifdef wxLongLong_t | |
205 | template<> void wxStringReadValue(const wxString &s, wxLongLong_t &data ) | |
206 | { | |
207 | wxSscanf(s, wxT("%lld"), &data ); | |
208 | } | |
209 | ||
210 | template<> void wxStringWriteValue(wxString &s, const wxLongLong_t &data ) | |
211 | { | |
212 | s = wxString::Format(wxT("%lld"), data ); | |
213 | } | |
214 | ||
215 | template<> void wxStringReadValue(const wxString &s, wxULongLong_t &data ) | |
216 | { | |
217 | wxSscanf(s, wxT("%lld"), &data ); | |
218 | } | |
219 | ||
220 | template<> void wxStringWriteValue(wxString &s, const wxULongLong_t &data ) | |
221 | { | |
222 | s = wxString::Format(wxT("%lld"), data ); | |
223 | } | |
224 | #endif | |
225 | // float | |
226 | ||
227 | template<> void wxStringReadValue(const wxString &s, float &data ) | |
228 | { | |
229 | wxSscanf(s, wxT("%f"), &data ); | |
230 | } | |
231 | ||
232 | template<> void wxStringWriteValue(wxString &s, const float &data ) | |
233 | { | |
234 | s = wxString::Format(wxT("%f"), data ); | |
235 | } | |
236 | ||
237 | // double | |
238 | ||
239 | template<> void wxStringReadValue(const wxString &s, double &data ) | |
240 | { | |
241 | wxSscanf(s, wxT("%lf"), &data ); | |
242 | } | |
243 | ||
244 | template<> void wxStringWriteValue(wxString &s, const double &data ) | |
245 | { | |
246 | s = wxString::Format(wxT("%lf"), data ); | |
247 | } | |
248 | ||
249 | // wxString | |
250 | ||
251 | template<> void wxStringReadValue(const wxString &s, wxString &data ) | |
252 | { | |
253 | data = s; | |
254 | } | |
255 | ||
256 | template<> void wxStringWriteValue(wxString &s, const wxString &data ) | |
257 | { | |
258 | s = data; | |
259 | } | |
260 | ||
261 | ||
262 | // built-ins | |
263 | // | |
264 | ||
265 | #if wxUSE_FUNC_TEMPLATE_POINTER | |
266 | #define wxBUILTIN_TYPE_INFO( element, type ) \ | |
267 | wxBuiltInTypeInfo \ | |
268 | s_typeInfo##type(element, &wxToStringConverter<type>, \ | |
269 | &wxFromStringConverter<type>, typeid(type).name()); | |
270 | #else | |
271 | #define wxBUILTIN_TYPE_INFO( element, type ) \ | |
272 | void _toString##element( const wxAny& data, wxString &result ) \ | |
273 | { wxToStringConverter<type, data, result); } \ | |
274 | void _fromString##element( const wxString& data, wxAny &result ) \ | |
275 | { wxFromStringConverter<type, data, result); } \ | |
276 | wxBuiltInTypeInfo s_typeInfo##type(element, &_toString##element, \ | |
277 | &_fromString##element, typeid(type).name()); | |
278 | #endif | |
279 | ||
280 | typedef unsigned char unsigned_char; | |
281 | typedef unsigned int unsigned_int; | |
282 | typedef unsigned long unsigned_long; | |
283 | ||
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); | |
295 | ||
296 | #ifdef wxLongLong_t | |
297 | wxBUILTIN_TYPE_INFO(wxT_LONGLONG, wxLongLong_t) | |
298 | wxBUILTIN_TYPE_INFO(wxT_ULONGLONG, wxULongLong_t) | |
299 | #endif | |
300 | ||
301 | // this are compiler induced specialization which are never used anywhere | |
302 | ||
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 * ) | |
310 | ||
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 | ||
329 | wxCOLLECTION_TYPE_INFO( wxString, wxArrayString ); | |
330 | ||
331 | template<> void wxCollectionToVariantArray( wxArrayString const &theArray, | |
332 | wxAnyList &value) | |
333 | { | |
334 | wxArrayCollectionToVariantArray( theArray, value ); | |
335 | } | |
336 | ||
337 | wxTypeInfoMap *wxTypeInfo::ms_typeTable = NULL; | |
338 | ||
339 | wxTypeInfo *wxTypeInfo::FindType(const wxString& typeName) | |
340 | { | |
341 | wxTypeInfoMap::iterator iter = ms_typeTable->find(typeName); | |
342 | ||
343 | if (iter == ms_typeTable->end()) | |
344 | return NULL; | |
345 | ||
346 | return (wxTypeInfo *)iter->second; | |
347 | } | |
348 | ||
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 | } | |
379 | ||
380 | void wxTypeInfo::Register() | |
381 | { | |
382 | if ( ms_typeTable == NULL ) | |
383 | ms_typeTable = new wxTypeInfoMap(); | |
384 | ||
385 | if( !m_name.empty() ) | |
386 | (*ms_typeTable)[m_name] = this; | |
387 | } | |
388 | ||
389 | void wxTypeInfo::Unregister() | |
390 | { | |
391 | if( !m_name.empty() ) | |
392 | ms_typeTable->erase(m_name); | |
393 | } | |
394 | ||
395 | // removing header dependency on string tokenizer | |
396 | ||
397 | void wxSetStringToArray( const wxString &s, wxArrayString &array ) | |
398 | { | |
399 | wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK); | |
400 | wxString flag; | |
401 | array.Clear(); | |
402 | while (tokenizer.HasMoreTokens()) | |
403 | { | |
404 | array.Add(tokenizer.GetNextToken()); | |
405 | } | |
406 | } | |
407 | ||
408 | // ---------------------------------------------------------------------------- | |
409 | // wxPropertyInfo | |
410 | // ---------------------------------------------------------------------------- | |
411 | ||
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() | |
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 | } | |
447 | ||
448 | } | |
449 | ||
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() | |
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 | ||
491 | ||
492 | // ---------------------------------------------------------------------------- | |
493 | // wxClassInfo | |
494 | // ---------------------------------------------------------------------------- | |
495 | ||
496 | bool wxClassInfo::Create(wxObject *object, int ParamCount, wxAny *Params) const | |
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 | ||
508 | wxObject *wxClassInfo::ConstructObject(int ParamCount, wxAny *Params) const | |
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 | ||
539 | const wxPropertyAccessor *wxClassInfo::FindAccessor(const wxChar *PropertyName) const | |
540 | { | |
541 | const wxPropertyInfo* info = FindPropertyInfo( PropertyName ); | |
542 | ||
543 | if ( info ) | |
544 | return info->GetAccessor(); | |
545 | ||
546 | return NULL; | |
547 | } | |
548 | ||
549 | wxPropertyInfo *wxClassInfo::FindPropertyInfoInThisClass (const wxChar *PropertyName) const | |
550 | { | |
551 | wxPropertyInfo* info = GetFirstProperty(); | |
552 | ||
553 | while( info ) | |
554 | { | |
555 | if ( wxStrcmp( info->GetName(), PropertyName ) == 0 ) | |
556 | return info; | |
557 | info = info->GetNext(); | |
558 | } | |
559 | ||
560 | return 0; | |
561 | } | |
562 | ||
563 | const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const wxChar *PropertyName) const | |
564 | { | |
565 | const wxPropertyInfo* info = FindPropertyInfoInThisClass( PropertyName ); | |
566 | if ( info ) | |
567 | return info; | |
568 | ||
569 | const wxClassInfo** parents = GetParents(); | |
570 | for ( int i = 0; parents[i]; ++ i ) | |
571 | { | |
572 | if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL ) | |
573 | return info; | |
574 | } | |
575 | ||
576 | return 0; | |
577 | } | |
578 | ||
579 | wxHandlerInfo *wxClassInfo::FindHandlerInfoInThisClass (const wxChar *PropertyName) const | |
580 | { | |
581 | wxHandlerInfo* info = GetFirstHandler(); | |
582 | ||
583 | while( info ) | |
584 | { | |
585 | if ( wxStrcmp( info->GetName(), PropertyName ) == 0 ) | |
586 | return info; | |
587 | info = info->GetNext(); | |
588 | } | |
589 | ||
590 | return 0; | |
591 | } | |
592 | ||
593 | const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const wxChar *PropertyName) const | |
594 | { | |
595 | const wxHandlerInfo* info = FindHandlerInfoInThisClass( PropertyName ); | |
596 | ||
597 | if ( info ) | |
598 | return info; | |
599 | ||
600 | const wxClassInfo** parents = GetParents(); | |
601 | for ( int i = 0; parents[i]; ++ i ) | |
602 | { | |
603 | if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL ) | |
604 | return info; | |
605 | } | |
606 | ||
607 | return 0; | |
608 | } | |
609 | ||
610 | wxObjectStreamingCallback wxClassInfo::GetStreamingCallback() const | |
611 | { | |
612 | if ( m_streamingCallback ) | |
613 | return m_streamingCallback; | |
614 | ||
615 | wxObjectStreamingCallback retval = NULL; | |
616 | const wxClassInfo** parents = GetParents(); | |
617 | for ( int i = 0; parents[i] && retval == NULL; ++ i ) | |
618 | { | |
619 | retval = parents[i]->GetStreamingCallback(); | |
620 | } | |
621 | return retval; | |
622 | } | |
623 | ||
624 | bool wxClassInfo::BeforeWriteObject( const wxObject *obj, wxObjectWriter *streamer, | |
625 | wxObjectWriterCallback *writercallback, const wxStringToAnyHashMap &metadata) const | |
626 | { | |
627 | wxObjectStreamingCallback sb = GetStreamingCallback(); | |
628 | if ( sb ) | |
629 | return (*sb)(obj, streamer, writercallback, metadata ); | |
630 | ||
631 | return true; | |
632 | } | |
633 | ||
634 | void wxClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, | |
635 | const wxAny &value) const | |
636 | { | |
637 | const wxPropertyAccessor *accessor; | |
638 | ||
639 | accessor = FindAccessor(propertyName); | |
640 | wxASSERT(accessor->HasSetter()); | |
641 | accessor->SetProperty( object, value ); | |
642 | } | |
643 | ||
644 | wxAny wxClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const | |
645 | { | |
646 | const wxPropertyAccessor *accessor; | |
647 | ||
648 | accessor = FindAccessor(propertyName); | |
649 | wxASSERT(accessor->HasGetter()); | |
650 | wxAny result; | |
651 | accessor->GetProperty(object,result); | |
652 | return result; | |
653 | } | |
654 | ||
655 | wxAnyList wxClassInfo::GetPropertyCollection(wxObject *object, | |
656 | const wxChar *propertyName) const | |
657 | { | |
658 | const wxPropertyAccessor *accessor; | |
659 | ||
660 | accessor = FindAccessor(propertyName); | |
661 | wxASSERT(accessor->HasGetter()); | |
662 | wxAnyList result; | |
663 | accessor->GetPropertyCollection(object,result); | |
664 | return result; | |
665 | } | |
666 | ||
667 | void wxClassInfo::AddToPropertyCollection(wxObject *object, const wxChar *propertyName, | |
668 | const wxAny& value) const | |
669 | { | |
670 | const wxPropertyAccessor *accessor; | |
671 | ||
672 | accessor = FindAccessor(propertyName); | |
673 | wxASSERT(accessor->HasAdder()); | |
674 | accessor->AddToPropertyCollection( object, value ); | |
675 | } | |
676 | ||
677 | // void wxClassInfo::GetProperties( wxPropertyInfoMap &map ) const | |
678 | // The map parameter (the name map that is) seems something special | |
679 | // to MSVC and so we use a other name. | |
680 | void wxClassInfo::GetProperties( wxPropertyInfoMap &infomap ) const | |
681 | { | |
682 | const wxPropertyInfo *pi = GetFirstProperty(); | |
683 | while( pi ) | |
684 | { | |
685 | if ( infomap.find( pi->GetName() ) == infomap.end() ) | |
686 | infomap[pi->GetName()] = (wxPropertyInfo*) pi; | |
687 | ||
688 | pi = pi->GetNext(); | |
689 | } | |
690 | ||
691 | const wxClassInfo** parents = GetParents(); | |
692 | for ( int i = 0; parents[i]; ++ i ) | |
693 | { | |
694 | parents[i]->GetProperties( infomap ); | |
695 | } | |
696 | } | |
697 | ||
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 | } | |
715 | ||
716 | bool wxClassInfo::NeedsDirectConstruction() const | |
717 | { | |
718 | return wx_dynamic_cast(wxObjectAllocator*, m_constructor) != NULL; | |
719 | } | |
720 | ||
721 | // ---------------------------------------------------------------------------- | |
722 | // wxDynamicObject support | |
723 | // ---------------------------------------------------------------------------- | |
724 | ||
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 | { | |
731 | wxDynamicObjectInternal() {} | |
732 | ||
733 | wxStringToAnyHashMap m_properties; | |
734 | }; | |
735 | ||
736 | typedef list< wxDynamicObject* > wxDynamicObjectList; | |
737 | ||
738 | struct wxDynamicClassInfo::wxDynamicClassInfoInternal | |
739 | { | |
740 | wxDynamicObjectList m_dynamicObjects; | |
741 | }; | |
742 | ||
743 | // instantiates this object with an instance of its superclass | |
744 | wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info) | |
745 | { | |
746 | m_superClassInstance = superClassInstance; | |
747 | m_classInfo = info; | |
748 | m_data = new wxDynamicObjectInternal; | |
749 | } | |
750 | ||
751 | wxDynamicObject::~wxDynamicObject() | |
752 | { | |
753 | wx_dynamic_cast(const wxDynamicClassInfo*, m_classInfo)-> | |
754 | m_data->m_dynamicObjects.remove( this ); | |
755 | delete m_data; | |
756 | delete m_superClassInstance; | |
757 | } | |
758 | ||
759 | void wxDynamicObject::SetProperty (const wxChar *propertyName, const wxAny &value) | |
760 | { | |
761 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), | |
762 | wxT("Accessing Unknown Property in a Dynamic Object") ); | |
763 | m_data->m_properties[propertyName] = value; | |
764 | } | |
765 | ||
766 | wxAny wxDynamicObject::GetProperty (const wxChar *propertyName) const | |
767 | { | |
768 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), | |
769 | wxT("Accessing Unknown Property in a Dynamic Object") ); | |
770 | return m_data->m_properties[propertyName]; | |
771 | } | |
772 | ||
773 | void wxDynamicObject::RemoveProperty( const wxChar *propertyName ) | |
774 | { | |
775 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName), | |
776 | wxT("Removing Unknown Property in a Dynamic Object") ); | |
777 | m_data->m_properties.erase( propertyName ); | |
778 | } | |
779 | ||
780 | void wxDynamicObject::RenameProperty( const wxChar *oldPropertyName, | |
781 | const wxChar *newPropertyName ) | |
782 | { | |
783 | wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(oldPropertyName), | |
784 | wxT("Renaming Unknown Property in a Dynamic Object") ); | |
785 | ||
786 | wxAny value = m_data->m_properties[oldPropertyName]; | |
787 | m_data->m_properties.erase( oldPropertyName ); | |
788 | m_data->m_properties[newPropertyName] = value; | |
789 | } | |
790 | ||
791 | ||
792 | // ---------------------------------------------------------------------------- | |
793 | // wxDynamicClassInfo | |
794 | // ---------------------------------------------------------------------------- | |
795 | ||
796 | wxDynamicClassInfo::wxDynamicClassInfo( const wxChar *unitName, | |
797 | const wxChar *className, | |
798 | const wxClassInfo* superClass ) : | |
799 | wxClassInfo( unitName, className, new const wxClassInfo*[2]) | |
800 | { | |
801 | GetParents()[0] = superClass; | |
802 | GetParents()[1] = NULL; | |
803 | m_data = new wxDynamicClassInfoInternal; | |
804 | } | |
805 | ||
806 | wxDynamicClassInfo::~wxDynamicClassInfo() | |
807 | { | |
808 | delete[] GetParents(); | |
809 | delete m_data; | |
810 | } | |
811 | ||
812 | wxObject *wxDynamicClassInfo::AllocateObject() const | |
813 | { | |
814 | wxObject* parent = GetParents()[0]->AllocateObject(); | |
815 | wxDynamicObject *obj = new wxDynamicObject( parent, this ); | |
816 | m_data->m_dynamicObjects.push_back( obj ); | |
817 | return obj; | |
818 | } | |
819 | ||
820 | bool wxDynamicClassInfo::Create (wxObject *object, int paramCount, wxAny *params) const | |
821 | { | |
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 ); | |
828 | } | |
829 | ||
830 | // get number of parameters for constructor | |
831 | int wxDynamicClassInfo::GetCreateParamCount() const | |
832 | { | |
833 | return GetParents()[0]->GetCreateParamCount(); | |
834 | } | |
835 | ||
836 | // get i-th constructor parameter | |
837 | const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const | |
838 | { | |
839 | return GetParents()[0]->GetCreateParamName( i ); | |
840 | } | |
841 | ||
842 | void wxDynamicClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, const wxAny &value) const | |
843 | { | |
844 | wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); | |
845 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
846 | if ( FindPropertyInfoInThisClass(propertyName) ) | |
847 | dynobj->SetProperty( propertyName, value ); | |
848 | else | |
849 | GetParents()[0]->SetProperty( dynobj->GetSuperClassInstance(), propertyName, value ); | |
850 | } | |
851 | ||
852 | wxAny wxDynamicClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const | |
853 | { | |
854 | wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); | |
855 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
856 | if ( FindPropertyInfoInThisClass(propertyName) ) | |
857 | return dynobj->GetProperty( propertyName ); | |
858 | else | |
859 | return GetParents()[0]->GetProperty( dynobj->GetSuperClassInstance(), propertyName ); | |
860 | } | |
861 | ||
862 | void wxDynamicClassInfo::AddProperty( const wxChar *propertyName, const wxTypeInfo* typeInfo ) | |
863 | { | |
864 | EnsureInfosInited(); | |
865 | new wxPropertyInfo( m_firstProperty, this, propertyName, typeInfo->GetTypeName(), new wxGenericPropertyAccessor( propertyName ), wxAny() ); | |
866 | } | |
867 | ||
868 | void wxDynamicClassInfo::AddHandler( const wxChar *handlerName, wxObjectEventFunction address, const wxClassInfo* eventClassInfo ) | |
869 | { | |
870 | EnsureInfosInited(); | |
871 | new wxHandlerInfo( m_firstHandler, this, handlerName, address, eventClassInfo ); | |
872 | } | |
873 | ||
874 | // removes an existing runtime-property | |
875 | void wxDynamicClassInfo::RemoveProperty( const wxChar *propertyName ) | |
876 | { | |
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); | |
880 | } | |
881 | ||
882 | // removes an existing runtime-handler | |
883 | void wxDynamicClassInfo::RemoveHandler( const wxChar *handlerName ) | |
884 | { | |
885 | delete FindHandlerInfoInThisClass(handlerName); | |
886 | } | |
887 | ||
888 | // renames an existing runtime-property | |
889 | void wxDynamicClassInfo::RenameProperty( const wxChar *oldPropertyName, const wxChar *newPropertyName ) | |
890 | { | |
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 ); | |
897 | } | |
898 | ||
899 | // renames an existing runtime-handler | |
900 | void wxDynamicClassInfo::RenameHandler( const wxChar *oldHandlerName, const wxChar *newHandlerName ) | |
901 | { | |
902 | wxASSERT_MSG(FindHandlerInfoInThisClass(oldHandlerName),wxT("not existing handler") ); | |
903 | FindHandlerInfoInThisClass(oldHandlerName)->m_name = newHandlerName; | |
904 | } | |
905 | ||
906 | // ---------------------------------------------------------------------------- | |
907 | // wxGenericPropertyAccessor | |
908 | // ---------------------------------------------------------------------------- | |
909 | ||
910 | struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal | |
911 | { | |
912 | char filler; | |
913 | }; | |
914 | ||
915 | wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString& propertyName ) | |
916 | : wxPropertyAccessor( NULL, NULL, NULL, NULL ) | |
917 | { | |
918 | m_data = new wxGenericPropertyAccessorInternal; | |
919 | m_propertyName = propertyName; | |
920 | m_getterName = wxT("Get")+propertyName; | |
921 | m_setterName = wxT("Set")+propertyName; | |
922 | } | |
923 | ||
924 | wxGenericPropertyAccessor::~wxGenericPropertyAccessor() | |
925 | { | |
926 | delete m_data; | |
927 | } | |
928 | ||
929 | void wxGenericPropertyAccessor::SetProperty(wxObject *object, const wxAny &value) const | |
930 | { | |
931 | wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object); | |
932 | wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ); | |
933 | dynobj->SetProperty(m_propertyName.c_str(), value ); | |
934 | } | |
935 | ||
936 | void wxGenericPropertyAccessor::GetProperty(const wxObject *object, wxAny& value) const | |
937 | { | |
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") ); | |
940 | value = dynobj->GetProperty( m_propertyName.c_str() ); | |
941 | } | |
942 | ||
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 | ||
971 | #endif // wxUSE_EXTENDED_RTTI |