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