added wxDynamicObject (kind of delegate, docs to come once this has calmed down)
[wxWidgets.git] / src / common / xti.cpp
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 // RCS-ID: $Id$
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2003 Stefan Csomor
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "xti.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/hash.h"
26 #include "wx/object.h"
27 #endif
28
29 #include "wx/xml/xml.h"
30 #include "wx/tokenzr.h"
31
32 #include <string.h>
33
34 #if wxUSE_EXTENDED_RTTI
35
36 #include <map>
37 #include <string>
38
39 using namespace std ;
40
41 // ----------------------------------------------------------------------------
42 // Enum Support
43 // ----------------------------------------------------------------------------
44
45 wxEnumData::wxEnumData( wxEnumMemberData* data )
46 {
47 m_members = data ;
48 for ( m_count = 0; m_members[m_count].m_name ; m_count++)
49 {} ;
50 }
51
52 bool wxEnumData::HasEnumMemberValue(const wxChar *name, int *value)
53 {
54 int i;
55 for (i = 0; m_members[i].m_name ; i++ )
56 {
57 if (!strcmp(name, m_members[i].m_name))
58 {
59 if ( value )
60 *value = m_members[i].m_value;
61 return true ;
62 }
63 }
64 return false ;
65 }
66
67 int wxEnumData::GetEnumMemberValue(const wxChar *name)
68 {
69 int i;
70 for (i = 0; m_members[i].m_name ; i++ )
71 {
72 if (!strcmp(name, m_members[i].m_name))
73 {
74 return m_members[i].m_value;
75 }
76 }
77 return 0 ;
78 }
79
80 const wxChar *wxEnumData::GetEnumMemberName(int value)
81 {
82 int i;
83 for (i = 0; m_members[i].m_name ; i++)
84 if (value == m_members[i].m_value)
85 return m_members[i].m_name;
86
87 return wxT("") ;
88 }
89
90 int wxEnumData::GetEnumMemberValueByIndex( int idx )
91 {
92 // we should cache the count in order to avoid out-of-bounds errors
93 return m_members[idx].m_value ;
94 }
95
96 const char * wxEnumData::GetEnumMemberNameByIndex( int idx )
97 {
98 // we should cache the count in order to avoid out-of-bounds errors
99 return m_members[idx].m_name ;
100 }
101
102 // ----------------------------------------------------------------------------
103 // Type Information
104 // ----------------------------------------------------------------------------
105
106 template<> const wxTypeInfo* wxGetTypeInfo( void * )
107 {
108 static wxBuiltInTypeInfo s_typeInfo( wxT_VOID ) ;
109 return &s_typeInfo ;
110 }
111
112 template<> const wxTypeInfo* wxGetTypeInfo( bool * )
113 {
114 static wxBuiltInTypeInfo s_typeInfo( wxT_BOOL ) ;
115 return &s_typeInfo ;
116 }
117
118 template<> const wxTypeInfo* wxGetTypeInfo( char * )
119 {
120 static wxBuiltInTypeInfo s_typeInfo( wxT_CHAR ) ;
121 return &s_typeInfo ;
122 }
123
124 template<> const wxTypeInfo* wxGetTypeInfo( unsigned char * )
125 {
126 static wxBuiltInTypeInfo s_typeInfo( wxT_UCHAR ) ;
127 return &s_typeInfo ;
128 }
129
130 template<> const wxTypeInfo* wxGetTypeInfo( int * )
131 {
132 static wxBuiltInTypeInfo s_typeInfo( wxT_CHAR ) ;
133 return &s_typeInfo ;
134 }
135
136 template<> const wxTypeInfo* wxGetTypeInfo( unsigned int * )
137 {
138 static wxBuiltInTypeInfo s_typeInfo( wxT_UCHAR ) ;
139 return &s_typeInfo ;
140 }
141
142 template<> const wxTypeInfo* wxGetTypeInfo( long * )
143 {
144 static wxBuiltInTypeInfo s_typeInfo( wxT_CHAR ) ;
145 return &s_typeInfo ;
146 }
147
148 template<> const wxTypeInfo* wxGetTypeInfo( unsigned long * )
149 {
150 static wxBuiltInTypeInfo s_typeInfo( wxT_UCHAR ) ;
151 return &s_typeInfo ;
152 }
153
154 template<> const wxTypeInfo* wxGetTypeInfo( float * )
155 {
156 static wxBuiltInTypeInfo s_typeInfo( wxT_FLOAT ) ;
157 return &s_typeInfo ;
158 }
159
160 template<> const wxTypeInfo* wxGetTypeInfo( double * )
161 {
162 static wxBuiltInTypeInfo s_typeInfo( wxT_DOUBLE ) ;
163 return &s_typeInfo ;
164 }
165
166 template<> const wxTypeInfo* wxGetTypeInfo( wxString * )
167 {
168 static wxBuiltInTypeInfo s_typeInfo( wxT_STRING ) ;
169 return &s_typeInfo ;
170 }
171
172 // this are compiler induced specialization which are never used anywhere
173
174 WX_ILLEGAL_TYPE_SPECIALIZATION( char const * )
175 WX_ILLEGAL_TYPE_SPECIALIZATION( char * )
176 WX_ILLEGAL_TYPE_SPECIALIZATION( unsigned char * )
177 WX_ILLEGAL_TYPE_SPECIALIZATION( int * )
178 WX_ILLEGAL_TYPE_SPECIALIZATION( bool * )
179 WX_ILLEGAL_TYPE_SPECIALIZATION( long * )
180 WX_ILLEGAL_TYPE_SPECIALIZATION( wxString * )
181
182 // ----------------------------------------------------------------------------
183 // value streaming
184 // ----------------------------------------------------------------------------
185
186 // streamer specializations
187 // for all built-in types
188
189 // bool
190
191 template<> void wxStringReadValue(const wxString &s , bool &data )
192 {
193 int intdata ;
194 wxSscanf(s, _T("%d"), &intdata ) ;
195 data = bool(intdata) ;
196 }
197
198 template<> void wxStringWriteValue(wxString &s , const bool &data )
199 {
200 s = wxString::Format("%d", data ) ;
201 }
202
203 // char
204
205 template<> void wxStringReadValue(const wxString &s , char &data )
206 {
207 int intdata ;
208 wxSscanf(s, _T("%d"), &intdata ) ;
209 data = char(intdata) ;
210 }
211
212 template<> void wxStringWriteValue(wxString &s , const char &data )
213 {
214 s = wxString::Format("%d", data ) ;
215 }
216
217 // unsigned char
218
219 template<> void wxStringReadValue(const wxString &s , unsigned char &data )
220 {
221 int intdata ;
222 wxSscanf(s, _T("%d"), &intdata ) ;
223 data = (unsigned char)(intdata) ;
224 }
225
226 template<> void wxStringWriteValue(wxString &s , const unsigned char &data )
227 {
228 s = wxString::Format("%d", data ) ;
229 }
230
231 // int
232
233 template<> void wxStringReadValue(const wxString &s , int &data )
234 {
235 wxSscanf(s, _T("%d"), &data ) ;
236 }
237
238 template<> void wxStringWriteValue(wxString &s , const int &data )
239 {
240 s = wxString::Format("%d", data ) ;
241 }
242
243 // unsigned int
244
245 template<> void wxStringReadValue(const wxString &s , unsigned int &data )
246 {
247 wxSscanf(s, _T("%d"), &data ) ;
248 }
249
250 template<> void wxStringWriteValue(wxString &s , const unsigned int &data )
251 {
252 s = wxString::Format("%d", data ) ;
253 }
254
255 // long
256
257 template<> void wxStringReadValue(const wxString &s , long &data )
258 {
259 wxSscanf(s, _T("%ld"), &data ) ;
260 }
261
262 template<> void wxStringWriteValue(wxString &s , const long &data )
263 {
264 s = wxString::Format("%ld", data ) ;
265 }
266
267 // unsigned long
268
269 template<> void wxStringReadValue(const wxString &s , unsigned long &data )
270 {
271 wxSscanf(s, _T("%ld"), &data ) ;
272 }
273
274 template<> void wxStringWriteValue(wxString &s , const unsigned long &data )
275 {
276 s = wxString::Format("%ld", data ) ;
277 }
278
279 // float
280
281 template<> void wxStringReadValue(const wxString &s , float &data )
282 {
283 wxSscanf(s, _T("%f"), &data ) ;
284 }
285
286 template<> void wxStringWriteValue(wxString &s , const float &data )
287 {
288 s = wxString::Format("%f", data ) ;
289 }
290
291 // double
292
293 template<> void wxStringReadValue(const wxString &s , double &data )
294 {
295 wxSscanf(s, _T("%lf"), &data ) ;
296 }
297
298 template<> void wxStringWriteValue(wxString &s , const double &data )
299 {
300 s = wxString::Format("%lf", data ) ;
301 }
302
303 // wxString
304
305 template<> void wxStringReadValue(const wxString &s , wxString &data )
306 {
307 data = s ;
308 }
309
310 template<> void wxStringWriteValue(wxString &s , const wxString &data )
311 {
312 s = data ;
313 }
314
315 /*
316 Custom Data Streaming / Type Infos
317 we will have to add this for all wx non object types, but it is also an example
318 for custom data structures
319 */
320
321 // wxPoint
322
323 template<> void wxStringReadValue(const wxString &s , wxPoint &data )
324 {
325 wxSscanf(s, _T("%d,%d"), &data.x , &data.y ) ;
326 }
327
328 template<> void wxStringWriteValue(wxString &s , const wxPoint &data )
329 {
330 s = wxString::Format("%d,%d", data.x , data.y ) ;
331 }
332
333 template<> void wxStringReadValue(const wxString & , wxPoint* & )
334 {
335 assert(0) ;
336 }
337
338 template<> void wxStringWriteValue(wxString & , wxPoint* const & )
339 {
340 assert(0) ;
341 }
342
343 WX_CUSTOM_TYPE_INFO(wxPoint)
344
345 template<> void wxStringReadValue(const wxString &s , wxSize &data )
346 {
347 wxSscanf(s, _T("%d,%d"), &data.x , &data.y ) ;
348 }
349
350 template<> void wxStringWriteValue(wxString &s , const wxSize &data )
351 {
352 s = wxString::Format("%d,%d", data.x , data.y ) ;
353 }
354
355 template<> void wxStringReadValue(const wxString & , wxSize* & )
356 {
357 assert(0) ;
358 }
359
360 template<> void wxStringWriteValue(wxString & , wxSize * const & )
361 {
362 assert(0) ;
363 }
364
365 WX_CUSTOM_TYPE_INFO(wxSize)
366
367 /*
368
369 template<> void wxStringReadValue(const wxString &s , wxColour &data )
370 {
371 // copied from VS xrc
372 unsigned long tmp = 0;
373
374 if (s.Length() != 7 || s[0u] != wxT('#') ||
375 wxSscanf(s.c_str(), wxT("#%lX"), &tmp) != 1)
376 {
377 wxLogError(_("String To Colour : Incorrect colour specification : %s"),
378 s.c_str() );
379 data = wxNullColour;
380 }
381 else
382 {
383 data = wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) ,
384 (unsigned char) ((tmp & 0x00FF00) >> 8),
385 (unsigned char) ((tmp & 0x0000FF)));
386 }
387 }
388
389 template<> void wxStringWriteValue(wxString &s , const wxColour &data )
390 {
391 s = wxString::Format("#%2X%2X%2X", data.Red() , data.Green() , data.Blue() ) ;
392 }
393
394 WX_CUSTOM_TYPE_INFO(wxColour)
395
396 */
397
398 // removing header dependancy on string tokenizer
399
400 void wxSetStringToArray( const wxString &s , wxArrayString &array )
401 {
402 wxStringTokenizer tokenizer(s, wxT("| \t\n"), wxTOKEN_STRTOK);
403 wxString flag;
404 array.Clear() ;
405 while (tokenizer.HasMoreTokens())
406 {
407 array.Add(tokenizer.GetNextToken()) ;
408 }
409 }
410
411 // ----------------------------------------------------------------------------
412 // wxClassInfo
413 // ----------------------------------------------------------------------------
414
415 const wxPropertyAccessor *wxClassInfo::FindAccessor(const char *PropertyName) const
416 {
417 const wxPropertyInfo* info = FindPropertyInfo( PropertyName ) ;
418
419 if ( info )
420 return info->GetAccessor() ;
421
422 return NULL ;
423 }
424
425 const wxPropertyInfo *wxClassInfo::FindPropertyInfoInThisClass (const char *PropertyName) const
426 {
427 const wxPropertyInfo* info = GetFirstProperty() ;
428
429 while( info )
430 {
431 if ( strcmp( info->GetName() , PropertyName ) == 0 )
432 return info ;
433 info = info->GetNext() ;
434 }
435
436 return 0;
437 }
438
439 const wxPropertyInfo *wxClassInfo::FindPropertyInfo (const char *PropertyName) const
440 {
441 const wxPropertyInfo* info = FindPropertyInfoInThisClass( PropertyName ) ;
442 if ( info )
443 return info ;
444
445 const wxClassInfo** parents = GetParents() ;
446 for ( int i = 0 ; parents[i] ; ++ i )
447 {
448 if ( ( info = parents[i]->FindPropertyInfo( PropertyName ) ) != NULL )
449 return info ;
450 }
451
452 return 0;
453 }
454
455 const wxHandlerInfo *wxClassInfo::FindHandlerInfoInThisClass (const char *PropertyName) const
456 {
457 const wxHandlerInfo* info = GetFirstHandler() ;
458
459 while( info )
460 {
461 if ( strcmp( info->GetName() , PropertyName ) == 0 )
462 return info ;
463 info = info->GetNext() ;
464 }
465
466 return 0;
467 }
468
469 const wxHandlerInfo *wxClassInfo::FindHandlerInfo (const char *PropertyName) const
470 {
471 const wxHandlerInfo* info = FindHandlerInfoInThisClass( PropertyName ) ;
472
473 if ( info )
474 return info ;
475
476 const wxClassInfo** parents = GetParents() ;
477 for ( int i = 0 ; parents[i] ; ++ i )
478 {
479 if ( ( info = parents[i]->FindHandlerInfo( PropertyName ) ) != NULL )
480 return info ;
481 }
482
483 return 0;
484 }
485
486
487 void wxClassInfo::SetProperty(wxObject *object, const char *propertyName, const wxxVariant &value) const
488 {
489 const wxPropertyAccessor *accessor;
490
491 accessor = FindAccessor(propertyName);
492 wxASSERT(accessor->HasSetter());
493 accessor->SetProperty( object , value ) ;
494 }
495
496 wxxVariant wxClassInfo::GetProperty(wxObject *object, const char *propertyName) const
497 {
498 const wxPropertyAccessor *accessor;
499
500 accessor = FindAccessor(propertyName);
501 wxASSERT(accessor->HasGetter());
502 return accessor->GetProperty(object);
503 }
504
505 /*
506 VARIANT TO OBJECT
507 */
508
509 wxObject* wxxVariant::GetAsObject()
510 {
511 const wxClassTypeInfo *ti = dynamic_cast<const wxClassTypeInfo*>( m_data->GetTypeInfo() ) ;
512 if ( ti )
513 return ti->GetClassInfo()->VariantToInstance(*this) ;
514 else
515 return NULL ;
516 }
517
518 // ----------------------------------------------------------------------------
519 // wxDynamicObject support
520 // ----------------------------------------------------------------------------
521 //
522 // Dynamic Objects are objects that have a real superclass instance and carry their
523 // own attributes in a hash map. Like this it is possible to create the objects and
524 // stream them, as if their class information was already available from compiled data
525
526 struct wxDynamicObject::wxDynamicObjectInternal
527 {
528 map<string,wxxVariant> m_properties ;
529 } ;
530
531 // instantiates this object with an instance of its superclass
532 wxDynamicObject::wxDynamicObject(wxObject* superClassInstance, const wxDynamicClassInfo *info)
533 {
534 m_superClassInstance = superClassInstance ;
535 m_classInfo = info ;
536 m_data = new wxDynamicObjectInternal ;
537 }
538
539 wxDynamicObject::~wxDynamicObject()
540 {
541 delete m_data ;
542 delete m_superClassInstance ;
543 }
544
545 void wxDynamicObject::SetProperty (const wxChar *propertyName, const wxxVariant &value)
546 {
547 wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
548 m_data->m_properties[propertyName] = value ;
549 }
550
551 wxxVariant wxDynamicObject::GetProperty (const wxChar *propertyName) const
552 {
553 wxASSERT_MSG(m_classInfo->FindPropertyInfoInThisClass(propertyName),wxT("Accessing Unknown Property in a Dynamic Object") ) ;
554 return m_data->m_properties[propertyName] ;
555 }
556
557 // ----------------------------------------------------------------------------
558 // wxDynamiClassInfo
559 // ----------------------------------------------------------------------------
560
561 wxDynamicClassInfo::wxDynamicClassInfo( const wxChar *unitName, const wxChar *className , const wxClassInfo* superClass ) :
562 wxClassInfo( unitName, className , new const wxClassInfo*[2])
563 {
564 GetParents()[0] = superClass ;
565 GetParents()[1] = NULL ;
566 }
567
568 wxDynamicClassInfo::~wxDynamicClassInfo()
569 {
570 delete[] GetParents() ;
571 }
572
573 wxObject *wxDynamicClassInfo::CreateObject() const
574 {
575 wxObject* parent = GetParents()[0]->CreateObject() ;
576 return new wxDynamicObject( parent , this ) ;
577 }
578
579 void wxDynamicClassInfo::Create (wxObject *object, int paramCount, wxxVariant *params) const
580 {
581 wxDynamicObject *dynobj = dynamic_cast< wxDynamicObject *>( object ) ;
582 wxASSERT_MSG( dynobj , wxT("cannot call wxDynamicClassInfo::Create on an object other than wxDynamicObject") ) ;
583 GetParents()[0]->Create( dynobj->GetSuperClassInstance() , paramCount , params ) ;
584 }
585
586 // get number of parameters for constructor
587 int wxDynamicClassInfo::GetCreateParamCount() const
588 {
589 return GetParents()[0]->GetCreateParamCount() ;
590 }
591
592 // get i-th constructor parameter
593 const wxChar* wxDynamicClassInfo::GetCreateParamName(int i) const
594 {
595 return GetParents()[0]->GetCreateParamName( i ) ;
596 }
597
598 void wxDynamicClassInfo::SetProperty(wxObject *object, const char *propertyName, const wxxVariant &value) const
599 {
600 wxDynamicObject* dynobj = dynamic_cast< wxDynamicObject * >( object ) ;
601 wxASSERT_MSG( dynobj , wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
602 if ( FindPropertyInfoInThisClass(propertyName) )
603 dynobj->SetProperty( propertyName , value ) ;
604 else
605 GetParents()[0]->SetProperty( dynobj->GetSuperClassInstance() , propertyName , value ) ;
606 }
607
608 wxxVariant wxDynamicClassInfo::GetProperty(wxObject *object, const char *propertyName) const
609 {
610 wxDynamicObject* dynobj = dynamic_cast< wxDynamicObject * >( object ) ;
611 wxASSERT_MSG( dynobj , wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
612 if ( FindPropertyInfoInThisClass(propertyName) )
613 return dynobj->GetProperty( propertyName ) ;
614 else
615 return GetParents()[0]->GetProperty( dynobj->GetSuperClassInstance() , propertyName ) ;
616 }
617
618 void wxDynamicClassInfo::AddProperty( const wxChar *propertyName , const wxTypeInfo* typeInfo )
619 {
620 new wxPropertyInfo( m_firstProperty , propertyName , "" , typeInfo , new wxGenericPropertyAccessor( propertyName ) , wxxVariant() ) ;
621 }
622
623 void wxDynamicClassInfo::AddHandler( const wxChar *handlerName , wxObjectEventFunction address , const wxClassInfo* eventClassInfo )
624 {
625 new wxHandlerInfo( m_firstHandler , handlerName , address , eventClassInfo ) ;
626 }
627
628 // ----------------------------------------------------------------------------
629 // wxGenericPropertyAccessor
630 // ----------------------------------------------------------------------------
631
632 struct wxGenericPropertyAccessor::wxGenericPropertyAccessorInternal
633 {
634 wxString m_propertyName ;
635 } ;
636
637 wxGenericPropertyAccessor::wxGenericPropertyAccessor( const wxChar* propertyName )
638 {
639 m_data = new wxGenericPropertyAccessorInternal ;
640 m_data->m_propertyName = propertyName ;
641 }
642
643 wxGenericPropertyAccessor::~wxGenericPropertyAccessor()
644 {
645 delete m_data ;
646 }
647 void wxGenericPropertyAccessor::SetProperty(wxObject *object, const wxxVariant &value) const
648 {
649 wxDynamicObject* dynobj = dynamic_cast< wxDynamicObject * >( object ) ;
650 wxASSERT_MSG( dynobj , wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
651 dynobj->SetProperty(m_data->m_propertyName , value ) ;
652 }
653
654 wxxVariant wxGenericPropertyAccessor::GetProperty(const wxObject *object) const
655 {
656 const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject * >( object ) ;
657 wxASSERT_MSG( dynobj , wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
658 return dynobj->GetProperty( m_data->m_propertyName ) ;
659 }
660
661 wxxVariant wxGenericPropertyAccessor::ReadValue( const wxString &value ) const
662 {
663 return wxxVariant(value) ;
664 }
665
666 void wxGenericPropertyAccessor::WriteValue( wxString& value , const wxObject *object ) const
667 {
668 const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject * >( object ) ;
669 wxASSERT_MSG( dynobj , wxT("cannot call wxDynamicClassInfo::SetProperty on an object other than wxDynamicObject") ) ;
670 wxxVariant val = dynobj->GetProperty( m_data->m_propertyName ) ;
671 value = val.GetAsString() ;
672 }
673
674 #endif