]> git.saurik.com Git - wxWidgets.git/blob - samples/xti/codereadercallback.cpp
Ensure that we never return negative client size.
[wxWidgets.git] / samples / xti / codereadercallback.cpp
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 &param )
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 }