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