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