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"
31 #include "wx/notebook.h"
33 #include "wx/datetime.h"
36 #if wxUSE_EXTENDED_RTTI
38 #include "wx/beforestd.h"
41 #include "wx/afterstd.h"
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 wxEnumData::wxEnumData( wxEnumMemberData
* data
)
52 for ( m_count
= 0; m_members
[m_count
].m_name
; m_count
++)
56 bool wxEnumData::HasEnumMemberValue(const wxChar
*name
, int *value
)
59 for (i
= 0; m_members
[i
].m_name
; i
++ )
61 if (!strcmp(name
, m_members
[i
].m_name
))
64 *value
= m_members
[i
].m_value
;
71 int wxEnumData::GetEnumMemberValue(const wxChar
*name
)
74 for (i
= 0; m_members
[i
].m_name
; i
++ )
76 if (!strcmp(name
, m_members
[i
].m_name
))
78 return m_members
[i
].m_value
;
84 const wxChar
*wxEnumData::GetEnumMemberName(int value
)
87 for (i
= 0; m_members
[i
].m_name
; i
++)
88 if (value
== m_members
[i
].m_value
)
89 return m_members
[i
].m_name
;
94 int wxEnumData::GetEnumMemberValueByIndex( int idx
)
96 // we should cache the count in order to avoid out-of-bounds errors
97 return m_members
[idx
].m_value
;
100 const char * wxEnumData::GetEnumMemberNameByIndex( int idx
)
102 // we should cache the count in order to avoid out-of-bounds errors
103 return m_members
[idx
].m_name
;
106 // ----------------------------------------------------------------------------
108 // ----------------------------------------------------------------------------
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
113 // streamer specializations
114 // for all built-in types
118 template<> void wxStringReadValue(const wxString
&s
, bool &data
)
121 wxSscanf(s
, _T("%d"), &intdata
) ;
122 data
= bool(intdata
) ;
125 template<> void wxStringWriteValue(wxString
&s
, const bool &data
)
127 s
= wxString::Format("%d", data
) ;
132 template<> void wxStringReadValue(const wxString
&s
, char &data
)
135 wxSscanf(s
, _T("%d"), &intdata
) ;
136 data
= char(intdata
) ;
139 template<> void wxStringWriteValue(wxString
&s
, const char &data
)
141 s
= wxString::Format("%d", data
) ;
146 template<> void wxStringReadValue(const wxString
&s
, unsigned char &data
)
149 wxSscanf(s
, _T("%d"), &intdata
) ;
150 data
= (unsigned char)(intdata
) ;
153 template<> void wxStringWriteValue(wxString
&s
, const unsigned char &data
)
155 s
= wxString::Format("%d", data
) ;
160 template<> void wxStringReadValue(const wxString
&s
, int &data
)
162 wxSscanf(s
, _T("%d"), &data
) ;
165 template<> void wxStringWriteValue(wxString
&s
, const int &data
)
167 s
= wxString::Format("%d", data
) ;
172 template<> void wxStringReadValue(const wxString
&s
, unsigned int &data
)
174 wxSscanf(s
, _T("%d"), &data
) ;
177 template<> void wxStringWriteValue(wxString
&s
, const unsigned int &data
)
179 s
= wxString::Format("%d", data
) ;
184 template<> void wxStringReadValue(const wxString
&s
, long &data
)
186 wxSscanf(s
, _T("%ld"), &data
) ;
189 template<> void wxStringWriteValue(wxString
&s
, const long &data
)
191 s
= wxString::Format("%ld", data
) ;
196 template<> void wxStringReadValue(const wxString
&s
, unsigned long &data
)
198 wxSscanf(s
, _T("%ld"), &data
) ;
201 template<> void wxStringWriteValue(wxString
&s
, const unsigned long &data
)
203 s
= wxString::Format("%ld", data
) ;
208 template<> void wxStringReadValue(const wxString
&s
, float &data
)
210 wxSscanf(s
, _T("%f"), &data
) ;
213 template<> void wxStringWriteValue(wxString
&s
, const float &data
)
215 s
= wxString::Format("%f", data
) ;
220 template<> void wxStringReadValue(const wxString
&s
, double &data
)
222 wxSscanf(s
, _T("%lf"), &data
) ;
225 template<> void wxStringWriteValue(wxString
&s
, const double &data
)
227 s
= wxString::Format("%lf", data
) ;
232 template<> void wxStringReadValue(const wxString
&s
, wxString
&data
)
237 template<> void wxStringWriteValue(wxString
&s
, const wxString
&data
)
243 Custom Data Streaming / Type Infos
244 we will have to add this for all wx non object types, but it is also an example
245 for custom data structures
250 template<> void wxStringReadValue(const wxString
&s
, wxPoint
&data
)
252 wxSscanf(s
, _T("%d,%d"), &data
.x
, &data
.y
) ;
255 template<> void wxStringWriteValue(wxString
&s
, const wxPoint
&data
)
257 s
= wxString::Format("%d,%d", data
.x
, data
.y
) ;
260 template<> void wxStringReadValue(const wxString
& , wxPoint
* & )
265 template<> void wxStringWriteValue(wxString
& , wxPoint
* const & )
270 WX_CUSTOM_TYPE_INFO(wxPoint
)
272 template<> void wxStringReadValue(const wxString
&s
, wxSize
&data
)
274 wxSscanf(s
, _T("%d,%d"), &data
.x
, &data
.y
) ;
277 template<> void wxStringWriteValue(wxString
&s
, const wxSize
&data
)
279 s
= wxString::Format("%d,%d", data
.x
, data
.y
) ;
282 template<> void wxStringReadValue(const wxString
& , wxSize
* & )
287 template<> void wxStringWriteValue(wxString
& , wxSize
* const & )
292 WX_CUSTOM_TYPE_INFO(wxSize
)
294 template<> void wxStringReadValue(const wxString
&s
, wxDateTime
&data
)
296 data
.ParseFormat(s
,wxT("%Y-%m-%d %H:%M:%S")) ;
299 template<> void wxStringWriteValue(wxString
&s
, const wxDateTime
&data
)
301 s
= data
.Format(wxT("%Y-%m-%d %H:%M:%S")) ;
304 WX_CUSTOM_TYPE_INFO(wxDateTime
)
310 template<> const wxTypeInfo
* wxGetTypeInfo( void * )
312 static wxBuiltInTypeInfo
s_typeInfo( wxT_VOID
) ;
316 template<> const wxTypeInfo
* wxGetTypeInfo( bool * )
318 static wxBuiltInTypeInfo
s_typeInfo( wxT_BOOL
, &wxToStringConverter
<bool> , &wxFromStringConverter
<bool>) ;
322 template<> const wxTypeInfo
* wxGetTypeInfo( char * )
324 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
, &wxToStringConverter
<char> , &wxFromStringConverter
<char>) ;
328 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned char * )
330 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
, &wxToStringConverter
< unsigned char > , &wxFromStringConverter
<unsigned char>) ;
334 template<> const wxTypeInfo
* wxGetTypeInfo( int * )
336 static wxBuiltInTypeInfo
s_typeInfo( wxT_CHAR
, &wxToStringConverter
<int> , &wxFromStringConverter
<int>) ;
340 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned int * )
342 static wxBuiltInTypeInfo
s_typeInfo( wxT_UCHAR
, &wxToStringConverter
<unsigned int> , &wxFromStringConverter
<unsigned int>) ;
346 template<> const wxTypeInfo
* wxGetTypeInfo( long * )
348 static wxBuiltInTypeInfo
s_typeInfo( wxT_LONG
, &wxToStringConverter
<long> , &wxFromStringConverter
<long>) ;
352 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned long * )
354 static wxBuiltInTypeInfo
s_typeInfo( wxT_ULONG
, &wxToStringConverter
<unsigned long> , &wxFromStringConverter
<unsigned long>) ;
358 template<> const wxTypeInfo
* wxGetTypeInfo( float * )
360 static wxBuiltInTypeInfo
s_typeInfo( wxT_FLOAT
, &wxToStringConverter
<float> , &wxFromStringConverter
<float>) ;
364 template<> const wxTypeInfo
* wxGetTypeInfo( double * )
366 static wxBuiltInTypeInfo
s_typeInfo( wxT_DOUBLE
, &wxToStringConverter
<double> , &wxFromStringConverter
<double>) ;
370 template<> const wxTypeInfo
* wxGetTypeInfo( wxString
* )
372 static wxBuiltInTypeInfo
s_typeInfo( wxT_STRING
, &wxToStringConverter
<wxString
> , &wxFromStringConverter
<wxString
>) ;
376 // this are compiler induced specialization which are never used anywhere
378 WX_ILLEGAL_TYPE_SPECIALIZATION( char const * )
379 WX_ILLEGAL_TYPE_SPECIALIZATION( char * )
380 WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
381 WX_ILLEGAL_TYPE_SPECIALIZATION( int * )
382 WX_ILLEGAL_TYPE_SPECIALIZATION( bool * )
383 WX_ILLEGAL_TYPE_SPECIALIZATION( long * )
384 WX_ILLEGAL_TYPE_SPECIALIZATION( wxString
* )
388 // make wxWindowList known
390 template<> const wxTypeInfo
* wxGetTypeInfo( wxArrayString
* )
392 static wxCollectionTypeInfo
s_typeInfo( (wxTypeInfo
*) wxGetTypeInfo( (wxString
*) NULL
) ) ;
396 template<> void wxCollectionToVariantArray( wxArrayString
const &theArray
, wxxVariantArray
&value
)
398 wxArrayCollectionToVariantArray( theArray
, value
) ;
405 template<> void wxStringReadValue(const wxString &s , wxColour &data )
407 // copied from VS xrc
408 unsigned long tmp = 0;
410 if (s.Length() != 7 || s[0u] != wxT('#') ||
411 wxSscanf(s.c_str(), wxT("#%lX"), &tmp) != 1)
413 wxLogError(_("String To Colour : Incorrect colour specification : %s"),
419 data = wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) ,
420 (unsigned char) ((tmp & 0x00FF00) >> 8),
421 (unsigned char) ((tmp & 0x0000FF)));
425 template<> void wxStringWriteValue(wxString &s , const wxColour &data )
427 s = wxString::Format("#%2X%2X%2X", data.Red() , data.Green() , data.Blue() ) ;
430 WX_CUSTOM_TYPE_INFO(wxColour)
434 // removing header dependancy on string tokenizer
436 void wxSetStringToArray( const wxString
&s
, wxArrayString
&array
)
438 wxStringTokenizer
tokenizer(s
, wxT("| \t\n"), wxTOKEN_STRTOK
);
441 while (tokenizer
.HasMoreTokens())
443 array
.Add(tokenizer
.GetNextToken()) ;
447 // ----------------------------------------------------------------------------
449 // ----------------------------------------------------------------------------
451 const wxPropertyAccessor
*wxClassInfo::FindAccessor(const char *PropertyName
) const
453 const wxPropertyInfo
* info
= FindPropertyInfo( PropertyName
) ;
456 return info
->GetAccessor() ;
461 const wxPropertyInfo
*wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName
) const
463 const wxPropertyInfo
* info
= GetFirstProperty() ;
467 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
469 info
= info
->GetNext() ;
475 const wxPropertyInfo
*wxClassInfo::FindPropertyInfo (const char *PropertyName
) const
477 const wxPropertyInfo
* info
= FindPropertyInfoInThisClass( PropertyName
) ;
481 const wxClassInfo
** parents
= GetParents() ;
482 for ( int i
= 0 ; parents
[i
] ; ++ i
)
484 if ( ( info
= parents
[i
]->FindPropertyInfo( PropertyName
) ) != NULL
)
491 const wxHandlerInfo
*wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName
) const
493 const wxHandlerInfo
* info
= GetFirstHandler() ;
497 if ( strcmp( info
->GetName() , PropertyName
) == 0 )
499 info
= info
->GetNext() ;
505 const wxHandlerInfo
*wxClassInfo::FindHandlerInfo (const char *PropertyName
) const
507 const wxHandlerInfo
* info
= FindHandlerInfoInThisClass( PropertyName
) ;
512 const wxClassInfo
** parents
= GetParents() ;
513 for ( int i
= 0 ; parents
[i
] ; ++ i
)
515 if ( ( info
= parents
[i
]->FindHandlerInfo( PropertyName
) ) != NULL
)
523 void wxClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
525 const wxPropertyAccessor
*accessor
;
527 accessor
= FindAccessor(propertyName
);
528 wxASSERT(accessor
->HasSetter());
529 accessor
->SetProperty( object
, value
) ;
532 wxxVariant
wxClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
534 const wxPropertyAccessor
*accessor
;
536 accessor
= FindAccessor(propertyName
);
537 wxASSERT(accessor
->HasGetter());
539 accessor
->GetProperty(object
,result
);
543 wxxVariantArray
wxClassInfo::GetPropertyCollection(wxObject
*object
, const wxChar
*propertyName
) const
545 const wxPropertyAccessor
*accessor
;
547 accessor
= FindAccessor(propertyName
);
548 wxASSERT(accessor
->HasGetter());
549 wxxVariantArray result
;
550 accessor
->GetPropertyCollection(object
,result
);
554 void wxClassInfo::AddToPropertyCollection(wxObject
*object
, const wxChar
*propertyName
, const wxxVariant
& value
) const
556 const wxPropertyAccessor
*accessor
;
558 accessor
= FindAccessor(propertyName
);
559 wxASSERT(accessor
->HasAdder());
560 accessor
->AddToPropertyCollection( object
, value
) ;
567 wxObject
* wxxVariant::GetAsObject()
569 const wxClassTypeInfo
*ti
= dynamic_cast<const wxClassTypeInfo
*>( m_data
->GetTypeInfo() ) ;
571 return ti
->GetClassInfo()->VariantToInstance(*this) ;
576 // ----------------------------------------------------------------------------
577 // wxDynamicObject support
578 // ----------------------------------------------------------------------------
580 // Dynamic Objects are objects that have a real superclass instance and carry their
581 // own attributes in a hash map. Like this it is possible to create the objects and
582 // stream them, as if their class information was already available from compiled data
584 struct wxDynamicObject::wxDynamicObjectInternal
586 map
<string
,wxxVariant
> m_properties
;
589 // instantiates this object with an instance of its superclass
590 wxDynamicObject::wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo
*info
)
592 m_superClassInstance
= superClassInstance
;
594 m_data
= new wxDynamicObjectInternal
;
597 wxDynamicObject::~wxDynamicObject()
600 delete m_superClassInstance
;
603 void wxDynamicObject::SetProperty (const wxChar
*propertyName
, const wxxVariant
&value
)
605 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
606 m_data
->m_properties
[propertyName
] = value
;
609 wxxVariant
wxDynamicObject::GetProperty (const wxChar
*propertyName
) const
611 wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
612 return m_data
->m_properties
[propertyName
] ;
615 // ----------------------------------------------------------------------------
617 // ----------------------------------------------------------------------------
619 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar
*unitName
, const wxChar
*className
, const wxClassInfo
* superClass
) :
620 wxClassInfo( unitName
, className
, new const wxClassInfo
*[2])
622 GetParents()[0] = superClass
;
623 GetParents()[1] = NULL
;
626 wxDynamicClassInfo::~wxDynamicClassInfo()
628 delete[] GetParents() ;
631 wxObject
*wxDynamicClassInfo::AllocateObject() const
633 wxObject
* parent
= GetParents()[0]->AllocateObject() ;
634 return new wxDynamicObject( parent
, this ) ;
637 void wxDynamicClassInfo::Create (wxObject
*object
, int paramCount
, wxxVariant
*params
) const
639 wxDynamicObject
*dynobj
= dynamic_cast< wxDynamicObject
*>( object
) ;
640 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ;
641 GetParents()[0]->Create( dynobj
->GetSuperClassInstance() , paramCount
, params
) ;
644 // get number of parameters for constructor
645 int wxDynamicClassInfo::GetCreateParamCount() const
647 return GetParents()[0]->GetCreateParamCount() ;
650 // get i-th constructor parameter
651 const wxChar
* wxDynamicClassInfo::GetCreateParamName(int i
) const
653 return GetParents()[0]->GetCreateParamName( i
) ;
656 void wxDynamicClassInfo::SetProperty(wxObject
*object
, const char *propertyName
, const wxxVariant
&value
) const
658 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
659 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
660 if ( FindPropertyInfoInThisClass(propertyName
) )
661 dynobj
->SetProperty( propertyName
, value
) ;
663 GetParents()[0]->SetProperty( dynobj
->GetSuperClassInstance() , propertyName
, value
) ;
666 wxxVariant
wxDynamicClassInfo::GetProperty(wxObject
*object
, const char *propertyName
) const
668 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
669 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
670 if ( FindPropertyInfoInThisClass(propertyName
) )
671 return dynobj
->GetProperty( propertyName
) ;
673 return GetParents()[0]->GetProperty( dynobj
->GetSuperClassInstance() , propertyName
) ;
676 void wxDynamicClassInfo::AddProperty( const wxChar
*propertyName
, const wxTypeInfo
* typeInfo
)
678 new wxPropertyInfo( m_firstProperty
, propertyName
, typeInfo
, new wxGenericPropertyAccessor( propertyName
) , wxxVariant() ) ;
681 void wxDynamicClassInfo::AddHandler( const wxChar
*handlerName
, wxObjectEventFunction address
, const wxClassInfo
* eventClassInfo
)
683 new wxHandlerInfo( m_firstHandler
, handlerName
, address
, eventClassInfo
) ;
686 // ----------------------------------------------------------------------------
687 // wxGenericPropertyAccessor
688 // ----------------------------------------------------------------------------
690 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
695 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString
& propertyName
)
696 : wxPropertyAccessor( NULL
, NULL
, NULL
, NULL
)
698 m_data
= new wxGenericPropertyAccessorInternal
;
699 m_propertyName
= propertyName
;
700 m_getterName
= wxT("Get")+propertyName
;
701 m_setterName
= wxT("Set")+propertyName
;
704 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
708 void wxGenericPropertyAccessor::SetProperty(wxObject
*object
, const wxxVariant
&value
) const
710 wxDynamicObject
* dynobj
= dynamic_cast< wxDynamicObject
* >( object
) ;
711 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
712 dynobj
->SetProperty(m_propertyName
, value
) ;
715 void wxGenericPropertyAccessor::GetProperty(const wxObject
*object
, wxxVariant
& value
) const
717 const wxDynamicObject
* dynobj
= dynamic_cast< const wxDynamicObject
* >( object
) ;
718 wxASSERT_MSG( dynobj
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
719 value
= dynobj
->GetProperty( m_propertyName
) ;