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" 
  32 #include "wx/datetime.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 
) 
 242         Custom Data Streaming / Type Infos 
 243         we will have to add this for all wx non object types, but it is also an example 
 244         for custom data structures 
 249 template<> void wxStringReadValue(const wxString 
&s 
, wxPoint 
&data 
) 
 251         wxSscanf(s
, _T("%d,%d"), &data
.x 
, &data
.y 
) ; 
 254 template<> void wxStringWriteValue(wxString 
&s 
, const wxPoint 
&data 
) 
 256         s 
= wxString::Format("%d,%d", data
.x 
, data
.y 
) ; 
 259 template<> void wxStringReadValue(const wxString 
& , wxPoint
* & ) 
 264 template<> void wxStringWriteValue(wxString 
& , wxPoint
* const & ) 
 269 WX_CUSTOM_TYPE_INFO(wxPoint
) 
 271 template<> void wxStringReadValue(const wxString 
&s 
, wxSize 
&data 
) 
 273         wxSscanf(s
, _T("%d,%d"), &data
.x 
, &data
.y 
) ; 
 276 template<> void wxStringWriteValue(wxString 
&s 
, const wxSize 
&data 
) 
 278         s 
= wxString::Format("%d,%d", data
.x 
, data
.y 
) ; 
 281 template<> void wxStringReadValue(const wxString 
& , wxSize
* & ) 
 286 template<> void wxStringWriteValue(wxString 
& , wxSize 
* const & ) 
 291 WX_CUSTOM_TYPE_INFO(wxSize
) 
 293 template<> void wxStringReadValue(const wxString 
&s 
, wxDateTime 
&data 
) 
 295     data
.ParseFormat(s
,wxT("%Y-%m-%d %H:%M:%S")) ; 
 298 template<> void wxStringWriteValue(wxString 
&s 
, const wxDateTime 
&data 
) 
 300     s 
= data
.Format(wxT("%Y-%m-%d %H:%M:%S")) ; 
 303 WX_CUSTOM_TYPE_INFO(wxDateTime
) 
 309 template<> const wxTypeInfo
* wxGetTypeInfo( void * ) 
 311         static wxBuiltInTypeInfo 
s_typeInfo( wxT_VOID 
) ; 
 315 template<> const wxTypeInfo
* wxGetTypeInfo( bool * ) 
 317         static wxBuiltInTypeInfo 
s_typeInfo( wxT_BOOL 
, &wxToStringConverter
<bool> , &wxFromStringConverter
<bool>) ; 
 321 template<> const wxTypeInfo
* wxGetTypeInfo( char * ) 
 323         static wxBuiltInTypeInfo 
s_typeInfo( wxT_CHAR 
, &wxToStringConverter
<char> , &wxFromStringConverter
<char>) ; 
 327 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned char * ) 
 329         static wxBuiltInTypeInfo 
s_typeInfo( wxT_UCHAR 
, &wxToStringConverter
< unsigned char > , &wxFromStringConverter
<unsigned char>) ; 
 333 template<> const wxTypeInfo
* wxGetTypeInfo( int * ) 
 335         static wxBuiltInTypeInfo 
s_typeInfo( wxT_CHAR 
, &wxToStringConverter
<int> , &wxFromStringConverter
<int>) ; 
 339 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned int * ) 
 341         static wxBuiltInTypeInfo 
s_typeInfo( wxT_UCHAR 
, &wxToStringConverter
<unsigned int> , &wxFromStringConverter
<unsigned int>) ; 
 345 template<> const wxTypeInfo
* wxGetTypeInfo( long * ) 
 347         static wxBuiltInTypeInfo 
s_typeInfo( wxT_LONG 
, &wxToStringConverter
<long> , &wxFromStringConverter
<long>) ; 
 351 template<> const wxTypeInfo
* wxGetTypeInfo( unsigned long * ) 
 353         static wxBuiltInTypeInfo 
s_typeInfo( wxT_ULONG 
, &wxToStringConverter
<unsigned long> , &wxFromStringConverter
<unsigned long>) ; 
 357 template<> const wxTypeInfo
* wxGetTypeInfo( float * ) 
 359         static wxBuiltInTypeInfo 
s_typeInfo( wxT_FLOAT 
, &wxToStringConverter
<float> , &wxFromStringConverter
<float>) ; 
 363 template<> const wxTypeInfo
