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
* )
321 // make wxWindowList known
323 WX_COLLECTION_TYPE_INFO( wxString
, wxArrayString
) ;
325 template<> void wxCollectionToVariantArray( wxArrayString
const &theArray
, wxxVariantArray
&value
)
327 wxArrayCollectionToVariantArray( theArray
, value
) ;
330 wxTypeInfoMap
*wxTypeInfo::sm_typeTable
= NULL
;
332 wxTypeInfo
*wxTypeInfo::FindType(const wxChar
*typeName
)
334 return (wxTypeInfo
*)sm_typeTable
->find(typeName
)->second
;
337 wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
, converterToString_t to
, converterFromString_t from
) :
338 wxTypeInfo( kind
, to
, from
, classInfo
->GetClassName() )
339 { wxASSERT_MSG( kind
== wxT_OBJECT_PTR
|| kind
== wxT_OBJECT
, wxT("Illegal Kind for Enum Type")) ; m_classInfo
= classInfo
;}
341 wxDelegateTypeInfo::wxDelegateTypeInfo( int eventType
, wxClassInfo
* eventClass
, converterToString_t to
, converterFromString_t from
) :
342 wxTypeInfo ( wxT_DELEGATE
, to
, from
, wxEmptyString
)
343 { m_eventClass
= eventClass
; m_eventType
= eventType
;}
345 void wxTypeInfo::Register()
347 if ( sm_typeTable
== NULL
)
348 sm_typeTable
= new wxTypeInfoMap() ;
350 if( !m_name
.IsEmpty() )
351 (*sm_typeTable
)[m_name
] = this ;
354 void wxTypeInfo::Unregister()
356 if( !m_name
.IsEmpty() )
357 sm_typeTable
->erase(m_name
);
360 // removing header dependancy on string tokenizer
362 void wxSetStringToArray( const wxString
&s
, wxArrayString
&array
)
364 wxStringTokenizer
tokenizer(s
, wxT("| \t\n"), wxTOKEN_STRTOK
);
367 while (tokenizer
.HasMoreTokens())
369 array
.Add(tokenizer
.GetNextToken()) ;
373 // ----------------------------------------------------------------------------
375 // ----------------------------------------------------------------------------
377 const wxPropertyAccessor
*wxClassInfo::FindAccessor(const char *PropertyName
) const
379 const wxPropertyInfo
* info
= FindPropertyInfo( PropertyName
) ;
382 return info
->GetAccessor() ;
387 const wxPropertyInfo
*wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName
) const
389 const wxPropertyInfo
* info
= GetFirstProperty() ;
393 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
395 info
= info
->GetNext() ;
401 const wxPropertyInfo
*wxClassInfo::FindPropertyInfo (const char *PropertyName
) const
403 const wxPropertyInfo
* info
= FindPropertyInfoInThisClass( PropertyName
) ;
407 const wxClassInfo
** parents
= GetParents() ;
408 for ( int i
= 0 ; parents
[i
] ; ++ i
)
410 if ( ( info
= parents
[i
]->FindPropertyInfo( PropertyName
) ) != NULL
)
417 const wxHandlerInfo
*wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName
) const
419 const wxHandlerInfo
* info
= GetFirstHandler() ;
423 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
425 info
= info
->GetNext() ;
431 const wxHandlerInfo
*wxClassInfo::FindHandlerInfo (const char *PropertyName
) const
433 const wxHandlerInfo
* info
= FindHandlerInfoInThisClass( PropertyName
) ;
438 const wxClassInfo
** parents
= GetParents() ;
439 for ( int i
= 0 ; parents
[i
] ; ++ i
)
441 if ( ( info
= parents
[i
]->FindHandlerInfo( PropertyName
) ) != NULL
)
449 void wxClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
451 const wxPropertyAccessor
*accessor
;
453 accessor
= FindAccessor(propertyName
);
454 wxASSERT(accessor
->HasSetter());
455 accessor
->SetProperty( object
, value
) ;
458 wxxVariant
wxClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
460 const wxPropertyAccessor
*accessor
;
462 accessor
= FindAccessor(propertyName
);
463 wxASSERT(accessor
->HasGetter());
465 accessor
->GetProperty(object
,result
);
469 wxxVariantArray
wxClassInfo::GetPropertyCollection(wxObject
*object
, const wxChar
*propertyName
) const
471 const wxPropertyAccessor
*accessor
;
473 accessor
= FindAccessor(propertyName
);
474 wxASSERT(accessor
->HasGetter());
475 wxxVariantArray result
;
476 accessor
->GetPropertyCollection(object
,result
);
480 void wxClassInfo::AddToPropertyCollection(wxObject
*object
, const wxChar
*propertyName
, const wxxVariant
& value
) const
482 const wxPropertyAccessor
*accessor
;
484 accessor
= FindAccessor(propertyName
);
485 wxASSERT(accessor
->HasAdder());
486 accessor
->AddToPropertyCollection( object
, value
) ;
489 void wxClassInfo::GetProperties( wxPropertyInfoMap
&map
) const
491 const wxPropertyInfo
*pi
= GetFirstProperty() ;
494 if ( map
.find( pi
->GetName() ) == map
.end() )
495 map
[pi
->GetName()] = (wxPropertyInfo
*) pi
;
500 const wxClassInfo
** parents
= GetParents() ;
501 for ( int i
= 0 ; parents
[i
] ; ++ i
)
503 parents
[i
]->GetProperties( map
) ;
511 wxObject
* wxxVariant::GetAsObject()
513 const wxClassTypeInfo
*ti
= dynamic_cast<const wxClassTypeInfo
*>( m_data
->GetTypeInfo() ) ;
515 return ti
->GetClassInfo()->VariantToInstance(*this) ;
520 // ----------------------------------------------------------------------------
521 // wxDynamicObject support
522 // ----------------------------------------------------------------------------
524 // Dynamic Objects are objects that have a real superclass instance and carry their
525 // own attributes in a hash map. Like this it is possible to create the objects and
526 // stream them, as if their class information was already available from compiled data
528 struct wxDynamicObject::wxDynamicObjectInternal
530 map
<string
,wxxVariant
> m_properties
;
533 // instantiates this object with an instance of its superclass
534 wxDynamicObject::wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo
*info
)
536 m_superClassInstance
= superClassInstance
;
538 m_data
= new wxDynamicObjectInternal
;
541 wxDynamicObject::~wxDynamicObject()
544 delete m_superClassInstance
;
547 void wxDynamicObject::SetProperty (const wxChar
*propertyName
, const wxxVariant
&value
)
549 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
550 m_data
->m_properties
[propertyName
] = value
;
553 wxxVariant
wxDynamicObject::GetProperty (const wxChar
*propertyName
) const
555 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
556 return m_data
->m_properties
[propertyName
] ;
559 // ----------------------------------------------------------------------------
561 // ----------------------------------------------------------------------------
563 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar
*unitName
, const wxChar
*className
, const wxClassInfo
* superClass
) :
564 wxClassInfo( unitName
, className
, new const wxClassInfo
*[2])
566 GetParents()[0] = superClass
;
567 GetParents()[1] = NULL
;
570 wxDynamicClassInfo::~wxDynamicClassInfo()
572 delete[] GetParents() ;
575 wxObject
*wxDynamicClassInfo::AllocateObject() const
577 wxObject
* parent
= GetParents()[0]->AllocateObject() ;
578 return new wxDynamicObject( parent
, this ) ;
581 void wxDynamicClassInfo::Create (wxObject
*object
, int paramCount
, wxxVariant
*params
) const
583 wxDynamicObject
*dynobj
= dynamic_cast< wxDynamicObject
*>( object
) ;
584 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ;
585 GetParents()[0]->Create( dynobj
->GetSuperClassInstance() , paramCount
, params
) ;
588 // get number of parameters for constructor
589 int wxDynamicClassInfo::GetCreateParamCount() const
591 return GetParents()[0]->GetCreateParamCount() ;
594 // get i-th constructor parameter
595 const wxChar
* wxDynamicClassInfo::GetCreateParamName(int i
) const
597 return GetParents()[0]->GetCreateParamName( i
) ;
600 void wxDynamicClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
602 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
603 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
604 if ( FindPropertyInfoInThisClass(propertyName
) )
605 dynobj
->SetProperty( propertyName
, value
) ;
607 GetParents()[0]->SetProperty( dynobj
->GetSuperClassInstance() , propertyName
, value
) ;
610 wxxVariant
wxDynamicClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
612 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
613 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
614 if ( FindPropertyInfoInThisClass(propertyName
) )
615 return dynobj
->GetProperty( propertyName
) ;
617 return GetParents()[0]->GetProperty( dynobj
->GetSuperClassInstance() , propertyName
) ;
620 void wxDynamicClassInfo::AddProperty( const wxChar
*propertyName
, const wxTypeInfo
* typeInfo
)
622 new wxPropertyInfo( m_firstProperty
, this , propertyName
, typeInfo
, new wxGenericPropertyAccessor( propertyName
) , wxxVariant() ) ;
625 void wxDynamicClassInfo::AddHandler( const wxChar
*handlerName
, wxObjectEventFunction address
, const wxClassInfo
* eventClassInfo
)
627 new wxHandlerInfo( m_firstHandler
, handlerName
, address
, eventClassInfo
) ;
630 // ----------------------------------------------------------------------------
631 // wxGenericPropertyAccessor
632 // ----------------------------------------------------------------------------
634 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
639 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString
& propertyName
)
640 : wxPropertyAccessor( NULL
, NULL
, NULL
, NULL
)
642 m_data
= new wxGenericPropertyAccessorInternal
;
643 m_propertyName
= propertyName
;
644 m_getterName
= wxT("Get")+propertyName
;
645 m_setterName
= wxT("Set")+propertyName
;
648 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
652 void wxGenericPropertyAccessor::SetProperty(wxObject
*object
, const wxxVariant
&value
) const
654 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
655 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
656 dynobj
->SetProperty(m_propertyName
, value
) ;
659 void wxGenericPropertyAccessor::GetProperty(const wxObject
*object
, wxxVariant
& value
) const
661 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* >( object
) ;
662 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
663 value
= dynobj
->GetProperty( m_propertyName
) ;