Allow handling EVT_UPDATE_UI for wxID_UNDO/REDO at wxDocument level.
[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, wxT("%d"), &intdata );
121 data = (bool)(intdata != 0);
122 }
123
124 template<> void wxStringWriteValue(wxString &s, const bool &data )
125 {
126 s = wxString::Format(wxT("%d"), data );
127 }
128
129 // char
130
131 template<> void wxStringReadValue(const wxString &s, char &data )
132 {
133 int intdata;
134 wxSscanf(s, wxT("%d"), &intdata );
135 data = char(intdata);
136 }
137
138 template<> void wxStringWriteValue(wxString &s, const char &data )
139 {
140 s = wxString::Format(wxT("%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, wxT("%d"), &intdata );
149 data = (unsigned char)(intdata);
150 }
151
152 template<> void wxStringWriteValue(wxString &s, const unsigned char &data )
153 {
154 s = wxString::Format(wxT("%d"), data );
155 }
156
157 // int
158
159 template<> void wxStringReadValue(const wxString &s, int &data )
160 {
161 wxSscanf(s, wxT("%d"), &data );
162 }
163
164 template<> void wxStringWriteValue(wxString &s, const int &data )
165 {
166 s = wxString::Format(wxT("%d"), data );
167 }
168
169 // unsigned int
170
171 template<> void wxStringReadValue(const wxString &s, unsigned int &data )
172 {
173 wxSscanf(s, wxT("%d"), &data );
174 }
175
176 template<> void wxStringWriteValue(wxString &s, const unsigned int &data )
177 {
178 s = wxString::Format(wxT("%d"), data );
179 }
180
181 // long
182
183 template<> void wxStringReadValue(const wxString &s, long &data )
184 {
185 wxSscanf(s, wxT("%ld"), &data );
186 }
187
188 template<> void wxStringWriteValue(wxString &s, const long &data )
189 {
190 s = wxString::Format(wxT("%ld"), data );
191 }
192
193 // unsigned long
194
195 template<> void wxStringReadValue(const wxString &s, unsigned long &data )
196 {
197 wxSscanf(s, wxT("%ld"), &data );
198 }
199
200 template<> void wxStringWriteValue(wxString &s, const unsigned long &data )
201 {
202 s = wxString::Format(wxT("%ld"), data );
203 }
204
205 #ifdef wxLongLong_t
206 template<> void wxStringReadValue(const wxString &s, wxLongLong_t &data )
207 {
208 wxSscanf(s, wxT("%lld"), &data );
209 }
210
211 template<> void wxStringWriteValue(wxString &s, const wxLongLong_t &data )
212 {
213 s = wxString::Format(wxT("%lld"), data );
214 }
215
216 template<> void wxStringReadValue(const wxString &s, wxULongLong_t &data )
217 {
218 wxSscanf(s, wxT("%lld"), &data );
219 }
220
221 template<> void wxStringWriteValue(wxString &s, const wxULongLong_t &data )
222 {
223 s = wxString::Format(wxT("%lld"), data );
224 }
225 #endif
226 // float
227
228 template<> void wxStringReadValue(const wxString &s, float &data )
229 {
230 wxSscanf(s, wxT("%f"), &data );
231 }
232
233 template<> void wxStringWriteValue(wxString &s, const float &data )
234 {
235 s = wxString::Format(wxT("%f"), data );
236 }
237
238 // double
239
240 template<> void wxStringReadValue(const wxString &s, double &data )
241 {
242 wxSscanf(s, wxT("%lf"), &data );
243 }
244
245 template<> void wxStringWriteValue(wxString &s, const double &data )
246 {
247 s = wxString::Format(wxT("%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