]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: src/common/xtistrm.cpp | |
3 | // Purpose: streaming runtime metadata information | |
4 | // Author: Stefan Csomor | |
5 | // Modified by: | |
6 | // Created: 27/07/03 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 2003 Stefan Csomor | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // For compilers that support precompilation, includes "wx.h". | |
13 | #include "wx/wxprec.h" | |
14 | ||
15 | #ifdef __BORLANDC__ | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #include "wx/xtistrm.h" | |
20 | ||
21 | #ifndef WX_PRECOMP | |
22 | #include "wx/object.h" | |
23 | #include "wx/hash.h" | |
24 | #include "wx/event.h" | |
25 | #endif | |
26 | ||
27 | #include <map> | |
28 | #include <vector> | |
29 | #include <string> | |
30 | using namespace std; | |
31 | ||
32 | #include "wx/tokenzr.h" | |
33 | #include "wx/txtstrm.h" | |
34 | #include "codereadercallback.h" | |
35 | ||
36 | #if !wxUSE_EXTENDED_RTTI | |
37 | #error This sample requires XTI (eXtended RTTI) enabled | |
38 | #endif | |
39 | ||
40 | // ---------------------------------------------------------------------------- | |
41 | // wxObjectCodeReaderCallback - depersisting to code | |
42 | // ---------------------------------------------------------------------------- | |
43 | ||
44 | struct wxObjectCodeReaderCallback::wxObjectCodeReaderCallbackInternal | |
45 | { | |
46 | #if wxUSE_UNICODE | |
47 | map<int,wstring> m_objectNames; | |
48 | #else | |
49 | map<int,string> m_objectNames; | |
50 | #endif | |
51 | ||
52 | void SetObjectName(int objectID, const wxString &name ) | |
53 | { | |
54 | if ( m_objectNames.find(objectID) != m_objectNames.end() ) | |
55 | { | |
56 | wxLogError( _("Passing a already registered object to SetObjectName") ); | |
57 | return ; | |
58 | } | |
59 | m_objectNames[objectID] = (const wxChar *)name; | |
60 | } | |
61 | ||
62 | wxString GetObjectName( int objectID ) | |
63 | { | |
64 | if ( objectID == wxNullObjectID ) | |
65 | return wxT("NULL"); | |
66 | ||
67 | if ( m_objectNames.find(objectID) == m_objectNames.end() ) | |
68 | { | |
69 | wxLogError( _("Passing an unkown object to GetObject") ); | |
70 | return wxEmptyString; | |
71 | } | |
72 | return wxString( m_objectNames[objectID].c_str() ); | |
73 | } | |
74 | }; | |
75 | ||
76 | wxObjectCodeReaderCallback::wxObjectCodeReaderCallback(wxString& headerincludes, wxString &source) | |
77 | : m_headerincludes(headerincludes),m_source(source) | |
78 | { | |
79 | m_data = new wxObjectCodeReaderCallbackInternal; | |
80 | } | |
81 | ||
82 | wxObjectCodeReaderCallback::~wxObjectCodeReaderCallback() | |
83 | { | |
84 | delete m_data; | |
85 | } | |
86 | ||
87 | void wxObjectCodeReaderCallback::AllocateObject(int objectID, wxClassInfo *classInfo, | |
88 | wxStringToAnyHashMap &WXUNUSED(metadata)) | |
89 | { | |
90 | if ( classInfo->GetIncludeName() != wxEmptyString) | |
91 | { | |
92 | // add corresponding header if not already included | |
93 | wxString include; | |
94 | include.Printf(wxT("#include \"%s\"\n"),classInfo->GetIncludeName()); | |
95 | if ( m_headerincludes.Find(include) == wxNOT_FOUND) | |
96 | m_headerincludes += include; | |
97 | } | |
98 | ||
99 | wxString objectName = wxString::Format( wxT("LocalObject_%d"), objectID ); | |
100 | m_source += ( wxString::Format( wxT("\t%s *%s = new %s;\n"), | |
101 | classInfo->GetClassName(), | |
102 | objectName.c_str(), | |
103 | classInfo->GetClassName()) ); | |
104 | m_data->SetObjectName( objectID, objectName ); | |
105 | } | |
106 | ||
107 | void wxObjectCodeReaderCallback::DestroyObject(int objectID, wxClassInfo *WXUNUSED(classInfo)) | |
108 | { | |
109 | m_source += ( wxString::Format( wxT("\tdelete %s;\n"), | |
110 | m_data->GetObjectName( objectID).c_str() ) ); | |
111 | } | |
112 | ||
113 | class WXDLLIMPEXP_BASE wxObjectConstructorWriter: public wxObjectWriterFunctor | |
114 | { | |
115 | public: | |
116 | wxObjectConstructorWriter(const wxClassTypeInfo* cti, | |
117 | wxObjectCodeReaderCallback* writer) : | |
118 | m_cti(cti),m_writer(writer) | |
119 | {} | |
120 | ||
121 | virtual void operator()(const wxObject *vobj) | |
122 | { | |
123 | const wxClassInfo* ci = m_cti->GetClassInfo(); | |
124 | ||
125 | for ( int i = 0; i < ci->GetCreateParamCount(); ++i ) | |
126 | { | |
127 | wxString name = ci->GetCreateParamName(i); | |
128 | const wxPropertyInfo* prop = ci->FindPropertyInfo(name); | |
129 | if ( i > 0 ) | |
130 | m_constructor += ", "; | |
131 | wxAny value; | |
132 | prop->GetAccessor()->GetProperty(vobj, value); | |
133 | m_constructor+= m_writer->ValueAsCode(value); | |
134 | } | |
135 | } | |
136 | ||
137 | const wxString& GetConstructorString() const { return m_constructor;} | |
138 | private: | |
139 | const wxClassTypeInfo* m_cti; | |
140 | wxObjectCodeReaderCallback* m_writer; | |
141 | wxString m_constructor; | |
142 | }; | |
143 | ||
144 | wxString wxObjectCodeReaderCallback::ValueAsCode( const wxAny ¶m ) | |
145 | { | |
146 | wxString value; | |
147 | ||
148 | const wxTypeInfo* type = param.GetTypeInfo(); | |
149 | if ( type->GetKind() == wxT_CUSTOM ) | |
150 | { | |
151 | const wxCustomTypeInfo* cti = wx_dynamic_cast(const wxCustomTypeInfo*, type); | |
152 | if ( cti ) | |
153 | { | |
154 | value.Printf( wxT("%s(%s)"), cti->GetTypeName().c_str(), | |
155 | wxAnyGetAsString(param).c_str() ); | |
156 | } | |
157 | else | |
158 | { | |
159 | wxLogError ( _("Internal error, illegal wxCustomTypeInfo") ); | |
160 | } | |
161 | } | |
162 | else if ( type->GetKind() == wxT_STRING ) | |
163 | { | |
164 | value.Printf( wxT("\"%s\""), wxAnyGetAsString(param).c_str() ); | |
165 | } | |
166 | else if ( type->GetKind() == wxT_OBJECT ) | |
167 | { | |
168 | const wxClassTypeInfo* ctype = wx_dynamic_cast(const wxClassTypeInfo*,type); | |
169 | const wxClassInfo* ci = ctype->GetClassInfo(); | |
170 | if( ci->NeedsDirectConstruction()) | |
171 | { | |
172 | wxObjectConstructorWriter cw(ctype,this); | |
173 | ||
174 | ci->CallOnAny(param,&cw); | |
175 | ||
176 | value.Printf( wxT("%s(%s)"), ctype->GetClassInfo()->GetClassName(), | |
177 | cw.GetConstructorString() ); | |
178 | } | |
179 | } | |
180 | else | |
181 | { | |
182 | value.Printf( wxT("%s"), wxAnyGetAsString(param).c_str() ); | |
183 | } | |
184 | ||
185 | return value; | |
186 | } | |
187 | ||
188 | void wxObjectCodeReaderCallback::CreateObject(int objectID, | |
189 | const wxClassInfo *WXUNUSED(classInfo), | |
190 | int paramCount, | |
191 | wxAny *params, | |
192 | int *objectIDValues, | |
193 | const wxClassInfo **WXUNUSED(objectClassInfos), | |
194 | wxStringToAnyHashMap &WXUNUSED(metadata) | |
195 | ) | |
196 | { | |
197 | int i; | |
198 | m_source += ( wxString::Format( wxT("\t%s->Create("), | |
199 | m_data->GetObjectName(objectID).c_str() ) ); | |
200 | for (i = 0; i < paramCount; i++) | |
201 | { | |
202 | if ( objectIDValues[i] != wxInvalidObjectID ) | |
203 | { | |
204 | wxString str = | |
205 | wxString::Format( wxT("%s"), | |
206 | m_data->GetObjectName( objectIDValues[i] ).c_str() ); | |
207 | m_source += ( str ); | |
208 | } | |
209 | else | |
210 | { | |
211 | m_source += ( | |
212 | wxString::Format( wxT("%s"), ValueAsCode(params[i]).c_str() ) ); | |
213 | } | |
214 | if (i < paramCount - 1) | |
215 | m_source += ( wxT(", ")); | |
216 | } | |
217 | m_source += ( wxT(");\n") ); | |
218 | } | |
219 | ||
220 | void wxObjectCodeReaderCallback::ConstructObject(int objectID, | |
221 | const wxClassInfo *classInfo, | |
222 | int paramCount, | |
223 | wxAny *params, | |
224 | int *objectIDValues, | |
225 | const wxClassInfo **WXUNUSED(objectClassInfos), | |
226 | wxStringToAnyHashMap &WXUNUSED(metadata) | |
227 | ) | |
228 | { | |
229 | wxString objectName = wxString::Format( wxT("LocalObject_%d"), objectID ); | |
230 | m_source += ( wxString::Format( wxT("\t%s *%s = new %s("), | |
231 | classInfo->GetClassName(), | |
232 | objectName.c_str(), | |
233 | classInfo->GetClassName()) ); | |
234 | m_data->SetObjectName( objectID, objectName ); | |
235 | ||
236 | int i; | |
237 | for (i = 0; i < paramCount; i++) | |
238 | { | |
239 | if ( objectIDValues[i] != wxInvalidObjectID ) | |
240 | m_source += ( wxString::Format( wxT("%s"), | |
241 | m_data->GetObjectName( objectIDValues[i] ).c_str() ) ); | |
242 | else | |
243 | { | |
244 | m_source += ( | |
245 | wxString::Format( wxT("%s"), ValueAsCode(params[i]).c_str() ) ); | |
246 | } | |
247 | if (i < paramCount - 1) | |
248 | m_source += ( wxT(", ") ); | |
249 | } | |
250 | m_source += ( wxT(");\n") ); | |
251 | } | |
252 | ||
253 | void wxObjectCodeReaderCallback::SetProperty(int objectID, | |
254 | const wxClassInfo *WXUNUSED(classInfo), | |
255 | const wxPropertyInfo* propertyInfo, | |
256 | const wxAny &value) | |
257 | { | |
258 | m_source += ( wxString::Format( wxT("\t%s->%s(%s);\n"), | |
259 | m_data->GetObjectName(objectID).c_str(), | |
260 | propertyInfo->GetAccessor()->GetSetterName().c_str(), | |
261 | ValueAsCode(value).c_str()) ); | |
262 | } | |
263 | ||
264 | void wxObjectCodeReaderCallback::SetPropertyAsObject(int objectID, | |
265 | const wxClassInfo *WXUNUSED(classInfo), | |
266 | const wxPropertyInfo* propertyInfo, | |
267 | int valueObjectId) | |
268 | { | |
269 | if ( propertyInfo->GetTypeInfo()->GetKind() == wxT_OBJECT ) | |
270 | m_source += ( wxString::Format( wxT("\t%s->%s(*%s);\n"), | |
271 | m_data->GetObjectName(objectID).c_str(), | |
272 | propertyInfo->GetAccessor()->GetSetterName().c_str(), | |
273 | m_data->GetObjectName( valueObjectId).c_str() ) ); | |
274 | else | |
275 | m_source += ( wxString::Format( wxT("\t%s->%s(%s);\n"), | |
276 | m_data->GetObjectName(objectID).c_str(), | |
277 | propertyInfo->GetAccessor()->GetSetterName().c_str(), | |
278 | m_data->GetObjectName( valueObjectId).c_str() ) ); | |
279 | } | |
280 | ||
281 | void wxObjectCodeReaderCallback::AddToPropertyCollection( int objectID, | |
282 | const wxClassInfo *WXUNUSED(classInfo), | |
283 | const wxPropertyInfo* propertyInfo, | |
284 | const wxAny &value) | |
285 | { | |
286 | m_source += ( wxString::Format( wxT("\t%s->%s(%s);\n"), | |
287 | m_data->GetObjectName(objectID).c_str(), | |
288 | propertyInfo->GetAccessor()->GetAdderName().c_str(), | |
289 | ValueAsCode(value).c_str()) ); | |
290 | } | |
291 | ||
292 | // sets the corresponding property (value is an object) | |
293 | void wxObjectCodeReaderCallback:: | |
294 | AddToPropertyCollectionAsObject(int WXUNUSED(objectID), | |
295 | const wxClassInfo *WXUNUSED(classInfo), | |
296 | const wxPropertyInfo* WXUNUSED(propertyInfo), | |
297 | int WXUNUSED(valueObjectId)) | |
298 | { | |
299 | // TODO | |
300 | } | |
301 | ||
302 | void wxObjectCodeReaderCallback::SetConnect(int eventSourceObjectID, | |
303 | const wxClassInfo *WXUNUSED(eventSourceClassInfo), | |
304 | const wxPropertyInfo *delegateInfo, | |
305 | const wxClassInfo *eventSinkClassInfo, | |
306 | const wxHandlerInfo* handlerInfo, | |
307 | int eventSinkObjectID ) | |
308 | { | |
309 | wxString ehsource = m_data->GetObjectName( eventSourceObjectID ); | |
310 | wxString ehsink = m_data->GetObjectName(eventSinkObjectID); | |
311 | wxString ehsinkClass = eventSinkClassInfo->GetClassName(); | |
312 | const wxEventSourceTypeInfo *delegateTypeInfo = | |
313 | wx_dynamic_cast(const wxEventSourceTypeInfo*, delegateInfo->GetTypeInfo()); | |
314 | if ( delegateTypeInfo ) | |
315 | { | |
316 | int eventType = delegateTypeInfo->GetEventType(); | |
317 | wxString handlerName = handlerInfo->GetName(); | |
318 | ||
319 | wxString code = | |
320 | wxString::Format( | |
321 | wxT("\t%s->Connect( %s->GetId(), %d, ") | |
322 | wxT("(wxObjectEventFunction)(wxEventFunction) & %s::%s, NULL, %s );"), | |
323 | ehsource.c_str(), ehsource.c_str(), eventType, ehsinkClass.c_str(), | |
324 | handlerName.c_str(), ehsink.c_str() ); | |
325 | ||
326 | m_source += ( code ); | |
327 | } | |
328 | else | |
329 | { | |
330 | wxLogError(_("delegate has no type info")); | |
331 | } | |
332 | } |