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 
SetObjectNamewxObjectCodeReaderCallback::wxObjectCodeReaderCallbackInternal51     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 
GetObjectNamewxObjectCodeReaderCallback::wxObjectCodeReaderCallbackInternal61     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 
wxObjectCodeReaderCallback(wxString & headerincludes,wxString & source)75 wxObjectCodeReaderCallback::wxObjectCodeReaderCallback(wxString& headerincludes, wxString &source)
76 : m_headerincludes(headerincludes),m_source(source)
77 {
78     m_data = new wxObjectCodeReaderCallbackInternal;
79 }
80 
~wxObjectCodeReaderCallback()81 wxObjectCodeReaderCallback::~wxObjectCodeReaderCallback()
82 {
83     delete m_data;
84 }
85 
AllocateObject(int objectID,wxClassInfo * classInfo,wxStringToAnyHashMap & WXUNUSED (metadata))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 
DestroyObject(int objectID,wxClassInfo * WXUNUSED (classInfo))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:
wxObjectConstructorWriter(const wxClassTypeInfo * cti,wxObjectCodeReaderCallback * writer)115     wxObjectConstructorWriter(const wxClassTypeInfo* cti,
116         wxObjectCodeReaderCallback* writer) :
117     m_cti(cti),m_writer(writer)
118     {}
119 
operator ()(const wxObject * vobj)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 
GetConstructorString() const136     const wxString& GetConstructorString() const { return m_constructor;}
137 private:
138     const wxClassTypeInfo* m_cti;
139     wxObjectCodeReaderCallback* m_writer;
140     wxString m_constructor;
141 };
142 
ValueAsCode(const wxAny & param)143 wxString wxObjectCodeReaderCallback::ValueAsCode( const wxAny &param )
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 
CreateObject(int objectID,const wxClassInfo * WXUNUSED (classInfo),int paramCount,wxAny * params,int * objectIDValues,const wxClassInfo ** WXUNUSED (objectClassInfos),wxStringToAnyHashMap & WXUNUSED (metadata))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 
ConstructObject(int objectID,const wxClassInfo * classInfo,int paramCount,wxAny * params,int * objectIDValues,const wxClassInfo ** WXUNUSED (objectClassInfos),wxStringToAnyHashMap & WXUNUSED (metadata))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 
SetProperty(int objectID,const wxClassInfo * WXUNUSED (classInfo),const wxPropertyInfo * propertyInfo,const wxAny & value)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 
SetPropertyAsObject(int objectID,const wxClassInfo * WXUNUSED (classInfo),const wxPropertyInfo * propertyInfo,int valueObjectId)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 
AddToPropertyCollection(int objectID,const wxClassInfo * WXUNUSED (classInfo),const wxPropertyInfo * propertyInfo,const wxAny & value)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::
AddToPropertyCollectionAsObject(int WXUNUSED (objectID),const wxClassInfo * WXUNUSED (classInfo),const wxPropertyInfo * WXUNUSED (propertyInfo),int WXUNUSED (valueObjectId))293     AddToPropertyCollectionAsObject(int WXUNUSED(objectID),
294                                     const wxClassInfo *WXUNUSED(classInfo),
295                                     const wxPropertyInfo* WXUNUSED(propertyInfo),
296                                     int WXUNUSED(valueObjectId))
297 {
298     // TODO
299 }
300 
SetConnect(int eventSourceObjectID,const wxClassInfo * WXUNUSED (eventSourceClassInfo),const wxPropertyInfo * delegateInfo,const wxClassInfo * eventSinkClassInfo,const wxHandlerInfo * handlerInfo,int eventSinkObjectID)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 }
332