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