* wxGetTypeInfo( double * ) 
 365         static wxBuiltInTypeInfo 
s_typeInfo( wxT_DOUBLE 
, &wxToStringConverter
<double> , &wxFromStringConverter
<double>) ; 
 369 template<> const wxTypeInfo
* wxGetTypeInfo( wxString 
* ) 
 371         static wxBuiltInTypeInfo 
s_typeInfo( wxT_STRING 
, &wxToStringConverter
<wxString
> , &wxFromStringConverter
<wxString
>) ; 
 375 // this are compiler induced specialization which are never used anywhere 
 377 WX_ILLEGAL_TYPE_SPECIALIZATION( char const * ) 
 378 WX_ILLEGAL_TYPE_SPECIALIZATION( char * ) 
 379 WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * ) 
 380 WX_ILLEGAL_TYPE_SPECIALIZATION( int * ) 
 381 WX_ILLEGAL_TYPE_SPECIALIZATION( bool * ) 
 382 WX_ILLEGAL_TYPE_SPECIALIZATION( long * ) 
 383 WX_ILLEGAL_TYPE_SPECIALIZATION( wxString 
* ) 
 387 // make wxWindowList known 
 389 template<> const wxTypeInfo
* wxGetTypeInfo( wxArrayString 
* ) 
 391     static wxCollectionTypeInfo 
s_typeInfo( (wxTypeInfo
*) wxGetTypeInfo( (wxString 
*) NULL
) ) ; 
 395 template<> void wxCollectionToVariantArray( wxArrayString 
const &theArray
, wxxVariantArray 
&value
) 
 397     wxArrayCollectionToVariantArray( theArray 
, value 
) ; 
 404 template<> void wxStringReadValue(const wxString &s , wxColour &data ) 
 406         // copied from VS xrc 
 407         unsigned long tmp = 0; 
 409     if (s.Length() != 7 || s[0u] != wxT('#') || 
 410         wxSscanf(s.c_str(), wxT("#%lX"), &tmp) != 1) 
 412                 wxLogError(_("String To Colour : Incorrect colour specification : %s"), 
 418                 data = wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) , 
 419                     (unsigned char) ((tmp & 0x00FF00) >> 8), 
 420                     (unsigned char) ((tmp & 0x0000FF))); 
 424 template<> void wxStringWriteValue(wxString &s , const wxColour &data ) 
 426         s = wxString::Format("#%2X%2X%2X", data.Red() , data.Green() , data.Blue() ) ; 
 429 WX_CUSTOM_TYPE_INFO(wxColour) 
 433 // removing header dependancy on string tokenizer 
 435 void wxSetStringToArray( const wxString 
&s 
, wxArrayString 
&array 
) 
 437     wxStringTokenizer 
tokenizer(s
, wxT("| \t\n"), wxTOKEN_STRTOK
); 
 440     while (tokenizer
.HasMoreTokens()) 
 442                 array
.Add(tokenizer
.GetNextToken()) ; 
 446 // ---------------------------------------------------------------------------- 
 448 // ---------------------------------------------------------------------------- 
 450 const wxPropertyAccessor 
*wxClassInfo::FindAccessor(const char *PropertyName
) const 
 452     const wxPropertyInfo
* info 
= FindPropertyInfo( PropertyName 
) ; 
 455                 return info
->GetAccessor() ; 
 460 const wxPropertyInfo 
*wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName
) const 
 462         const wxPropertyInfo
* info 
= GetFirstProperty() ; 
 466                 if ( strcmp( info
->GetName() , PropertyName 
) == 0 ) 
 468                 info 
= info
->GetNext() ; 
 474 const wxPropertyInfo 
*wxClassInfo::FindPropertyInfo (const char *PropertyName
) const 
 476         const wxPropertyInfo
* info 
= FindPropertyInfoInThisClass( PropertyName 
) ; 
 480         const wxClassInfo
** parents 
= GetParents() ; 
 481         for ( int i 
= 0 ; parents
[i
] ; ++ i 
) 
 483                 if ( ( info 
= parents
[i
]->FindPropertyInfo( PropertyName 
) ) != NULL 
) 
 490 const wxHandlerInfo 
*wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName
) const 
 492         const wxHandlerInfo
* info 
= GetFirstHandler() ; 
 496                 if ( strcmp( info
->GetName() , PropertyName 
) == 0 ) 
 498                 info 
