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