]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/xti.cpp
fixing osx_carbon
[wxWidgets.git] / src / common / xti.cpp
... / ...
CommitLineData
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
41using namespace std;
42
43// ----------------------------------------------------------------------------
44// wxEnumData
45// ----------------------------------------------------------------------------
46
47wxEnumData::wxEnumData( wxEnumMemberData* data )
48{
49 m_members = data;
50 for ( m_count = 0; m_members[m_count].m_name; m_count++)
51 {};
52}
53
54bool 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
69int 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
82const 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
92int 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
98const 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
117template<> void wxStringReadValue(const wxString &s, bool &data )
118{
119 int intdata;
120 wxSscanf(s, _T("%d"), &intdata );
121 data = (bool)(intdata != 0);
122}
123
124template<> void wxStringWriteValue(wxString &s, const bool &data )
125{
126 s = wxString::Format(_T("%d"), data );
127}
128
129// char
130
131template<> void wxStringReadValue(const wxString &s, char &data )
132{
133 int intdata;
134 wxSscanf(s, _T("%d"), &intdata );
135 data = char(intdata);
136}
137
138template<> void wxStringWriteValue(wxString &s, const char &data )
139{
140 s = wxString::Format(_T("%d"), data );
141}
142
143// unsigned char
144
145template<> 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
152template<> void wxStringWriteValue(wxString &s, const unsigned char &data )
153{
154 s = wxString::Format(_T("%d"), data );
155}
156
157// int
158
159template<> void wxStringReadValue(const wxString &s, int &data )
160{
161 wxSscanf(s, _T("%d"), &data );
162}
163
164template<> void wxStringWriteValue(wxString &s, const int &data )
165{
166 s = wxString::Format(_T("%d"), data );
167}
168
169// unsigned int
170
171template<> void wxStringReadValue(const wxString &s, unsigned int &data )
172{
173 wxSscanf(s, _T("%d"), &data );
174}
175
176template<> void wxStringWriteValue(wxString &s, const unsigned int &data )
177{
178 s = wxString::Format(_T("%d"), data );
179}
180
181// long
182
183template<> void wxStringReadValue(const wxString &s, long &data )
184{
185 wxSscanf(s, _T("%ld"), &data );
186}
187
188template<> void wxStringWriteValue(wxString &s, const long &data )
189{
190 s = wxString::Format(_T("%ld"), data );
191}
192
193// unsigned long
194
195template<> void wxStringReadValue(const wxString &s, unsigned long &data )
196{
197 wxSscanf(s, _T("%ld"), &data );
198}
199
200template<> void wxStringWriteValue(wxString &s, const unsigned long &data )
201{
202 s = wxString::Format(_T("%ld"), data );
203}
204
205#ifdef wxLongLong_t
206template<> void wxStringReadValue(const wxString &s, wxLongLong_t &data )
207{
208 wxSscanf(s, _T("%lld"), &data );
209}
210
211template<> void wxStringWriteValue(wxString &s, const wxLongLong_t &data )
212{
213 s = wxString::Format(_T("%lld"), data );
214}
215
216template<> void wxStringReadValue(const wxString &s, wxULongLong_t &data )
217{
218 wxSscanf(s, _T("%lld"), &data );
219}
220
221template<> void wxStringWriteValue(wxString &s, const wxULongLong_t &data )
222{
223 s = wxString::Format(_T("%lld"), data );
224}
225#endif
226// float
227
228template<> void wxStringReadValue(const wxString &s, float &data )
229{
230 wxSscanf(s, _T("%f"), &data );
231}
232
233template<> void wxStringWriteValue(wxString &s, const float &data )
234{
235 s = wxString::Format(_T("%f"), data );
236}
237
238// double
239
240template<> void wxStringReadValue(const wxString &s, double &data )
241{
242 wxSscanf(s, _T("%lf"), &data );
243}
244
245template<> void wxStringWriteValue(wxString &s, const double &data )
246{
247 s = wxString::Format(_T("%lf"), data );
248}
249
250// wxString
251
252template<> void wxStringReadValue(const wxString &s, wxString &data )
253{
254 data = s;
255}
256
257template<> 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
281typedef unsigned char unsigned_char;
282typedef unsigned int unsigned_int;
283typedef unsigned long unsigned_long;
284
285wxBuiltInTypeInfo s_typeInfovoid( wxT_VOID, NULL, NULL, typeid(void).name());
286wxBUILTIN_TYPE_INFO( wxT_BOOL, bool);
287wxBUILTIN_TYPE_INFO( wxT_CHAR, char);
288wxBUILTIN_TYPE_INFO( wxT_UCHAR, unsigned_char);
289wxBUILTIN_TYPE_INFO( wxT_INT, int);
290wxBUILTIN_TYPE_INFO( wxT_UINT, unsigned_int);
291wxBUILTIN_TYPE_INFO( wxT_LONG, long);
292wxBUILTIN_TYPE_INFO( wxT_ULONG, unsigned_long);
293wxBUILTIN_TYPE_INFO( wxT_FLOAT, float);
294wxBUILTIN_TYPE_INFO( wxT_DOUBLE, double);
295wxBUILTIN_TYPE_INFO( wxT_STRING, wxString);
296
297#ifdef wxLongLong_t
298wxBUILTIN_TYPE_INFO(wxT_LONGLONG, wxLongLong_t)
299wxBUILTIN_TYPE_INFO(wxT_ULONGLONG, wxULongLong_t)
300#endif
301
302// this are compiler induced specialization which are never used anywhere
303
304wxILLEGAL_TYPE_SPECIALIZATION( char const * )
305wxILLEGAL_TYPE_SPECIALIZATION( char * )
306wxILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
307wxILLEGAL_TYPE_SPECIALIZATION( int * )
308wxILLEGAL_TYPE_SPECIALIZATION( bool * )
309wxILLEGAL_TYPE_SPECIALIZATION( long * )
310wxILLEGAL_TYPE_SPECIALIZATION( wxString * )
311
312// wxRange
313
314template<> 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
321template<> void wxStringWriteValue(wxString &s , const wxRange &data)
322{
323 s = wxString::Format(wxT("%d,%d"), data.GetMin() , data.GetMax());
324}
325
326wxCUSTOM_TYPE_INFO(wxRange, wxToStringConverter<wxRange> , wxFromStringConverter<wxRange>)
327
328// other types
329
330wxCOLLECTION_TYPE_INFO( wxString, wxArrayString );
331
332template<> void wxCollectionToVariantArray( wxArrayString const &theArray,
333 wxAnyList &value)
334{
335 wxArrayCollectionToVariantArray( theArray, value );
336}
337
338wxTypeInfoMap *wxTypeInfo::ms_typeTable = NULL;
339
340wxTypeInfo *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
350wxClassTypeInfo::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
360wxEventSourceTypeInfo::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
370wxEventSourceTypeInfo::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
381void 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
390void wxTypeInfo::Unregister()
391{
392 if( !m_name.empty() )
393 ms_typeTable->erase(m_name);
394}
395
396// removing header dependancy on string tokenizer
397
398void 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
413void 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
428void 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
455void 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
470void 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
497bool 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
509wxObject *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
524bool 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
540const 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
550wxPropertyInfo *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
564const 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
580wxHandlerInfo *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
594const 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
611wxObjectStreamingCallback 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
625bool 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
635void 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
645wxAny 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
656wxAnyList 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
668void 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.
681void 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
699wxObject* wxClassInfo::AnyToObjectPtr( const wxAny &data) const
700{
701 return m_variantOfPtrToObjectConverter(data);
702}
703
704void 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
712wxAny wxClassInfo::ObjectPtrToAny( wxObject* obj) const
713{
714 return m_objectToVariantConverter(obj);
715}
716
717bool 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
730struct wxDynamicObject::wxDynamicObjectInternal
731{
732 wxDynamicObjectInternal() {}
733
734 wxStringToAnyHashMap m_properties;
735};
736
737typedef list< wxDynamicObject* > wxDynamicObjectList;
738
739struct wxDynamicClassInfo::wxDynamicClassInfoInternal
740{
741 wxDynamicObjectList m_dynamicObjects;
742};
743
744// instantiates this object with an instance of its superclass
745wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info)
746{
747 m_superClassInstance = superClassInstance;
748 m_classInfo = info;
749 m_data = new wxDynamicObjectInternal;
750}
751
752wxDynamicObject::~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
760void 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
767wxAny 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
774void 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
781void 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
797wxDynamicClassInfo::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
807wxDynamicClassInfo::~wxDynamicClassInfo()
808{
809 delete[] GetParents();
810 delete m_data;
811}
812
813wxObject *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
821bool 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
832int wxDynamicClassInfo::GetCreateParamCount() const
833{
834 return GetParents()[0]->GetCreateParamCount();
835}
836
837// get i-th constructor parameter
838const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const
839{
840 return GetParents()[0]->GetCreateParamName( i );
841}
842
843void 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
853wxAny 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
863void 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
869void 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
876void 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
884void wxDynamicClassInfo::RemoveHandler( const wxChar *handlerName )
885{
886 delete FindHandlerInfoInThisClass(handlerName);
887}
888
889// renames an existing runtime-property
890void 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
901void 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
911struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
912{
913 char filler;
914};
915
916wxGenericPropertyAccessor::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
925wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
926{
927 delete m_data;
928}
929
930void 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
937void 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
948wxString 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
958const 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
969wxObjectFunctor::~wxObjectFunctor()
970{};
971
972#endif // wxUSE_EXTENDED_RTTI