1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/xti.cpp
3 // Purpose:     runtime metadata information (extended class info)
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     27/07/03
7 // Copyright:   (c) 1997 Julian Smart
8 //              (c) 2003 Stefan Csomor
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14 
15 #ifdef __BORLANDC__
16     #pragma hdrstop
17 #endif
18 
19 #if wxUSE_EXTENDED_RTTI
20 
21 #ifndef WX_PRECOMP
22     #include "wx/object.h"
23     #include "wx/list.h"
24     #include "wx/hash.h"
25 #endif
26 
27 #include "wx/xti.h"
28 #include "wx/xml/xml.h"
29 #include "wx/tokenzr.h"
30 #include "wx/range.h"
31 
32 #include <string.h>
33 
34 #include "wx/beforestd.h"
35 #include <map>
36 #include <string>
37 #include <list>
38 #include "wx/afterstd.h"
39 
40 using namespace std;
41 
42 // ----------------------------------------------------------------------------
43 // wxEnumData
44 // ----------------------------------------------------------------------------
45 
wxEnumData(wxEnumMemberData * data)46 wxEnumData::wxEnumData( wxEnumMemberData* data )
47 {
48     m_members = data;
49     for ( m_count = 0; m_members[m_count].m_name; m_count++)
50     {};
51 }
52 
HasEnumMemberValue(const wxChar * name,int * value) const53 bool wxEnumData::HasEnumMemberValue(const wxChar *name, int *value) const
54 {
55     int i;
56     for (i = 0; m_members[i].m_name; i++ )
57     {
58         if (!wxStrcmp(name, m_members[i].m_name))
59         {
60             if ( value )
61                 *value = m_members[i].m_value;
62             return true;
63         }
64     }
65     return false;
66 }
67 
GetEnumMemberValue(const wxChar * name) const68 int wxEnumData::GetEnumMemberValue(const wxChar *name) const
69 {
70     int i;
71     for (i = 0; m_members[i].m_name; i++ )
72     {
73         if (!wxStrcmp(name, m_members[i].m_name))
74         {
75             return m_members[i].m_value;
76         }
77     }
78     return 0;
79 }
80 
GetEnumMemberName(int value) const81 const wxChar *wxEnumData::GetEnumMemberName(int value) const
82 {
83     int i;
84     for (i = 0; m_members[i].m_name; i++)
85         if (value == m_members[i].m_value)
86             return m_members[i].m_name;
87 
88     return wxEmptyString;
89 }
90 
GetEnumMemberValueByIndex(int idx) const91 int wxEnumData::GetEnumMemberValueByIndex( int idx ) const
92 {
93     // we should cache the count in order to avoid out-of-bounds errors
94     return m_members[idx].m_value;
95 }
96 
GetEnumMemberNameByIndex(int idx) const97 const wxChar * wxEnumData::GetEnumMemberNameByIndex( int idx ) const
98 {
99     // we should cache the count in order to avoid out-of-bounds errors
100     return m_members[idx].m_name;
101 }
102 
103 // ----------------------------------------------------------------------------
104 // Type Information
105 // ----------------------------------------------------------------------------
106 
107 // ----------------------------------------------------------------------------
108 // value streaming
109 // ----------------------------------------------------------------------------
110 
111 // streamer specializations
112 // for all built-in types
113 
114 // bool
115 
wxStringReadValue(const wxString & s,bool & data)116 template<> void wxStringReadValue(const wxString &s, bool &data )
117 {
118     int intdata;
119     wxSscanf(s, wxT("%d"), &intdata );
120     data = (bool)(intdata != 0);
121 }
122 
wxStringWriteValue(wxString & s,const bool & data)123 template<> void wxStringWriteValue(wxString &s, const bool &data )
124 {
125     s = wxString::Format(wxT("%d"), data );
126 }
127 
128 // char
129 
wxStringReadValue(const wxString & s,char & data)130 template<> void wxStringReadValue(const wxString &s, char &data )
131 {
132     int intdata;
133     wxSscanf(s, wxT("%d"), &intdata );
134     data = char(intdata);
135 }
136 
wxStringWriteValue(wxString & s,const char & data)137 template<> void wxStringWriteValue(wxString &s, const char &data )
138 {
139     s = wxString::Format(wxT("%d"), data );
140 }
141 
142 // unsigned char
143 
wxStringReadValue(const wxString & s,unsigned char & data)144 template<> void wxStringReadValue(const wxString &s, unsigned char &data )
145 {
146     int intdata;
147     wxSscanf(s, wxT("%d"), &intdata );
148     data = (unsigned char)(intdata);
149 }
150 
wxStringWriteValue(wxString & s,const unsigned char & data)151 template<> void wxStringWriteValue(wxString &s, const unsigned char &data )
152 {
153     s = wxString::Format(wxT("%d"), data );
154 }
155 
156 // int
157 
wxStringReadValue(const wxString & s,int & data)158 template<> void wxStringReadValue(const wxString &s, int &data )
159 {
160     wxSscanf(s, wxT("%d"), &data );
161 }
162 
wxStringWriteValue(wxString & s,const int & data)163 template<> void wxStringWriteValue(wxString &s, const int &data )
164 {
165     s = wxString::Format(wxT("%d"), data );
166 }
167 
168 // unsigned int
169 
wxStringReadValue(const wxString & s,unsigned int & data)170 template<> void wxStringReadValue(const wxString &s, unsigned int &data )
171 {
172     wxSscanf(s, wxT("%d"), &data );
173 }
174 
wxStringWriteValue(wxString & s,const unsigned int & data)175 template<> void wxStringWriteValue(wxString &s, const unsigned int &data )
176 {
177     s = wxString::Format(wxT("%d"), data );
178 }
179 
180 // long
181 
wxStringReadValue(const wxString & s,long & data)182 template<> void wxStringReadValue(const wxString &s, long &data )
183 {
184     wxSscanf(s, wxT("%ld"), &data );
185 }
186 
wxStringWriteValue(wxString & s,const long & data)187 template<> void wxStringWriteValue(wxString &s, const long &data )
188 {
189     s = wxString::Format(wxT("%ld"), data );
190 }
191 
192 // unsigned long
193 
wxStringReadValue(const wxString & s,unsigned long & data)194 template<> void wxStringReadValue(const wxString &s, unsigned long &data )
195 {
196     wxSscanf(s, wxT("%ld"), &data );
197 }
198 
wxStringWriteValue(wxString & s,const unsigned long & data)199 template<> void wxStringWriteValue(wxString &s, const unsigned long &data )
200 {
201     s = wxString::Format(wxT("%ld"), data );
202 }
203 
204 #ifdef wxLongLong_t
wxStringReadValue(const wxString & s,wxLongLong_t & data)205 template<> void wxStringReadValue(const wxString &s, wxLongLong_t &data )
206 {
207     wxSscanf(s, wxT("%lld"), &data );
208 }
209 
wxStringWriteValue(wxString & s,const wxLongLong_t & data)210 template<> void wxStringWriteValue(wxString &s, const wxLongLong_t &data )
211 {
212     s = wxString::Format(wxT("%lld"), data );
213 }
214 
wxStringReadValue(const wxString & s,wxULongLong_t & data)215 template<> void wxStringReadValue(const wxString &s, wxULongLong_t &data )
216 {
217     wxSscanf(s, wxT("%lld"), &data );
218 }
219 
wxStringWriteValue(wxString & s,const wxULongLong_t & data)220 template<> void wxStringWriteValue(wxString &s, const wxULongLong_t &data )
221 {
222     s = wxString::Format(wxT("%lld"), data );
223 }
224 #endif
225 // float
226 
wxStringReadValue(const wxString & s,float & data)227 template<> void wxStringReadValue(const wxString &s, float &data )
228 {
229     wxSscanf(s, wxT("%f"), &data );
230 }
231 
wxStringWriteValue(wxString & s,const float & data)232 template<> void wxStringWriteValue(wxString &s, const float &data )
233 {
234     s = wxString::Format(wxT("%f"), data );
235 }
236 
237 // double
238 
wxStringReadValue(const wxString & s,double & data)239 template<> void wxStringReadValue(const wxString &s, double &data )
240 {
241     wxSscanf(s, wxT("%lf"), &data );
242 }
243 
wxStringWriteValue(wxString & s,const double & data)244 template<> void wxStringWriteValue(wxString &s, const double &data )
245 {
246     s = wxString::Format(wxT("%lf"), data );
247 }
248 
249 // wxString
250 
wxStringReadValue(const wxString & s,wxString & data)251 template<> void wxStringReadValue(const wxString &s, wxString &data )
252 {
253     data = s;
254 }
255 
wxStringWriteValue(wxString & s,const wxString & data)256 template<> void wxStringWriteValue(wxString &s, const wxString &data )
257 {
258     s = data;
259 }
260 
261 
262 // built-ins
263 //
264 
265 #if wxUSE_FUNC_TEMPLATE_POINTER
266     #define wxBUILTIN_TYPE_INFO( element, type )                                    \
267         wxBuiltInTypeInfo                                                           \
268             s_typeInfo##type(element, &wxToStringConverter<type>,                   \
269                              &wxFromStringConverter<type>, typeid(type).name());
270 #else
271     #define wxBUILTIN_TYPE_INFO( element, type )                                    \
272         void _toString##element( const wxAny& data, wxString &result )         \
273             { wxToStringConverter<type, data, result); }                            \
274         void _fromString##element( const wxString& data, wxAny &result )       \
275             { wxFromStringConverter<type, data, result); }                          \
276         wxBuiltInTypeInfo s_typeInfo##type(element, &_toString##element,            \
277                                            &_fromString##element, typeid(type).name());
278 #endif
279 
280 typedef unsigned char unsigned_char;
281 typedef unsigned int unsigned_int;
282 typedef unsigned long unsigned_long;
283 
284 wxBuiltInTypeInfo s_typeInfovoid( wxT_VOID, NULL, NULL, typeid(void).name());
285 wxBUILTIN_TYPE_INFO( wxT_BOOL,  bool);
286 wxBUILTIN_TYPE_INFO( wxT_CHAR,  char);
287 wxBUILTIN_TYPE_INFO( wxT_UCHAR, unsigned_char);
288 wxBUILTIN_TYPE_INFO( wxT_INT, int);
289 wxBUILTIN_TYPE_INFO( wxT_UINT, unsigned_int);
290 wxBUILTIN_TYPE_INFO( wxT_LONG, long);
291 wxBUILTIN_TYPE_INFO( wxT_ULONG, unsigned_long);
292 wxBUILTIN_TYPE_INFO( wxT_FLOAT, float);
293 wxBUILTIN_TYPE_INFO( wxT_DOUBLE, double);
294 wxBUILTIN_TYPE_INFO( wxT_STRING, wxString);
295 
296 #ifdef wxLongLong_t
wxBUILTIN_TYPE_INFO(wxT_LONGLONG,wxLongLong_t)297 wxBUILTIN_TYPE_INFO(wxT_LONGLONG, wxLongLong_t)
298 wxBUILTIN_TYPE_INFO(wxT_ULONGLONG, wxULongLong_t)
299 #endif
300 
301 // this are compiler induced specialization which are never used anywhere
302 
303 wxILLEGAL_TYPE_SPECIALIZATION( char const * )
304 wxILLEGAL_TYPE_SPECIALIZATION( char * )
305 wxILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
306 wxILLEGAL_TYPE_SPECIALIZATION( int * )
307 wxILLEGAL_TYPE_SPECIALIZATION( bool * )
308 wxILLEGAL_TYPE_SPECIALIZATION( long * )
309 wxILLEGAL_TYPE_SPECIALIZATION( wxString * )
310 
311 // wxRange
312 
313 template<> void wxStringReadValue(const wxString &s , wxRange &data)
314 {
315     int minValue, maxValue;
316     wxSscanf(s, wxT("%d,%d"), &minValue , &maxValue);
317     data = wxRange(minValue, maxValue);
318 }
319 
wxStringWriteValue(wxString & s,const wxRange & data)320 template<> void wxStringWriteValue(wxString &s , const wxRange &data)
321 {
322     s = wxString::Format(wxT("%d,%d"), data.GetMin() , data.GetMax());
323 }
324 
325 wxCUSTOM_TYPE_INFO(wxRange, wxToStringConverter<wxRange> , wxFromStringConverter<wxRange>)
326 
327 // other types
328 
329 wxCOLLECTION_TYPE_INFO( wxString, wxArrayString );
330 
wxCollectionToVariantArray(wxArrayString const & theArray,wxAnyList & value)331 template<> void wxCollectionToVariantArray( wxArrayString const &theArray,
332                                             wxAnyList &value)
333 {
334     wxArrayCollectionToVariantArray( theArray, value );
335 }
336 
337 wxTypeInfoMap *wxTypeInfo::ms_typeTable = NULL;
338 
FindType(const wxString & typeName)339 wxTypeInfo *wxTypeInfo::FindType(const wxString& typeName)
340 {
341     wxTypeInfoMap::iterator iter = ms_typeTable->find(typeName);
342 
343     if (iter == ms_typeTable->end())
344         return NULL;
345 
346     return (wxTypeInfo *)iter->second;
347 }
348 
wxClassTypeInfo(wxTypeKind kind,wxClassInfo * classInfo,wxVariant2StringFnc to,wxString2VariantFnc from,const wxString & name)349 wxClassTypeInfo::wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo,
350                                   wxVariant2StringFnc to,
351                                   wxString2VariantFnc from,
352                                   const wxString &name) :
353     wxTypeInfo( kind, to, from, name)
354 {
355     wxASSERT_MSG( kind == wxT_OBJECT_PTR || kind == wxT_OBJECT,
356                   wxT("Illegal Kind for Enum Type")); m_classInfo = classInfo;
357 }
358 
wxEventSourceTypeInfo(int eventType,wxClassInfo * eventClass,wxVariant2StringFnc to,wxString2VariantFnc from)359 wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass,
360                                         wxVariant2StringFnc to,
361                                         wxString2VariantFnc from ) :
362     wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString )
363 {
364     m_eventClass = eventClass;
365     m_eventType = eventType;
366     m_lastEventType = -1;
367 }
368 
wxEventSourceTypeInfo(int eventType,int lastEventType,wxClassInfo * eventClass,wxVariant2StringFnc to,wxString2VariantFnc from)369 wxEventSourceTypeInfo::wxEventSourceTypeInfo( int eventType, int lastEventType,
370                                         wxClassInfo* eventClass,
371                                         wxVariant2StringFnc to,
372                                         wxString2VariantFnc from ) :
373     wxTypeInfo ( wxT_DELEGATE, to, from, wxEmptyString )
374 {
375     m_eventClass = eventClass;
376     m_eventType = eventType;
377     m_lastEventType = lastEventType;
378 }
379 
Register()380 void wxTypeInfo::Register()
381 {
382     if ( ms_typeTable == NULL )
383         ms_typeTable = new wxTypeInfoMap();
384 
385     if( !m_name.empty() )
386         (*ms_typeTable)[m_name] = this;
387 }
388 
Unregister()389 void wxTypeInfo::Unregister()
390 {
391     if( !m_name.empty() )
392         ms_typeTable->erase(m_name);
393 }
394 
395 // removing header dependency on string tokenizer
396 
wxSetStringToArray(const wxString & s,wxArrayString & array)397 void wxSetStringToArray( const wxString &s, wxArrayString &array )
398 {
399     wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK);
400     wxString flag;
401     array.Clear();
402     while (tokenizer.HasMoreTokens())
403     {
404         array.Add(tokenizer.GetNextToken());
405     }
406 }
407 
408 // ----------------------------------------------------------------------------
409 // wxPropertyInfo
410 // ----------------------------------------------------------------------------
411 
Insert(wxPropertyInfo * & iter)412 void wxPropertyInfo::Insert(wxPropertyInfo* &iter)
413 {
414     m_next = NULL;
415     if ( iter == NULL )
416         iter = this;
417     else
418     {
419         wxPropertyInfo* i = iter;
420         while( i->m_next )
421             i = i->m_next;
422 
423         i->m_next = this;
424     }
425 }
426 
Remove()427 void wxPropertyInfo::Remove()
428 {
429     if ( this == m_itsClass->m_firstProperty )
430     {
431         m_itsClass->m_firstProperty = m_next;
432     }
433     else
434     {
435         wxPropertyInfo *info = m_itsClass->m_firstProperty;
436         while (info)
437         {
438             if ( info->m_next == this )
439             {
440                 info->m_next = m_next;
441                 break;
442             }
443 
444             info = info->m_next;
445         }
446     }
447 
448 }
449 
450 // ----------------------------------------------------------------------------
451 // wxHandlerInfo
452 // ----------------------------------------------------------------------------
453 
Insert(wxHandlerInfo * & iter)454 void wxHandlerInfo::Insert(wxHandlerInfo* &iter)
455 {
456     m_next = NULL;
457     if ( iter == NULL )
458         iter = this;
459     else
460     {
461         wxHandlerInfo* i = iter;
462         while( i->m_next )
463             i = i->m_next;
464 
465         i->m_next = this;
466     }
467 }
468 
Remove()469 void wxHandlerInfo::Remove()
470 {
471     if ( this == m_itsClass->m_firstHandler )
472     {
473         m_itsClass->m_firstHandler = m_next;
474     }
475     else
476     {
477         wxHandlerInfo *info = m_itsClass->m_firstHandler;
478         while (info)
479         {
480             if ( info->m_next == this )
481             {
482                 info->m_next = m_next;
483                 break;
484             }
485 
486             info = info->m_next;
487         }
488     }
489 }
490 
491 
492 // ----------------------------------------------------------------------------
493 // wxClassInfo
494 // ----------------------------------------------------------------------------
495 
Create(wxObject * object,int ParamCount,wxAny * Params) const496 bool wxClassInfo::Create(wxObject *object, int ParamCount, wxAny *Params) const
497 {
498     if ( ParamCount != m_constructorPropertiesCount )
499     {
500         // FIXME: shouldn't we just return false and let the caller handle it?
501         wxLogError( _("Illegal Parameter Count for Create Method") );
502         return false;
503     }
504 
505     return m_constructor->Create( object, Params );
506 }
507 
ConstructObject(int ParamCount,wxAny * Params) const508 wxObject *wxClassInfo::ConstructObject(int ParamCount, wxAny *Params) const
509 {
510     if ( ParamCount != m_constructorPropertiesCount )
511     {
512         // FIXME: shouldn't we just return NULL and let the caller handle this case?
513         wxLogError( _("Illegal Parameter Count for ConstructObject Method") );
514         return NULL;
515     }
516 
517     wxObject *object = NULL;
518     if (!m_constructor->Create( object, Params ))
519         return NULL;
520     return object;
521 }
522 
IsKindOf(const wxClassInfo * info) const523 bool wxClassInfo::IsKindOf(const wxClassInfo *info) const
524 {
525     if ( info != 0 )
526     {
527         if ( info == this )
528             return true;
529 
530         for ( int i = 0; m_parents[i]; ++ i )
531         {
532             if ( m_parents[i]->IsKindOf( info ) )
533                 return true;
534         }
535     }
536     return false;
537 }
538 
FindAccessor(const wxChar * PropertyName) const539 const wxPropertyAccessor *wxClassInfo::FindAccessor(const wxChar *PropertyName) const
540 {
541     const wxPropertyInfo* info = FindPropertyInfo( PropertyName );
542 
543     if ( info )
544         return info->GetAccessor();
545 
546     return NULL;
547 }
548 
FindPropertyInfoInThisClass(const wxChar * PropertyName) const549 wxPropertyInfo *wxClassInfo::FindPropertyInfoInThisClass (const wxChar *PropertyName) const
550 {
551     wxPropertyInfo* info = GetFirstProperty();
552 
553     while( info )
554     {
555         if ( wxStrcmp( info->GetName(), PropertyName ) == 0 )
556             return info;
557         info = info->GetNext();
558     }
559 
560     return 0;
561 }
562 
FindPropertyInfo(const wxChar * PropertyName) const563 const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const wxChar *PropertyName) const
564 {
565     const wxPropertyInfo* info = FindPropertyInfoInThisClass( PropertyName );
566     if ( info )
567         return info;
568 
569     const wxClassInfo** parents = GetParents();
570     for ( int i = 0; parents[i]; ++ i )
571     {
572         if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL )
573             return info;
574     }
575 
576     return 0;
577 }
578 
FindHandlerInfoInThisClass(const wxChar * PropertyName) const579 wxHandlerInfo *wxClassInfo::FindHandlerInfoInThisClass (const wxChar *PropertyName) const
580 {
581     wxHandlerInfo* info = GetFirstHandler();
582 
583     while( info )
584     {
585         if ( wxStrcmp( info->GetName(), PropertyName ) == 0 )
586             return info;
587         info = info->GetNext();
588     }
589 
590     return 0;
591 }
592 
FindHandlerInfo(const wxChar * PropertyName) const593 const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const wxChar *PropertyName) const
594 {
595     const wxHandlerInfo* info = FindHandlerInfoInThisClass( PropertyName );
596 
597     if ( info )
598         return info;
599 
600     const wxClassInfo** parents = GetParents();
601     for ( int i = 0; parents[i]; ++ i )
602     {
603         if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL )
604             return info;
605     }
606 
607     return 0;
608 }
609 
GetStreamingCallback() const610 wxObjectStreamingCallback wxClassInfo::GetStreamingCallback() const
611 {
612     if ( m_streamingCallback )
613         return m_streamingCallback;
614 
615     wxObjectStreamingCallback retval = NULL;
616     const wxClassInfo** parents = GetParents();
617     for ( int i = 0; parents[i] && retval == NULL; ++ i )
618     {
619         retval = parents[i]->GetStreamingCallback();
620     }
621     return retval;
622 }
623 
BeforeWriteObject(const wxObject * obj,wxObjectWriter * streamer,wxObjectWriterCallback * writercallback,const wxStringToAnyHashMap & metadata) const624 bool wxClassInfo::BeforeWriteObject( const wxObject *obj, wxObjectWriter *streamer,
625                                      wxObjectWriterCallback *writercallback, const wxStringToAnyHashMap &metadata) const
626 {
627     wxObjectStreamingCallback sb = GetStreamingCallback();
628     if ( sb )
629         return (*sb)(obj, streamer, writercallback, metadata );
630 
631     return true;
632 }
633 
SetProperty(wxObject * object,const wxChar * propertyName,const wxAny & value) const634 void wxClassInfo::SetProperty(wxObject *object, const wxChar *propertyName,
635                               const wxAny &value) const
636 {
637     const wxPropertyAccessor *accessor;
638 
639     accessor = FindAccessor(propertyName);
640     wxASSERT(accessor->HasSetter());
641     accessor->SetProperty( object, value );
642 }
643 
GetProperty(wxObject * object,const wxChar * propertyName) const644 wxAny wxClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const
645 {
646     const wxPropertyAccessor *accessor;
647 
648     accessor = FindAccessor(propertyName);
649     wxASSERT(accessor->HasGetter());
650     wxAny result;
651     accessor->GetProperty(object,result);
652     return result;
653 }
654 
GetPropertyCollection(wxObject * object,const wxChar * propertyName) const655 wxAnyList wxClassInfo::GetPropertyCollection(wxObject *object,
656                                                    const wxChar *propertyName) const
657 {
658     const wxPropertyAccessor *accessor;
659 
660     accessor = FindAccessor(propertyName);
661     wxASSERT(accessor->HasGetter());
662     wxAnyList result;
663     accessor->GetPropertyCollection(object,result);
664     return result;
665 }
666 
AddToPropertyCollection(wxObject * object,const wxChar * propertyName,const wxAny & value) const667 void wxClassInfo::AddToPropertyCollection(wxObject *object, const wxChar *propertyName,
668                                           const wxAny& value) const
669 {
670     const wxPropertyAccessor *accessor;
671 
672     accessor = FindAccessor(propertyName);
673     wxASSERT(accessor->HasAdder());
674     accessor->AddToPropertyCollection( object, value );
675 }
676 
677 // void wxClassInfo::GetProperties( wxPropertyInfoMap &map ) const
678 // The map parameter (the name map that is) seems something special
679 // to MSVC and so we use a other name.
GetProperties(wxPropertyInfoMap & infomap) const680 void wxClassInfo::GetProperties( wxPropertyInfoMap &infomap ) const
681 {
682     const wxPropertyInfo *pi = GetFirstProperty();
683     while( pi )
684     {
685         if ( infomap.find( pi->GetName() ) == infomap.end() )
686             infomap[pi->GetName()] = (wxPropertyInfo*) pi;
687 
688         pi = pi->GetNext();
689     }
690 
691     const wxClassInfo** parents = GetParents();
692     for ( int i = 0; parents[i]; ++ i )
693     {
694         parents[i]->GetProperties( infomap );
695     }
696 }
697 
AnyToObjectPtr(const wxAny & data) const698 wxObject* wxClassInfo::AnyToObjectPtr( const wxAny &data) const
699 {
700     return m_variantOfPtrToObjectConverter(data);
701 }
702 
CallOnAny(const wxAny & data,wxObjectFunctor * functor) const703 void wxClassInfo::CallOnAny( const wxAny &data, wxObjectFunctor* functor ) const
704 {
705     if ( data.GetTypeInfo()->GetKind() == wxT_OBJECT )
706         return m_variantToObjectConverter(data, functor);
707     else
708         return (*functor)(m_variantOfPtrToObjectConverter(data));
709 }
710 
ObjectPtrToAny(wxObject * obj) const711 wxAny wxClassInfo::ObjectPtrToAny( wxObject* obj) const
712 {
713     return m_objectToVariantConverter(obj);
714 }
715 
NeedsDirectConstruction() const716 bool wxClassInfo::NeedsDirectConstruction() const
717 {
718     return wx_dynamic_cast(wxObjectAllocator*, m_constructor) != NULL;
719 }
720 
721 // ----------------------------------------------------------------------------
722 // wxDynamicObject support
723 // ----------------------------------------------------------------------------
724 
725 // Dynamic Objects are objects that have a real superclass instance and carry their
726 // own attributes in a hash map. Like this it is possible to create the objects and
727 // stream them, as if their class information was already available from compiled data
728 
729 struct wxDynamicObject::wxDynamicObjectInternal
730 {
wxDynamicObjectInternalwxDynamicObject::wxDynamicObjectInternal731     wxDynamicObjectInternal() {}
732 
733     wxStringToAnyHashMap m_properties;
734 };
735 
736 typedef list< wxDynamicObject* > wxDynamicObjectList;
737 
738 struct wxDynamicClassInfo::wxDynamicClassInfoInternal
739 {
740     wxDynamicObjectList m_dynamicObjects;
741 };
742 
743 // instantiates this object with an instance of its superclass
wxDynamicObject(wxObject * superClassInstance,const wxDynamicClassInfo * info)744 wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info)
745 {
746     m_superClassInstance = superClassInstance;
747     m_classInfo = info;
748     m_data = new wxDynamicObjectInternal;
749 }
750 
~wxDynamicObject()751 wxDynamicObject::~wxDynamicObject()
752 {
753     wx_dynamic_cast(const wxDynamicClassInfo*, m_classInfo)->
754         m_data->m_dynamicObjects.remove( this );
755     delete m_data;
756     delete m_superClassInstance;
757 }
758 
SetProperty(const wxChar * propertyName,const wxAny & value)759 void wxDynamicObject::SetProperty (const wxChar *propertyName, const wxAny &value)
760 {
761     wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),
762                  wxT("Accessing Unknown Property in a Dynamic Object") );
763     m_data->m_properties[propertyName] = value;
764 }
765 
GetProperty(const wxChar * propertyName) const766 wxAny wxDynamicObject::GetProperty (const wxChar *propertyName) const
767 {
768     wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),
769                  wxT("Accessing Unknown Property in a Dynamic Object") );
770     return m_data->m_properties[propertyName];
771 }
772 
RemoveProperty(const wxChar * propertyName)773 void wxDynamicObject::RemoveProperty( const wxChar *propertyName )
774 {
775     wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),
776                  wxT("Removing Unknown Property in a Dynamic Object") );
777     m_data->m_properties.erase( propertyName );
778 }
779 
RenameProperty(const wxChar * oldPropertyName,const wxChar * newPropertyName)780 void wxDynamicObject::RenameProperty( const wxChar *oldPropertyName,
781                                       const wxChar *newPropertyName )
782 {
783     wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(oldPropertyName),
784                  wxT("Renaming Unknown Property in a Dynamic Object") );
785 
786     wxAny value = m_data->m_properties[oldPropertyName];
787     m_data->m_properties.erase( oldPropertyName );
788     m_data->m_properties[newPropertyName] = value;
789 }
790 
791 
792 // ----------------------------------------------------------------------------
793 // wxDynamicClassInfo
794 // ----------------------------------------------------------------------------
795 
wxDynamicClassInfo(const wxChar * unitName,const wxChar * className,const wxClassInfo * superClass)796 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar *unitName,
797                                         const wxChar *className,
798                                         const wxClassInfo* superClass ) :
799     wxClassInfo( unitName, className, new const wxClassInfo*[2])
800 {
801     GetParents()[0] = superClass;
802     GetParents()[1] = NULL;
803     m_data = new wxDynamicClassInfoInternal;
804 }
805 
~wxDynamicClassInfo()806 wxDynamicClassInfo::~wxDynamicClassInfo()
807 {
808     delete[] GetParents();
809     delete m_data;
810 }
811 
AllocateObject() const812 wxObject *wxDynamicClassInfo::AllocateObject() const
813 {
814     wxObject* parent = GetParents()[0]->AllocateObject();
815     wxDynamicObject *obj = new wxDynamicObject( parent, this );
816     m_data->m_dynamicObjects.push_back( obj );
817     return obj;
818 }
819 
Create(wxObject * object,int paramCount,wxAny * params) const820 bool wxDynamicClassInfo::Create (wxObject *object, int paramCount, wxAny *params) const
821 {
822     wxDynamicObject *dynobj = wx_dynamic_cast( wxDynamicObject *,  object );
823     wxASSERT_MSG( dynobj,
824         wxT("cannot call wxDynamicClassInfo::Create on ")
825         wxT("an object other than wxDynamicObject") );
826 
827     return GetParents()[0]->Create( dynobj->GetSuperClassInstance(), paramCount, params );
828 }
829 
830 // get number of parameters for constructor
GetCreateParamCount() const831 int wxDynamicClassInfo::GetCreateParamCount() const
832 {
833     return GetParents()[0]->GetCreateParamCount();
834 }
835 
836 // get i-th constructor parameter
GetCreateParamName(int i) const837 const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const
838 {
839     return GetParents()[0]->GetCreateParamName( i );
840 }
841 
SetProperty(wxObject * object,const wxChar * propertyName,const wxAny & value) const842 void wxDynamicClassInfo::SetProperty(wxObject *object, const wxChar *propertyName, const wxAny &value) const
843 {
844     wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object);
845     wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
846     if ( FindPropertyInfoInThisClass(propertyName) )
847         dynobj->SetProperty( propertyName, value );
848     else
849         GetParents()[0]->SetProperty( dynobj->GetSuperClassInstance(), propertyName, value );
850 }
851 
GetProperty(wxObject * object,const wxChar * propertyName) const852 wxAny wxDynamicClassInfo::GetProperty(wxObject *object, const wxChar *propertyName) const
853 {
854     wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object);
855     wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
856     if ( FindPropertyInfoInThisClass(propertyName) )
857         return dynobj->GetProperty( propertyName );
858     else
859         return GetParents()[0]->GetProperty( dynobj->GetSuperClassInstance(), propertyName );
860 }
861 
AddProperty(const wxChar * propertyName,const wxTypeInfo * typeInfo)862 void wxDynamicClassInfo::AddProperty( const wxChar *propertyName, const wxTypeInfo* typeInfo )
863 {
864     EnsureInfosInited();
865     new wxPropertyInfo( m_firstProperty, this, propertyName, typeInfo->GetTypeName(), new wxGenericPropertyAccessor( propertyName ), wxAny() );
866 }
867 
AddHandler(const wxChar * handlerName,wxObjectEventFunction address,const wxClassInfo * eventClassInfo)868 void wxDynamicClassInfo::AddHandler( const wxChar *handlerName, wxObjectEventFunction address, const wxClassInfo* eventClassInfo )
869 {
870     EnsureInfosInited();
871     new wxHandlerInfo( m_firstHandler, this, handlerName, address, eventClassInfo );
872 }
873 
874 // removes an existing runtime-property
RemoveProperty(const wxChar * propertyName)875 void wxDynamicClassInfo::RemoveProperty( const wxChar *propertyName )
876 {
877     for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter )
878         (*iter)->RemoveProperty( propertyName );
879     delete FindPropertyInfoInThisClass(propertyName);
880 }
881 
882 // removes an existing runtime-handler
RemoveHandler(const wxChar * handlerName)883 void wxDynamicClassInfo::RemoveHandler( const wxChar *handlerName )
884 {
885     delete FindHandlerInfoInThisClass(handlerName);
886 }
887 
888 // renames an existing runtime-property
RenameProperty(const wxChar * oldPropertyName,const wxChar * newPropertyName)889 void wxDynamicClassInfo::RenameProperty( const wxChar *oldPropertyName, const wxChar *newPropertyName )
890 {
891     wxPropertyInfo* pi = FindPropertyInfoInThisClass(oldPropertyName);
892     wxASSERT_MSG( pi,wxT("not existing property") );
893     pi->m_name = newPropertyName;
894     wx_dynamic_cast(wxGenericPropertyAccessor*, pi->GetAccessor())->RenameProperty( oldPropertyName, newPropertyName );
895     for ( wxDynamicObjectList::iterator iter = m_data->m_dynamicObjects.begin(); iter != m_data->m_dynamicObjects.end(); ++iter )
896         (*iter)->RenameProperty( oldPropertyName, newPropertyName );
897 }
898 
899 // renames an existing runtime-handler
RenameHandler(const wxChar * oldHandlerName,const wxChar * newHandlerName)900 void wxDynamicClassInfo::RenameHandler( const wxChar *oldHandlerName, const wxChar *newHandlerName )
901 {
902     wxASSERT_MSG(FindHandlerInfoInThisClass(oldHandlerName),wxT("not existing handler") );
903     FindHandlerInfoInThisClass(oldHandlerName)->m_name = newHandlerName;
904 }
905 
906 // ----------------------------------------------------------------------------
907 // wxGenericPropertyAccessor
908 // ----------------------------------------------------------------------------
909 
910 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
911 {
912     char filler;
913 };
914 
wxGenericPropertyAccessor(const wxString & propertyName)915 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxString& propertyName )
916 : wxPropertyAccessor( NULL, NULL, NULL, NULL )
917 {
918     m_data = new wxGenericPropertyAccessorInternal;
919     m_propertyName = propertyName;
920     m_getterName = wxT("Get")+propertyName;
921     m_setterName = wxT("Set")+propertyName;
922 }
923 
~wxGenericPropertyAccessor()924 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
925 {
926     delete m_data;
927 }
928 
SetProperty(wxObject * object,const wxAny & value) const929 void wxGenericPropertyAccessor::SetProperty(wxObject *object, const wxAny &value) const
930 {
931     wxDynamicObject* dynobj = wx_dynamic_cast(wxDynamicObject*, object);
932     wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
933     dynobj->SetProperty(m_propertyName.c_str(), value );
934 }
935 
GetProperty(const wxObject * object,wxAny & value) const936 void wxGenericPropertyAccessor::GetProperty(const wxObject *object, wxAny& value) const
937 {
938     const wxDynamicObject* dynobj = wx_dynamic_cast( const wxDynamicObject * ,  object );
939     wxASSERT_MSG( dynobj, wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") );
940     value = dynobj->GetProperty( m_propertyName.c_str() );
941 }
942 
943 // ----------------------------------------------------------------------------
944 // wxGenericPropertyAccessor
945 // ----------------------------------------------------------------------------
946 
wxAnyGetAsString(const wxAny & data)947 wxString wxAnyGetAsString( const wxAny& data)
948 {
949     if ( data.IsNull() || data.GetTypeInfo()==NULL )
950         return wxEmptyString;
951 
952     wxString s;
953     data.GetTypeInfo()->ConvertToString(data,s);
954     return s;
955 }
956 
wxAnyGetAsObjectPtr(const wxAny & data)957 const wxObject* wxAnyGetAsObjectPtr( const wxAny& data)
958 {
959     if ( !data.IsNull() )
960     {
961         const wxClassTypeInfo* ti = wx_dynamic_cast(const wxClassTypeInfo*, data.GetTypeInfo());
962         if( ti )
963             return ti->GetClassInfo()->AnyToObjectPtr(data);
964     }
965     return NULL;
966 }
967 
~wxObjectFunctor()968 wxObjectFunctor::~wxObjectFunctor()
969 {};
970 
971 #endif // wxUSE_EXTENDED_RTTI
972