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