]>
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 | #include "wx/beforestd.h" | |
33 | #include <map> | |
34 | #include <vector> | |
35 | #include <string> | |
36 | #include "wx/afterstd.h" | |
37 | ||
38 | using namespace std ; | |
39 | ||
40 | struct wxWriter::wxWriterInternal | |
41 | { | |
42 | map< const wxObject* , int > m_writtenObjects ; | |
43 | int m_nextId ; | |
44 | } ; | |
45 | ||
46 | wxWriter::wxWriter() | |
47 | { | |
48 | m_data = new wxWriterInternal ; | |
49 | m_data->m_nextId = 0 ; | |
50 | } | |
51 | ||
52 | wxWriter::~wxWriter() | |
53 | { | |
54 | delete m_data ; | |
55 | } | |
56 | ||
57 | struct wxWriter::wxWriterInternalPropertiesData | |
58 | { | |
59 | char nothing ; | |
60 | } ; | |
61 | ||
62 | void wxWriter::ClearObjectContext() | |
63 | { | |
64 | delete m_data ; | |
65 | m_data = new wxWriterInternal() ; | |
66 | m_data->m_nextId = 0 ; | |
67 | } | |
68 | ||
69 | void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name , wxxVariantArray &metadata ) | |
70 | { | |
71 | DoBeginWriteTopLevelEntry( name ) ; | |
72 | WriteObject( object , classInfo , persister , false , metadata) ; | |
73 | DoEndWriteTopLevelEntry( name ) ; | |
74 | } | |
75 | ||
76 | void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded, wxxVariantArray &metadata ) | |
77 | { | |
78 | if ( !classInfo->BeforeWriteObject( object , this , persister , metadata) ) | |
79 | return ; | |
80 | ||
81 | if ( persister->BeforeWriteObject( this , object , classInfo , metadata) ) | |
82 | { | |
83 | if ( object == NULL ) | |
84 | DoWriteNullObject() ; | |
85 | else if ( IsObjectKnown( object ) ) | |
86 | DoWriteRepeatedObject( GetObjectID(object) ) ; | |
87 | else | |
88 | { | |
89 | int oid = m_data->m_nextId++ ; | |
90 | if ( !isEmbedded ) | |
91 | m_data->m_writtenObjects[object] = oid ; | |
92 | ||
93 | // in case this object is a wxDynamicObject we also have to insert is superclass | |
94 | // instance with the same id, so that object relations are streamed out correctly | |
95 | const wxDynamicObject* dynobj = dynamic_cast<const wxDynamicObject *>( object ) ; | |
96 | if ( !isEmbedded && dynobj ) | |
97 | m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ; | |
98 | ||
99 | DoBeginWriteObject( object , classInfo , oid , metadata ) ; | |
100 | wxWriterInternalPropertiesData data ; | |
101 | WriteAllProperties( object , classInfo , persister , &data ) ; | |
102 | DoEndWriteObject( object , classInfo , oid ) ; | |
103 | } | |
104 | persister->AfterWriteObject( this ,object , classInfo ) ; | |
105 | } | |
106 | } | |
107 | ||
108 | void wxWriter::FindConnectEntry(const wxEvtHandler * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler) | |
109 | { | |
110 | wxList *dynamicEvents = evSource->GetDynamicEventTable() ; | |
111 | ||
112 | if ( dynamicEvents ) | |
113 | { | |
114 | wxList::compatibility_iterator node = dynamicEvents->GetFirst(); | |
115 | while (node) | |
116 | { | |
117 | wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData(); | |
118 | ||
119 | // find the match | |
120 | if ( entry->m_fn && | |
121 | (dti->GetEventType() == entry->m_eventType) && | |
122 | (entry->m_id == -1 ) && | |
123 | (entry->m_eventSink != NULL ) ) | |
124 | { | |
125 | sink = entry->m_eventSink ; | |
126 | const wxClassInfo* sinkClassInfo = sink->GetClassInfo() ; | |
127 | const wxHandlerInfo* sinkHandler = sinkClassInfo->GetFirstHandler() ; | |
128 | while ( sinkHandler ) | |
129 | { | |
130 | if ( sinkHandler->GetEventFunction() == entry->m_fn ) | |
131 | { | |
132 | handler = sinkHandler ; | |
133 | break ; | |
134 | } | |
135 | sinkHandler = sinkHandler->GetNext() ; | |
136 | } | |
137 | break ; | |
138 | } | |
139 | node = node->GetNext(); | |
140 | } | |
141 | } | |
142 | } | |
143 | void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data ) | |
144 | { | |
145 | wxPropertyInfoMap map ; | |
146 | ci->GetProperties( map ) ; | |
147 | for ( int i = 0 ; i < ci->GetCreateParamCount() ; ++i ) | |
148 | { | |
149 | wxString name = ci->GetCreateParamName(i) ; | |
150 | const wxPropertyInfo* prop = map.find(name)->second ; | |
151 | if ( prop ) | |
152 | { | |
153 | WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ; | |
154 | } | |
155 | else | |
156 | { | |
157 | wxLogError( _("Create Parameter not found in declared RTTI Parameters") ) ; | |
158 | } | |
159 | map.erase( name ) ; | |
160 | } | |
161 | { // Extra block for broken compilers | |
162 | for( wxPropertyInfoMap::iterator iter = map.begin() ; iter != map.end() ; ++iter ) | |
163 | { | |
164 | const wxPropertyInfo* prop = iter->second ; | |
165 | if ( prop->GetFlags() & wxPROP_OBJECT_GRAPH ) | |
166 | { | |
167 | WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ; | |
168 | } | |
169 | } | |
170 | } | |
171 | { // Extra block for broken compilers | |
172 | for( wxPropertyInfoMap::iterator iter = map.begin() ; iter != map.end() ; ++iter ) | |
173 | { | |
174 | const wxPropertyInfo* prop = iter->second ; | |
175 | if ( !(prop->GetFlags() & wxPROP_OBJECT_GRAPH) ) | |
176 | { | |
177 | WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ; | |
178 | } | |
179 | } | |
180 | } | |
181 | } | |
182 | ||
183 | void wxWriter::WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , const wxPropertyInfo* pi , wxPersister *persister , wxWriterInternalPropertiesData *WXUNUSED(data) ) | |
184 | { | |
185 | if ( pi->GetFlags() & wxPROP_DONT_STREAM ) | |
186 | return ; | |
187 | ||
188 | // make sure that we are picking the correct object for accessing the property | |
189 | const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject* > (obj ) ; | |
190 | if ( dynobj && (dynamic_cast<const wxDynamicClassInfo*>(ci) == NULL) ) | |
191 | obj = dynobj->GetSuperClassInstance() ; | |
192 | ||
193 | if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION ) | |
194 | { | |
195 | wxxVariantArray data ; | |
196 | pi->GetAccessor()->GetPropertyCollection(obj, data) ; | |
197 | const wxTypeInfo * elementType = dynamic_cast< const wxCollectionTypeInfo* >( pi->GetTypeInfo() )->GetElementType() ; | |
198 | for ( size_t i = 0 ; i < data.GetCount() ; ++i ) | |
199 | { | |
200 | if ( i == 0 ) | |
201 | DoBeginWriteProperty( pi ) ; | |
202 | ||
203 | DoBeginWriteElement() ; | |
204 | wxxVariant value = data[i] ; | |
205 | if ( persister->BeforeWriteProperty( this , obj, pi , value ) ) | |
206 | { | |
207 | const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( elementType ) ; | |
208 | if ( cti ) | |
209 | { | |
210 | const wxClassInfo* pci = cti->GetClassInfo() ; | |
211 | wxObject *vobj = pci->VariantToInstance( value ) ; | |
212 | wxxVariantArray md ; | |
213 | WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT , md ) ; | |
214 | } | |
215 | else | |
216 | { | |
217 | DoWriteSimpleType( value ) ; | |
218 | } | |
219 | } | |
220 | DoEndWriteElement() ; | |
221 | if ( i == data.GetCount() - 1 ) | |
222 | DoEndWriteProperty( pi ) ; | |
223 | } | |
224 | } | |
225 | else | |
226 | { | |
227 | const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ; | |
228 | if ( dti ) | |
229 | { | |
230 | const wxObject* sink = NULL ; | |
231 | const wxHandlerInfo *handler = NULL ; | |
232 | ||
233 | const wxEvtHandler * evSource = dynamic_cast<const wxEvtHandler *>(obj) ; | |
234 | if ( evSource ) | |
235 | { | |
236 | FindConnectEntry( evSource , dti , sink , handler ) ; | |
237 | if ( persister->BeforeWriteDelegate( this , obj , ci , pi , sink , handler ) ) | |
238 | { | |
239 | if ( sink != NULL && handler != NULL ) | |
240 | { | |
241 | DoBeginWriteProperty( pi ) ; | |
242 | if ( IsObjectKnown( sink ) ) | |
243 | { | |
244 | DoWriteDelegate( obj , ci , pi , sink , GetObjectID( sink ) , sink->GetClassInfo() , handler ) ; | |
245 | DoEndWriteProperty( pi ) ; | |
246 | } | |
247 | else | |
248 | { | |
249 | wxLogError( _("Streaming delegates for not already streamed objects not yet supported") ) ; | |
250 | } | |
251 | } | |
252 | } | |
253 | } | |
254 | else | |
255 | { | |
256 | wxLogError(_("Illegal Object Class (Non-wxEvtHandler) as Event Source") ) ; | |
257 | } | |
258 | } | |
259 | else | |
260 | { | |
261 | wxxVariant value ; | |
262 | pi->GetAccessor()->GetProperty(obj, value) ; | |
263 | ||
264 | // avoid streaming out void objects | |
265 | if( value.IsEmpty() ) | |
266 | return ; | |
267 | ||
268 | if ( pi->GetFlags() & wxPROP_ENUM_STORE_LONG ) | |
269 | { | |
270 | const wxEnumTypeInfo *eti = dynamic_cast<const wxEnumTypeInfo*>( pi->GetTypeInfo() ) ; | |
271 | if ( eti ) | |
272 | { | |
273 | eti->ConvertFromLong( value.wxTEMPLATED_MEMBER_CALL(Get , long) , value ) ; | |
274 | } | |
275 | else | |
276 | { | |
277 | wxLogError( _("Type must have enum - long conversion") ) ; | |
278 | } | |
279 | } | |
280 | ||
281 | // avoid streaming out default values | |
282 | if ( pi->GetTypeInfo()->HasStringConverters() && !pi->GetDefaultValue().IsEmpty() ) | |
283 | { | |
284 | if ( value.GetAsString() == pi->GetDefaultValue().GetAsString() ) | |
285 | return ; | |
286 | } | |
287 | ||
288 | // avoid streaming out null objects | |
289 | const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ; | |
290 | ||
291 | if ( cti && value.GetAsObject() == NULL ) | |
292 | return ; | |
293 | ||
294 | if ( persister->BeforeWriteProperty( this , obj, pi , value ) ) | |
295 | { | |
296 | DoBeginWriteProperty( pi ) ; | |
297 | if ( cti ) | |
298 | { | |
299 | const wxClassInfo* pci = cti->GetClassInfo() ; | |
300 | wxObject *vobj = pci->VariantToInstance( value ) ; | |
301 | if ( vobj && pi->GetTypeInfo()->HasStringConverters() ) | |
302 | { | |
303 | wxString stringValue ; | |
304 | cti->ConvertToString( value , stringValue ) ; | |
305 | wxxVariant convertedValue(stringValue) ; | |
306 | DoWriteSimpleType( convertedValue ) ; | |
307 | } | |
308 | else | |
309 | { | |
310 | wxxVariantArray md ; | |
311 | WriteObject( vobj , (vobj ? vobj->GetClassInfo() : pci ) , persister , cti->GetKind()== wxT_OBJECT , md) ; | |
312 | } | |
313 | } | |
314 | else | |
315 | { | |
316 | DoWriteSimpleType( value ) ; | |
317 | } | |
318 | DoEndWriteProperty( pi ) ; | |
319 | } | |
320 | } | |
321 | } | |
322 | } | |
323 | ||
324 | int wxWriter::GetObjectID(const wxObject *obj) | |
325 | { | |
326 | if ( !IsObjectKnown( obj ) ) | |
327 | return wxInvalidObjectID ; | |
328 | ||
329 | return m_data->m_writtenObjects[obj] ; | |
330 | } | |
331 | ||
332 | bool wxWriter::IsObjectKnown( const wxObject *obj ) | |
333 | { | |
334 | return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ; | |
335 | } | |
336 | ||
337 | ||
338 | // ---------------------------------------------------------------------------- | |
339 | // reading objects in | |
340 | // ---------------------------------------------------------------------------- | |
341 | ||
342 | struct wxReader::wxReaderInternal | |
343 | { | |
344 | map<int,wxClassInfo*> m_classInfos; | |
345 | }; | |
346 | ||
347 | wxReader::wxReader() | |
348 | { | |
349 | m_data = new wxReaderInternal; | |
350 | } | |
351 | ||
352 | wxReader::~wxReader() | |
353 | { | |
354 | delete m_data; | |
355 | } | |
356 | ||
357 | wxClassInfo* wxReader::GetObjectClassInfo(int objectID) | |
358 | { | |
359 | if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID ) | |
360 | { | |
361 | wxLogError( _("Invalid or Null Object ID passed to GetObjectClassInfo" ) ) ; | |
362 | return NULL ; | |
363 | } | |
364 | if ( m_data->m_classInfos.find(objectID) == m_data->m_classInfos.end() ) | |
365 | { | |
366 | wxLogError( _("Unknown Object passed to GetObjectClassInfo" ) ) ; | |
367 | return NULL ; | |
368 | } | |
369 | return m_data->m_classInfos[objectID] ; | |
370 | } | |
371 | ||
372 | void wxReader::SetObjectClassInfo(int objectID, wxClassInfo *classInfo ) | |
373 | { | |
374 | if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID ) | |
375 | { | |
376 | wxLogError( _("Invalid or Null Object ID passed to GetObjectClassInfo" ) ) ; | |
377 | return ; | |
378 | } | |
379 | if ( m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() ) | |
380 | { | |
381 | wxLogError( _("Already Registered Object passed to SetObjectClassInfo" ) ) ; | |
382 | return ; | |
383 | } | |
384 | m_data->m_classInfos[objectID] = classInfo ; | |
385 | } | |
386 | ||
387 | bool wxReader::HasObjectClassInfo( int objectID ) | |
388 | { | |
389 | if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID ) | |
390 | { | |
391 | wxLogError( _("Invalid or Null Object ID passed to HasObjectClassInfo" ) ) ; | |
392 | return false ; | |
393 | } | |
394 | return m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() ; | |
395 | } | |
396 | ||
397 | ||
398 | // ---------------------------------------------------------------------------- | |
399 | // reading xml in | |
400 | // ---------------------------------------------------------------------------- | |
401 | ||
402 | /* | |
403 | Reading components has not to be extended for components | |
404 | as properties are always sought by typeinfo over all levels | |
405 | and create params are always toplevel class only | |
406 | */ | |
407 | ||
408 | ||
409 | // ---------------------------------------------------------------------------- | |
410 | // depersisting to memory | |
411 | // ---------------------------------------------------------------------------- | |
412 | ||
413 | struct wxRuntimeDepersister::wxRuntimeDepersisterInternal | |
414 | { | |
415 | map<int,wxObject *> m_objects; | |
416 | ||
417 | void SetObject(int objectID, wxObject *obj ) | |
418 | { | |
419 | if ( m_objects.find(objectID) != m_objects.end() ) | |
420 | { | |
421 | wxLogError( _("Passing a already registered object to SetObject") ) ; | |
422 | return ; | |
423 | } | |
424 | m_objects[objectID] = obj ; | |
425 | } | |
426 | wxObject* GetObject( int objectID ) | |
427 | { | |
428 | if ( objectID == wxNullObjectID ) | |
429 | return NULL ; | |
430 | if ( m_objects.find(objectID) == m_objects.end() ) | |
431 | { | |
432 | wxLogError( _("Passing an unknown object to GetObject") ) ; | |
433 | return NULL ; | |
434 | } | |
435 | ||
436 | return m_objects[objectID] ; | |
437 | } | |
438 | } ; | |
439 | ||
440 | wxRuntimeDepersister::wxRuntimeDepersister() | |
441 | { | |
442 | m_data = new wxRuntimeDepersisterInternal() ; | |
443 | } | |
444 | ||
445 | wxRuntimeDepersister::~wxRuntimeDepersister() | |
446 | { | |
447 | delete m_data ; | |
448 | } | |
449 | ||
450 | void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo , | |
451 | wxxVariantArray &WXUNUSED(metadata)) | |
452 | { | |
453 | wxObject *O; | |
454 | O = classInfo->CreateObject(); | |
455 | m_data->SetObject(objectID, O); | |
456 | } | |
457 | ||
458 | void wxRuntimeDepersister::CreateObject(int objectID, | |
459 | const wxClassInfo *classInfo, | |
460 | int paramCount, | |
461 | wxxVariant *params, | |
462 | int *objectIdValues, | |
463 | const wxClassInfo **objectClassInfos , | |
464 | wxxVariantArray &WXUNUSED(metadata)) | |
465 | { | |
466 | wxObject *o; | |
467 | o = m_data->GetObject(objectID); | |
468 | for ( int i = 0 ; i < paramCount ; ++i ) | |
469 | { | |
470 | if ( objectIdValues[i] != wxInvalidObjectID ) | |
471 | { | |
472 | wxObject *o; | |
473 | o = m_data->GetObject(objectIdValues[i]); | |
474 | // if this is a dynamic object and we are asked for another class | |
475 | // than wxDynamicObject we cast it down manually. | |
476 | wxDynamicObject *dyno = dynamic_cast< wxDynamicObject * > (o) ; | |
477 | if ( dyno!=NULL && (objectClassInfos[i] != dyno->GetClassInfo()) ) | |
478 | { | |
479 | o = dyno->GetSuperClassInstance() ; | |
480 | } | |
481 | params[i] = objectClassInfos[i]->InstanceToVariant(o) ; | |
482 | } | |
483 | } | |
484 | classInfo->Create(o, paramCount, params); | |
485 | } | |
486 | ||
487 | void wxRuntimeDepersister::ConstructObject(int objectID, | |
488 | const wxClassInfo *classInfo, | |
489 | int paramCount, | |
490 | wxxVariant *params, | |
491 | int *objectIdValues, | |
492 | const wxClassInfo **objectClassInfos , | |
493 | wxxVariantArray &WXUNUSED(metadata)) | |
494 | { | |
495 | wxObject *o; | |
496 | for ( int i = 0 ; i < paramCount ; ++i ) | |
497 | { | |
498 | if ( objectIdValues[i] != wxInvalidObjectID ) | |
499 | { | |
500 | wxObject *o; | |
501 | o = m_data->GetObject(objectIdValues[i]); | |
502 | // if this is a dynamic object and we are asked for another class | |
503 | // than wxDynamicObject we cast it down manually. | |
504 | wxDynamicObject *dyno = dynamic_cast< wxDynamicObject * > (o) ; | |
505 | if ( dyno!=NULL && (objectClassInfos[i] != dyno->GetClassInfo()) ) | |
506 | { | |
507 | o = dyno->GetSuperClassInstance() ; | |
508 | } | |
509 | params[i] = objectClassInfos[i]->InstanceToVariant(o) ; | |
510 | } | |
511 | } | |
512 | o = classInfo->ConstructObject(paramCount, params); | |
513 | m_data->SetObject(objectID, o); | |
514 | } | |
515 | ||
516 | ||
517 | void wxRuntimeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo)) | |
518 | { | |
519 | wxObject *o; | |
520 | o = m_data->GetObject(objectID); | |
521 | delete o ; | |
522 | } | |
523 | ||
524 | void wxRuntimeDepersister::SetProperty(int objectID, | |
525 | const wxClassInfo *classInfo, | |
526 | const wxPropertyInfo* propertyInfo, | |
527 | const wxxVariant &value) | |
528 | { | |
529 | wxObject *o; | |
530 | o = m_data->GetObject(objectID); | |
531 | classInfo->SetProperty( o , propertyInfo->GetName() , value ) ; | |
532 | } | |
533 | ||
534 | void wxRuntimeDepersister::SetPropertyAsObject(int objectID, | |
535 | const wxClassInfo *classInfo, | |
536 | const wxPropertyInfo* propertyInfo, | |
537 | int valueObjectId) | |
538 | { | |
539 | wxObject *o, *valo; | |
540 | o = m_data->GetObject(objectID); | |
541 | valo = m_data->GetObject(valueObjectId); | |
542 | const wxClassInfo* valClassInfo = (dynamic_cast<const wxClassTypeInfo*>(propertyInfo->GetTypeInfo()))->GetClassInfo() ; | |
543 | // if this is a dynamic object and we are asked for another class | |
544 | // than wxDynamicObject we cast it down manually. | |
545 | wxDynamicObject *dynvalo = dynamic_cast< wxDynamicObject * > (valo) ; | |
546 | if ( dynvalo!=NULL && (valClassInfo != dynvalo->GetClassInfo()) ) | |
547 | { | |
548 | valo = dynvalo->GetSuperClassInstance() ; | |
549 | } | |
550 | ||
551 | classInfo->SetProperty( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ; | |
552 | } | |
553 | ||
554 | void wxRuntimeDepersister::SetConnect(int eventSourceObjectID, | |
555 | const wxClassInfo *WXUNUSED(eventSourceClassInfo), | |
556 | const wxPropertyInfo *delegateInfo , | |
557 | const wxClassInfo *WXUNUSED(eventSinkClassInfo) , | |
558 | const wxHandlerInfo* handlerInfo , | |
559 | int eventSinkObjectID ) | |
560 | { | |
561 | wxEvtHandler *ehsource = dynamic_cast< wxEvtHandler* >( m_data->GetObject( eventSourceObjectID ) ) ; | |
562 | wxEvtHandler *ehsink = dynamic_cast< wxEvtHandler *>(m_data->GetObject(eventSinkObjectID) ) ; | |
563 | ||
564 | if ( ehsource && ehsink ) | |
565 | { | |
566 | const wxDelegateTypeInfo *delegateTypeInfo = dynamic_cast<const wxDelegateTypeInfo*>(delegateInfo->GetTypeInfo()); | |
567 | if( delegateTypeInfo && delegateTypeInfo->GetLastEventType() == -1 ) | |
568 | { | |
569 | ehsource->Connect( -1 , delegateTypeInfo->GetEventType() , | |
570 | handlerInfo->GetEventFunction() , NULL /*user data*/ , | |
571 | ehsink ) ; | |
572 | } | |
573 | else | |
574 | { | |
575 | for ( wxEventType iter = delegateTypeInfo->GetEventType() ; iter <= delegateTypeInfo->GetLastEventType() ; ++iter ) | |
576 | { | |
577 | ehsource->Connect( -1 , iter , | |
578 | handlerInfo->GetEventFunction() , NULL /*user data*/ , | |
579 | ehsink ) ; | |
580 | } | |
581 | } | |
582 | } | |
583 | } | |
584 | ||
585 | wxObject *wxRuntimeDepersister::GetObject(int objectID) | |
586 | { | |
587 | return m_data->GetObject( objectID ) ; | |
588 | } | |
589 | ||
590 | // adds an element to a property collection | |
591 | void wxRuntimeDepersister::AddToPropertyCollection( int objectID , | |
592 | const wxClassInfo *classInfo, | |
593 | const wxPropertyInfo* propertyInfo , | |
594 | const wxxVariant &value) | |
595 | { | |
596 | wxObject *o; | |
597 | o = m_data->GetObject(objectID); | |
598 | classInfo->AddToPropertyCollection( o , propertyInfo->GetName() , value ) ; | |
599 | } | |
600 | ||
601 | // sets the corresponding property (value is an object) | |
602 | void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID, | |
603 | const wxClassInfo *classInfo, | |
604 | const wxPropertyInfo* propertyInfo , | |
605 | int valueObjectId) | |
606 | { | |
607 | wxObject *o, *valo; | |
608 | o = m_data->GetObject(objectID); | |
609 | valo = m_data->GetObject(valueObjectId); | |
610 | const wxCollectionTypeInfo * collectionTypeInfo = dynamic_cast< const wxCollectionTypeInfo * >(propertyInfo->GetTypeInfo() ) ; | |
611 | const wxClassInfo* valClassInfo = (dynamic_cast<const wxClassTypeInfo*>(collectionTypeInfo->GetElementType()))->GetClassInfo() ; | |
612 | // if this is a dynamic object and we are asked for another class | |
613 | // than wxDynamicObject we cast it down manually. | |
614 | wxDynamicObject *dynvalo = dynamic_cast< wxDynamicObject * > (valo) ; | |
615 | if ( dynvalo!=NULL && (valClassInfo != dynvalo->GetClassInfo()) ) | |
616 | { | |
617 | valo = dynvalo->GetSuperClassInstance() ; | |
618 | } | |
619 | ||
620 | classInfo->AddToPropertyCollection( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ; | |
621 | } | |
622 | ||
623 | // ---------------------------------------------------------------------------- | |
624 | // depersisting to code | |
625 | // ---------------------------------------------------------------------------- | |
626 | ||
627 | struct wxCodeDepersister::wxCodeDepersisterInternal | |
628 | { | |
629 | #if wxUSE_UNICODE | |
630 | map<int,wstring> m_objectNames ; | |
631 | #else | |
632 | map<int,string> m_objectNames ; | |
633 | #endif | |
634 | ||
635 | void SetObjectName(int objectID, const wxString &name ) | |
636 | { | |
637 | if ( m_objectNames.find(objectID) != m_objectNames.end() ) | |
638 | { | |
639 | wxLogError( _("Passing a already registered object to SetObjectName") ) ; | |
640 | return ; | |
641 | } | |
642 | m_objectNames[objectID] = (const wxChar *)name; | |
643 | } | |
644 | ||
645 | wxString GetObjectName( int objectID ) | |
646 | { | |
647 | if ( objectID == wxNullObjectID ) | |
648 | return wxT("NULL") ; | |
649 | ||
650 | if ( m_objectNames.find(objectID) == m_objectNames.end() ) | |
651 | { | |
652 | wxLogError( _("Passing an unknown object to GetObject") ) ; | |
653 | return wxEmptyString ; | |
654 | } | |
655 | return wxString( m_objectNames[objectID].c_str() ) ; | |
656 | } | |
657 | } ; | |
658 | ||
659 | wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out) | |
660 | : m_fp(out) | |
661 | { | |
662 | m_data = new wxCodeDepersisterInternal ; | |
663 | } | |
664 | ||
665 | wxCodeDepersister::~wxCodeDepersister() | |
666 | { | |
667 | delete m_data ; | |
668 | } | |
669 | ||
670 | void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo , | |
671 | wxxVariantArray &WXUNUSED(metadata)) | |
672 | { | |
673 | wxString objectName = wxString::Format( wxT("LocalObject_%d") , objectID ) ; | |
674 | m_fp->WriteString( wxString::Format( wxT("\t%s *%s = new %s;\n"), | |
675 | classInfo->GetClassName(), | |
676 | objectName.c_str(), | |
677 | classInfo->GetClassName()) ); | |
678 | m_data->SetObjectName( objectID , objectName ) ; | |
679 | } | |
680 | ||
681 | void wxCodeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo)) | |
682 | { | |
683 | m_fp->WriteString( wxString::Format( wxT("\tdelete %s;\n"), | |
684 | m_data->GetObjectName( objectID).c_str() ) ); | |
685 | } | |
686 | ||
687 | wxString wxCodeDepersister::ValueAsCode( const wxxVariant ¶m ) | |
688 | { | |
689 | wxString value ; | |
690 | const wxTypeInfo* type = param.GetTypeInfo() ; | |
691 | if ( type->GetKind() == wxT_CUSTOM ) | |
692 | { | |
693 | const wxCustomTypeInfo* cti = dynamic_cast<const wxCustomTypeInfo*>(type) ; | |
694 | if ( cti ) | |
695 | { | |
696 | value.Printf( wxT("%s(%s)"), cti->GetTypeName().c_str(),param.GetAsString().c_str() ); | |
697 | } | |
698 | else | |
699 | { | |
700 | wxLogError ( _("Internal error, illegal wxCustomTypeInfo") ) ; | |
701 | } | |
702 | } | |
703 | else if ( type->GetKind() == wxT_STRING ) | |
704 | { | |
705 | value.Printf( wxT("\"%s\""),param.GetAsString().c_str() ); | |
706 | } | |
707 | else | |
708 | { | |
709 | value.Printf( wxT("%s"), param.GetAsString().c_str() ); | |
710 | } | |
711 | return value ; | |
712 | } | |
713 | ||
714 | void wxCodeDepersister::CreateObject(int objectID, | |
715 | const wxClassInfo *WXUNUSED(classInfo), | |
716 | int paramCount, | |
717 | wxxVariant *params, | |
718 | int *objectIDValues, | |
719 | const wxClassInfo **WXUNUSED(objectClassInfos) , | |
720 | wxxVariantArray &WXUNUSED(metadata) | |
721 | ) | |
722 | { | |
723 | int i; | |
724 | m_fp->WriteString( wxString::Format( wxT("\t%s->Create("), m_data->GetObjectName(objectID).c_str() ) ); | |
725 | for (i = 0; i < paramCount; i++) | |
726 | { | |
727 | if ( objectIDValues[i] != wxInvalidObjectID ) | |
728 | m_fp->WriteString( wxString::Format( wxT("%s"), m_data->GetObjectName( objectIDValues[i] ).c_str() ) ); | |
729 | else | |
730 | { | |
731 | m_fp->WriteString( wxString::Format( wxT("%s"), ValueAsCode(params[i]).c_str() ) ); | |
732 | } | |
733 | if (i < paramCount - 1) | |
734 | m_fp->WriteString( wxT(", ")); | |
735 | } | |
736 | m_fp->WriteString( wxT(");\n") ); | |
737 | } | |
738 | ||
739 | void wxCodeDepersister::ConstructObject(int objectID, | |
740 | const wxClassInfo *classInfo, | |
741 | int paramCount, | |
742 | wxxVariant *params, | |
743 | int *objectIDValues, | |
744 | const wxClassInfo **WXUNUSED(objectClassInfos) , | |
745 | wxxVariantArray &WXUNUSED(metadata) | |
746 | ) | |
747 | { | |
748 | wxString objectName = wxString::Format( wxT("LocalObject_%d") , objectID ) ; | |
749 | m_fp->WriteString( wxString::Format( wxT("\t%s *%s = new %s("), | |
750 | classInfo->GetClassName(), | |
751 | objectName.c_str(), | |
752 | classInfo->GetClassName()) ); | |
753 | m_data->SetObjectName( objectID , objectName ) ; | |
754 | ||
755 | int i; | |
756 | for (i = 0; i < paramCount; i++) | |
757 | { | |
758 | if ( objectIDValues[i] != wxInvalidObjectID ) | |
759 | m_fp->WriteString( wxString::Format( wxT("%s"), m_data->GetObjectName( objectIDValues[i] ).c_str() ) ); | |
760 | else | |
761 | { | |
762 | m_fp->WriteString( wxString::Format( wxT("%s"), ValueAsCode(params[i]).c_str() ) ); | |
763 | } | |
764 | if (i < paramCount - 1) | |
765 | m_fp->WriteString( wxT(", ") ); | |
766 | } | |
767 | m_fp->WriteString( wxT(");\n") ); | |
768 | } | |
769 | ||
770 | void wxCodeDepersister::SetProperty(int objectID, | |
771 | const wxClassInfo *WXUNUSED(classInfo), | |
772 | const wxPropertyInfo* propertyInfo, | |
773 | const wxxVariant &value) | |
774 | { | |
775 | m_fp->WriteString( wxString::Format( wxT("\t%s->%s(%s);\n"), | |
776 | m_data->GetObjectName(objectID).c_str(), | |
777 | propertyInfo->GetAccessor()->GetSetterName().c_str(), | |
778 | ValueAsCode(value).c_str()) ); | |
779 | } | |
780 | ||
781 | void wxCodeDepersister::SetPropertyAsObject(int objectID, | |
782 | const wxClassInfo *WXUNUSED(classInfo), | |
783 | const wxPropertyInfo* propertyInfo, | |
784 | int valueObjectId) | |
785 | { | |
786 | if ( propertyInfo->GetTypeInfo()->GetKind() == wxT_OBJECT ) | |
787 | m_fp->WriteString( wxString::Format( wxT("\t%s->%s(*%s);\n"), | |
788 | m_data->GetObjectName(objectID).c_str(), | |
789 | propertyInfo->GetAccessor()->GetSetterName().c_str(), | |
790 | m_data->GetObjectName( valueObjectId).c_str() ) ); | |
791 | else | |
792 | m_fp->WriteString( wxString::Format( wxT("\t%s->%s(%s);\n"), | |
793 | m_data->GetObjectName(objectID).c_str(), | |
794 | propertyInfo->GetAccessor()->GetSetterName().c_str(), | |
795 | m_data->GetObjectName( valueObjectId).c_str() ) ); | |
796 | } | |
797 | ||
798 | void wxCodeDepersister::AddToPropertyCollection( int objectID , | |
799 | const wxClassInfo *WXUNUSED(classInfo), | |
800 | const wxPropertyInfo* propertyInfo , | |
801 | const wxxVariant &value) | |
802 | { | |
803 | m_fp->WriteString( wxString::Format( wxT("\t%s->%s(%s);\n"), | |
804 | m_data->GetObjectName(objectID).c_str(), | |
805 | propertyInfo->GetAccessor()->GetAdderName().c_str(), | |
806 | ValueAsCode(value).c_str()) ); | |
807 | } | |
808 | ||
809 | // sets the corresponding property (value is an object) | |
810 | void wxCodeDepersister::AddToPropertyCollectionAsObject(int WXUNUSED(objectID), | |
811 | const wxClassInfo *WXUNUSED(classInfo), | |
812 | const wxPropertyInfo* WXUNUSED(propertyInfo) , | |
813 | int WXUNUSED(valueObjectId)) | |
814 | { | |
815 | // TODO | |
816 | } | |
817 | ||
818 | void wxCodeDepersister::SetConnect(int eventSourceObjectID, | |
819 | const wxClassInfo *WXUNUSED(eventSourceClassInfo), | |
820 | const wxPropertyInfo *delegateInfo , | |
821 | const wxClassInfo *eventSinkClassInfo , | |
822 | const wxHandlerInfo* handlerInfo , | |
823 | int eventSinkObjectID ) | |
824 | { | |
825 | wxString ehsource = m_data->GetObjectName( eventSourceObjectID ) ; | |
826 | wxString ehsink = m_data->GetObjectName(eventSinkObjectID) ; | |
827 | wxString ehsinkClass = eventSinkClassInfo->GetClassName() ; | |
828 | const wxDelegateTypeInfo *delegateTypeInfo = dynamic_cast<const wxDelegateTypeInfo*>(delegateInfo->GetTypeInfo()); | |
829 | if ( delegateTypeInfo ) | |
830 | { | |
831 | int eventType = delegateTypeInfo->GetEventType() ; | |
832 | wxString handlerName = handlerInfo->GetName() ; | |
833 | ||
834 | m_fp->WriteString( wxString::Format( wxT("\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;") , | |
835 | ehsource.c_str() , ehsource.c_str() , eventType , ehsinkClass.c_str() , handlerName.c_str() , ehsink.c_str() ) ); | |
836 | } | |
837 | else | |
838 | { | |
839 | wxLogError(_("delegate has no type info")); | |
840 | } | |
841 | } | |
842 | ||
843 | #include "wx/arrimpl.cpp" | |
844 | ||
845 | WX_DEFINE_OBJARRAY(wxxVariantArray) | |
846 | ||
847 | #endif // wxUSE_EXTENDED_RTTI |