1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/xtistrm.cpp
3 // Purpose:     streaming runtime metadata information
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     27/07/03
7 // Copyright:   (c) 2003 Stefan Csomor
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13 
14 
15 #if wxUSE_EXTENDED_RTTI
16 
17 #include "wx/xtistrm.h"
18 
19 #ifndef WX_PRECOMP
20     #include "wx/object.h"
21     #include "wx/hash.h"
22     #include "wx/event.h"
23 #endif
24 
25 #include "wx/tokenzr.h"
26 #include "wx/txtstrm.h"
27 
28 // STL headers:
29 
30 #include "wx/beforestd.h"
31 #include <map>
32 #include <vector>
33 #include <string>
34 #include "wx/afterstd.h"
35 using namespace std;
36 
37 
38 // ----------------------------------------------------------------------------
39 // wxObjectWriter
40 // ----------------------------------------------------------------------------
41 
42 struct wxObjectWriter::wxObjectWriterInternal
43 {
44     map< const wxObject*, int > m_writtenObjects;
45     int m_nextId;
46 };
47 
wxObjectWriter()48 wxObjectWriter::wxObjectWriter()
49 {
50     m_data = new wxObjectWriterInternal;
51     m_data->m_nextId = 0;
52 }
53 
~wxObjectWriter()54 wxObjectWriter::~wxObjectWriter()
55 {
56     delete m_data;
57 }
58 
59 struct wxObjectWriter::wxObjectWriterInternalPropertiesData
60 {
61     char nothing;
62 };
63 
ClearObjectContext()64 void wxObjectWriter::ClearObjectContext()
65 {
66     delete m_data;
67     m_data = new wxObjectWriterInternal();
68     m_data->m_nextId = 0;
69 }
70 
WriteObject(const wxObject * object,const wxClassInfo * classInfo,wxObjectWriterCallback * writercallback,const wxString & name,const wxStringToAnyHashMap & metadata)71 void wxObjectWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo,
72                            wxObjectWriterCallback *writercallback, const wxString &name,
73                            const wxStringToAnyHashMap &metadata )
74 {
75     DoBeginWriteTopLevelEntry( name );
76     WriteObject( object, classInfo, writercallback, false, metadata);
77     DoEndWriteTopLevelEntry( name );
78 }
79 
WriteObject(const wxObject * object,const wxClassInfo * classInfo,wxObjectWriterCallback * writercallback,bool isEmbedded,const wxStringToAnyHashMap & metadata)80 void wxObjectWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo,
81                            wxObjectWriterCallback *writercallback, bool isEmbedded,
82                            const wxStringToAnyHashMap &metadata )
83 {
84     if ( !classInfo->BeforeWriteObject( object, this, writercallback, metadata) )
85         return;
86 
87     if ( writercallback->BeforeWriteObject( this, object, classInfo, metadata) )
88     {
89         if ( object == NULL )
90             DoWriteNullObject();
91         else if ( IsObjectKnown( object ) )
92             DoWriteRepeatedObject( GetObjectID(object) );
93         else
94         {
95             int oid = m_data->m_nextId++;
96             if ( !isEmbedded )
97                 m_data->m_writtenObjects[object] = oid;
98 
99             // in case this object is a wxDynamicObject we also have to insert is superclass
100             // instance with the same id, so that object relations are streamed out correctly
101             const wxDynamicObject* dynobj = wx_dynamic_cast(const wxDynamicObject*, object);
102             if ( !isEmbedded && dynobj )
103                 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid;
104 
105             DoBeginWriteObject( object, classInfo, oid, metadata );
106             wxObjectWriterInternalPropertiesData data;
107             WriteAllProperties( object, classInfo, writercallback, &data );
108             DoEndWriteObject( object, classInfo, oid  );
109         }
110         writercallback->AfterWriteObject( this,object, classInfo );
111     }
112 }
113 
FindConnectEntry(const wxEvtHandler * evSource,const wxEventSourceTypeInfo * dti,const wxObject * & sink,const wxHandlerInfo * & handler)114 void wxObjectWriter::FindConnectEntry(const wxEvtHandler * evSource,
115                                 const wxEventSourceTypeInfo* dti,
116                                 const wxObject* &sink,
117                                 const wxHandlerInfo *&handler)
118 {
119     size_t cookie;
120     for ( wxDynamicEventTableEntry* entry = evSource->GetFirstDynamicEntry(cookie);
121           entry;
122           entry = evSource->GetNextDynamicEntry(cookie) )
123     {
124         // find the match
125         if ( entry->m_fn &&
126             (dti->GetEventType() == entry->m_eventType) &&
127             (entry->m_id == -1 ) &&
128             (entry->m_fn->GetEvtHandler() != NULL ) )
129         {
130             sink = entry->m_fn->GetEvtHandler();
131             const wxClassInfo* sinkClassInfo = sink->GetClassInfo();
132             const wxHandlerInfo* sinkHandler = sinkClassInfo->GetFirstHandler();
133             while ( sinkHandler )
134             {
135                 if ( sinkHandler->GetEventFunction() == entry->m_fn->GetEvtMethod() )
136                 {
137                     handler = sinkHandler;
138                     break;
139                 }
140                 sinkHandler = sinkHandler->GetNext();
141             }
142             break;
143         }
144     }
145 }
WriteAllProperties(const wxObject * obj,const wxClassInfo * ci,wxObjectWriterCallback * writercallback,wxObjectWriterInternalPropertiesData * data)146 void wxObjectWriter::WriteAllProperties( const wxObject * obj, const wxClassInfo* ci,
147                                    wxObjectWriterCallback *writercallback,
148                                    wxObjectWriterInternalPropertiesData * data )
149 {
150     wxPropertyInfoMap map;
151     ci->GetProperties( map );
152     for ( int i = 0; i < ci->GetCreateParamCount(); ++i )
153     {
154         wxString name = ci->GetCreateParamName(i);
155         wxPropertyInfoMap::const_iterator iter = map.find(name);
156         const wxPropertyInfo* prop = iter == map.end() ? NULL : iter->second;
157         if ( prop )
158         {
159             WriteOneProperty( obj, prop->GetDeclaringClass(), prop, writercallback, data );
160         }
161         else
162         {
163             wxLogError( _("Create Parameter %s not found in declared RTTI Parameters"), name.c_str() );
164         }
165         map.erase( name );
166     }
167     { // Extra block for broken compilers
168         for( wxPropertyInfoMap::iterator iter = map.begin(); iter != map.end(); ++iter )
169         {
170             const wxPropertyInfo* prop = iter->second;
171             if ( prop->GetFlags() & wxPROP_OBJECT_GRAPH )
172             {
173                 WriteOneProperty( obj, prop->GetDeclaringClass(), prop, writercallback, data );
174             }
175         }
176     }
177     { // Extra block for broken compilers
178         for( wxPropertyInfoMap::iterator iter = map.begin(); iter != map.end(); ++iter )
179         {
180             const wxPropertyInfo* prop = iter->second;
181             if ( !(prop->GetFlags() & wxPROP_OBJECT_GRAPH) )
182             {
183                 WriteOneProperty( obj, prop->GetDeclaringClass(), prop, writercallback, data );
184             }
185         }
186     }
187 }
188 
189 class WXDLLIMPEXP_BASE wxObjectPropertyWriter: public wxObjectWriterFunctor
190 {
191 public:
wxObjectPropertyWriter(const wxClassTypeInfo * cti,wxObjectWriterCallback * writercallback,wxObjectWriter * writer,wxStringToAnyHashMap & props)192     wxObjectPropertyWriter(const wxClassTypeInfo* cti,
193         wxObjectWriterCallback *writercallback,
194         wxObjectWriter* writer,
195         wxStringToAnyHashMap &props) :
196     m_cti(cti),m_persister(writercallback),m_writer(writer),m_props(props)
197     {}
198 
operator ()(const wxObject * vobj)199     virtual void operator()(const wxObject *vobj)
200     {
201         m_writer->WriteObject( vobj, (vobj ? vobj->GetClassInfo() : m_cti->GetClassInfo() ),
202             m_persister, m_cti->GetKind()== wxT_OBJECT, m_props );
203     }
204 private:
205     const wxClassTypeInfo* m_cti;
206     wxObjectWriterCallback *m_persister;
207     wxObjectWriter* m_writer;
208     wxStringToAnyHashMap& m_props;
209 };
210 
WriteOneProperty(const wxObject * obj,const wxClassInfo * ci,const wxPropertyInfo * pi,wxObjectWriterCallback * writercallback,wxObjectWriterInternalPropertiesData * WXUNUSED (data))211 void wxObjectWriter::WriteOneProperty( const wxObject *obj, const wxClassInfo* ci,
212                                  const wxPropertyInfo* pi, wxObjectWriterCallback *writercallback,
213                                  wxObjectWriterInternalPropertiesData *WXUNUSED(data) )
214 {
215     if ( pi->GetFlags() & wxPROP_DONT_STREAM )
216         return;
217 
218     // make sure that we are picking the correct object for accessing the property
219     const wxDynamicObject* dynobj = wx_dynamic_cast(const wxDynamicObject*, obj );
220     if ( dynobj && (wx_dynamic_cast(const wxDynamicClassInfo*, ci) == NULL) )
221         obj = dynobj->GetSuperClassInstance();
222 
223     if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
224     {
225         wxAnyList data;
226         pi->GetAccessor()->GetPropertyCollection(obj, data);
227         const wxTypeInfo * elementType =
228             wx_dynamic_cast( const wxCollectionTypeInfo*, pi->GetTypeInfo() )->GetElementType();
229         if ( !data.empty() )
230         {
231             DoBeginWriteProperty( pi );
232             for ( wxAnyList::const_iterator iter = data.begin(); iter != data.end(); ++iter )
233             {
234                 DoBeginWriteElement();
235                 const wxAny* valptr = *iter;
236                 if ( writercallback->BeforeWriteProperty( this, obj, pi, *valptr ) )
237                 {
238                     const wxClassTypeInfo* cti =
239                         wx_dynamic_cast( const wxClassTypeInfo*, elementType );
240                     if ( cti )
241                     {
242                         wxStringToAnyHashMap md;
243                         wxObjectPropertyWriter pw(cti,writercallback,this, md);
244 
245                         const wxClassInfo* pci = cti->GetClassInfo();
246                         pci->CallOnAny( *valptr, &pw);
247                     }
248                     else
249                     {
250                         DoWriteSimpleType( *valptr );
251                     }
252                 }
253                 DoEndWriteElement();
254             }
255             DoEndWriteProperty( pi );
256         }
257     }
258     else
259     {
260         const wxEventSourceTypeInfo* dti =
261             wx_dynamic_cast( const wxEventSourceTypeInfo* , pi->GetTypeInfo() );
262         if ( dti )
263         {
264             const wxObject* sink = NULL;
265             const wxHandlerInfo *handler = NULL;
266 
267             const wxEvtHandler * evSource = wx_dynamic_cast(const wxEvtHandler *, obj);
268             if ( evSource )
269             {
270                 FindConnectEntry( evSource, dti, sink, handler );
271                 if ( writercallback->BeforeWriteDelegate( this, obj, ci, pi, sink, handler ) )
272                 {
273                     if ( sink != NULL && handler != NULL )
274                     {
275                         DoBeginWriteProperty( pi );
276                         if ( IsObjectKnown( sink ) )
277                         {
278                             DoWriteDelegate( obj, ci, pi, sink, GetObjectID( sink ),
279                                              sink->GetClassInfo(), handler );
280                             DoEndWriteProperty( pi );
281                         }
282                         else
283                         {
284                             wxLogError( wxT("Streaming delegates for not already ")
285                                         wxT("streamed objects not yet supported") );
286                         }
287                     }
288                 }
289             }
290             else
291             {
292                 wxLogError(_("Illegal Object Class (Non-wxEvtHandler) as Event Source") );
293             }
294         }
295         else
296         {
297             wxAny value;
298             pi->GetAccessor()->GetProperty(obj, value);
299 
300             // avoid streaming out void objects
301             // TODO Verify
302             if( value.IsNull() )
303                 return;
304 
305             if ( pi->GetFlags() & wxPROP_ENUM_STORE_LONG )
306             {
307                 const wxEnumTypeInfo *eti =
308                     wx_dynamic_cast(const wxEnumTypeInfo*,  pi->GetTypeInfo() );
309                 if ( eti )
310                 {
311                     eti->ConvertFromLong( value.As<long >(), value );
312                 }
313                 else
314                 {
315                     wxLogError( _("Type must have enum - long conversion") );
316                 }
317             }
318 
319             // avoid streaming out default values
320             if ( pi->GetTypeInfo()->HasStringConverters() &&
321                  !pi->GetDefaultValue().IsNull() ) // TODO Verify
322             {
323                 if ( wxAnyGetAsString(value) == wxAnyGetAsString(pi->GetDefaultValue()) )
324                     return;
325             }
326 
327             // avoid streaming out null objects
328             const wxClassTypeInfo* cti =
329                 wx_dynamic_cast( const wxClassTypeInfo* , pi->GetTypeInfo() );
330 
331             if ( cti && cti->GetKind() == wxT_OBJECT_PTR && wxAnyGetAsObjectPtr(value) == NULL )
332                 return;
333 
334             if ( writercallback->BeforeWriteProperty( this, obj, pi, value ) )
335             {
336                 DoBeginWriteProperty( pi );
337                 if ( cti )
338                 {
339                     if ( cti->HasStringConverters() )
340                     {
341                         wxString stringValue;
342                         cti->ConvertToString( value, stringValue );
343                         wxAny convertedValue(stringValue);
344                         DoWriteSimpleType( convertedValue );
345                     }
346                     else
347                     {
348                         wxStringToAnyHashMap md;
349                         wxObjectPropertyWriter pw(cti,writercallback,this, md);
350 
351                         const wxClassInfo* pci = cti->GetClassInfo();
352                         pci->CallOnAny(value, &pw);
353                     }
354                 }
355                 else
356                 {
357                     DoWriteSimpleType( value );
358                 }
359                 DoEndWriteProperty( pi );
360             }
361         }
362     }
363 }
364 
GetObjectID(const wxObject * obj)365 int wxObjectWriter::GetObjectID(const wxObject *obj)
366 {
367     if ( !IsObjectKnown( obj ) )
368         return wxInvalidObjectID;
369 
370     return m_data->m_writtenObjects[obj];
371 }
372 
IsObjectKnown(const wxObject * obj)373 bool wxObjectWriter::IsObjectKnown( const wxObject *obj )
374 {
375     return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end();
376 }
377 
378 
379 // ----------------------------------------------------------------------------
380 // wxObjectReader
381 // ----------------------------------------------------------------------------
382 
383 struct wxObjectReader::wxObjectReaderInternal
384 {
385     map<int,wxClassInfo*> m_classInfos;
386 };
387 
wxObjectReader()388 wxObjectReader::wxObjectReader()
389 {
390     m_data = new wxObjectReaderInternal;
391 }
392 
~wxObjectReader()393 wxObjectReader::~wxObjectReader()
394 {
395     delete m_data;
396 }
397 
GetObjectClassInfo(int objectID)398 wxClassInfo* wxObjectReader::GetObjectClassInfo(int objectID)
399 {
400     if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID )
401     {
402         wxLogError( _("Invalid or Null Object ID passed to GetObjectClassInfo" ) );
403         return NULL;
404     }
405     if ( m_data->m_classInfos.find(objectID) == m_data->m_classInfos.end() )
406     {
407         wxLogError( _("Unknown Object passed to GetObjectClassInfo" ) );
408         return NULL;
409     }
410     return m_data->m_classInfos[objectID];
411 }
412 
SetObjectClassInfo(int objectID,wxClassInfo * classInfo)413 void wxObjectReader::SetObjectClassInfo(int objectID, wxClassInfo *classInfo )
414 {
415     if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID )
416     {
417         wxLogError( _("Invalid or Null Object ID passed to GetObjectClassInfo" ) );
418         return;
419     }
420     if ( m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() )
421     {
422         wxLogError( _("Already Registered Object passed to SetObjectClassInfo" ) );
423         return;
424     }
425     m_data->m_classInfos[objectID] = classInfo;
426 }
427 
HasObjectClassInfo(int objectID)428 bool wxObjectReader::HasObjectClassInfo( int objectID )
429 {
430     if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID )
431     {
432         wxLogError( _("Invalid or Null Object ID passed to HasObjectClassInfo" ) );
433         return false;
434     }
435     return m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end();
436 }
437 
438 
439 // ----------------------------------------------------------------------------
440 // reading xml in
441 // ----------------------------------------------------------------------------
442 
443 /*
444 Reading components has not to be extended for components
445 as properties are always sought by typeinfo over all levels
446 and create params are always toplevel class only
447 */
448 
449 
450 // ----------------------------------------------------------------------------
451 // wxObjectRuntimeReaderCallback - depersisting to memory
452 // ----------------------------------------------------------------------------
453 
454 struct wxObjectRuntimeReaderCallback::wxObjectRuntimeReaderCallbackInternal
455 {
456     map<int,wxObject *> m_objects;
457 
SetObjectwxObjectRuntimeReaderCallback::wxObjectRuntimeReaderCallbackInternal458     void SetObject(int objectID, wxObject *obj )
459     {
460         if ( m_objects.find(objectID) != m_objects.end() )
461         {
462             wxLogError( _("Passing a already registered object to SetObject") );
463             return ;
464         }
465         m_objects[objectID] = obj;
466     }
GetObjectwxObjectRuntimeReaderCallback::wxObjectRuntimeReaderCallbackInternal467     wxObject* GetObject( int objectID )
468     {
469         if ( objectID == wxNullObjectID )
470             return NULL;
471         if ( m_objects.find(objectID) == m_objects.end() )
472         {
473             wxLogError( _("Passing an unknown object to GetObject") );
474             return NULL;
475         }
476 
477         return m_objects[objectID];
478     }
479 };
480 
wxObjectRuntimeReaderCallback()481 wxObjectRuntimeReaderCallback::wxObjectRuntimeReaderCallback()
482 {
483     m_data = new wxObjectRuntimeReaderCallbackInternal();
484 }
485 
~wxObjectRuntimeReaderCallback()486 wxObjectRuntimeReaderCallback::~wxObjectRuntimeReaderCallback()
487 {
488     delete m_data;
489 }
490 
AllocateObject(int objectID,wxClassInfo * classInfo,wxStringToAnyHashMap & WXUNUSED (metadata))491 void wxObjectRuntimeReaderCallback::AllocateObject(int objectID, wxClassInfo *classInfo,
492                                           wxStringToAnyHashMap &WXUNUSED(metadata))
493 {
494     wxObject *O;
495     O = classInfo->CreateObject();
496     m_data->SetObject(objectID, O);
497 }
498 
CreateObject(int objectID,const wxClassInfo * classInfo,int paramCount,wxAny * params,int * objectIdValues,const wxClassInfo ** objectClassInfos,wxStringToAnyHashMap & WXUNUSED (metadata))499 void wxObjectRuntimeReaderCallback::CreateObject(int objectID,
500                                         const wxClassInfo *classInfo,
501                                         int paramCount,
502                                         wxAny *params,
503                                         int *objectIdValues,
504                                         const wxClassInfo **objectClassInfos,
505                                         wxStringToAnyHashMap &WXUNUSED(metadata))
506 {
507     wxObject *o;
508     o = m_data->GetObject(objectID);
509     for ( int i = 0; i < paramCount; ++i )
510     {
511         if ( objectIdValues[i] != wxInvalidObjectID )
512         {
513             wxObject *o;
514             o = m_data->GetObject(objectIdValues[i]);
515             // if this is a dynamic object and we are asked for another class
516             // than wxDynamicObject we cast it down manually.
517             wxDynamicObject *dyno = wx_dynamic_cast( wxDynamicObject *, o);
518             if ( dyno!=NULL && (objectClassInfos[i] != dyno->GetClassInfo()) )
519             {
520                 o = dyno->GetSuperClassInstance();
521             }
522             params[i] = objectClassInfos[i]->ObjectPtrToAny(o);
523         }
524     }
525     classInfo->Create(o, paramCount, params);
526 }
527 
ConstructObject(int objectID,const wxClassInfo * classInfo,int paramCount,wxAny * params,int * objectIdValues,const wxClassInfo ** objectClassInfos,wxStringToAnyHashMap & WXUNUSED (metadata))528 void wxObjectRuntimeReaderCallback::ConstructObject(int objectID,
529                                         const wxClassInfo *classInfo,
530                                         int paramCount,
531                                         wxAny *params,
532                                         int *objectIdValues,
533                                         const wxClassInfo **objectClassInfos,
534                                         wxStringToAnyHashMap &WXUNUSED(metadata))
535 {
536     wxObject *o;
537     for ( int i = 0; i < paramCount; ++i )
538     {
539         if ( objectIdValues[i] != wxInvalidObjectID )
540         {
541             wxObject *o;
542             o = m_data->GetObject(objectIdValues[i]);
543             // if this is a dynamic object and we are asked for another class
544             // than wxDynamicObject we cast it down manually.
545             wxDynamicObject *dyno = wx_dynamic_cast( wxDynamicObject *, o);
546             if ( dyno!=NULL && (objectClassInfos[i] != dyno->GetClassInfo()) )
547             {
548                 o = dyno->GetSuperClassInstance();
549             }
550             params[i] = objectClassInfos[i]->ObjectPtrToAny(o);
551         }
552     }
553     o = classInfo->ConstructObject(paramCount, params);
554     m_data->SetObject(objectID, o);
555 }
556 
557 
DestroyObject(int objectID,wxClassInfo * WXUNUSED (classInfo))558 void wxObjectRuntimeReaderCallback::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
559 {
560     wxObject *o;
561     o = m_data->GetObject(objectID);
562     delete o;
563 }
564 
SetProperty(int objectID,const wxClassInfo * classInfo,const wxPropertyInfo * propertyInfo,const wxAny & value)565 void wxObjectRuntimeReaderCallback::SetProperty(int objectID,
566                                        const wxClassInfo *classInfo,
567                                        const wxPropertyInfo* propertyInfo,
568                                        const wxAny &value)
569 {
570     wxObject *o;
571     o = m_data->GetObject(objectID);
572     classInfo->SetProperty( o, propertyInfo->GetName().c_str(), value );
573 }
574 
SetPropertyAsObject(int objectID,const wxClassInfo * classInfo,const wxPropertyInfo * propertyInfo,int valueObjectId)575 void wxObjectRuntimeReaderCallback::SetPropertyAsObject(int objectID,
576                                                const wxClassInfo *classInfo,
577                                                const wxPropertyInfo* propertyInfo,
578                                                int valueObjectId)
579 {
580     wxObject *o, *valo;
581     o = m_data->GetObject(objectID);
582     valo = m_data->GetObject(valueObjectId);
583     const wxClassInfo* valClassInfo =
584         (wx_dynamic_cast(const wxClassTypeInfo*,propertyInfo->GetTypeInfo()))->GetClassInfo();
585 
586     // if this is a dynamic object and we are asked for another class
587     // than wxDynamicObject we cast it down manually.
588     wxDynamicObject *dynvalo = wx_dynamic_cast( wxDynamicObject *, valo);
589     if ( dynvalo!=NULL  && (valClassInfo != dynvalo->GetClassInfo()) )
590     {
591         valo = dynvalo->GetSuperClassInstance();
592     }
593 
594     classInfo->SetProperty( o, propertyInfo->GetName().c_str(),
595                             valClassInfo->ObjectPtrToAny(valo) );
596 }
597 
SetConnect(int eventSourceObjectID,const wxClassInfo * WXUNUSED (eventSourceClassInfo),const wxPropertyInfo * delegateInfo,const wxClassInfo * WXUNUSED (eventSinkClassInfo),const wxHandlerInfo * handlerInfo,int eventSinkObjectID)598 void wxObjectRuntimeReaderCallback::SetConnect(int eventSourceObjectID,
599                                       const wxClassInfo *WXUNUSED(eventSourceClassInfo),
600                                       const wxPropertyInfo *delegateInfo,
601                                       const wxClassInfo *WXUNUSED(eventSinkClassInfo),
602                                       const wxHandlerInfo* handlerInfo,
603                                       int eventSinkObjectID )
604 {
605     wxEvtHandler *ehsource =
606         wx_dynamic_cast( wxEvtHandler* , m_data->GetObject( eventSourceObjectID ) );
607     wxEvtHandler *ehsink =
608         wx_dynamic_cast( wxEvtHandler *,m_data->GetObject(eventSinkObjectID) );
609 
610     if ( ehsource && ehsink )
611     {
612         const wxEventSourceTypeInfo *delegateTypeInfo =
613             wx_dynamic_cast(const wxEventSourceTypeInfo*,delegateInfo->GetTypeInfo());
614         if( delegateTypeInfo && delegateTypeInfo->GetLastEventType() == -1 )
615         {
616             ehsource->Connect( -1, delegateTypeInfo->GetEventType(),
617                 handlerInfo->GetEventFunction(), NULL /*user data*/,
618                 ehsink );
619         }
620         else
621         {
622             for ( wxEventType iter = delegateTypeInfo->GetEventType();
623                   iter <= delegateTypeInfo->GetLastEventType(); ++iter )
624             {
625                 ehsource->Connect( -1, iter,
626                     handlerInfo->GetEventFunction(), NULL /*user data*/,
627                     ehsink );
628             }
629         }
630     }
631 }
632 
GetObject(int objectID)633 wxObject *wxObjectRuntimeReaderCallback::GetObject(int objectID)
634 {
635     return m_data->GetObject( objectID );
636 }
637 
AddToPropertyCollection(int objectID,const wxClassInfo * classInfo,const wxPropertyInfo * propertyInfo,const wxAny & value)638 void wxObjectRuntimeReaderCallback::AddToPropertyCollection( int objectID,
639                                                    const wxClassInfo *classInfo,
640                                                    const wxPropertyInfo* propertyInfo,
641                                                    const wxAny &value)
642 {
643     wxObject *o;
644     o = m_data->GetObject(objectID);
645     classInfo->AddToPropertyCollection( o, propertyInfo->GetName().c_str(), value );
646 }
647 
AddToPropertyCollectionAsObject(int objectID,const wxClassInfo * classInfo,const wxPropertyInfo * propertyInfo,int valueObjectId)648 void wxObjectRuntimeReaderCallback::AddToPropertyCollectionAsObject(int objectID,
649                                                            const wxClassInfo *classInfo,
650                                                            const wxPropertyInfo* propertyInfo,
651                                                            int valueObjectId)
652 {
653     wxObject *o, *valo;
654     o = m_data->GetObject(objectID);
655     valo = m_data->GetObject(valueObjectId);
656     const wxCollectionTypeInfo * collectionTypeInfo =
657         wx_dynamic_cast( const wxCollectionTypeInfo *, propertyInfo->GetTypeInfo() );
658     const wxClassInfo* valClassInfo =
659         (wx_dynamic_cast(const wxClassTypeInfo*,collectionTypeInfo->GetElementType()))->GetClassInfo();
660 
661     // if this is a dynamic object and we are asked for another class
662     // than wxDynamicObject we cast it down manually.
663     wxDynamicObject *dynvalo = wx_dynamic_cast( wxDynamicObject *, valo);
664     if ( dynvalo!=NULL  && (valClassInfo != dynvalo->GetClassInfo()) )
665     {
666         valo = dynvalo->GetSuperClassInstance();
667     }
668 
669     classInfo->AddToPropertyCollection( o, propertyInfo->GetName().c_str(),
670                                         valClassInfo->ObjectPtrToAny(valo) );
671 }
672 
673 #endif // wxUSE_EXTENDED_RTTI
674