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