]> git.saurik.com Git - wxWidgets.git/blob - src/common/xtistrm.cpp
added wxDynamicObject (kind of delegate, docs to come once this has calmed down)
[wxWidgets.git] / src / common / xtistrm.cpp
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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "xtistrm.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/hash.h"
25 #include "wx/object.h"
26 #endif
27
28 #include "wx/xml/xml.h"
29 #include "wx/tokenzr.h"
30 #include "wx/xtistrm.h"
31 #include "wx/txtstrm.h"
32
33 #if wxUSE_EXTENDED_RTTI
34 #include <map>
35 #include <vector>
36 #include <string>
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 map< string , int > m_writtenProperties ;
60 } ;
61
62 void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name )
63 {
64 if ( persister->BeforeWriteObject( object , classInfo , name ) )
65 {
66 if ( object == NULL || IsObjectKnown( object ) )
67 {
68 DoWriteObjectReference( NULL , NULL , object , classInfo , GetObjectID(object) , NULL ) ;
69 }
70 else
71 {
72 int oid = m_data->m_nextId++ ;
73 m_data->m_writtenObjects[object] = oid ;
74 // in case this object is a wxDynamicObject we also have to insert is superclass
75 // instance with the same id, so that object relations are streamed out correctly
76 const wxDynamicObject* dynobj = dynamic_cast<const wxDynamicObject *>( object ) ;
77 if ( dynobj )
78 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
79
80 DoBeginWriteObject( object , classInfo , oid , name ) ;
81 wxWriterInternalPropertiesData data ;
82 WriteAllProperties( object , classInfo , persister , &data ) ;
83 DoEndWriteObject( object , classInfo , oid , name ) ;
84 }
85 }
86 }
87
88 void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
89 {
90 const wxPropertyInfo *pi = ci->GetFirstProperty() ;
91 while( pi )
92 {
93 if ( data->m_writtenProperties.find( pi->GetName() ) == data->m_writtenProperties.end() )
94 {
95 data->m_writtenProperties[ pi->GetName() ] = 1 ;
96 const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( pi->GetTypeInfo() ) ;
97 if ( cti )
98 {
99 const wxClassInfo* pci = cti->GetClassInfo() ;
100 wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
101 if ( persister->BeforeWritePropertyAsObject( obj , ci , pi , value ) )
102 {
103 wxObject *vobj = pci->VariantToInstance( value ) ;
104 bool embeddedObject = cti->GetKind() == wxT_OBJECT ;
105
106 if ( vobj == NULL || IsObjectKnown( vobj ) )
107 {
108 DoWriteObjectReference( obj , ci , vobj , pci , GetObjectID(vobj) , pi ) ;
109 }
110 else
111 {
112 int oid = m_data->m_nextId++ ;
113 if ( !embeddedObject)
114 {
115 // insert this object and its id
116 m_data->m_writtenObjects[vobj] = oid ;
117 // in case this object is a wxDynamicObject we also have to insert is superclass
118 // instance with the same id, so that object relations are streamed out correctly
119 const wxDynamicObject* dynobj = dynamic_cast<const wxDynamicObject *>( vobj ) ;
120 if ( dynobj )
121 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
122 }
123
124 DoBeginWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ;
125 if ( vobj != NULL )
126 {
127 wxWriterInternalPropertiesData data ;
128 WriteAllProperties( vobj , pci , persister , &data ) ;
129 }
130 DoEndWriteParamAsObject( obj , ci , vobj , pci , oid , pi ) ;
131 }
132 }
133 }
134 else
135 {
136 const wxDelegateTypeInfo* dti = dynamic_cast< const wxDelegateTypeInfo* > ( pi->GetTypeInfo() ) ;
137 if ( dti )
138 {
139 const wxObject* sink = NULL ;
140 const wxHandlerInfo *handler = NULL ;
141
142 const wxWindow * evSource = dynamic_cast<const wxWindow *>(obj) ;
143 wxASSERT_MSG( evSource , wxT("Illegal Object Class (Non-Window) as Event Source") ) ;
144
145 wxList *dynamicEvents = evSource->GetDynamicEventTable() ;
146
147 if ( dynamicEvents )
148 {
149 wxList::compatibility_iterator node = dynamicEvents->GetFirst();
150 while (node)
151 {
152 wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
153
154 // find the match
155 if ( entry->m_fn && (dti->GetEventType() == entry->m_eventType) &&
156 (entry->m_id == -1 ||
157 (entry->m_lastId == -1 && evSource->GetId() == entry->m_id) ||
158 (entry->m_lastId != -1 &&
159 (evSource->GetId() >= entry->m_id && evSource->GetId() <= entry->m_lastId) ) ) &&
160 entry->m_eventSink
161 )
162 {
163 sink = entry->m_eventSink ;
164 const wxClassInfo* sinkClassInfo = sink->GetClassInfo() ;
165 const wxHandlerInfo* sinkHandler = sinkClassInfo->GetFirstHandler() ;
166 while ( sinkHandler )
167 {
168 if ( sinkHandler->GetEventFunction() == entry->m_fn )
169 {
170 handler = sinkHandler ;
171 break ;
172 }
173 sinkHandler = sinkHandler->GetNext() ;
174 }
175 break ;
176 }
177 node = node->GetNext();
178 }
179 }
180 if ( persister->BeforeWriteDelegate( obj , ci , pi , sink , handler ) )
181 {
182 if ( sink != NULL && handler != NULL )
183 {
184 wxASSERT_MSG( IsObjectKnown( sink ) , wxT("Streaming delegates for not already streamed objects not yet supported") ) ;
185 DoWriteDelegate( obj , ci , pi , sink , GetObjectID( sink ) , sink->GetClassInfo() , handler ) ;
186 }
187 }
188 }
189 else
190 {
191 wxxVariant value = pi->GetAccessor()->GetProperty(obj) ;
192 if ( persister->BeforeWriteProperty( obj , ci , pi , value ) )
193 {
194 DoWriteProperty( obj , ci , pi , value ) ;
195 }
196 }
197 }
198 }
199 pi = pi->GetNext() ;
200 }
201 // in case this object is wxDynamic object we have to hand over the streaming
202 // of the properties of the superclasses to the real super class instance
203 const wxDynamicObject* dynobj = dynamic_cast< const wxDynamicObject* > (obj ) ;
204 if ( dynobj )
205 obj = dynobj->GetSuperClassInstance() ;
206 const wxClassInfo** parents = ci->GetParents() ;
207 for ( int i = 0 ; parents[i] ; ++ i )
208 {
209 WriteAllProperties( obj , parents[i] , persister , data ) ;
210 }
211 }
212
213 int wxWriter::GetObjectID(const wxObject *obj)
214 {
215 if ( !IsObjectKnown( obj ) )
216 return wxInvalidObjectID ;
217
218 return m_data->m_writtenObjects[obj] ;
219 }
220
221 bool wxWriter::IsObjectKnown( const wxObject *obj )
222 {
223 return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ;
224 }
225
226 //
227 // XML Streaming
228 //
229
230 // convenience functions
231
232 void wxXmlAddContentToNode( wxXmlNode* node , const wxString& data )
233 {
234 node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, "value", data ) );
235 }
236
237 wxString wxXmlGetContentFromNode( wxXmlNode *node )
238 {
239 if ( node->GetChildren() )
240 return node->GetChildren()->GetContent() ;
241 else
242 return wxEmptyString ;
243 }
244
245 struct wxXmlWriter::wxXmlWriterInternal
246 {
247 wxXmlNode *m_root ;
248 wxXmlNode *m_current ;
249 vector< wxXmlNode * > m_objectStack ;
250 } ;
251
252 wxXmlWriter::wxXmlWriter( wxXmlNode * rootnode )
253 {
254 m_data = new wxXmlWriterInternal() ;
255 m_data->m_root = rootnode ;
256 m_data->m_current = rootnode ;
257 }
258
259 wxXmlWriter::~wxXmlWriter()
260 {
261 delete m_data ;
262 }
263
264 // start of writing the root object
265 void wxXmlWriter::DoBeginWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *classInfo, int objectID , const wxString &name )
266 {
267 wxXmlNode *onode;
268 onode = new wxXmlNode(wxXML_ELEMENT_NODE, name);
269 onode->AddProperty(wxString("class"), wxString(classInfo->GetClassName()));
270 onode->AddProperty(wxString("id"), wxString::Format( "%d" , objectID ) );
271
272 m_data->m_current->AddChild(onode) ;
273 m_data->m_objectStack.push_back( m_data->m_current ) ;
274 m_data->m_current = onode ;
275 }
276
277 // end of writing the root object
278 void wxXmlWriter::DoEndWriteObject(const wxObject *WXUNUSED(object), const wxClassInfo *WXUNUSED(classInfo), int WXUNUSED(objectID) , const wxString &WXUNUSED(name) )
279 {
280 m_data->m_current = m_data->m_objectStack.back() ;
281 m_data->m_objectStack.pop_back() ;
282 }
283
284 // writes a property in the stream format
285 void wxXmlWriter::DoWriteProperty( const wxObject *WXUNUSED(obj), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi , wxxVariant &value )
286 {
287 wxXmlNode *pnode;
288 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
289 wxXmlAddContentToNode( pnode ,value.GetAsString() ) ;
290 m_data->m_current->AddChild(pnode);
291 }
292
293 void wxXmlWriter::DoBeginWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject),
294 const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
295 {
296 wxXmlNode *onode;
297 onode = new wxXmlNode(wxXML_ELEMENT_NODE, propInfo->GetName());
298 onode->AddProperty(wxString("class"), wxString(valueObjectClassInfo->GetClassName()));
299 onode->AddProperty(wxString("id"), wxString::Format( "%d" , valueObjectID ) );
300 m_data->m_current->AddChild(onode) ;
301 m_data->m_objectStack.push_back( m_data->m_current ) ;
302 m_data->m_current = onode ;
303 }
304
305 // insert an object reference to an already written object
306 void wxXmlWriter::DoWriteObjectReference(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *valueObject,
307 const wxClassInfo *valueObjectClassInfo, int valueObjectID , const wxPropertyInfo *propInfo )
308 {
309 wxXmlNode *onode;
310 onode = new wxXmlNode(wxXML_ELEMENT_NODE, propInfo->GetName());
311 onode->AddProperty(wxString("class"), wxString(valueObjectClassInfo->GetClassName()));
312 if ( valueObject == NULL )
313 {
314 wxXmlNode* nullnode = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, "null");
315 onode->AddChild(nullnode);
316 }
317 else
318 {
319 onode->AddProperty(wxString("id"), wxString::Format( "%d" , valueObjectID ) );
320 }
321
322 m_data->m_current->AddChild(onode) ;
323 }
324
325 void wxXmlWriter::DoEndWriteParamAsObject(const wxObject *WXUNUSED(parentObject), const wxClassInfo *WXUNUSED(parentClassInfo), const wxObject *WXUNUSED(valueObject),
326 const wxClassInfo *WXUNUSED(valueObjectClassInfo), int WXUNUSED(valueObjectID) , const wxPropertyInfo *WXUNUSED(propInfo) )
327 {
328 m_data->m_current = m_data->m_objectStack.back() ;
329 m_data->m_objectStack.pop_back() ;
330 }
331
332
333 // writes a delegate in the stream format
334 void wxXmlWriter::DoWriteDelegate( const wxObject *WXUNUSED(object), const wxClassInfo* WXUNUSED(classInfo) , const wxPropertyInfo *pi ,
335 const wxObject *eventSink, int sinkObjectID , const wxClassInfo* WXUNUSED(eventSinkClassInfo) , const wxHandlerInfo* handlerInfo )
336 {
337 if ( eventSink != NULL && handlerInfo != NULL )
338 {
339 wxXmlNode *pnode;
340 pnode = new wxXmlNode(wxXML_ELEMENT_NODE, pi->GetName() );
341 wxString s ;
342 s.Printf(wxT("%d.%s"), sinkObjectID , handlerInfo->GetName() ) ;
343 wxXmlAddContentToNode( pnode ,s ) ;
344 m_data->m_current->AddChild(pnode);
345 }
346 }
347
348 // ----------------------------------------------------------------------------
349 // reading objects in
350 // ----------------------------------------------------------------------------
351
352 struct wxReader::wxReaderInternal
353 {
354 map<int,wxClassInfo*> m_classInfos;
355 };
356
357 wxReader::wxReader()
358 {
359 m_data = new wxReaderInternal;
360 }
361
362 wxReader::~wxReader()
363 {
364 delete m_data;
365 }
366
367 wxClassInfo* wxReader::GetObjectClassInfo(int objectID)
368 {
369 assert( m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() );
370 return m_data->m_classInfos[objectID] ;
371 }
372
373 void wxReader::SetObjectClassInfo(int objectID, wxClassInfo *classInfo )
374 {
375 assert( m_data->m_classInfos.find(objectID) == m_data->m_classInfos.end() ) ;
376 m_data->m_classInfos[objectID] = classInfo ;
377 }
378
379 bool wxReader::HasObjectClassInfo( int objectID )
380 {
381 return m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() ;
382 }
383
384
385 // ----------------------------------------------------------------------------
386 // reading xml in
387 // ----------------------------------------------------------------------------
388
389 /*
390 Reading components has not to be extended for components
391 as properties are always sought by typeinfo over all levels
392 and create params are always toplevel class only
393 */
394
395 int wxXmlReader::ReadComponent(wxXmlNode *node, wxDepersister *callbacks)
396 {
397 wxString className;
398 wxClassInfo *classInfo;
399
400 wxxVariant *createParams ;
401 int *createParamOids ;
402 const wxClassInfo** createClassInfos ;
403 wxXmlNode *children;
404 int objectID;
405
406 children = node->GetChildren();
407 if (!node->GetPropVal("class", &className))
408 {
409 // No class name. Eek. FIXME: error handling
410 return wxInvalidObjectID;
411 }
412 classInfo = wxClassInfo::FindClass(className);
413 if (children && children->GetType() == wxXML_TEXT_NODE)
414 {
415 assert( wxXmlGetContentFromNode(node) == "null" ) ;
416 // this must be a NULL component reference. We just bail out
417 return wxNullObjectID;
418 }
419
420 wxString ObjectIdString ;
421 if (!node->GetPropVal("id", &ObjectIdString))
422 {
423 // No object id. Eek. FIXME: error handling
424 return wxInvalidObjectID;
425 }
426
427 objectID = atoi( ObjectIdString.c_str() ) ;
428 // is this object already has been streamed in, return it here
429 if ( HasObjectClassInfo( objectID ) )
430 return objectID ;
431
432 // new object, start with allocation
433 // first make the object know to our internal registry
434 SetObjectClassInfo( objectID , classInfo ) ;
435
436 callbacks->AllocateObject(objectID, classInfo);
437
438 //
439 // stream back the Create parameters first
440 createParams = new wxxVariant[ classInfo->GetCreateParamCount() ] ;
441 createParamOids = new int[classInfo->GetCreateParamCount() ] ;
442 createClassInfos = new const wxClassInfo*[classInfo->GetCreateParamCount() ] ;
443
444 typedef map<string, wxXmlNode *> PropertyNodes ;
445 typedef vector<string> PropertyNames ;
446
447 PropertyNodes propertyNodes ;
448 PropertyNames propertyNames ;
449
450 while( children )
451 {
452 propertyNames.push_back( children->GetName().c_str() ) ;
453 propertyNodes[children->GetName().c_str()] = children ;
454 children = children->GetNext() ;
455 }
456
457 for ( int i = 0 ; i <classInfo->GetCreateParamCount() ; ++i )
458 {
459 const wxChar* paramName = classInfo->GetCreateParamName(i) ;
460 PropertyNodes::iterator propiter = propertyNodes.find( paramName ) ;
461 const wxPropertyInfo* pi = classInfo->FindPropertyInfo( paramName ) ;
462 // if we don't have the value of a create param set in the xml
463 // we use the default value
464 if ( propiter != propertyNodes.end() )
465 {
466 wxXmlNode* prop = propiter->second ;
467 if ( pi->GetTypeInfo()->IsObjectType() )
468 {
469 createParamOids[i] = ReadComponent( prop , callbacks ) ;
470 createClassInfos[i] = dynamic_cast<const wxClassTypeInfo*>(pi->GetTypeInfo())->GetClassInfo() ;
471 }
472 else
473 {
474 createParamOids[i] = wxInvalidObjectID ;
475 createParams[i] = ReadValue( prop , pi->GetAccessor() ) ;
476 createClassInfos[i] = NULL ;
477 }
478
479 for ( size_t j = 0 ; j < propertyNames.size() ; ++j )
480 {
481 if ( propertyNames[j] == paramName )
482 {
483 propertyNames[j] = "" ;
484 break ;
485 }
486 }
487 }
488 else
489 {
490 createParams[i] = pi->GetDefaultValue() ;
491 }
492 }
493
494 // got the parameters. Call the Create method
495 callbacks->CreateObject(objectID, classInfo,
496 classInfo->GetCreateParamCount(),
497 createParams, createParamOids, createClassInfos);
498
499 // now stream in the rest of the properties, in the sequence their properties were written in the xml
500 for ( size_t j = 0 ; j < propertyNames.size() ; ++j )
501 {
502 if ( propertyNames[j].length() )
503 {
504 PropertyNodes::iterator propiter = propertyNodes.find( propertyNames[j] ) ;
505 if ( propiter != propertyNodes.end() )
506 {
507 wxXmlNode* prop = propiter->second ;
508 const wxPropertyInfo* pi = classInfo->FindPropertyInfo( propertyNames[j].c_str() ) ;
509 if ( pi->GetTypeInfo()->IsObjectType() )
510 {
511 int valueId = ReadComponent( prop , callbacks ) ;
512 if ( callbacks )
513 {
514 if ( valueId != wxInvalidObjectID )
515 {
516 callbacks->SetPropertyAsObject( objectID , classInfo , pi , valueId ) ;
517 if ( pi->GetTypeInfo()->GetKind() == wxT_OBJECT && valueId != wxNullObjectID )
518 callbacks->DestroyObject( valueId , GetObjectClassInfo( valueId ) ) ;
519 }
520 }
521 }
522 else if ( pi->GetTypeInfo()->IsDelegateType() )
523 {
524 wxString resstring = wxXmlGetContentFromNode(prop) ;
525 wxInt32 pos = resstring.Find('.') ;
526 assert( pos != wxNOT_FOUND ) ;
527 int sinkOid = atol(resstring.Left(pos)) ;
528 wxString handlerName = resstring.Mid(pos+1) ;
529 wxClassInfo* sinkClassInfo = GetObjectClassInfo( sinkOid ) ;
530
531 if (callbacks)
532 callbacks->SetConnect( objectID , classInfo , dynamic_cast<const wxDelegateTypeInfo*>(pi->GetTypeInfo()) , sinkClassInfo ,
533 sinkClassInfo->FindHandlerInfo(handlerName) , sinkOid ) ;
534
535 }
536 else
537 {
538 if ( callbacks )
539 callbacks->SetProperty( objectID, classInfo ,pi , ReadValue( prop , pi->GetAccessor() ) ) ;
540 }
541 }
542 }
543 }
544
545 delete[] createParams ;
546 delete[] createParamOids ;
547 delete[] createClassInfos ;
548
549 return objectID;
550 }
551
552 wxxVariant wxXmlReader::ReadValue(wxXmlNode *node,
553 wxPropertyAccessor *accessor )
554 {
555 return accessor->ReadValue(wxXmlGetContentFromNode( node ) ) ;
556 }
557
558 int wxXmlReader::ReadObject(wxDepersister *callbacks)
559 {
560 return ReadComponent( m_parent , callbacks ) ;
561 }
562
563 // ----------------------------------------------------------------------------
564 // depersisting to memory
565 // ----------------------------------------------------------------------------
566
567 struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
568 {
569 map<int,wxObject *> m_objects;
570
571 void SetObject(int objectID, wxObject *obj )
572 {
573 assert( m_objects.find(objectID) == m_objects.end() ) ;
574 m_objects[objectID] = obj ;
575 }
576 wxObject* GetObject( int objectID )
577 {
578 if ( objectID == wxNullObjectID )
579 return NULL ;
580
581 assert( m_objects.find(objectID) != m_objects.end() ) ;
582 return m_objects[objectID] ;
583 }
584 } ;
585
586 wxRuntimeDepersister::wxRuntimeDepersister()
587 {
588 m_data = new wxRuntimeDepersisterInternal() ;
589 }
590
591 wxRuntimeDepersister::~wxRuntimeDepersister()
592 {
593 delete m_data ;
594 }
595
596 void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo)
597 {
598 wxObject *O;
599 O = classInfo->CreateObject();
600 m_data->SetObject(objectID, O);
601 }
602
603 void wxRuntimeDepersister::CreateObject(int objectID,
604 const wxClassInfo *classInfo,
605 int paramCount,
606 wxxVariant *params,
607 int *objectIdValues,
608 const wxClassInfo **objectClassInfos)
609 {
610 wxObject *o;
611 o = m_data->GetObject(objectID);
612 for ( int i = 0 ; i < paramCount ; ++i )
613 {
614 if ( objectIdValues[i] != wxInvalidObjectID )
615 {
616 wxObject *o;
617 o = m_data->GetObject(objectIdValues[i]);
618 // if this is a dynamic object and we are asked for another class
619 // than wxDynamicObject we cast it down manually.
620 wxDynamicObject *dyno = dynamic_cast< wxDynamicObject * > (o) ;
621 if ( dyno!=NULL && (objectClassInfos[i] != dyno->GetClassInfo()) )
622 {
623 o = dyno->GetSuperClassInstance() ;
624 }
625 params[i] = objectClassInfos[i]->InstanceToVariant(o) ;
626 }
627 }
628 classInfo->Create(o, paramCount, params);
629 }
630
631 void wxRuntimeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
632 {
633 wxObject *o;
634 o = m_data->GetObject(objectID);
635 delete o ;
636 }
637
638 void wxRuntimeDepersister::SetProperty(int objectID,
639 const wxClassInfo *classInfo,
640 const wxPropertyInfo* propertyInfo,
641 const wxxVariant &value)
642 {
643 wxObject *o;
644 o = m_data->GetObject(objectID);
645 classInfo->SetProperty( o , propertyInfo->GetName() , value ) ;
646 // propertyInfo->GetAccessor()->SetProperty( o , value ) ;
647 }
648
649 void wxRuntimeDepersister::SetPropertyAsObject(int objectID,
650 const wxClassInfo *classInfo,
651 const wxPropertyInfo* propertyInfo,
652 int valueObjectId)
653 {
654 wxObject *o, *valo;
655 o = m_data->GetObject(objectID);
656 valo = m_data->GetObject(valueObjectId);
657 const wxClassInfo* valClassInfo = (dynamic_cast<const wxClassTypeInfo*>(propertyInfo->GetTypeInfo()))->GetClassInfo() ;
658 // if this is a dynamic object and we are asked for another class
659 // than wxDynamicObject we cast it down manually.
660 wxDynamicObject *dynvalo = dynamic_cast< wxDynamicObject * > (valo) ;
661 if ( dynvalo!=NULL && (valClassInfo != dynvalo->GetClassInfo()) )
662 {
663 valo = dynvalo->GetSuperClassInstance() ;
664 }
665
666 classInfo->SetProperty( o , propertyInfo->GetName() , valClassInfo->InstanceToVariant(valo) ) ;
667 // propertyInfo->GetAccessor()->SetProperty( o ,
668 // (dynamic_cast<const wxClassTypeInfo*>(propertyInfo->GetTypeInfo()))->GetClassInfo()->InstanceToVariant(valo) ) ;
669 }
670
671 void wxRuntimeDepersister::SetConnect(int eventSourceObjectID,
672 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
673 const wxDelegateTypeInfo *delegateInfo ,
674 const wxClassInfo *WXUNUSED(eventSinkClassInfo) ,
675 const wxHandlerInfo* handlerInfo ,
676 int eventSinkObjectID )
677 {
678 wxWindow *ehsource = dynamic_cast< wxWindow* >( m_data->GetObject( eventSourceObjectID ) ) ;
679 wxEvtHandler *ehsink = dynamic_cast< wxEvtHandler *>(m_data->GetObject(eventSinkObjectID) ) ;
680
681 if ( ehsource && ehsink )
682 {
683 ehsource->Connect( ehsource->GetId() , delegateInfo->GetEventType() ,
684 handlerInfo->GetEventFunction() , NULL /*user data*/ ,
685 ehsink ) ;
686 }
687 }
688
689 wxObject *wxRuntimeDepersister::GetObject(int objectID)
690 {
691 return m_data->GetObject( objectID ) ;
692 }
693
694
695 // ----------------------------------------------------------------------------
696 // depersisting to code
697 // ----------------------------------------------------------------------------
698
699 struct wxCodeDepersister::wxCodeDepersisterInternal
700 {
701 map<int,string> m_objectNames ;
702
703 void SetObjectName(int objectID, const wxString &name )
704 {
705 assert( m_objectNames.find(objectID) == m_objectNames.end() ) ;
706 m_objectNames[objectID] = (const char *)name;
707 }
708 wxString GetObjectName( int objectID )
709 {
710 if ( objectID == wxNullObjectID )
711 return "NULL" ;
712
713 assert( m_objectNames.find(objectID) != m_objectNames.end() ) ;
714 return wxString( m_objectNames[objectID].c_str() ) ;
715 }
716 } ;
717
718 wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out)
719 : m_fp(out)
720 {
721 m_data = new wxCodeDepersisterInternal ;
722 }
723
724 wxCodeDepersister::~wxCodeDepersister()
725 {
726 delete m_data ;
727 }
728
729 void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo)
730 {
731 wxString objectName = wxString::Format( "LocalObject_%d" , objectID ) ;
732 m_fp->WriteString( wxString::Format( "\t%s *%s = new %s;\n",
733 classInfo->GetClassName(),
734 objectName,
735 classInfo->GetClassName()) );
736 m_data->SetObjectName( objectID , objectName ) ;
737 }
738
739 void wxCodeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
740 {
741 m_fp->WriteString( wxString::Format( "\tdelete %s;\n",
742 m_data->GetObjectName( objectID) ) );
743 }
744
745 wxString wxCodeDepersister::ValueAsCode( const wxxVariant &param )
746 {
747 wxString value ;
748 const wxTypeInfo* type = param.GetTypeInfo() ;
749 if ( type->GetKind() == wxT_CUSTOM )
750 {
751 const wxCustomTypeInfo* cti = dynamic_cast<const wxCustomTypeInfo*>(type) ;
752 wxASSERT_MSG( cti , wxT("Internal error, illegal wxCustomTypeInfo") ) ;
753 value.Printf( "%s(%s)",cti->GetTypeName(),param.GetAsString() );
754 }
755 else if ( type->GetKind() == wxT_STRING )
756 {
757 value.Printf( "\"%s\"",param.GetAsString() );
758 }
759 else
760 {
761 value.Printf( "%s", param.GetAsString() );
762 }
763 return value ;
764 }
765
766 void wxCodeDepersister::CreateObject(int objectID,
767 const wxClassInfo *WXUNUSED(classInfo),
768 int paramCount,
769 wxxVariant *params,
770 int *objectIDValues,
771 const wxClassInfo **WXUNUSED(objectClassInfos)
772 )
773 {
774 int i;
775 m_fp->WriteString( wxString::Format( "\t%s->Create(", m_data->GetObjectName(objectID) ) );
776 for (i = 0; i < paramCount; i++)
777 {
778 if ( objectIDValues[i] != wxInvalidObjectID )
779 m_fp->WriteString( wxString::Format( "%s", m_data->GetObjectName( objectIDValues[i] ) ) );
780 else
781 {
782 m_fp->WriteString( wxString::Format( "%s", ValueAsCode(params[i]) ) );
783 }
784 if (i < paramCount - 1)
785 m_fp->WriteString( ", ");
786 }
787 m_fp->WriteString( ");\n");
788 }
789
790 void wxCodeDepersister::SetProperty(int objectID,
791 const wxClassInfo *WXUNUSED(classInfo),
792 const wxPropertyInfo* propertyInfo,
793 const wxxVariant &value)
794 {
795 m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
796 m_data->GetObjectName(objectID),
797 propertyInfo->GetAccessor()->GetSetterName(),
798 ValueAsCode(value)) );
799 }
800
801 void wxCodeDepersister::SetPropertyAsObject(int objectID,
802 const wxClassInfo *WXUNUSED(classInfo),
803 const wxPropertyInfo* propertyInfo,
804 int valueObjectId)
805 {
806 if ( propertyInfo->GetTypeInfo()->GetKind() == wxT_OBJECT )
807 m_fp->WriteString( wxString::Format( "\t%s->%s(*%s);\n",
808 m_data->GetObjectName(objectID),
809 propertyInfo->GetAccessor()->GetSetterName(),
810 m_data->GetObjectName( valueObjectId) ) );
811 else
812 m_fp->WriteString( wxString::Format( "\t%s->%s(%s);\n",
813 m_data->GetObjectName(objectID),
814 propertyInfo->GetAccessor()->GetSetterName(),
815 m_data->GetObjectName( valueObjectId) ) );
816 }
817
818 void wxCodeDepersister::SetConnect(int eventSourceObjectID,
819 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
820 const wxDelegateTypeInfo *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 int eventType = delegateInfo->GetEventType() ;
829 wxString handlerName = handlerInfo->GetName() ;
830
831 m_fp->WriteString( wxString::Format( "\t%s->Connect( %s->GetId() , %d , (wxObjectEventFunction)(wxEventFunction) & %s::%s , NULL , %s ) ;" ,
832 ehsource , ehsource , eventType , ehsinkClass , handlerName , ehsink ) );
833 }
834
835 #endif