1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/xti.cpp
3 // Purpose: runtime metadata information (extended class info
4 // Author: Stefan Csomor
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2003 Stefan Csomor
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "xti.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
26 #include "wx/object.h"
29 #include "wx/xml/xml.h"
30 #include "wx/tokenzr.h"
34 #if wxUSE_EXTENDED_RTTI
36 #include "wx/beforestd.h"
39 #include "wx/afterstd.h"
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 wxEnumData::wxEnumData( wxEnumMemberData
* data
)
50 for ( m_count
= 0; m_members
[m_count
].m_name
; m_count
++)
54 bool wxEnumData::HasEnumMemberValue(const wxChar
*name
, int *value
)
57 for (i
= 0; m_members
[i
].m_name
; i
++ )
59 if (!strcmp(name
, m_members
[i
].m_name
))
62 *value
= m_members
[i
].m_value
;
69 int wxEnumData::GetEnumMemberValue(const wxChar
*name
)
72 for (i
= 0; m_members
[i
].m_name
; i
++ )
74 if (!strcmp(name
, m_members
[i
].m_name
))
76 return m_members
[i
].m_value
;
82 const wxChar
*wxEnumData::GetEnumMemberName(int value
)
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
;
92 int wxEnumData::GetEnumMemberValueByIndex( int idx
)
94 // we should cache the count in order to avoid out-of-bounds errors
95 return m_members
[idx
].m_value
;
98 const char * wxEnumData::GetEnumMemberNameByIndex( int idx
)
100 // we should cache the count in order to avoid out-of-bounds errors
101 return m_members
[idx
].m_name
;
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 // ----------------------------------------------------------------------------
111 // streamer specializations
112 // for all built-in types
116 template<> void wxStringReadValue(const wxString
&s
, bool &data
)
119 wxSscanf(s
, _T("%d"), &intdata
) ;
120 data
= bool(intdata
) ;
123 template<> void wxStringWriteValue(wxString
&s
, const bool &data
)
125 s
= wxString::Format("%d", data
) ;
130 template<> void wxStringReadValue(const wxString
&s
, char &data
)
133 wxSscanf(s
, _T("%d"), &intdata
) ;
134 data
= char(intdata
) ;
137 template<> void wxStringWriteValue(wxString
&s
, const char &data
)
139 s
= wxString::Format("%d", data
) ;
144 template<> void wxStringReadValue(const wxString
&s
, unsigned char &data
)
147 wxSscanf(s
, _T("%d"), &intdata
) ;
148 data
= (unsigned char)(intdata
) ;
151 template<> void wxStringWriteValue(wxString
&s
, const unsigned char &data
)
153 s
= wxString::Format("%d", data
) ;
158 template<> void wxStringReadValue(const wxString
&s
, int &data
)
160 wxSscanf(s
, _T("%d"), &data
) ;
163 template<> void wxStringWriteValue(wxString
&s
, const int &data
)
165 s
= wxString::Format("%d", data
) ;
170 template<> void wxStringReadValue(const wxString
&s
, unsigned int &data
)
172 wxSscanf(s
, _T("%d"), &data
) ;
175 template<> void wxStringWriteValue(wxString
&s
, const unsigned int &data
)
177 s
= wxString::Format("%d", data
) ;
182 template<> void wxStringReadValue(const wxString
&s
, long &data
)
184 wxSscanf(s
, _T("%ld"), &data
) ;
187 template<> void wxStringWriteValue(wxString
&s
, const long &data
)
189 s
= wxString::Format("%ld", data
) ;
194 template<> void wxStringReadValue(const wxString
&s
, unsigned long &data
)
196 wxSscanf(s
, _T("%ld"), &data
) ;
199 template<> void wxStringWriteValue(wxString
&s
, const unsigned long &data
)
201 s
= wxString::Format("%ld", data
) ;
206 template<> void wxStringReadValue(const wxString
&s
, float &data
)
208 wxSscanf(s
, _T("%f"), &data
) ;
211 template<> void wxStringWriteValue(wxString
&s
, const float &data
)
213 s
= wxString::Format("%f", data
) ;
218 template<> void wxStringReadValue(const wxString
&s
, double &data
)
220 wxSscanf(s
, _T("%lf"), &data
) ;
223 template<> void wxStringWriteValue(wxString
&s
, const double &data
)
225 s
= wxString::Format("%lf", data
) ;
230 template<> void wxStringReadValue(const wxString
&s
, wxString
&data
)
235 template<> void wxStringWriteValue(wxString
&s
, const wxString
&data
)
243 template<> const wxTypeInfo
* wxGetTypeInfo( void * )
245 static wxBuiltInTypeInfo
s_typeInfo( wxT_VOID
) ;
249 template<> const wxTypeInfo
* wxGetTypeInfo( bool * )
251 static wxBuiltInTypeInfo
s_typeInfo( wxT_BOOL
, &wxToStringConverter
<bool> , &wxFromStringConverter
<bool>) ;
255 template<> const wxTypeInfo
* wxGetTypeInfo( char * )
257 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
, &wxToStringConverter
<char> , &wxFromStringConverter
<char>) ;
261 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned char * )
263 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
, &wxToStringConverter
< unsigned char > , &wxFromStringConverter
<unsigned char>) ;
267 template<> const wxTypeInfo
* wxGetTypeInfo( int * )
269 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
, &wxToStringConverter
<int> , &wxFromStringConverter
<int>) ;
273 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned int * )
275 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
, &wxToStringConverter
<unsigned int> , &wxFromStringConverter
<unsigned int>) ;
279 template<> const wxTypeInfo
* wxGetTypeInfo( long * )
281 static wxBuiltInTypeInfo
s_typeInfo( wxT_LONG
, &wxToStringConverter
<long> , &wxFromStringConverter
<long>) ;
285 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned long * )
287 static wxBuiltInTypeInfo
s_typeInfo( wxT_ULONG
, &wxToStringConverter
<unsigned long> , &wxFromStringConverter
<unsigned long>) ;
291 template<> const wxTypeInfo
* wxGetTypeInfo( float * )
293 static wxBuiltInTypeInfo
s_typeInfo( wxT_FLOAT
, &wxToStringConverter
<float> , &wxFromStringConverter
<float>) ;
297 template<> const wxTypeInfo
* wxGetTypeInfo( double * )
299 static wxBuiltInTypeInfo
s_typeInfo( wxT_DOUBLE
, &wxToStringConverter
<double> , &wxFromStringConverter
<double>) ;
303 template<> const wxTypeInfo
* wxGetTypeInfo( wxString
* )
305 static wxBuiltInTypeInfo
s_typeInfo( wxT_STRING
, &wxToStringConverter
<wxString
> , &wxFromStringConverter
<wxString
>) ;
309 // this are compiler induced specialization which are never used anywhere
311 WX_ILLEGAL_TYPE_SPECIALIZATION( char const * )
312 WX_ILLEGAL_TYPE_SPECIALIZATION( char * )
313 WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
314 WX_ILLEGAL_TYPE_SPECIALIZATION( int * )
315 WX_ILLEGAL_TYPE_SPECIALIZATION( bool * )
316 WX_ILLEGAL_TYPE_SPECIALIZATION( long * )
317 WX_ILLEGAL_TYPE_SPECIALIZATION( wxString
* )
319 WX_COLLECTION_TYPE_INFO( wxString
, wxArrayString
) ;
321 template<> void wxCollectionToVariantArray( wxArrayString
const &theArray
, wxxVariantArray
&value
)
323 wxArrayCollectionToVariantArray( theArray
, value
) ;
326 wxTypeInfoMap
*wxTypeInfo::sm_typeTable
= NULL
;
328 wxTypeInfo
*wxTypeInfo::FindType(const wxChar
*typeName
)
330 return (wxTypeInfo
*)sm_typeTable
->find(typeName
)->second
;
333 wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
, converterToString_t to
, converterFromString_t from
) :
334 wxTypeInfo( kind
, to
, from
, classInfo
->GetClassName() )
335 { wxASSERT_MSG( kind
== wxT_OBJECT_PTR
|| kind
== wxT_OBJECT
, wxT("Illegal Kind for Enum Type")) ; m_classInfo
= classInfo
;}
337 wxDelegateTypeInfo::wxDelegateTypeInfo( int eventType
, wxClassInfo
* eventClass
, converterToString_t to
, converterFromString_t from
) :
338 wxTypeInfo ( wxT_DELEGATE
, to
, from
, wxEmptyString
)
339 { m_eventClass
= eventClass
; m_eventType
= eventType
;}
341 void wxTypeInfo::Register()
343 if ( sm_typeTable
== NULL
)
344 sm_typeTable
= new wxTypeInfoMap() ;
346 if( !m_name
.IsEmpty() )
347 (*sm_typeTable
)[m_name
] = this ;
350 void wxTypeInfo::Unregister()
352 if( !m_name
.IsEmpty() )
353 sm_typeTable
->erase(m_name
);
356 // removing header dependancy on string tokenizer
358 void wxSetStringToArray( const wxString
&s
, wxArrayString
&array
)
360 wxStringTokenizer
tokenizer(s
, wxT("| \t\n"), wxTOKEN_STRTOK
);
363 while (tokenizer
.HasMoreTokens())
365 array
.Add(tokenizer
.GetNextToken()) ;
369 // ----------------------------------------------------------------------------
371 // ----------------------------------------------------------------------------
373 const wxPropertyAccessor
*wxClassInfo::FindAccessor(const char *PropertyName
) const
375 const wxPropertyInfo
* info
= FindPropertyInfo( PropertyName
) ;
378 return info
->GetAccessor() ;
383 const wxPropertyInfo
*wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName
) const
385 const wxPropertyInfo
* info
= GetFirstProperty() ;
389 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
391 info
= info
->GetNext() ;
397 const wxPropertyInfo
*wxClassInfo::FindPropertyInfo (const char *PropertyName
) const
399 const wxPropertyInfo
* info
= FindPropertyInfoInThisClass( PropertyName
) ;
403 const wxClassInfo
** parents
= GetParents() ;
404 for ( int i
= 0 ; parents
[i
] ; ++ i
)
406 if ( ( info
= parents
[i
]->FindPropertyInfo( PropertyName
) ) != NULL
)
413 const wxHandlerInfo
*wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName
) const
415 const wxHandlerInfo
* info
= GetFirstHandler() ;
419 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
421 info
= info
->GetNext() ;
427 const wxHandlerInfo
*wxClassInfo::FindHandlerInfo (const char *PropertyName
) const
429 const wxHandlerInfo
* info
= FindHandlerInfoInThisClass( PropertyName
) ;
434 const wxClassInfo
** parents
= GetParents() ;
435 for ( int i
= 0 ; parents
[i
] ; ++ i
)
437 if ( ( info
= parents
[i
]->FindHandlerInfo( PropertyName
) ) != NULL
)
444 wxObjectStreamingCallback
wxClassInfo::GetStreamingCallback() const
446 if ( m_streamingCallback
)
447 return m_streamingCallback
;
449 wxObjectStreamingCallback retval
= NULL
;
450 const wxClassInfo
** parents
= GetParents() ;
451 for ( int i
= 0 ; parents
[i
] && retval
== NULL
; ++ i
)
453 retval
= parents
[i
]->GetStreamingCallback() ;
458 bool wxClassInfo::BeforeWriteObject( const wxObject
*obj
, wxWriter
*streamer
, wxPersister
*persister
, wxxVariantArray
&metadata
) const
460 wxObjectStreamingCallback sb
= GetStreamingCallback() ;
462 return (*sb
)(obj
, streamer
, persister
, metadata
) ;
467 void wxClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
469 const wxPropertyAccessor
*accessor
;
471 accessor
= FindAccessor(propertyName
);
472 wxASSERT(accessor
->HasSetter());
473 accessor
->SetProperty( object
, value
) ;
476 wxxVariant
wxClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
478 const wxPropertyAccessor
*accessor
;
480 accessor
= FindAccessor(propertyName
);
481 wxASSERT(accessor
->HasGetter());
483 accessor
->GetProperty(object
,result
);
487 wxxVariantArray
wxClassInfo::GetPropertyCollection(wxObject
*object
, const wxChar
*propertyName
) const
489 const wxPropertyAccessor
*accessor
;
491 accessor
= FindAccessor(propertyName
);
492 wxASSERT(accessor
->HasGetter());
493 wxxVariantArray result
;
494 accessor
->GetPropertyCollection(object
,result
);
498 void wxClassInfo::AddToPropertyCollection(wxObject
*object
, const wxChar
*propertyName
, const wxxVariant
& value
) const
500 const wxPropertyAccessor
*accessor
;
502 accessor
= FindAccessor(propertyName
);
503 wxASSERT(accessor
->HasAdder());
504 accessor
->AddToPropertyCollection( object
, value
) ;
507 void wxClassInfo::GetProperties( wxPropertyInfoMap
&map
) const
509 const wxPropertyInfo
*pi
= GetFirstProperty() ;
512 if ( map
.find( pi
->GetName() ) == map
.end() )
513 map
[pi
->GetName()] = (wxPropertyInfo
*) pi
;
518 const wxClassInfo
** parents
= GetParents() ;
519 for ( int i
= 0 ; parents
[i
] ; ++ i
)
521 parents
[i
]->GetProperties( map
) ;
529 wxObject
* wxxVariant::GetAsObject()
531 const wxClassTypeInfo
*ti
= dynamic_cast<const wxClassTypeInfo
*>( m_data
->GetTypeInfo() ) ;
533 return ti
->GetClassInfo()->VariantToInstance(*this) ;
538 // ----------------------------------------------------------------------------
539 // wxDynamicObject support
540 // ----------------------------------------------------------------------------
542 // Dynamic Objects are objects that have a real superclass instance and carry their
543 // own attributes in a hash map. Like this it is possible to create the objects and
544 // stream them, as if their class information was already available from compiled data
546 struct wxDynamicObject::wxDynamicObjectInternal
548 map
<string
,wxxVariant
> m_properties
;
551 // instantiates this object with an instance of its superclass
552 wxDynamicObject::wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo
*info
)
554 m_superClassInstance
= superClassInstance
;
556 m_data
= new wxDynamicObjectInternal
;
559 wxDynamicObject::~wxDynamicObject()
562 delete m_superClassInstance
;
565 void wxDynamicObject::SetProperty (const wxChar
*propertyName
, const wxxVariant
&value
)
567 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
568 m_data
->m_properties
[propertyName
] = value
;
571 wxxVariant
wxDynamicObject::GetProperty (const wxChar
*propertyName
) const
573 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
574 return m_data
->m_properties
[propertyName
] ;
577 // ----------------------------------------------------------------------------
579 // ----------------------------------------------------------------------------
581 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar
*unitName
, const wxChar
*className
, const wxClassInfo
* superClass
) :
582 wxClassInfo( unitName
, className
, new const wxClassInfo
*[2])
584 GetParents()[0] = superClass
;
585 GetParents()[1] = NULL
;
588 wxDynamicClassInfo::~wxDynamicClassInfo()
590 delete[] GetParents() ;
593 wxObject
*wxDynamicClassInfo::AllocateObject() const
595 wxObject
* parent
= GetParents()[0]->AllocateObject() ;
596 return new wxDynamicObject( parent
, this ) ;
599 void wxDynamicClassInfo::Create (wxObject
*object
, int paramCount
, wxxVariant
*params
) const
601 wxDynamicObject
*dynobj
= dynamic_cast< wxDynamicObject
*>( object
) ;
602 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ;
603 GetParents()[0]->Create( dynobj
->GetSuperClassInstance() , paramCount
, params
) ;
606 // get number of parameters for constructor
607 int wxDynamicClassInfo::GetCreateParamCount() const
609 return GetParents()[0]->GetCreateParamCount() ;
612 // get i-th constructor parameter
613 const wxChar
* wxDynamicClassInfo::GetCreateParamName(int i
) const
615 return GetParents()[0]->GetCreateParamName( i
) ;
618 void wxDynamicClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
620 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
621 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
622 if ( FindPropertyInfoInThisClass(propertyName
) )
623 dynobj
->SetProperty( propertyName
, value
) ;
625 GetParents()[0]->SetProperty( dynobj
->GetSuperClassInstance() , propertyName
, value
) ;
628 wxxVariant
wxDynamicClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
630 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
631 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
632 if ( FindPropertyInfoInThisClass(propertyName
) )
633 return dynobj
->GetProperty( propertyName
) ;
635 return GetParents()[0]->GetProperty( dynobj
->GetSuperClassInstance() , propertyName
) ;
638 void wxDynamicClassInfo::AddProperty( const wxChar
*propertyName
, const wxTypeInfo
* typeInfo
)
640 new wxPropertyInfo( m_firstProperty
, this , propertyName
, typeInfo
, new wxGenericPropertyAccessor( propertyName
) , wxxVariant() ) ;
643 void wxDynamicClassInfo::AddHandler( const wxChar
*handlerName
, wxObjectEventFunction address
, const wxClassInfo
* eventClassInfo
)
645 new wxHandlerInfo( m_firstHandler
, handlerName
, address
, eventClassInfo
) ;
648 // ----------------------------------------------------------------------------
649 // wxGenericPropertyAccessor
650 // ----------------------------------------------------------------------------
652 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
657 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString
& propertyName
)
658 : wxPropertyAccessor( NULL
, NULL
, NULL
, NULL
)
660 m_data
= new wxGenericPropertyAccessorInternal
;
661 m_propertyName
= propertyName
;
662 m_getterName
= wxT("Get")+propertyName
;
663 m_setterName
= wxT("Set")+propertyName
;
666 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
670 void wxGenericPropertyAccessor::SetProperty(wxObject
*object
, const wxxVariant
&value
) const
672 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
673 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
674 dynobj
->SetProperty(m_propertyName
, value
) ;
677 void wxGenericPropertyAccessor::GetProperty(const wxObject
*object
, wxxVariant
& value
) const
679 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* >( object
) ;
680 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
681 value
= dynobj
->GetProperty( m_propertyName
) ;