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