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"
30 #include "wx/xml/xml.h"
31 #include "wx/tokenzr.h"
35 #if wxUSE_EXTENDED_RTTI
37 #include "wx/beforestd.h"
40 #include "wx/afterstd.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 wxEnumData::wxEnumData( wxEnumMemberData
* data
)
51 for ( m_count
= 0; m_members
[m_count
].m_name
; m_count
++)
55 bool wxEnumData::HasEnumMemberValue(const wxChar
*name
, int *value
)
58 for (i
= 0; m_members
[i
].m_name
; i
++ )
60 if (!strcmp(name
, m_members
[i
].m_name
))
63 *value
= m_members
[i
].m_value
;
70 int wxEnumData::GetEnumMemberValue(const wxChar
*name
)
73 for (i
= 0; m_members
[i
].m_name
; i
++ )
75 if (!strcmp(name
, m_members
[i
].m_name
))
77 return m_members
[i
].m_value
;
83 const wxChar
*wxEnumData::GetEnumMemberName(int value
)
86 for (i
= 0; m_members
[i
].m_name
; i
++)
87 if (value
== m_members
[i
].m_value
)
88 return m_members
[i
].m_name
;
93 int wxEnumData::GetEnumMemberValueByIndex( int idx
)
95 // we should cache the count in order to avoid out-of-bounds errors
96 return m_members
[idx
].m_value
;
99 const char * wxEnumData::GetEnumMemberNameByIndex( int idx
)
101 // we should cache the count in order to avoid out-of-bounds errors
102 return m_members
[idx
].m_name
;
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 // streamer specializations
113 // for all built-in types
117 template<> void wxStringReadValue(const wxString
&s
, bool &data
)
120 wxSscanf(s
, _T("%d"), &intdata
) ;
121 data
= bool(intdata
) ;
124 template<> void wxStringWriteValue(wxString
&s
, const bool &data
)
126 s
= wxString::Format("%d", data
) ;
131 template<> void wxStringReadValue(const wxString
&s
, char &data
)
134 wxSscanf(s
, _T("%d"), &intdata
) ;
135 data
= char(intdata
) ;
138 template<> void wxStringWriteValue(wxString
&s
, const char &data
)
140 s
= wxString::Format("%d", data
) ;
145 template<> void wxStringReadValue(const wxString
&s
, unsigned char &data
)
148 wxSscanf(s
, _T("%d"), &intdata
) ;
149 data
= (unsigned char)(intdata
) ;
152 template<> void wxStringWriteValue(wxString
&s
, const unsigned char &data
)
154 s
= wxString::Format("%d", data
) ;
159 template<> void wxStringReadValue(const wxString
&s
, int &data
)
161 wxSscanf(s
, _T("%d"), &data
) ;
164 template<> void wxStringWriteValue(wxString
&s
, const int &data
)
166 s
= wxString::Format("%d", data
) ;
171 template<> void wxStringReadValue(const wxString
&s
, unsigned int &data
)
173 wxSscanf(s
, _T("%d"), &data
) ;
176 template<> void wxStringWriteValue(wxString
&s
, const unsigned int &data
)
178 s
= wxString::Format("%d", data
) ;
183 template<> void wxStringReadValue(const wxString
&s
, long &data
)
185 wxSscanf(s
, _T("%ld"), &data
) ;
188 template<> void wxStringWriteValue(wxString
&s
, const long &data
)
190 s
= wxString::Format("%ld", data
) ;
195 template<> void wxStringReadValue(const wxString
&s
, unsigned long &data
)
197 wxSscanf(s
, _T("%ld"), &data
) ;
200 template<> void wxStringWriteValue(wxString
&s
, const unsigned long &data
)
202 s
= wxString::Format("%ld", data
) ;
207 template<> void wxStringReadValue(const wxString
&s
, float &data
)
209 wxSscanf(s
, _T("%f"), &data
) ;
212 template<> void wxStringWriteValue(wxString
&s
, const float &data
)
214 s
= wxString::Format("%f", data
) ;
219 template<> void wxStringReadValue(const wxString
&s
, double &data
)
221 wxSscanf(s
, _T("%lf"), &data
) ;
224 template<> void wxStringWriteValue(wxString
&s
, const double &data
)
226 s
= wxString::Format("%lf", data
) ;
231 template<> void wxStringReadValue(const wxString
&s
, wxString
&data
)
236 template<> void wxStringWriteValue(wxString
&s
, const wxString
&data
)
244 template<> const wxTypeInfo
* wxGetTypeInfo( void * )
246 static wxBuiltInTypeInfo
s_typeInfo( wxT_VOID
) ;
250 template<> const wxTypeInfo
* wxGetTypeInfo( bool * )
252 static wxBuiltInTypeInfo
s_typeInfo( wxT_BOOL
, &wxToStringConverter
<bool> , &wxFromStringConverter
<bool>) ;
256 template<> const wxTypeInfo
* wxGetTypeInfo( char * )
258 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
, &wxToStringConverter
<char> , &wxFromStringConverter
<char>) ;
262 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned char * )
264 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
, &wxToStringConverter
< unsigned char > , &wxFromStringConverter
<unsigned char>) ;
268 template<> const wxTypeInfo
* wxGetTypeInfo( int * )
270 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
, &wxToStringConverter
<int> , &wxFromStringConverter
<int>) ;
274 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned int * )
276 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
, &wxToStringConverter
<unsigned int> , &wxFromStringConverter
<unsigned int>) ;
280 template<> const wxTypeInfo
* wxGetTypeInfo( long * )
282 static wxBuiltInTypeInfo
s_typeInfo( wxT_LONG
, &wxToStringConverter
<long> , &wxFromStringConverter
<long>) ;
286 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned long * )
288 static wxBuiltInTypeInfo
s_typeInfo( wxT_ULONG
, &wxToStringConverter
<unsigned long> , &wxFromStringConverter
<unsigned long>) ;
292 template<> const wxTypeInfo
* wxGetTypeInfo( float * )
294 static wxBuiltInTypeInfo
s_typeInfo( wxT_FLOAT
, &wxToStringConverter
<float> , &wxFromStringConverter
<float>) ;
298 template<> const wxTypeInfo
* wxGetTypeInfo( double * )
300 static wxBuiltInTypeInfo
s_typeInfo( wxT_DOUBLE
, &wxToStringConverter
<double> , &wxFromStringConverter
<double>) ;
304 template<> const wxTypeInfo
* wxGetTypeInfo( wxString
* )
306 static wxBuiltInTypeInfo
s_typeInfo( wxT_STRING
, &wxToStringConverter
<wxString
> , &wxFromStringConverter
<wxString
>) ;
310 // this are compiler induced specialization which are never used anywhere
312 WX_ILLEGAL_TYPE_SPECIALIZATION( char const * )
313 WX_ILLEGAL_TYPE_SPECIALIZATION( char * )
314 WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
315 WX_ILLEGAL_TYPE_SPECIALIZATION( int * )
316 WX_ILLEGAL_TYPE_SPECIALIZATION( bool * )
317 WX_ILLEGAL_TYPE_SPECIALIZATION( long * )
318 WX_ILLEGAL_TYPE_SPECIALIZATION( wxString
* )
320 WX_COLLECTION_TYPE_INFO( wxString
, wxArrayString
) ;
322 template<> void wxCollectionToVariantArray( wxArrayString
const &theArray
, wxxVariantArray
&value
)
324 wxArrayCollectionToVariantArray( theArray
, value
) ;
327 wxTypeInfoMap
*wxTypeInfo::sm_typeTable
= NULL
;
329 wxTypeInfo
*wxTypeInfo::FindType(const wxChar
*typeName
)
331 return (wxTypeInfo
*)sm_typeTable
->find(typeName
)->second
;
334 wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind
, wxClassInfo
* classInfo
, converterToString_t to
, converterFromString_t from
) :
335 wxTypeInfo( kind
, to
, from
, classInfo
->GetClassName() )
336 { wxASSERT_MSG( kind
== wxT_OBJECT_PTR
|| kind
== wxT_OBJECT
, wxT("Illegal Kind for Enum Type")) ; m_classInfo
= classInfo
;}
338 wxDelegateTypeInfo::wxDelegateTypeInfo( int eventType
, wxClassInfo
* eventClass
, converterToString_t to
, converterFromString_t from
) :
339 wxTypeInfo ( wxT_DELEGATE
, to
, from
, wxEmptyString
)
340 { m_eventClass
= eventClass
; m_eventType
= eventType
;}
342 void wxTypeInfo::Register()
344 if ( sm_typeTable
== NULL
)
345 sm_typeTable
= new wxTypeInfoMap() ;
347 if( !m_name
.IsEmpty() )
348 (*sm_typeTable
)[m_name
] = this ;
351 void wxTypeInfo::Unregister()
353 if( !m_name
.IsEmpty() )
354 sm_typeTable
->erase(m_name
);
357 // removing header dependancy on string tokenizer
359 void wxSetStringToArray( const wxString
&s
, wxArrayString
&array
)
361 wxStringTokenizer
tokenizer(s
, wxT("| \t\n"), wxTOKEN_STRTOK
);
364 while (tokenizer
.HasMoreTokens())
366 array
.Add(tokenizer
.GetNextToken()) ;
370 // ----------------------------------------------------------------------------
372 // ----------------------------------------------------------------------------
374 const wxPropertyAccessor
*wxClassInfo::FindAccessor(const char *PropertyName
) const
376 const wxPropertyInfo
* info
= FindPropertyInfo( PropertyName
) ;
379 return info
->GetAccessor() ;
384 const wxPropertyInfo
*wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName
) const
386 const wxPropertyInfo
* info
= GetFirstProperty() ;
390 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
392 info
= info
->GetNext() ;
398 const wxPropertyInfo
*wxClassInfo::FindPropertyInfo (const char *PropertyName
) const
400 const wxPropertyInfo
* info
= FindPropertyInfoInThisClass( PropertyName
) ;
404 const wxClassInfo
** parents
= GetParents() ;
405 for ( int i
= 0 ; parents
[i
] ; ++ i
)
407 if ( ( info
= parents
[i
]->FindPropertyInfo( PropertyName
) ) != NULL
)
414 const wxHandlerInfo
*wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName
) const
416 const wxHandlerInfo
* info
= GetFirstHandler() ;
420 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
422 info
= info
->GetNext() ;
428 const wxHandlerInfo
*wxClassInfo::FindHandlerInfo (const char *PropertyName
) const
430 const wxHandlerInfo
* info
= FindHandlerInfoInThisClass( PropertyName
) ;
435 const wxClassInfo
** parents
= GetParents() ;
436 for ( int i
= 0 ; parents
[i
] ; ++ i
)
438 if ( ( info
= parents
[i
]->FindHandlerInfo( PropertyName
) ) != NULL
)
445 wxObjectStreamingCallback
wxClassInfo::GetStreamingCallback() const
447 if ( m_streamingCallback
)
448 return m_streamingCallback
;
450 wxObjectStreamingCallback retval
= NULL
;
451 const wxClassInfo
** parents
= GetParents() ;
452 for ( int i
= 0 ; parents
[i
] && retval
== NULL
; ++ i
)
454 retval
= parents
[i
]->GetStreamingCallback() ;
459 bool wxClassInfo::BeforeWriteObject( const wxObject
*obj
, wxWriter
*streamer
, wxPersister
*persister
, wxxVariantArray
&metadata
) const
461 wxObjectStreamingCallback sb
= GetStreamingCallback() ;
463 return (*sb
)(obj
, streamer
, persister
, metadata
) ;
468 void wxClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
470 const wxPropertyAccessor
*accessor
;
472 accessor
= FindAccessor(propertyName
);
473 wxASSERT(accessor
->HasSetter());
474 accessor
->SetProperty( object
, value
) ;
477 wxxVariant
wxClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
479 const wxPropertyAccessor
*accessor
;
481 accessor
= FindAccessor(propertyName
);
482 wxASSERT(accessor
->HasGetter());
484 accessor
->GetProperty(object
,result
);
488 wxxVariantArray
wxClassInfo::GetPropertyCollection(wxObject
*object
, const wxChar
*propertyName
) const
490 const wxPropertyAccessor
*accessor
;
492 accessor
= FindAccessor(propertyName
);
493 wxASSERT(accessor
->HasGetter());
494 wxxVariantArray result
;
495 accessor
->GetPropertyCollection(object
,result
);
499 void wxClassInfo::AddToPropertyCollection(wxObject
*object
, const wxChar
*propertyName
, const wxxVariant
& value
) const
501 const wxPropertyAccessor
*accessor
;
503 accessor
= FindAccessor(propertyName
);
504 wxASSERT(accessor
->HasAdder());
505 accessor
->AddToPropertyCollection( object
, value
) ;
508 void wxClassInfo::GetProperties( wxPropertyInfoMap
&map
) const
510 const wxPropertyInfo
*pi
= GetFirstProperty() ;
513 if ( map
.find( pi
->GetName() ) == map
.end() )
514 map
[pi
->GetName()] = (wxPropertyInfo
*) pi
;
519 const wxClassInfo
** parents
= GetParents() ;
520 for ( int i
= 0 ; parents
[i
] ; ++ i
)
522 parents
[i
]->GetProperties( map
) ;
530 wxObject
* wxxVariant::GetAsObject()
532 const wxClassTypeInfo
*ti
= dynamic_cast<const wxClassTypeInfo
*>( m_data
->GetTypeInfo() ) ;
534 return ti
->GetClassInfo()->VariantToInstance(*this) ;
539 // ----------------------------------------------------------------------------
540 // wxDynamicObject support
541 // ----------------------------------------------------------------------------
543 // Dynamic Objects are objects that have a real superclass instance and carry their
544 // own attributes in a hash map. Like this it is possible to create the objects and
545 // stream them, as if their class information was already available from compiled data
547 struct wxDynamicObject::wxDynamicObjectInternal
549 map
<string
,wxxVariant
> m_properties
;
552 // instantiates this object with an instance of its superclass
553 wxDynamicObject::wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo
*info
)
555 m_superClassInstance
= superClassInstance
;
557 m_data
= new wxDynamicObjectInternal
;
560 wxDynamicObject::~wxDynamicObject()
563 delete m_superClassInstance
;
566 void wxDynamicObject::SetProperty (const wxChar
*propertyName
, const wxxVariant
&value
)
568 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
569 m_data
->m_properties
[propertyName
] = value
;
572 wxxVariant
wxDynamicObject::GetProperty (const wxChar
*propertyName
) const
574 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
575 return m_data
->m_properties
[propertyName
] ;
578 // ----------------------------------------------------------------------------
580 // ----------------------------------------------------------------------------
582 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar
*unitName
, const wxChar
*className
, const wxClassInfo
* superClass
) :
583 wxClassInfo( unitName
, className
, new const wxClassInfo
*[2])
585 GetParents()[0] = superClass
;
586 GetParents()[1] = NULL
;
589 wxDynamicClassInfo::~wxDynamicClassInfo()
591 delete[] GetParents() ;
594 wxObject
*wxDynamicClassInfo::AllocateObject() const
596 wxObject
* parent
= GetParents()[0]->AllocateObject() ;
597 return new wxDynamicObject( parent
, this ) ;
600 void wxDynamicClassInfo::Create (wxObject
*object
, int paramCount
, wxxVariant
*params
) const
602 wxDynamicObject
*dynobj
= dynamic_cast< wxDynamicObject
*>( object
) ;
603 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ;
604 GetParents()[0]->Create( dynobj
->GetSuperClassInstance() , paramCount
, params
) ;
607 // get number of parameters for constructor
608 int wxDynamicClassInfo::GetCreateParamCount() const
610 return GetParents()[0]->GetCreateParamCount() ;
613 // get i-th constructor parameter
614 const wxChar
* wxDynamicClassInfo::GetCreateParamName(int i
) const
616 return GetParents()[0]->GetCreateParamName( i
) ;
619 void wxDynamicClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
621 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
622 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
623 if ( FindPropertyInfoInThisClass(propertyName
) )
624 dynobj
->SetProperty( propertyName
, value
) ;
626 GetParents()[0]->SetProperty( dynobj
->GetSuperClassInstance() , propertyName
, value
) ;
629 wxxVariant
wxDynamicClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
631 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
632 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
633 if ( FindPropertyInfoInThisClass(propertyName
) )
634 return dynobj
->GetProperty( propertyName
) ;
636 return GetParents()[0]->GetProperty( dynobj
->GetSuperClassInstance() , propertyName
) ;
639 void wxDynamicClassInfo::AddProperty( const wxChar
*propertyName
, const wxTypeInfo
* typeInfo
)
641 new wxPropertyInfo( m_firstProperty
, this , propertyName
, typeInfo
, new wxGenericPropertyAccessor( propertyName
) , wxxVariant() ) ;
644 void wxDynamicClassInfo::AddHandler( const wxChar
*handlerName
, wxObjectEventFunction address
, const wxClassInfo
* eventClassInfo
)
646 new wxHandlerInfo( m_firstHandler
, handlerName
, address
, eventClassInfo
) ;
649 // removes an existing runtime-property
650 void wxDynamicClassInfo::RemoveProperty( const wxChar
*propertyName
)
654 // removes an existing runtime-handler
655 void wxDynamicClassInfo::RemoveHandler( const wxChar
*handlerName
)
659 // ----------------------------------------------------------------------------
660 // wxGenericPropertyAccessor
661 // ----------------------------------------------------------------------------
663 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
668 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString
& propertyName
)
669 : wxPropertyAccessor( NULL
, NULL
, NULL
, NULL
)
671 m_data
= new wxGenericPropertyAccessorInternal
;
672 m_propertyName
= propertyName
;
673 m_getterName
= wxT("Get")+propertyName
;
674 m_setterName
= wxT("Set")+propertyName
;
677 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
681 void wxGenericPropertyAccessor::SetProperty(wxObject
*object
, const wxxVariant
&value
) const
683 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
684 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
685 dynobj
->SetProperty(m_propertyName
, value
) ;
688 void wxGenericPropertyAccessor::GetProperty(const wxObject
*object
, wxxVariant
& value
) const
690 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* >( object
) ;
691 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
692 value
= dynobj
->GetProperty( m_propertyName
) ;