= info
->GetNext() ; 
 504 const wxHandlerInfo 
*wxClassInfo::FindHandlerInfo (const char *PropertyName
) const 
 506         const wxHandlerInfo
* info 
= FindHandlerInfoInThisClass( PropertyName 
) ; 
 511         const wxClassInfo
** parents 
= GetParents() ; 
 512         for ( int i 
= 0 ; parents
[i
] ; ++ i 
) 
 514                 if ( ( info 
= parents
[i
]->FindHandlerInfo( PropertyName 
) ) != NULL 
) 
 522 void wxClassInfo::SetProperty(wxObject 
*object
, const char *propertyName
, const wxxVariant 
&value
) const 
 524     const wxPropertyAccessor 
*accessor
; 
 526     accessor 
= FindAccessor(propertyName
); 
 527     wxASSERT(accessor
->HasSetter()); 
 528         accessor
->SetProperty( object 
, value 
) ; 
 531 wxxVariant 
wxClassInfo::GetProperty(wxObject 
*object
, const char *propertyName
) const 
 533     const wxPropertyAccessor 
*accessor
; 
 535     accessor 
= FindAccessor(propertyName
); 
 536     wxASSERT(accessor
->HasGetter()); 
 538     accessor
->GetProperty(object
,result
); 
 542 wxxVariantArray 
wxClassInfo::GetPropertyCollection(wxObject 
*object
, const wxChar 
*propertyName
) const 
 544     const wxPropertyAccessor 
*accessor
; 
 546     accessor 
= FindAccessor(propertyName
); 
 547     wxASSERT(accessor
->HasGetter()); 
 548     wxxVariantArray result 
; 
 549     accessor
->GetPropertyCollection(object
,result
); 
 553 void wxClassInfo::AddToPropertyCollection(wxObject 
*object
, const wxChar 
*propertyName 
, const wxxVariant
& value
) const 
 555     const wxPropertyAccessor 
*accessor
; 
 557     accessor 
= FindAccessor(propertyName
); 
 558     wxASSERT(accessor
->HasAdder()); 
 559     accessor
->AddToPropertyCollection( object 
, value 
) ; 
 566 wxObject
* wxxVariant::GetAsObject() 
 568         const wxClassTypeInfo 
*ti 
= dynamic_cast<const wxClassTypeInfo
*>( m_data
->GetTypeInfo() ) ; 
 570                 return ti
->GetClassInfo()->VariantToInstance(*this) ; 
 575 // ---------------------------------------------------------------------------- 
 576 // wxDynamicObject support 
 577 // ---------------------------------------------------------------------------- 
 579 // Dynamic Objects are objects that have a real superclass instance and carry their 
 580 // own attributes in a hash map. Like this it is possible to create the objects and 
 581 // stream them, as if their class information was already available from compiled data 
 583 struct wxDynamicObject::wxDynamicObjectInternal
 
 585     map
<string
,wxxVariant
> m_properties 
; 
 588 // instantiates this object with an instance of its superclass 
 589 wxDynamicObject::wxDynamicObject(wxObject
* superClassInstance
, const wxDynamicClassInfo 
*info
) 
 591     m_superClassInstance 
= superClassInstance 
; 
 593     m_data 
= new wxDynamicObjectInternal 
; 
 596 wxDynamicObject::~wxDynamicObject() 
 599     delete m_superClassInstance 
; 
 602 void wxDynamicObject::SetProperty (const wxChar 
*propertyName
, const wxxVariant 
&value
) 
 604     wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ; 
 605     m_data
->m_properties
[propertyName
] = value 
; 
 608 wxxVariant 
wxDynamicObject::GetProperty (const wxChar 
*propertyName
) const 
 610    wxASSERT_MSG(m_classInfo
->FindPropertyInfoInThisClass(propertyName
),wxT("Accessing Unknown Property in a Dynamic Object") ) ; 
 611    return m_data
->m_properties
[propertyName
] ; 
 614 // ---------------------------------------------------------------------------- 
 616 // ---------------------------------------------------------------------------- 
 618 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar 
*unitName
, const wxChar 
*className 
, const wxClassInfo
* superClass 
) : 
 619     wxClassInfo( unitName
, className 
, new const wxClassInfo
*[2]) 
 621     GetParents()[0] = superClass 
; 
 622     GetParents()[1] = NULL 
; 
 625 wxDynamicClassInfo::~wxDynamicClassInfo() 
 627     delete[] GetParents() ; 
 630 wxObject 
