]> git.saurik.com Git - wxWidgets.git/blame - src/common/xtistrm.cpp
fix wxMBConv_iconv to respect the base class conventions: when the input is NUL-termi...
[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
70e88103
SC
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
8e3f3880 16 #pragma hdrstop
70e88103
SC
17#endif
18
8e3f3880
WS
19#if wxUSE_EXTENDED_RTTI
20
d5da0ce7
WS
21#include "wx/xtistrm.h"
22
70e88103 23#ifndef WX_PRECOMP
8e3f3880
WS
24 #include "wx/object.h"
25 #include "wx/hash.h"
d5da0ce7 26 #include "wx/event.h"
70e88103
SC
27#endif
28
70e88103 29#include "wx/tokenzr.h"
70e88103 30#include "wx/txtstrm.h"
8347b97a 31
ab6e4913 32#include "wx/beforestd.h"
70e88103
SC
33#include <map>
34#include <vector>
35#include <string>
ab6e4913 36#include "wx/afterstd.h"
70e88103
SC
37
38using namespace std ;
39
16776ad9
SC
40struct wxWriter::wxWriterInternal
41{
42 map< const wxObject* , int > m_writtenObjects ;
43 int m_nextId ;
44} ;
45
46wxWriter::wxWriter()
47{
48 m_data = new wxWriterInternal ;
49 m_data->m_nextId = 0 ;
50}
51
52wxWriter::~wxWriter()
53{
54 delete m_data ;
55}
56
57struct wxWriter::wxWriterInternalPropertiesData
58{
cb73e600 59 char nothing ;
16776ad9
SC
60} ;
61
ab6e4913
SC
62void wxWriter::ClearObjectContext()
63{
64 delete m_data ;
65 m_data = new wxWriterInternal() ;
66 m_data->m_nextId = 0 ;
67}
68
4f8ffae1 69void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , const wxString &name , wxxVariantArray &metadata )
16776ad9 70{
ab6e4913 71 DoBeginWriteTopLevelEntry( name ) ;
4f8ffae1 72 WriteObject( object , classInfo , persister , false , metadata) ;
ab6e4913
SC
73 DoEndWriteTopLevelEntry( name ) ;
74}
75
4f8ffae1 76void wxWriter::WriteObject(const wxObject *object, const wxClassInfo *classInfo , wxPersister *persister , bool isEmbedded, wxxVariantArray &metadata )
ab6e4913 77{
9c8046dd 78 if ( !classInfo->BeforeWriteObject( object , this , persister , metadata) )
c90b8250
SC
79 return ;
80
4f8ffae1 81 if ( persister->BeforeWriteObject( this , object , classInfo , metadata) )
16776ad9 82 {
ab6e4913
SC
83 if ( object == NULL )
84 DoWriteNullObject() ;
85 else if ( IsObjectKnown( object ) )
86 DoWriteRepeatedObject( GetObjectID(object) ) ;
2d51f067
SC
87 else
88 {
89 int oid = m_data->m_nextId++ ;
ab6e4913
SC
90 if ( !isEmbedded )
91 m_data->m_writtenObjects[object] = oid ;
92
2d51f067
SC
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 ) ;
ab6e4913 96 if ( !isEmbedded && dynobj )
2d51f067
SC
97 m_data->m_writtenObjects[dynobj->GetSuperClassInstance()] = oid ;
98
4f8ffae1 99 DoBeginWriteObject( object , classInfo , oid , metadata ) ;
2d51f067
SC
100 wxWriterInternalPropertiesData data ;
101 WriteAllProperties( object , classInfo , persister , &data ) ;
ab6e4913 102 DoEndWriteObject( object , classInfo , oid ) ;
2d51f067 103 }
ab6e4913 104 persister->AfterWriteObject( this ,object , classInfo ) ;
16776ad9
SC
105 }
106}
107
9c8046dd 108void wxWriter::FindConnectEntry(const wxEvtHandler * evSource,const wxDelegateTypeInfo* dti, const wxObject* &sink , const wxHandlerInfo *&handler)
ab6e4913
SC
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
2abce515 120 if ( entry->m_fn &&
9c8046dd
SC
121 (dti->GetEventType() == entry->m_eventType) &&
122 (entry->m_id == -1 ) &&
123 (entry->m_eventSink != NULL ) )
ab6e4913
SC
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}
16776ad9
SC
143void wxWriter::WriteAllProperties( const wxObject * obj , const wxClassInfo* ci , wxPersister *persister, wxWriterInternalPropertiesData * data )
144{
cb73e600
SC
145 wxPropertyInfoMap map ;
146 ci->GetProperties( map ) ;
147 for ( int i = 0 ; i < ci->GetCreateParamCount() ; ++i )
16a45a23 148 {
cb73e600
SC
149 wxString name = ci->GetCreateParamName(i) ;
150 const wxPropertyInfo* prop = map.find(name)->second ;
8f2b1cfd
SC
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 }
cb73e600
SC
159 map.erase( name ) ;
160 }
af498247
VZ
161 { // Extra block for broken compilers
162 for( wxPropertyInfoMap::iterator iter = map.begin() ; iter != map.end() ; ++iter )
cb73e600 163 {
af498247
VZ
164 const wxPropertyInfo* prop = iter->second ;
165 if ( prop->GetFlags() & wxPROP_OBJECT_GRAPH )
166 {
167 WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ;
168 }
cb73e600
SC
169 }
170 }
af498247
VZ
171 { // Extra block for broken compilers
172 for( wxPropertyInfoMap::iterator iter = map.begin() ; iter != map.end() ; ++iter )
16a45a23 173 {
af498247
VZ
174 const wxPropertyInfo* prop = iter->second ;
175 if ( !(prop->GetFlags() & wxPROP_OBJECT_GRAPH) )
176 {
177 WriteOneProperty( obj , prop->GetDeclaringClass() , prop , persister , data ) ;
178 }
16a45a23
SC
179 }
180 }
cb73e600
SC
181}
182
2abce515 183void wxWriter::WriteOneProperty( const wxObject *obj , const wxClassInfo* ci , const wxPropertyInfo* pi , wxPersister *persister , wxWriterInternalPropertiesData *WXUNUSED(data) )
cb73e600 184{
9c8046dd
SC
185 if ( pi->GetFlags() & wxPROP_DONT_STREAM )
186 return ;
187
cb73e600
SC
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() ;
16a45a23 192
cb73e600 193 if ( pi->GetTypeInfo()->GetKind() == wxT_COLLECTION )
16776ad9 194 {
cb73e600
SC
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 )
16776ad9 199 {
ed45345e
SC
200 if ( i == 0 )
201 DoBeginWriteProperty( pi ) ;
202
cb73e600
SC
203 DoBeginWriteElement() ;
204 wxxVariant value = data[i] ;
8805dbab 205 if ( persister->BeforeWriteProperty( this , obj, pi , value ) )
16776ad9 206 {
cb73e600
SC
207 const wxClassTypeInfo* cti = dynamic_cast< const wxClassTypeInfo* > ( elementType ) ;
208 if ( cti )
16776ad9 209 {
cb73e600
SC
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 ) ;
16776ad9 214 }
cb73e600 215 else
16776ad9 216 {
2abce515 217 DoWriteSimpleType( value ) ;
cb73e600
SC
218 }
219 }
220 DoEndWriteElement() ;
ed45345e
SC
221 if ( i == data.GetCount() - 1 )
222 DoEndWriteProperty( pi ) ;
223 }
224 }
cb73e600
SC
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 ;
ab6e4913 232
9c8046dd 233 const wxEvtHandler * evSource = dynamic_cast<const wxEvtHandler *>(obj) ;
8f2b1cfd 234 if ( evSource )
cb73e600 235 {
8f2b1cfd
SC
236 FindConnectEntry( evSource , dti , sink , handler ) ;
237 if ( persister->BeforeWriteDelegate( this , obj , ci , pi , sink , handler ) )
cb73e600 238 {
8f2b1cfd
SC
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 }
16776ad9 252 }
cb73e600 253 }
8f2b1cfd
SC
254 else
255 {
256 wxLogError(_("Illegal Object Class (Non-wxEvtHandler) as Event Source") ) ;
257 }
cb73e600
SC
258 }
259 else
260 {
261 wxxVariant value ;
262 pi->GetAccessor()->GetProperty(obj, value) ;
ed45345e
SC
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() ) ;
8f2b1cfd
SC
271 if ( eti )
272 {
2c4c3987 273 eti->ConvertFromLong( value.wxTEMPLATED_MEMBER_CALL(Get , long) , value ) ;
8f2b1cfd
SC
274 }
275 else
276 {
277 wxLogError( _("Type must have enum - long conversion") ) ;
278 }
ed45345e
SC
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 }
cab1a605 287
ed45345e
SC
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
8805dbab 294 if ( persister->BeforeWriteProperty( this , obj, pi , value ) )
cb73e600 295 {
ed45345e 296 DoBeginWriteProperty( pi ) ;
cb73e600 297 if ( cti )
16776ad9 298 {
cb73e600
SC
299 const wxClassInfo* pci = cti->GetClassInfo() ;
300 wxObject *vobj = pci->VariantToInstance( value ) ;
ed45345e
SC
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 }
cb73e600
SC
313 }
314 else
2abce515 315 {
cb73e600 316 DoWriteSimpleType( value ) ;
16776ad9 317 }
ed45345e 318 DoEndWriteProperty( pi ) ;
16776ad9
SC
319 }
320 }
16776ad9 321 }
4f8ffae1 322}
70e88103 323
2abce515 324int wxWriter::GetObjectID(const wxObject *obj)
16776ad9
SC
325{
326 if ( !IsObjectKnown( obj ) )
327 return wxInvalidObjectID ;
328
329 return m_data->m_writtenObjects[obj] ;
330}
331
2abce515 332bool wxWriter::IsObjectKnown( const wxObject *obj )
16776ad9
SC
333{
334 return m_data->m_writtenObjects.find( obj ) != m_data->m_writtenObjects.end() ;
335}
336
70e88103
SC
337
338// ----------------------------------------------------------------------------
2abce515 339// reading objects in
70e88103
SC
340// ----------------------------------------------------------------------------
341
70e88103
SC
342struct wxReader::wxReaderInternal
343{
45212047 344 map<int,wxClassInfo*> m_classInfos;
70e88103
SC
345};
346
2abce515 347wxReader::wxReader()
70e88103 348{
45212047 349 m_data = new wxReaderInternal;
70e88103
SC
350}
351
352wxReader::~wxReader()
353{
45212047 354 delete m_data;
70e88103
SC
355}
356
45212047 357wxClassInfo* wxReader::GetObjectClassInfo(int objectID)
70e88103 358{
8f2b1cfd
SC
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 }
45212047 369 return m_data->m_classInfos[objectID] ;
70e88103
SC
370}
371
45212047 372void wxReader::SetObjectClassInfo(int objectID, wxClassInfo *classInfo )
70e88103 373{
8f2b1cfd
SC
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 }
16776ad9 384 m_data->m_classInfos[objectID] = classInfo ;
70e88103
SC
385}
386
2abce515 387bool wxReader::HasObjectClassInfo( int objectID )
70e88103 388{
8f2b1cfd
SC
389 if ( objectID == wxNullObjectID || objectID == wxInvalidObjectID )
390 {
391 wxLogError( _("Invalid or Null Object ID passed to HasObjectClassInfo" ) ) ;
afc89ff4 392 return false ;
8f2b1cfd 393 }
16776ad9 394 return m_data->m_classInfos.find(objectID) != m_data->m_classInfos.end() ;
70e88103
SC
395}
396
70e88103 397
45212047 398// ----------------------------------------------------------------------------
2abce515 399// reading xml in
45212047 400// ----------------------------------------------------------------------------
70e88103 401
2abce515 402/*
16776ad9
SC
403Reading components has not to be extended for components
404as properties are always sought by typeinfo over all levels
405and create params are always toplevel class only
70e88103
SC
406*/
407
70e88103
SC
408
409// ----------------------------------------------------------------------------
2abce515 410// depersisting to memory
70e88103
SC
411// ----------------------------------------------------------------------------
412
45212047 413struct wxRuntimeDepersister::wxRuntimeDepersisterInternal
70e88103 414{
45212047
SC
415 map<int,wxObject *> m_objects;
416
16776ad9
SC
417 void SetObject(int objectID, wxObject *obj )
418 {
8f2b1cfd
SC
419 if ( m_objects.find(objectID) != m_objects.end() )
420 {
421 wxLogError( _("Passing a already registered object to SetObject") ) ;
422 return ;
423 }
16776ad9
SC
424 m_objects[objectID] = obj ;
425 }
426 wxObject* GetObject( int objectID )
427 {
428 if ( objectID == wxNullObjectID )
429 return NULL ;
8f2b1cfd
SC
430 if ( m_objects.find(objectID) == m_objects.end() )
431 {
432 wxLogError( _("Passing an unkown object to GetObject") ) ;
433 return NULL ;
434 }
16776ad9 435
16776ad9
SC
436 return m_objects[objectID] ;
437 }
45212047
SC
438} ;
439
440wxRuntimeDepersister::wxRuntimeDepersister()
441{
16776ad9 442 m_data = new wxRuntimeDepersisterInternal() ;
70e88103
SC
443}
444
45212047 445wxRuntimeDepersister::~wxRuntimeDepersister()
70e88103 446{
16776ad9 447 delete m_data ;
70e88103
SC
448}
449
4f8ffae1 450void wxRuntimeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo ,
9c8046dd 451 wxxVariantArray &WXUNUSED(metadata))
70e88103
SC
452{
453 wxObject *O;
45212047
SC
454 O = classInfo->CreateObject();
455 m_data->SetObject(objectID, O);
456}
457
458void wxRuntimeDepersister::CreateObject(int objectID,
16776ad9
SC
459 const wxClassInfo *classInfo,
460 int paramCount,
461 wxxVariant *params,
462 int *objectIdValues,
4f8ffae1 463 const wxClassInfo **objectClassInfos ,
9c8046dd 464 wxxVariantArray &WXUNUSED(metadata))
45212047
SC
465{
466 wxObject *o;
467 o = m_data->GetObject(objectID);
16776ad9
SC
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]);
2d51f067
SC
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 }
16776ad9
SC
481 params[i] = objectClassInfos[i]->InstanceToVariant(o) ;
482 }
483 }
45212047
SC
484 classInfo->Create(o, paramCount, params);
485}
486
ed45345e
SC
487void 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
2abce515 517void wxRuntimeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
45212047
SC
518{
519 wxObject *o;
520 o = m_data->GetObject(objectID);
16776ad9 521 delete o ;
70e88103
SC
522}
523
45212047 524void wxRuntimeDepersister::SetProperty(int objectID,
2d51f067 525 const wxClassInfo *classInfo,
16776ad9
SC
526 const wxPropertyInfo* propertyInfo,
527 const wxxVariant &value)
70e88103 528{
45212047
SC
529 wxObject *o;
530 o = m_data->GetObject(objectID);
2d51f067 531 classInfo->SetProperty( o , propertyInfo->GetName() , value ) ;
45212047
SC
532}
533
534void wxRuntimeDepersister::SetPropertyAsObject(int objectID,
2d51f067 535 const wxClassInfo *classInfo,
16776ad9
SC
536 const wxPropertyInfo* propertyInfo,
537 int valueObjectId)
45212047
SC
538{
539 wxObject *o, *valo;
540 o = m_data->GetObject(objectID);
541 valo = m_data->GetObject(valueObjectId);
2d51f067
SC
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) ) ;
45212047
SC
552}
553
554void wxRuntimeDepersister::SetConnect(int eventSourceObjectID,
16776ad9 555 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
8805dbab 556 const wxPropertyInfo *delegateInfo ,
16776ad9
SC
557 const wxClassInfo *WXUNUSED(eventSinkClassInfo) ,
558 const wxHandlerInfo* handlerInfo ,
559 int eventSinkObjectID )
45212047 560{
9c8046dd 561 wxEvtHandler *ehsource = dynamic_cast< wxEvtHandler* >( m_data->GetObject( eventSourceObjectID ) ) ;
16776ad9 562 wxEvtHandler *ehsink = dynamic_cast< wxEvtHandler *>(m_data->GetObject(eventSinkObjectID) ) ;
70e88103 563
16776ad9
SC
564 if ( ehsource && ehsink )
565 {
8805dbab
SC
566 const wxDelegateTypeInfo *delegateTypeInfo = dynamic_cast<const wxDelegateTypeInfo*>(delegateInfo->GetTypeInfo());
567 if( delegateTypeInfo && delegateTypeInfo->GetLastEventType() == -1 )
1d73f416 568 {
8805dbab 569 ehsource->Connect( -1 , delegateTypeInfo->GetEventType() ,
1d73f416
SC
570 handlerInfo->GetEventFunction() , NULL /*user data*/ ,
571 ehsink ) ;
572 }
573 else
574 {
8805dbab 575 for ( wxEventType iter = delegateTypeInfo->GetEventType() ; iter <= delegateTypeInfo->GetLastEventType() ; ++iter )
1d73f416
SC
576 {
577 ehsource->Connect( -1 , iter ,
578 handlerInfo->GetEventFunction() , NULL /*user data*/ ,
579 ehsink ) ;
580 }
cab1a605 581 }
16776ad9 582 }
70e88103
SC
583}
584
45212047
SC
585wxObject *wxRuntimeDepersister::GetObject(int objectID)
586{
16776ad9 587 return m_data->GetObject( objectID ) ;
45212047
SC
588}
589
16a45a23
SC
590// adds an element to a property collection
591void wxRuntimeDepersister::AddToPropertyCollection( int objectID ,
4f8ffae1
SC
592 const wxClassInfo *classInfo,
593 const wxPropertyInfo* propertyInfo ,
2abce515 594 const wxxVariant &value)
16a45a23
SC
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)
602void wxRuntimeDepersister::AddToPropertyCollectionAsObject(int objectID,
4f8ffae1
SC
603 const wxClassInfo *classInfo,
604 const wxPropertyInfo* propertyInfo ,
2abce515 605 int valueObjectId)
16a45a23
SC
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}
45212047 622
70e88103 623// ----------------------------------------------------------------------------
2abce515 624// depersisting to code
70e88103
SC
625// ----------------------------------------------------------------------------
626
45212047
SC
627struct wxCodeDepersister::wxCodeDepersisterInternal
628{
67b283a9
JS
629#if wxUSE_UNICODE
630 map<int,wstring> m_objectNames ;
631#else
45212047 632 map<int,string> m_objectNames ;
67b283a9 633#endif
45212047 634
16776ad9
SC
635 void SetObjectName(int objectID, const wxString &name )
636 {
8f2b1cfd
SC
637 if ( m_objectNames.find(objectID) != m_objectNames.end() )
638 {
639 wxLogError( _("Passing a already registered object to SetObjectName") ) ;
640 return ;
641 }
67b283a9 642 m_objectNames[objectID] = (const wxChar *)name;
16776ad9 643 }
8f2b1cfd 644
16776ad9
SC
645 wxString GetObjectName( int objectID )
646 {
647 if ( objectID == wxNullObjectID )
67b283a9 648 return wxT("NULL") ;
16776ad9 649
8f2b1cfd
SC
650 if ( m_objectNames.find(objectID) == m_objectNames.end() )
651 {
652 wxLogError( _("Passing an unkown object to GetObject") ) ;
653 return wxEmptyString ;
654 }
16776ad9
SC
655 return wxString( m_objectNames[objectID].c_str() ) ;
656 }
45212047 657} ;
70e88103 658
2abce515 659wxCodeDepersister::wxCodeDepersister(wxTextOutputStream *out)
16776ad9 660: m_fp(out)
70e88103 661{
16776ad9 662 m_data = new wxCodeDepersisterInternal ;
45212047
SC
663}
664
665wxCodeDepersister::~wxCodeDepersister()
666{
16776ad9 667 delete m_data ;
45212047
SC
668}
669
4f8ffae1 670void wxCodeDepersister::AllocateObject(int objectID, wxClassInfo *classInfo ,
9c8046dd 671 wxxVariantArray &WXUNUSED(metadata))
45212047 672{
67b283a9
JS
673 wxString objectName = wxString::Format( wxT("LocalObject_%d") , objectID ) ;
674 m_fp->WriteString( wxString::Format( wxT("\t%s *%s = new %s;\n"),
16776ad9 675 classInfo->GetClassName(),
2abce515 676 objectName.c_str(),
16776ad9
SC
677 classInfo->GetClassName()) );
678 m_data->SetObjectName( objectID , objectName ) ;
45212047
SC
679}
680
2abce515 681void wxCodeDepersister::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo))
45212047 682{
67b283a9 683 m_fp->WriteString( wxString::Format( wxT("\tdelete %s;\n"),
2abce515 684 m_data->GetObjectName( objectID).c_str() ) );
45212047
SC
685}
686
687wxString wxCodeDepersister::ValueAsCode( const wxxVariant &param )
688{
16776ad9
SC
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) ;
8f2b1cfd
SC
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 }
16776ad9
SC
702 }
703 else if ( type->GetKind() == wxT_STRING )
704 {
67b283a9 705 value.Printf( wxT("\"%s\""),param.GetAsString().c_str() );
16776ad9
SC
706 }
707 else
708 {
67b283a9 709 value.Printf( wxT("%s"), param.GetAsString().c_str() );
16776ad9
SC
710 }
711 return value ;
70e88103
SC
712}
713
45212047 714void wxCodeDepersister::CreateObject(int objectID,
16776ad9
SC
715 const wxClassInfo *WXUNUSED(classInfo),
716 int paramCount,
717 wxxVariant *params,
718 int *objectIDValues,
4f8ffae1 719 const wxClassInfo **WXUNUSED(objectClassInfos) ,
9c8046dd 720 wxxVariantArray &WXUNUSED(metadata)
16776ad9 721 )
70e88103
SC
722{
723 int i;
67b283a9 724 m_fp->WriteString( wxString::Format( wxT("\t%s->Create("), m_data->GetObjectName(objectID).c_str() ) );
45212047 725 for (i = 0; i < paramCount; i++)
70e88103 726 {
16776ad9 727 if ( objectIDValues[i] != wxInvalidObjectID )
67b283a9 728 m_fp->WriteString( wxString::Format( wxT("%s"), m_data->GetObjectName( objectIDValues[i] ).c_str() ) );
16776ad9
SC
729 else
730 {
67b283a9 731 m_fp->WriteString( wxString::Format( wxT("%s"), ValueAsCode(params[i]).c_str() ) );
16776ad9
SC
732 }
733 if (i < paramCount - 1)
67b283a9 734 m_fp->WriteString( wxT(", "));
70e88103 735 }
67b283a9 736 m_fp->WriteString( wxT(");\n") );
70e88103
SC
737}
738
ed45345e
SC
739void 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{
67b283a9
JS
748 wxString objectName = wxString::Format( wxT("LocalObject_%d") , objectID ) ;
749 m_fp->WriteString( wxString::Format( wxT("\t%s *%s = new %s("),
ed45345e
SC
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 )
67b283a9 759 m_fp->WriteString( wxString::Format( wxT("%s"), m_data->GetObjectName( objectIDValues[i] ).c_str() ) );
ed45345e
SC
760 else
761 {
67b283a9 762 m_fp->WriteString( wxString::Format( wxT("%s"), ValueAsCode(params[i]).c_str() ) );
ed45345e
SC
763 }
764 if (i < paramCount - 1)
67b283a9 765 m_fp->WriteString( wxT(", ") );
ed45345e 766 }
67b283a9 767 m_fp->WriteString( wxT(");\n") );
ed45345e
SC
768}
769
45212047 770void wxCodeDepersister::SetProperty(int objectID,
16776ad9
SC
771 const wxClassInfo *WXUNUSED(classInfo),
772 const wxPropertyInfo* propertyInfo,
773 const wxxVariant &value)
70e88103 774{
67b283a9 775 m_fp->WriteString( wxString::Format( wxT("\t%s->%s(%s);\n"),
2abce515
SC
776 m_data->GetObjectName(objectID).c_str(),
777 propertyInfo->GetAccessor()->GetSetterName().c_str(),
778 ValueAsCode(value).c_str()) );
45212047
SC
779}
780
781void wxCodeDepersister::SetPropertyAsObject(int objectID,
16776ad9
SC
782 const wxClassInfo *WXUNUSED(classInfo),
783 const wxPropertyInfo* propertyInfo,
784 int valueObjectId)
785{
786 if ( propertyInfo->GetTypeInfo()->GetKind() == wxT_OBJECT )
67b283a9 787 m_fp->WriteString( wxString::Format( wxT("\t%s->%s(*%s);\n"),
2abce515
SC
788 m_data->GetObjectName(objectID).c_str(),
789 propertyInfo->GetAccessor()->GetSetterName().c_str(),
790 m_data->GetObjectName( valueObjectId).c_str() ) );
16776ad9 791 else
67b283a9 792 m_fp->WriteString( wxString::Format( wxT("\t%s->%s(%s);\n"),
2abce515
SC
793 m_data->GetObjectName(objectID).c_str(),
794 propertyInfo->GetAccessor()->GetSetterName().c_str(),
795 m_data->GetObjectName( valueObjectId).c_str() ) );
70e88103
SC
796}
797
16a45a23 798void wxCodeDepersister::AddToPropertyCollection( int objectID ,
9c8046dd 799 const wxClassInfo *WXUNUSED(classInfo),
4f8ffae1 800 const wxPropertyInfo* propertyInfo ,
2abce515 801 const wxxVariant &value)
16a45a23 802{
67b283a9 803 m_fp->WriteString( wxString::Format( wxT("\t%s->%s(%s);\n"),
2abce515
SC
804 m_data->GetObjectName(objectID).c_str(),
805 propertyInfo->GetAccessor()->GetAdderName().c_str(),
806 ValueAsCode(value).c_str()) );
16a45a23
SC
807}
808
809// sets the corresponding property (value is an object)
9c8046dd
SC
810void wxCodeDepersister::AddToPropertyCollectionAsObject(int WXUNUSED(objectID),
811 const wxClassInfo *WXUNUSED(classInfo),
812 const wxPropertyInfo* WXUNUSED(propertyInfo) ,
2abce515 813 int WXUNUSED(valueObjectId))
16a45a23
SC
814{
815 // TODO
816}
817
45212047 818void wxCodeDepersister::SetConnect(int eventSourceObjectID,
16776ad9 819 const wxClassInfo *WXUNUSED(eventSourceClassInfo),
8805dbab 820 const wxPropertyInfo *delegateInfo ,
16776ad9
SC
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() ;
8805dbab 828 const wxDelegateTypeInfo *delegateTypeInfo = dynamic_cast<const wxDelegateTypeInfo*>(delegateInfo->GetTypeInfo());
8f2b1cfd
SC
829 if ( delegateTypeInfo )
830 {
831 int eventType = delegateTypeInfo->GetEventType() ;
832 wxString handlerName = handlerInfo->GetName() ;
16776ad9 833
8f2b1cfd
SC
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 }
70e88103
SC
841}
842
7ec69821 843#include "wx/arrimpl.cpp"
ab6e4913
SC
844
845WX_DEFINE_OBJARRAY(wxxVariantArray);
846
8e3f3880 847#endif // wxUSE_EXTENDED_RTTI