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