xti changes
[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 "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 //wxASSERT_MSG( iter != ms_typeTable->end(),
345 // wxT("lookup for a non-existent type-info") );
346 // FM 3/6/2007 - disabled because otherwise
347 // wxPropertyInfo::GetCollectionElementTypeInfo
348 // may easily crash
349 if (iter == ms_typeTable->end())
350 return NULL;
351
352 return (wxTypeInfo *)iter->second;
353 }
354
355 #if wxUSE_UNICODE
356 wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
357 wxVariant2StringFnc to,
358 wxString2VariantFnc from,
359 const char *name) :
360 wxTypeInfo( kind, to, from, name)
361 {
362 wxASSERT_MSG( kind == wxT_OBJECT_PTR ||
363 kind == wxT_OBJECT,
364 wxT("Illegal Kind for Enum Type")); m_classInfo = classInfo;
365 }
366 #endif
367
368 wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
369 wxVariant2StringFnc to,
370 wxString2VariantFnc from,
371 const wxString &name) :
372 wxTypeInfo( kind, to, from, name)
373 {
374 wxASSERT_MSG( kind == wxT_OBJECT_PTR || kind == wxT_OBJECT,
375 wxT("Illegal Kind for Enum Type")); m_classInfo = classInfo;
376 }
377
378 wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass,
379 wxVariant2StringFnc to,
380 wxString2VariantFnc from ) :
381 wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString )
382 {
383 m_eventClass = eventClass;
384 m_eventType = eventType;
385 m_lastEventType = -1;
386 }
387
388 wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, int lastEventType,
389 wxClassInfo* eventClass,
390 wxVariant2StringFnc to,
391 wxString2VariantFnc from ) :
392 wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString )
393 {
394 m_eventClass = eventClass;
395 m_eventType = eventType;
396 m_lastEventType = lastEventType;
397 }
398
399 void wxTypeInfo::Register()
400 {
401 if ( ms_typeTable == NULL )
402 ms_typeTable = new wxTypeInfoMap();
403
404 if( !m_name.empty() )
405 (*ms_typeTable)[m_name] = this;
406 }
407
408 void wxTypeInfo::Unregister()
409 {
410 if( !m_name.empty() )
411 ms_typeTable->erase(m_name);
412 }
413
414 // removing header dependancy on string tokenizer
415
416 void wxSetStringToArray( const wxString &s, wxArrayString &array )
417 {
418 wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK);
419 wxString flag;
420 array.Clear();
421 while (tokenizer.HasMoreTokens())
422 {
423 array.Add(tokenizer.GetNextToken());
424 }
425 }
426
427 // ----------------------------------------------------------------------------
428 // wxPropertyInfo
429 // ----------------------------------------------------------------------------
430
431 void wxPropertyInfo::Insert(wxPropertyInfo* &iter)
432 {
433 m_next = NULL;
434 if ( iter == NULL )
435 iter = this;
436 else
437 {
438 wxPropertyInfo* i = iter;
439 while( i->m_next )
440 i = i->m_next;
441
442 i->m_next = this;
443 }
444 }
445
446 void wxPropertyInfo::Remove()
447 {
448 if ( this == m_itsClass->m_firstProperty )
449 {
450 m_itsClass->m_firstProperty = m_next;
451 }
452 else
453 {
454 wxPropertyInfo *info = m_itsClass->m_firstProperty;
455 while (info)
456 {
457 if ( info->m_next == this )
458 {
459 info->m_next = m_next;
460 break;
461 }
462
463 info = info->m_next;
464 }
465 }
466
467 }
468
469 // ----------------------------------------------------------------------------
470 // wxHandlerInfo
471 // ----------------------------------------------------------------------------
472
473 void wxHandlerInfo::Insert(wxHandlerInfo* &iter)
474 {
475 m_next = NULL;
476 if ( iter == NULL )
477 iter = this;
478 else
479 {
480 wxHandlerInfo* i = iter;
481 while( i->m_next )
482 i = i->m_next;
483
484 i->m_next = this;
485 }
486 }
487
488 void wxHandlerInfo::Remove()
489 {
490 if ( this == m_itsClass->m_firstHandler )
491 {
492 m_itsClass->m_firstHandler = m_next;
493 }
494 else
495 {
496 wxHandlerInfo *info = m_itsClass->m_firstHandler;
497 while (info)
498 {
499 if ( info->m_next == this )
500 {
501 info->m_next = m_next;
502 break;
503 }
504
505 info = info->m_next;
506 }
507 }
508 }
509
510
511 // ----------------------------------------------------------------------------
512 // wxClassInfo
513 // ----------------------------------------------------------------------------
514
515 bool wxClassInfo::Create(wxObject *object, int ParamCount, wxAny *Params) const
516 {
517 if ( ParamCount != m_constructorPropertiesCount )
518 {
519 // FIXME: shouldn't we just return false and let the caller handle it?
520 wxLogError( _("Illegal Parameter Count for Create Method") );
521 return false;
522 }
523
524 return m_constructor->Create( object, Params );
525 }
526
527 wxObject *wxClassInfo::ConstructObject(int ParamCount, wxAny *Params) const
528 {
529 if ( ParamCount != m_constructorPropertiesCount )
530 {
531 // FIXME: shouldn't we just return NULL and let the caller handle this case?
532 wxLogError( _("Illegal Parameter Count for ConstructObject Method") );
533 return NULL;
534 }
535
536 wxObject *object = NULL;
537 if (!m_constructor->Create( object, Params ))
538 return NULL;
539 return object;
540 }
541
542 bool wxClassInfo::IsKindOf(const wxClassInfo *info) const
543 {
544 if ( info != 0 )
545 {
546 if ( info == this )
547 return true;
548
549 for ( int i = 0; m_parents[i]; ++ i )
550 {
551 if ( m_parents[i]->IsKindOf( info ) )
552 return true;
553 }
554 }
555 return false;
556 }
557
558 const wxPropertyAccessor *wxClassInfo::FindAccessor(const wxChar *PropertyName) const
559 {
560 const wxPropertyInfo* info = FindPropertyInfo( PropertyName );
561
562 if ( info )
563 return info->GetAccessor();
564
565 return NULL;
566 }
567
568 wxPropertyInfo *wxClassInfo::FindPropertyInfoInThisClass (const wxChar *PropertyName) const
569 {
570 wxPropertyInfo* info = GetFirstProperty();
571
572 while( info )
573 {
574 if ( wxStrcmp( info->GetName(), PropertyName ) == 0 )
575 return info;
576 info = info->GetNext();
577 }
578
579 return 0;
580 }
581
582 const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const wxChar *PropertyName) const
583 {
584 const wxPropertyInfo* info = FindPropertyInfoInThisClass( PropertyName );
585 if ( info )
586 return info;
587
588 const wxClassInfo** parents = GetParents();
589 for ( int i = 0; parents[i]; ++ i )
590 {
591 if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL )
592 return info;
593 }
594
595 return 0;
596 }
597
598 wxHandlerInfo *wxClassInfo::FindHandlerInfoInThisClass (const wxChar *PropertyName) const
599 {
600 wxHandlerInfo* info = GetFirstHandler();
601
602 while( info )
603 {
604 if ( wxStrcmp( info->GetName(), PropertyName ) == 0 )
605 return info;
606 info = info->GetNext();
607 }
608
609 return 0;
610 }
611
612 const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const wxChar *PropertyName) const
613 {
614 const wxHandlerInfo* info = FindHandlerInfoInThisClass( PropertyName );
615
616 if ( info )
617 return info;
618
619 const wxClassInfo** parents = GetParents();
620 for ( int i = 0; parents[i]; ++ i )
621 {
622 if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL )
623 return info;
624 }
625
626 return 0;
627 }
628
629 wxObjectStreamingCallback wxClassInfo::GetStreamingCallback() const
630 {
631 if ( m_streamingCallback )
632 return m_streamingCallback;
633
634 wxObjectStreamingCallback retval = NULL;
635 const wxClassInfo** parents = GetParents();
636 for ( int i = 0; parents[i] && retval == NULL; ++ i )
637 {
638 retval = parents[i]->GetStreamingCallback();
639 }
640 return retval;
641 }
642
643 bool wxClassInfo::BeforeWriteObject( const wxObject *obj, wxObjectWriter *streamer,
644 wxObjectWriterCallback *writercallback, const wxStringToAnyHashMap &metadata) const
645 {
646 wxObjectStreamingCallback sb = GetStreamingCallback();
647 if ( sb )
648 return (*sb)(obj, streamer, writercallback, metadata );
649
650 return true;
651 }
652
653 void wxClassInfo::SetProperty(wxObject *object, const wxChar *propertyName,
654 const wxAny &value) const
655 {
656 const wxPropertyAccessor *accessor;
657
658 accessor = FindAccessor(propertyName);
659 wxASSERT(accessor->HasSetter());
660 accessor->SetProperty( object, value );
661 }
662
663 wxAny wxClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const
664 {
665 const wxPropertyAccessor *accessor;
666
667 accessor = FindAccessor(propertyName);
668 wxASSERT(accessor->HasGetter());
669 wxAny result;
670 accessor->GetProperty(object,result);
671 return result;
672 }
673
674 wxAnyList wxClassInfo::GetPropertyCollection(wxObject *object,
675 const wxChar *propertyName) const
676 {
677 const wxPropertyAccessor *accessor;
678
679 accessor = FindAccessor(propertyName);
680 wxASSERT(accessor->HasGetter());
681 wxAnyList result;
682 accessor->GetPropertyCollection(object,result);
683 return result;
684 }
685
686 void wxClassInfo::AddToPropertyCollection(wxObject *object, const wxChar *propertyName,
687 const wxAny& value) const
688 {
689 const wxPropertyAccessor *accessor;
690
691 accessor = FindAccessor(propertyName);
692 wxASSERT(accessor->HasAdder());
693 accessor->AddToPropertyCollection( object, value );
694 }
695
696 // void wxClassInfo::GetProperties( wxPropertyInfoMap &map ) const
697 // The map parameter (the name map that is) seems something special
698 // to MSVC and so we use a other name.
699 void wxClassInfo::GetProperties( wxPropertyInfoMap &infomap ) const
700 {
701 const wxPropertyInfo *pi = GetFirstProperty();
702 while( pi )
703 {
704 if ( infomap.find( pi->GetName() ) == infomap.end() )
705 infomap[pi->GetName()] = (wxPropertyInfo*) pi;
706
707 pi = pi->GetNext();
708 }
709
710 const wxClassInfo** parents = GetParents();
711 for ( int i = 0; parents[i]; ++ i )
712 {
713 parents[i]->GetProperties( infomap );
714 }
715 }
716
717 wxObject* wxClassInfo::AnyToObjectPtr( const wxAny &data) const
718 {
719 return m_variantOfPtrToObjectConverter(data);
720 }
721
722 void wxClassInfo::CallOnAny( const wxAny &data, wxObjectFunctor* functor ) const
723 {
724 if ( data.GetTypeInfo()->GetKind() == wxT_OBJECT )
725 return m_variantToObjectConverter(data, functor);
726 else
727 return (*functor)(m_variantOfPtrToObjectConverter(data));
728 }
729
730 wxAny wxClassInfo::ObjectPtrToAny( wxObject* obj) const
731 {
732 return m_objectToVariantConverter(obj);
733 }
734
735 // ----------------------------------------------------------------------------
736 // wxDynamicObject support
737 // ----------------------------------------------------------------------------
738
739 // Dynamic Objects are objects that have a real superclass instance and carry their
740 // own attributes in a hash map. Like this it is possible to create the objects and
741 // stream them, as if their class information was already available from compiled data
742
743 struct wxDynamicObject::wxDynamicObjectInternal
744 {
745 wxDynamicObjectInternal() {}
746
747 wxStringToAnyHashMap m_properties;
748 };
749
750 typedef list< wxDynamicObject* > wxDynamicObjectList;
751
752 struct wxDynamicClassInfo::wxDynamicClassInfoInternal
753 {
754 wxDynamicObjectList m_dynamicObjects;
755 };
756
757 // instantiates this object with an instance of its superclass
758 wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info)
759 {
760 m_superClassInstance = superClassInstance;
761 m_classInfo = info;
762 m_data = new wxDynamicObjectInternal;
763 }
764
765 wxDynamicObject::~wxDynamicObject()
766 {
767 wx_dynamic_cast(const wxDynamicClassInfo*, m_classInfo)->
768 m_data->m_dynamicObjects.remove( this );
769 delete m_data;
770 delete m_superClassInstance;
771 }
772
773 void wxDynamicObject::SetProperty (const wxChar *propertyName, const wxAny &value)
774 {
775 wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),
776 wxT("Accessing Unknown Property in a Dynamic Object") );
777 m_data->m_properties[propertyName] = value;
778 }
779
780 wxAny wxDynamicObject::GetProperty (const wxChar *propertyName) const
781 {
782 wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),
783 wxT("Accessing Unknown Property in a Dynamic Object") );
784 return m_data->m_properties[propertyName];
785 }
786
787 void wxDynamicObject::RemoveProperty( const wxChar *propertyName )
788 {
789 wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),
790 wxT("Removing Unknown Property in a Dynamic Object") );
791 m_data->m_properties.erase( propertyName );
792 }
793
794 void wxDynamicObject::RenameProperty( const wxChar *oldPropertyName,
795 const wxChar *newPropertyName )
796 {
797 wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(oldPropertyName),
798 wxT("Renaming Unknown Property in a Dynamic Object") );
799
800 wxAny value = m_data->m_properties[oldPropertyName];
801 m_data->m_properties.erase( oldPropertyName );
802 m_data->m_properties[newPropertyName] = value;
803 }
804
805
806 // ----------------------------------------------------------------------------
807 // wxDynamicClassInfo
808 // ----------------------------------------------------------------------------
809
810 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar *unitName,
811 const wxChar *className,
812 const wxClassInfo* superClass ) :
813 wxClassInfo( unitName, className, new const wxClassInfo*[2])
814 {
815 GetParents()[0] = superClass;
816 GetParents()[1] = NULL;
817 m_data = new wxDynamicClassInfoInternal;
818 }
819
820 wxDynamicClassInfo::~wxDynamicClassInfo()
821 {
822 delete[] GetParents();
823 delete m_data;
824 }
825
826 wxObject *wxDynamicClassInfo::AllocateObject() const
827 {
828 wxObject* parent = GetParents()[0]->AllocateObject();
829 wxDynamicObject *obj = new wxDynamicObject( parent, this );
830 m_data->m_dynamicObjects.push_back( obj );
831 return obj;
832 }
833
834 bool wxDynamicClassInfo::Create (wxObject *object, int paramCount, wxAny *params) const
835 {
836 wxDynamicObject *dynobj = wx_dynamic_cast( wxDynamicObject *, object );
837 wxASSERT_MSG( dynobj,
838 wxT("cannot call wxDynamicClassInfo::Create on ")
839 wxT("an object other than wxDynamicObject") );
840
841 return GetParents()[0]->Create( dynobj->GetSuperClassInstance(), paramCount, params );
842 }
843
844 // get number of parameters for constructor
845 int wxDynamicClassInfo::GetCreateParamCount() const
846 {
847 return GetParents()[0]->GetCreateParamCount();
848 }
849
850 // get i-th constructor parameter
851 const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const
852 {
853 return GetParents()[0]->GetCreateParamName( i );
854 }
855
856 void wxDynamicClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, const wxAny &value) const
857 {
858 wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object);
859 wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
860 if ( FindPropertyInfoInThisClass(propertyName) )
861 dynobj->SetProperty( propertyName, value );
862 else
863 GetParents()[0]->SetProperty( dynobj->GetSuperClassInstance(), propertyName, value );
864 }
865
866 wxAny wxDynamicClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const
867 {
868 wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object);
869 wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
870 if ( FindPropertyInfoInThisClass(propertyName) )
871 return dynobj->GetProperty( propertyName );
872 else
873 return GetParents()[0]->GetProperty( dynobj->GetSuperClassInstance(), propertyName );
874 }
875
876 void wxDynamicClassInfo::AddProperty( const wxChar *propertyName, const wxTypeInfo* typeInfo )
877 {
878 EnsureInfosInited();
879 new wxPropertyInfo( m_firstProperty, this, propertyName, typeInfo->GetTypeName(), new wxGenericPropertyAccessor( propertyName ), wxAny() );
880 }
881
882 void wxDynamicClassInfo::AddHandler( const wxChar *handlerName, wxObjectEventFunction address, const wxClassInfo* eventClassInfo )
883 {
884 EnsureInfosInited();
885 new wxHandlerInfo( m_firstHandler, this, handlerName, address, eventClassInfo );
886 }
887
888 // removes an existing runtime-property
889 void wxDynamicClassInfo::RemoveProperty( const wxChar *propertyName )
890 {
891 for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter )
892 (*iter)->RemoveProperty( propertyName );
893 delete FindPropertyInfoInThisClass(propertyName);
894 }
895
896 // removes an existing runtime-handler
897 void wxDynamicClassInfo::RemoveHandler( const wxChar *handlerName )
898 {
899 delete FindHandlerInfoInThisClass(handlerName);
900 }
901
902 // renames an existing runtime-property
903 void wxDynamicClassInfo::RenameProperty( const wxChar *oldPropertyName, const wxChar *newPropertyName )
904 {
905 wxPropertyInfo* pi = FindPropertyInfoInThisClass(oldPropertyName);
906 wxASSERT_MSG( pi,wxT("not existing property") );
907 pi->m_name = newPropertyName;
908 wx_dynamic_cast(wxGenericPropertyAccessor*, pi->GetAccessor())->RenameProperty( oldPropertyName, newPropertyName );
909 for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter )
910 (*iter)->RenameProperty( oldPropertyName, newPropertyName );
911 }
912
913 // renames an existing runtime-handler
914 void wxDynamicClassInfo::RenameHandler( const wxChar *oldHandlerName, const wxChar *newHandlerName )
915 {
916 wxASSERT_MSG(FindHandlerInfoInThisClass(oldHandlerName),wxT("not existing handler") );
917 FindHandlerInfoInThisClass(oldHandlerName)->m_name = newHandlerName;
918 }
919
920 // ----------------------------------------------------------------------------
921 // wxGenericPropertyAccessor
922 // ----------------------------------------------------------------------------
923
924 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
925 {
926 char filler;
927 };
928
929 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString& propertyName )
930 : wxPropertyAccessor( NULL, NULL, NULL, NULL )
931 {
932 m_data = new wxGenericPropertyAccessorInternal;
933 m_propertyName = propertyName;
934 m_getterName = wxT("Get")+propertyName;
935 m_setterName = wxT("Set")+propertyName;
936 }
937
938 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
939 {
940 delete m_data;
941 }
942
943 void wxGenericPropertyAccessor::SetProperty(wxObject *object, const wxAny &value) const
944 {
945 wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object);
946 wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
947 dynobj->SetProperty(m_propertyName, value );
948 }
949
950 void wxGenericPropertyAccessor::GetProperty(const wxObject *object, wxAny& value) const
951 {
952 const wxDynamicObject* dynobj = wx_dynamic_cast( const wxDynamicObject * , object );
953 wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
954 value = dynobj->GetProperty( m_propertyName );
955 }
956
957 // ----------------------------------------------------------------------------
958 // wxGenericPropertyAccessor
959 // ----------------------------------------------------------------------------
960
961 wxString wxAnyGetAsString( const wxAny& data)
962 {
963 if ( data.IsNull() || data.GetTypeInfo()==NULL )
964 return wxEmptyString;
965
966 wxString s;
967 data.GetTypeInfo()->ConvertToString(data,s);
968 return s;
969 }
970
971 const wxObject* wxAnyGetAsObjectPtr( const wxAny& data)
972 {
973 if ( !data.IsNull() )
974 {
975 const wxClassTypeInfo* ti = wx_dynamic_cast(const wxClassTypeInfo*, data.GetTypeInfo());
976 if( ti )
977 return ti->GetClassInfo()->AnyToObjectPtr(data);
978 }
979 return NULL;
980 }
981
982 wxObjectFunctor::~wxObjectFunctor()
983 {};
984
985 #endif // wxUSE_EXTENDED_RTTI