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 // ----------------------------------------------------------------------------
108 template<> const wxTypeInfo
* wxGetTypeInfo( void * )
110 static wxBuiltInTypeInfo
s_typeInfo( wxT_VOID
) ;
114 template<> const wxTypeInfo
* wxGetTypeInfo( bool * )
116 static wxBuiltInTypeInfo
s_typeInfo( wxT_BOOL
) ;
120 template<> const wxTypeInfo
* wxGetTypeInfo( char * )
122 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
) ;
126 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned char * )
128 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
) ;
132 template<> const wxTypeInfo
* wxGetTypeInfo( int * )
134 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
) ;
138 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned int * )
140 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
) ;
144 template<> const wxTypeInfo
* wxGetTypeInfo( long * )
146 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
) ;
150 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned long * )
152 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
) ;
156 template<> const wxTypeInfo
* wxGetTypeInfo( float * )
158 static wxBuiltInTypeInfo
s_typeInfo( wxT_FLOAT
) ;
162 template<> const wxTypeInfo
* wxGetTypeInfo( double * )
164 static wxBuiltInTypeInfo
s_typeInfo( wxT_DOUBLE
) ;
168 template<> const wxTypeInfo
* wxGetTypeInfo( wxString
* )
170 static wxBuiltInTypeInfo
s_typeInfo( wxT_STRING
) ;
174 template<> const wxTypeInfo
* wxGetTypeInfo( wxWindowList
* )
176 static wxCollectionTypeInfo
s_typeInfo( (wxTypeInfo
*) wxGetTypeInfo( (wxWindow
**) NULL
) ) ;
180 // this are compiler induced specialization which are never used anywhere
182 WX_ILLEGAL_TYPE_SPECIALIZATION( char const * )
183 WX_ILLEGAL_TYPE_SPECIALIZATION( char * )
184 WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
185 WX_ILLEGAL_TYPE_SPECIALIZATION( int * )
186 WX_ILLEGAL_TYPE_SPECIALIZATION( bool * )
187 WX_ILLEGAL_TYPE_SPECIALIZATION( long * )
188 WX_ILLEGAL_TYPE_SPECIALIZATION( wxString
* )
190 // ----------------------------------------------------------------------------
192 // ----------------------------------------------------------------------------
194 // streamer specializations
195 // for all built-in types
199 template<> void wxStringReadValue(const wxString
&s
, bool &data
)
202 wxSscanf(s
, _T("%d"), &intdata
) ;
203 data
= bool(intdata
) ;
206 template<> void wxStringWriteValue(wxString
&s
, const bool &data
)
208 s
= wxString::Format("%d", data
) ;
213 template<> void wxStringReadValue(const wxString
&s
, char &data
)
216 wxSscanf(s
, _T("%d"), &intdata
) ;
217 data
= char(intdata
) ;
220 template<> void wxStringWriteValue(wxString
&s
, const char &data
)
222 s
= wxString::Format("%d", data
) ;
227 template<> void wxStringReadValue(const wxString
&s
, unsigned char &data
)
230 wxSscanf(s
, _T("%d"), &intdata
) ;
231 data
= (unsigned char)(intdata
) ;
234 template<> void wxStringWriteValue(wxString
&s
, const unsigned char &data
)
236 s
= wxString::Format("%d", data
) ;
241 template<> void wxStringReadValue(const wxString
&s
, int &data
)
243 wxSscanf(s
, _T("%d"), &data
) ;
246 template<> void wxStringWriteValue(wxString
&s
, const int &data
)
248 s
= wxString::Format("%d", data
) ;
253 template<> void wxStringReadValue(const wxString
&s
, unsigned int &data
)
255 wxSscanf(s
, _T("%d"), &data
) ;
258 template<> void wxStringWriteValue(wxString
&s
, const unsigned int &data
)
260 s
= wxString::Format("%d", data
) ;
265 template<> void wxStringReadValue(const wxString
&s
, long &data
)
267 wxSscanf(s
, _T("%ld"), &data
) ;
270 template<> void wxStringWriteValue(wxString
&s
, const long &data
)
272 s
= wxString::Format("%ld", data
) ;
277 template<> void wxStringReadValue(const wxString
&s
, unsigned long &data
)
279 wxSscanf(s
, _T("%ld"), &data
) ;
282 template<> void wxStringWriteValue(wxString
&s
, const unsigned long &data
)
284 s
= wxString::Format("%ld", data
) ;
289 template<> void wxStringReadValue(const wxString
&s
, float &data
)
291 wxSscanf(s
, _T("%f"), &data
) ;
294 template<> void wxStringWriteValue(wxString
&s
, const float &data
)
296 s
= wxString::Format("%f", data
) ;
301 template<> void wxStringReadValue(const wxString
&s
, double &data
)
303 wxSscanf(s
, _T("%lf"), &data
) ;
306 template<> void wxStringWriteValue(wxString
&s
, const double &data
)
308 s
= wxString::Format("%lf", data
) ;
313 template<> void wxStringReadValue(const wxString
&s
, wxString
&data
)
318 template<> void wxStringWriteValue(wxString
&s
, const wxString
&data
)
324 Custom Data Streaming / Type Infos
325 we will have to add this for all wx non object types, but it is also an example
326 for custom data structures
331 template<> void wxStringReadValue(const wxString
&s
, wxPoint
&data
)
333 wxSscanf(s
, _T("%d,%d"), &data
.x
, &data
.y
) ;
336 template<> void wxStringWriteValue(wxString
&s
, const wxPoint
&data
)
338 s
= wxString::Format("%d,%d", data
.x
, data
.y
) ;
341 template<> void wxStringReadValue(const wxString
& , wxPoint
* & )
346 template<> void wxStringWriteValue(wxString
& , wxPoint
* const & )
351 WX_CUSTOM_TYPE_INFO(wxPoint
)
353 template<> void wxStringReadValue(const wxString
&s
, wxSize
&data
)
355 wxSscanf(s
, _T("%d,%d"), &data
.x
, &data
.y
) ;
358 template<> void wxStringWriteValue(wxString
&s
, const wxSize
&data
)
360 s
= wxString::Format("%d,%d", data
.x
, data
.y
) ;
363 template<> void wxStringReadValue(const wxString
& , wxSize
* & )
368 template<> void wxStringWriteValue(wxString
& , wxSize
* const & )
373 WX_CUSTOM_TYPE_INFO(wxSize
)
377 template<> void wxStringReadValue(const wxString &s , wxColour &data )
379 // copied from VS xrc
380 unsigned long tmp = 0;
382 if (s.Length() != 7 || s[0u] != wxT('#') ||
383 wxSscanf(s.c_str(), wxT("#%lX"), &tmp) != 1)
385 wxLogError(_("String To Colour : Incorrect colour specification : %s"),
391 data = wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) ,
392 (unsigned char) ((tmp & 0x00FF00) >> 8),
393 (unsigned char) ((tmp & 0x0000FF)));
397 template<> void wxStringWriteValue(wxString &s , const wxColour &data )
399 s = wxString::Format("#%2X%2X%2X", data.Red() , data.Green() , data.Blue() ) ;
402 WX_CUSTOM_TYPE_INFO(wxColour)
406 // removing header dependancy on string tokenizer
408 void wxSetStringToArray( const wxString
&s
, wxArrayString
&array
)
410 wxStringTokenizer
tokenizer(s
, wxT("| \t\n"), wxTOKEN_STRTOK
);
413 while (tokenizer
.HasMoreTokens())
415 array
.Add(tokenizer
.GetNextToken()) ;
419 // ----------------------------------------------------------------------------
421 // ----------------------------------------------------------------------------
423 const wxPropertyAccessor
*wxClassInfo::FindAccessor(const char *PropertyName
) const
425 const wxPropertyInfo
* info
= FindPropertyInfo( PropertyName
) ;
428 return info
->GetAccessor() ;
433 const wxPropertyInfo
*wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName
) const
435 const wxPropertyInfo
* info
= GetFirstProperty() ;
439 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
441 info
= info
->GetNext() ;
447 const wxPropertyInfo
*wxClassInfo::FindPropertyInfo (const char *PropertyName
) const
449 const wxPropertyInfo
* info
= FindPropertyInfoInThisClass( PropertyName
) ;
453 const wxClassInfo
** parents
= GetParents() ;
454 for ( int i
= 0 ; parents
[i
] ; ++ i
)
456 if ( ( info
= parents
[i
]->FindPropertyInfo( PropertyName
) ) != NULL
)
463 const wxHandlerInfo
*wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName
) const
465 const wxHandlerInfo
* info
= GetFirstHandler() ;
469 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
471 info
= info
->GetNext() ;
477 const wxHandlerInfo
*wxClassInfo::FindHandlerInfo (const char *PropertyName
) const
479 const wxHandlerInfo
* info
= FindHandlerInfoInThisClass( PropertyName
) ;
484 const wxClassInfo
** parents
= GetParents() ;
485 for ( int i
= 0 ; parents
[i
] ; ++ i
)
487 if ( ( info
= parents
[i
]->FindHandlerInfo( PropertyName
) ) != NULL
)
495 void wxClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
497 const wxPropertyAccessor
*accessor
;
499 accessor
= FindAccessor(propertyName
);
500 wxASSERT(accessor
->HasSetter());
501 accessor
->SetProperty( object
, value
) ;
504 wxxVariant
wxClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
506 const wxPropertyAccessor
*accessor
;
508 accessor
= FindAccessor(propertyName
);
509 wxASSERT(accessor
->HasGetter());
510 return accessor
->GetProperty(object
);
513 wxxVariantArray
wxClassInfo::GetPropertyCollection(wxObject
*object
, const wxChar
*propertyName
) const
515 const wxPropertyAccessor
*accessor
;
517 accessor
= FindAccessor(propertyName
);
518 wxASSERT(accessor
->HasGetter());
519 return accessor
->GetPropertyCollection(object
);
522 void wxClassInfo::AddToPropertyCollection(wxObject
*object
, const wxChar
*propertyName
, const wxxVariant
& value
) const
524 const wxPropertyAccessor
*accessor
;
526 accessor
= FindAccessor(propertyName
);
527 wxASSERT(accessor
->HasAdder());
528 accessor
->AddToPropertyCollection( object
, value
) ;
535 wxObject
* wxxVariant::GetAsObject()
537 const wxClassTypeInfo
*ti
= dynamic_cast<const wxClassTypeInfo
*>( m_data
->GetTypeInfo() ) ;
539 return ti
->GetClassInfo()->VariantToInstance(*this) ;
544 // ----------------------------------------------------------------------------
545 // wxDynamicObject support
546 // ----------------------------------------------------------------------------
548 // Dynamic Objects are objects that have a real superclass instance and carry their
549 // own attributes in a hash map. Like this it is possible to create the objects and
550 // stream them, as if their class information was already available from compiled data
552 struct wxDynamicObject::wxDynamicObjectInternal
554 map
<string
,wxxVariant
> m_properties
;
557 // instantiates this object with an instance of its superclass
558 wxDynamicObject::wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo
*info
)
560 m_superClassInstance
= superClassInstance
;
562 m_data
= new wxDynamicObjectInternal
;
565 wxDynamicObject::~wxDynamicObject()
568 delete m_superClassInstance
;
571 void wxDynamicObject::SetProperty (const wxChar
*propertyName
, const wxxVariant
&value
)
573 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
574 m_data
->m_properties
[propertyName
] = value
;
577 wxxVariant
wxDynamicObject::GetProperty (const wxChar
*propertyName
) const
579 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
580 return m_data
->m_properties
[propertyName
] ;
583 // ----------------------------------------------------------------------------
585 // ----------------------------------------------------------------------------
587 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar
*unitName
, const wxChar
*className
, const wxClassInfo
* superClass
) :
588 wxClassInfo( unitName
, className
, new const wxClassInfo
*[2])
590 GetParents()[0] = superClass
;
591 GetParents()[1] = NULL
;
594 wxDynamicClassInfo::~wxDynamicClassInfo()
596 delete[] GetParents() ;
599 wxObject
*wxDynamicClassInfo::AllocateObject() const
601 wxObject
* parent
= GetParents()[0]->AllocateObject() ;
602 return new wxDynamicObject( parent
, this ) ;
605 void wxDynamicClassInfo::Create (wxObject
*object
, int paramCount
, wxxVariant
*params
) const
607 wxDynamicObject
*dynobj
= dynamic_cast< wxDynamicObject
*>( object
) ;
608 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ;
609 GetParents()[0]->Create( dynobj
->GetSuperClassInstance() , paramCount
, params
) ;
612 // get number of parameters for constructor
613 int wxDynamicClassInfo::GetCreateParamCount() const
615 return GetParents()[0]->GetCreateParamCount() ;
618 // get i-th constructor parameter
619 const wxChar
* wxDynamicClassInfo::GetCreateParamName(int i
) const
621 return GetParents()[0]->GetCreateParamName( i
) ;
624 void wxDynamicClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
626 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
627 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
628 if ( FindPropertyInfoInThisClass(propertyName
) )
629 dynobj
->SetProperty( propertyName
, value
) ;
631 GetParents()[0]->SetProperty( dynobj
->GetSuperClassInstance() , propertyName
, value
) ;
634 wxxVariant
wxDynamicClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
636 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
637 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
638 if ( FindPropertyInfoInThisClass(propertyName
) )
639 return dynobj
->GetProperty( propertyName
) ;
641 return GetParents()[0]->GetProperty( dynobj
->GetSuperClassInstance() , propertyName
) ;
644 void wxDynamicClassInfo::AddProperty( const wxChar
*propertyName
, const wxTypeInfo
* typeInfo
)
646 new wxPropertyInfo( m_firstProperty
, propertyName
, typeInfo
, new wxGenericPropertyAccessor( propertyName
) , wxxVariant() ) ;
649 void wxDynamicClassInfo::AddHandler( const wxChar
*handlerName
, wxObjectEventFunction address
, const wxClassInfo
* eventClassInfo
)
651 new wxHandlerInfo( m_firstHandler
, handlerName
, address
, eventClassInfo
) ;
654 // ----------------------------------------------------------------------------
655 // wxGenericPropertyAccessor
656 // ----------------------------------------------------------------------------
658 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
660 wxString m_propertyName
;
663 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxChar
* propertyName
)
665 m_data
= new wxGenericPropertyAccessorInternal
;
666 m_data
->m_propertyName
= propertyName
;
669 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
673 void wxGenericPropertyAccessor::SetProperty(wxObject
*object
, const wxxVariant
&value
) const
675 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
676 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
677 dynobj
->SetProperty(m_data
->m_propertyName
, value
) ;
680 wxxVariant
wxGenericPropertyAccessor::GetProperty(const wxObject
*object
) const
682 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* >( object
) ;
683 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
684 return dynobj
->GetProperty( m_data
->m_propertyName
) ;
687 wxxVariant
wxGenericPropertyAccessor::ReadValue( const wxString
&value
) const
689 return wxxVariant(value
) ;
692 void wxGenericPropertyAccessor::WriteValue( wxString
& value
, const wxObject
*object
) const
694 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* >( object
) ;
695 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
696 wxxVariant val
= dynobj
->GetProperty( m_data
->m_propertyName
) ;
697 value
= val
.GetAsString() ;