*wxDynamicClassInfo::AllocateObject() const 
 632     wxObject
* parent 
= GetParents()[0]->AllocateObject() ; 
 633     return new wxDynamicObject( parent 
, this ) ; 
 636 void wxDynamicClassInfo::Create (wxObject 
*object
, int paramCount
, wxxVariant 
*params
) const 
 638     wxDynamicObject 
*dynobj 
= dynamic_cast< wxDynamicObject 
*>( object 
) ; 
 639     wxASSERT_MSG( dynobj 
, wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ; 
 640     GetParents()[0]->Create( dynobj
->GetSuperClassInstance() , paramCount 
, params 
) ; 
 643 // get number of parameters for constructor 
 644 int wxDynamicClassInfo::GetCreateParamCount() const 
 646     return GetParents()[0]->GetCreateParamCount() ; 
 649 // get i-th constructor parameter 
 650 const wxChar
* wxDynamicClassInfo::GetCreateParamName(int i
) const 
 652     return GetParents()[0]->GetCreateParamName( i 
) ; 
 655 void wxDynamicClassInfo::SetProperty(wxObject 
*object
, const char *propertyName
, const wxxVariant 
&value
) const 
 657     wxDynamicObject
* dynobj 
= dynamic_cast< wxDynamicObject 
* >( object 
) ; 
 658     wxASSERT_MSG( dynobj 
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ; 
 659     if ( FindPropertyInfoInThisClass(propertyName
) ) 
 660         dynobj
->SetProperty( propertyName 
, value 
) ; 
 662         GetParents()[0]->SetProperty( dynobj
->GetSuperClassInstance() , propertyName 
, value 
) ; 
 665 wxxVariant 
wxDynamicClassInfo::GetProperty(wxObject 
*object
, const char *propertyName
) const 
 667     wxDynamicObject
* dynobj 
= dynamic_cast< wxDynamicObject 
* >( object 
) ; 
 668     wxASSERT_MSG( dynobj 
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ; 
 669     if ( FindPropertyInfoInThisClass(propertyName
) ) 
 670         return dynobj
->GetProperty( propertyName 
) ; 
 672         return GetParents()[0]->GetProperty( dynobj
->GetSuperClassInstance() , propertyName 
) ; 
 675 void wxDynamicClassInfo::AddProperty( const wxChar 
*propertyName 
, const wxTypeInfo
* typeInfo 
) 
 677     new wxPropertyInfo( m_firstProperty 
, propertyName 
, typeInfo 
, new wxGenericPropertyAccessor( propertyName 
) , wxxVariant() ) ; 
 680 void wxDynamicClassInfo::AddHandler( const wxChar 
*handlerName 
, wxObjectEventFunction address 
, const wxClassInfo
* eventClassInfo 
) 
 682     new wxHandlerInfo( m_firstHandler 
, handlerName 
, address 
, eventClassInfo 
) ; 
 685 // ---------------------------------------------------------------------------- 
 686 // wxGenericPropertyAccessor 
 687 // ---------------------------------------------------------------------------- 
 689 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
 
 694 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString
& propertyName 
) 
 695 : wxPropertyAccessor( NULL 
, NULL 
, NULL 
, NULL 
) 
 697     m_data 
= new wxGenericPropertyAccessorInternal 
; 
 698     m_propertyName 
= propertyName 
; 
 699     m_getterName 
= wxT("Get")+propertyName 
; 
 700     m_setterName 
= wxT("Set")+propertyName 
; 
 703 wxGenericPropertyAccessor::~wxGenericPropertyAccessor() 
 707 void wxGenericPropertyAccessor::SetProperty(wxObject 
*object
, const wxxVariant 
&value
) const 
 709     wxDynamicObject
* dynobj 
= dynamic_cast< wxDynamicObject 
* >( object 
) ; 
 710     wxASSERT_MSG( dynobj 
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ; 
 711     dynobj
->SetProperty(m_propertyName 
, value 
) ; 
 714 void wxGenericPropertyAccessor::GetProperty(const wxObject 
*object
, wxxVariant
& value
) const 
 716     const wxDynamicObject
* dynobj 
= dynamic_cast< const wxDynamicObject 
* >( object 
) ; 
 717     wxASSERT_MSG( dynobj 
, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ; 
 718     value 
= dynobj
->GetProperty( m_propertyName 
) ;