]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: xti.cpp | |
3 | // Purpose: eXtended RTTI support sample | |
4 | // Author: Stefan Csomor, Francesco Montorsi | |
5 | // Modified by: | |
6 | // Created: 13/5/2007 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Stefan Csomor, Francesco Montorsi | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // ============================================================================ | |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
20 | // For compilers that support precompilation, includes "wx/wx.h". | |
21 | #include "wx/wxprec.h" | |
22 | ||
23 | #ifdef __BORLANDC__ | |
24 | #pragma hdrstop | |
25 | #endif | |
26 | ||
27 | // for all others, include the necessary headers (this file is usually all you | |
28 | // need because it includes almost all "standard" wxWidgets headers) | |
29 | #ifndef WX_PRECOMP | |
30 | #include "wx/wx.h" | |
31 | #endif | |
32 | ||
33 | #include "wx/wx.h" | |
34 | #include "wx/variant.h" | |
35 | #include "wx/xml/xml.h" | |
36 | #include "wx/frame.h" | |
37 | #include "wx/notebook.h" | |
38 | #include "wx/event.h" | |
39 | #include "wx/spinbutt.h" | |
40 | #include "wx/spinctrl.h" | |
41 | ||
42 | #include "wx/xtistrm.h" | |
43 | #include "wx/xtixml.h" | |
44 | #include "wx/txtstrm.h" | |
45 | #include "wx/wfstream.h" | |
46 | #include "wx/sstream.h" | |
47 | #include "wx/spinctrl.h" | |
48 | ||
49 | #include "classlist.h" | |
50 | #include "codereadercallback.h" | |
51 | ||
52 | #if !wxUSE_EXTENDED_RTTI | |
53 | #error This sample requires XTI (eXtended RTTI) enabled | |
54 | #endif | |
55 | ||
56 | ||
57 | // ---------------------------------------------------------------------------- | |
58 | // resources | |
59 | // ---------------------------------------------------------------------------- | |
60 | ||
61 | #ifndef wxHAS_IMAGES_IN_RESOURCES | |
62 | #include "../sample.xpm" | |
63 | #endif | |
64 | ||
65 | // ---------------------------------------------------------------------------- | |
66 | // private classes | |
67 | // ---------------------------------------------------------------------------- | |
68 | ||
69 | // Define a new application type, each program should derive a class from wxApp | |
70 | class MyApp : public wxApp | |
71 | { | |
72 | public: | |
73 | virtual bool OnInit(); | |
74 | }; | |
75 | ||
76 | // Define a new frame type: this is going to be our main frame | |
77 | class MyFrame : public wxFrame | |
78 | { | |
79 | public: | |
80 | // ctor(s) | |
81 | MyFrame(const wxString& title); | |
82 | ||
83 | void OnPersist(wxCommandEvent& event); | |
84 | void OnDepersist(wxCommandEvent& event); | |
85 | void OnGenerateCode(wxCommandEvent& event); | |
86 | void OnDumpClasses(wxCommandEvent& event); | |
87 | void OnQuit(wxCommandEvent& event); | |
88 | void OnAbout(wxCommandEvent& event); | |
89 | ||
90 | private: | |
91 | // any class wishing to process wxWidgets events must use this macro | |
92 | wxDECLARE_EVENT_TABLE(); | |
93 | }; | |
94 | ||
95 | // ---------------------------------------------------------------------------- | |
96 | // constants | |
97 | // ---------------------------------------------------------------------------- | |
98 | ||
99 | // IDs for the controls and the menu commands | |
100 | enum | |
101 | { | |
102 | // menu items | |
103 | Minimal_Persist = wxID_HIGHEST, | |
104 | Minimal_Depersist, | |
105 | Minimal_GenerateCode, | |
106 | Minimal_DumpClasses, | |
107 | Minimal_Quit = wxID_EXIT, | |
108 | Minimal_About = wxID_ABOUT | |
109 | }; | |
110 | ||
111 | // ---------------------------------------------------------------------------- | |
112 | // event tables and other macros for wxWidgets | |
113 | // ---------------------------------------------------------------------------- | |
114 | ||
115 | BEGIN_EVENT_TABLE(MyFrame, wxFrame) | |
116 | EVT_MENU(Minimal_Persist, MyFrame::OnPersist) | |
117 | EVT_MENU(Minimal_Depersist, MyFrame::OnDepersist) | |
118 | EVT_MENU(Minimal_GenerateCode, MyFrame::OnGenerateCode) | |
119 | EVT_MENU(Minimal_DumpClasses, MyFrame::OnDumpClasses) | |
120 | EVT_MENU(Minimal_Quit, MyFrame::OnQuit) | |
121 | EVT_MENU(Minimal_About, MyFrame::OnAbout) | |
122 | END_EVENT_TABLE() | |
123 | ||
124 | wxIMPLEMENT_APP(MyApp); | |
125 | ||
126 | // ============================================================================ | |
127 | // implementation | |
128 | // ============================================================================ | |
129 | ||
130 | void RegisterFrameRTTI(); | |
131 | ||
132 | // ---------------------------------------------------------------------------- | |
133 | // the application class | |
134 | // ---------------------------------------------------------------------------- | |
135 | ||
136 | bool MyApp::OnInit() | |
137 | { | |
138 | if ( !wxApp::OnInit() ) | |
139 | return false; | |
140 | ||
141 | RegisterFrameRTTI(); | |
142 | ||
143 | // create the main application window | |
144 | MyFrame *frame = new MyFrame(wxT("Extended RTTI sample")); | |
145 | ||
146 | // and show it (the frames, unlike simple controls, are not shown when | |
147 | // created initially) | |
148 | frame->Show(true); | |
149 | ||
150 | // success: wxApp::OnRun() will be called which will enter the main message | |
151 | // loop and the application will run. If we returned false here, the | |
152 | // application would exit immediately. | |
153 | return true; | |
154 | } | |
155 | ||
156 | // ---------------------------------------------------------------------------- | |
157 | // main frame | |
158 | // ---------------------------------------------------------------------------- | |
159 | ||
160 | MyFrame::MyFrame(const wxString& title) | |
161 | : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(300, 200)) | |
162 | { | |
163 | // set the frame icon | |
164 | SetIcon(wxICON(sample)); | |
165 | ||
166 | #if wxUSE_MENUS | |
167 | // create a menu bar | |
168 | wxMenu *fileMenu = new wxMenu; | |
169 | ||
170 | // the "About" item should be in the help menu | |
171 | wxMenu *helpMenu = new wxMenu; | |
172 | helpMenu->Append(Minimal_About, wxT("&About\tF1"), wxT("Show about dialog")); | |
173 | ||
174 | fileMenu->Append(Minimal_Persist, wxT("Persist a wxFrame to XML..."), | |
175 | wxT("Creates a wxFrame using wxXTI and saves its description as XML")); | |
176 | fileMenu->Append(Minimal_Depersist, wxT("Depersist XML file..."), | |
177 | wxT("Loads the description of wxFrame from XML")); | |
178 | fileMenu->Append(Minimal_GenerateCode, wxT("Generate code for a wxFrame saved to XML..."), | |
179 | wxT("Generates the C++ code which belong to a persisted wxFrame")); | |
180 | fileMenu->AppendSeparator(); | |
181 | fileMenu->Append(Minimal_DumpClasses, wxT("Dump registered classes..."), | |
182 | wxT("Dumps the description of all wxWidgets classes registered in XTI")); | |
183 | fileMenu->AppendSeparator(); | |
184 | fileMenu->Append(Minimal_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program")); | |
185 | ||
186 | // now append the freshly created menu to the menu bar... | |
187 | wxMenuBar *menuBar = new wxMenuBar(); | |
188 | menuBar->Append(fileMenu, wxT("&File")); | |
189 | menuBar->Append(helpMenu, wxT("&Help")); | |
190 | ||
191 | // ... and attach this menu bar to the frame | |
192 | SetMenuBar(menuBar); | |
193 | #endif // wxUSE_MENUS | |
194 | ||
195 | #if wxUSE_STATUSBAR | |
196 | // create a status bar just for fun (by default with 1 pane only) | |
197 | CreateStatusBar(2); | |
198 | SetStatusText(wxT("Welcome to wxWidgets!")); | |
199 | #endif // wxUSE_STATUSBAR | |
200 | } | |
201 | ||
202 | ||
203 | ||
204 | // ---------------------------------------------------------------------------- | |
205 | // XTI sample code | |
206 | // ---------------------------------------------------------------------------- | |
207 | ||
208 | // this is the kind of source code that would end up being generated by a | |
209 | // designer corresponding to the information we are setting up via RTTI | |
210 | // in the CreateFrameRTTI function: | |
211 | // | |
212 | // class MyXTIFrame : public wxFrame | |
213 | // { | |
214 | // public: | |
215 | // // construction | |
216 | // MyXTIFrame() | |
217 | // { | |
218 | // Init(); | |
219 | // m_button = NULL; | |
220 | // } | |
221 | // | |
222 | // bool Create(wxWindow *parent, | |
223 | // wxWindowID id, | |
224 | // const wxString& title, | |
225 | // const wxPoint& pos = wxDefaultPosition, | |
226 | // const wxSize& size = wxDefaultSize, | |
227 | // long style = wxDEFAULT_FRAME_STYLE, | |
228 | // const wxString& name = wxFrameNameStr) | |
229 | // { | |
230 | // return wxFrame::Create( parent, id, title, pos, size, style, name ); | |
231 | // } | |
232 | // | |
233 | // void SetButton( wxButton * button ) { m_button = button; } | |
234 | // wxButton* GetButton() const { return m_button; } | |
235 | // | |
236 | // void ButtonClickHandler( wxEvent & WXUNUSED(event) ) | |
237 | // { | |
238 | // wxMessageBox( "Button Clicked ", "Hi!", wxOK ); | |
239 | // } | |
240 | // | |
241 | // protected: | |
242 | // wxButton* m_button; | |
243 | // | |
244 | // DECLARE_EVENT_TABLE() | |
245 | // DECLARE_DYNAMIC_CLASS_NO_COPY(MyXTIFrame) | |
246 | // }; | |
247 | // | |
248 | // IMPLEMENT_DYNAMIC_CLASS_XTI(MyXTIFrame, MyXTIFrame, "x.h") | |
249 | // | |
250 | // WX_BEGIN_PROPERTIES_TABLE(MyXTIFrame) | |
251 | // WX_PROPERTY( Button, wxButton*, SetButton, GetButton, ) | |
252 | // WX_END_PROPERTIES_TABLE() | |
253 | // | |
254 | // WX_BEGIN_HANDLERS_TABLE(MyXTIFrame) | |
255 | // WX_HANDLER( ButtonClickHandler, wxCommandEvent ) | |
256 | // WX_END_HANDLERS_TABLE() | |
257 | // | |
258 | // WX_CONSTRUCTOR_5( MyXTIFrame, wxWindow*, Parent, wxWindowID, Id, | |
259 | // wxString, Title, wxPoint, Position, wxSize, Size ) | |
260 | // | |
261 | // BEGIN_EVENT_TABLE(MyXTIFrame, wxFrame) | |
262 | // END_EVENT_TABLE() | |
263 | ||
264 | // the following class "persists" (i.e. saves) a wxFrame into a wxObjectWriter | |
265 | ||
266 | class MyDesignerPersister : public wxObjectWriterCallback | |
267 | { | |
268 | public: | |
269 | MyDesignerPersister( wxDynamicObject * frame) | |
270 | { | |
271 | m_frame = frame; | |
272 | } | |
273 | ||
274 | virtual bool BeforeWriteDelegate( wxObjectWriter *WXUNUSED(writer), | |
275 | const wxObject *object, | |
276 | const wxClassInfo* WXUNUSED(classInfo), | |
277 | const wxPropertyInfo *propInfo, | |
278 | const wxObject *&eventSink, | |
279 | const wxHandlerInfo* &handlerInfo ) | |
280 | { | |
281 | // this approach would be used if the handler would not | |
282 | // be connected really in the designer, so we have to supply | |
283 | // the information | |
284 | const wxObject* but = wxAnyGetAsObjectPtr( m_frame->GetProperty(wxT("Button")) ); | |
285 | if ( object == but && | |
286 | propInfo == wxCLASSINFO( wxButton )->FindPropertyInfo(wxT("OnClick")) ) | |
287 | { | |
288 | eventSink = m_frame; | |
289 | handlerInfo = m_frame->GetClassInfo()-> | |
290 | FindHandlerInfo(wxT("ButtonClickHandler")); | |
291 | return true; | |
292 | } | |
293 | return false; | |
294 | } | |
295 | ||
296 | private: | |
297 | wxDynamicObject *m_frame; | |
298 | }; | |
299 | ||
300 | // sometimes linkers (at least MSVC and GCC ones) optimize the final EXE | |
301 | // even in debug mode pruning the object files which he "thinks" are useless; | |
302 | // thus the classes defined in those files won't be available in the XTI | |
303 | // table and the program will fail to allocate them. | |
304 | // The following macro implements a simple hack to ensure that a given | |
305 | // class is linked in. | |
306 | // | |
307 | // TODO: in wx/link.h there are already similar macros (also more "optimized": | |
308 | // don't need the creation of fake object) which however require to use | |
309 | // the wxFORCE_LINK_THIS_MODULE() macro inside the source files corresponding | |
310 | // to the class being discarded. | |
311 | // | |
312 | #define wxENSURE_CLASS_IS_LINKED(x) { x test; } | |
313 | ||
314 | void RegisterFrameRTTI() | |
315 | { | |
316 | // set up the RTTI info for a class (MyXTIFrame) which | |
317 | // is not defined anywhere in this program | |
318 | wxDynamicClassInfo *dyninfo = | |
319 | wx_dynamic_cast( wxDynamicClassInfo *, wxClassInfo::FindClass(wxT("MyXTIFrame"))); | |
320 | if ( dyninfo == NULL ) | |
321 | { | |
322 | dyninfo = new wxDynamicClassInfo(wxT("myxtiframe.h"), | |
323 | wxT("MyXTIFrame"), | |
324 | CLASSINFO(wxFrame) ); | |
325 | ||
326 | // this class has a property named "Button" and the relative handler: | |
327 | dyninfo->AddProperty(wxT("Button"), wxGetTypeInfo((wxButton**) NULL)); | |
328 | dyninfo->AddHandler(wxT("ButtonClickHandler"), | |
329 | NULL /* no instance of the handler method */, CLASSINFO( wxEvent ) ); | |
330 | } | |
331 | } | |
332 | ||
333 | wxDynamicObject* CreateFrameRTTI() | |
334 | { | |
335 | int baseID = 100; | |
336 | wxAny Params[10]; | |
337 | ||
338 | // the class is now part of XTI internal table so that we can | |
339 | // get a pointer to it just searching it like any other class: | |
340 | wxFrame* frame; | |
341 | wxClassInfo *info = wxClassInfo::FindClass(wxT("MyXTIFrame")); | |
342 | wxASSERT( info ); | |
343 | wxDynamicObject* frameWrapper = | |
344 | wx_dynamic_cast(wxDynamicObject*, info->CreateObject() ); | |
345 | Params[0] = wxAny((wxWindow*)(NULL)); | |
346 | Params[1] = wxAny(wxWindowID(baseID++)); | |
347 | Params[2] = wxAny(wxString(wxT("This is a frame created from XTI"))); | |
348 | Params[3] = wxAny(wxPoint(-1,-1)); | |
349 | Params[4] = wxAny(wxSize(400,300)); | |
350 | Params[5] = wxAny((long)wxDEFAULT_FRAME_STYLE); | |
351 | wxASSERT( info->Create(frameWrapper, 6, Params )); | |
352 | frame = wx_dynamic_cast(wxFrame*, frameWrapper->GetSuperClassInstance()); | |
353 | ||
354 | #if 1 | |
355 | // now build a notebook inside it: | |
356 | wxNotebook* notebook; | |
357 | info = wxClassInfo::FindClass("wxNotebook"); | |
358 | wxASSERT( info ); | |
359 | notebook = wxDynamicCast( info->CreateObject(), wxNotebook ); | |
360 | Params[0] = wxAny((wxWindow*)frame); | |
361 | Params[1] = wxAny(wxWindowID(baseID++)); | |
362 | Params[2] = wxAny(wxPoint( 10, 10 )); | |
363 | Params[3] = wxAny(wxDefaultSize); | |
364 | Params[4] = wxAny((long)0); | |
365 | wxASSERT( info->Create(notebook, 5, Params )); | |
366 | ||
367 | // button page | |
368 | ||
369 | wxPanel* panel; | |
370 | info = wxClassInfo::FindClass("wxPanel"); | |
371 | wxASSERT( info ); | |
372 | panel = wxDynamicCast( info->CreateObject(), wxPanel ); | |
373 | Params[0] = wxAny((wxWindow*)(notebook)); | |
374 | Params[1] = wxAny(wxWindowID(baseID++)); | |
375 | Params[2] = wxAny(wxPoint(-1,-1)); | |
376 | Params[3] = wxAny(wxSize(-1,-1)); | |
377 | Params[4] = wxAny((long)0); | |
378 | Params[5] = wxAny(wxString(wxT("Hello"))); | |
379 | wxASSERT( info->Create(panel, 6, Params )); | |
380 | notebook->AddPage( panel, "Buttons" ); | |
381 | ||
382 | wxButton* button; | |
383 | info = wxClassInfo::FindClass("wxButton"); | |
384 | wxASSERT( info ); | |
385 | button = wxDynamicCast( info->CreateObject(), wxButton ); | |
386 | Params[0] = wxAny((wxWindow*)(panel)); | |
387 | Params[1] = wxAny(wxWindowID(baseID++)); | |
388 | Params[2] = wxAny(wxString(wxT("Click Me!"))); | |
389 | Params[3] = wxAny(wxPoint( 10, 10 )); | |
390 | Params[4] = wxAny(wxSize(-1,-1)); | |
391 | Params[5] = wxAny((long)0); | |
392 | wxASSERT( info->Create(button, 6, Params )); | |
393 | frameWrapper->SetProperty( wxT("Button"), wxAny( button ) ); | |
394 | ||
395 | // other controls page | |
396 | ||
397 | info = wxClassInfo::FindClass("wxPanel"); | |
398 | wxASSERT( info ); | |
399 | panel = wxDynamicCast( info->CreateObject(), wxPanel ); | |
400 | Params[0] = wxAny((wxWindow*)(notebook)); | |
401 | Params[1] = wxAny(wxWindowID(baseID++)); | |
402 | Params[2] = wxAny(wxPoint(-1,-1)); | |
403 | Params[3] = wxAny(wxSize(-1,-1)); | |
404 | Params[4] = wxAny((long)0); | |
405 | Params[5] = wxAny(wxString(wxT("Hello"))); | |
406 | wxASSERT( info->Create(panel, 6, Params )); | |
407 | notebook->AddPage( panel, "Other Standard controls" ); | |
408 | ||
409 | wxControl* control; | |
410 | info = wxClassInfo::FindClass("wxCheckBox"); | |
411 | wxASSERT( info ); | |
412 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
413 | Params[0] = wxAny((wxWindow*)(panel)); | |
414 | Params[1] = wxAny(wxWindowID(baseID++)); | |
415 | Params[2] = wxAny(wxString(wxT("A Checkbox"))); | |
416 | Params[3] = wxAny(wxPoint( 10, 10 )); | |
417 | Params[4] = wxAny(wxSize(-1,-1)); | |
418 | Params[5] = wxAny((long)0); | |
419 | wxASSERT( info->Create(control, 6, Params )); | |
420 | ||
421 | info = wxClassInfo::FindClass("wxRadioButton"); | |
422 | wxASSERT( info ); | |
423 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
424 | Params[0] = wxAny((wxWindow*)(panel)); | |
425 | Params[1] = wxAny(wxWindowID(baseID++)); | |
426 | Params[2] = wxAny(wxString(wxT("A Radiobutton"))); | |
427 | Params[3] = wxAny(wxPoint( 10, 30 )); | |
428 | Params[4] = wxAny(wxSize(-1,-1)); | |
429 | Params[5] = wxAny((long)0); | |
430 | wxASSERT( info->Create(control, 6, Params )); | |
431 | ||
432 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
433 | Params[1] = wxAny(wxWindowID(baseID++)); | |
434 | Params[2] = wxAny(wxString(wxT("Another One"))); | |
435 | Params[3] = wxAny(wxPoint( 10, 50 )); | |
436 | wxASSERT( info->Create(control, 6, Params )); | |
437 | ||
438 | info = wxClassInfo::FindClass("wxStaticText"); | |
439 | wxASSERT( info ); | |
440 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
441 | Params[0] = wxAny((wxWindow*)(panel)); | |
442 | Params[1] = wxAny(wxWindowID(baseID++)); | |
443 | Params[2] = wxAny(wxString(wxT("A Static Text!"))); | |
444 | Params[3] = wxAny(wxPoint( 10, 70 )); | |
445 | Params[4] = wxAny(wxSize(-1,-1)); | |
446 | Params[5] = wxAny((long)0); | |
447 | wxASSERT( info->Create(control, 6, Params )); | |
448 | ||
449 | info = wxClassInfo::FindClass("wxStaticBox"); | |
450 | wxASSERT( info ); | |
451 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
452 | Params[0] = wxAny((wxWindow*)(panel)); | |
453 | Params[1] = wxAny(wxWindowID(baseID++)); | |
454 | Params[2] = wxAny(wxString(wxT("A Static Box"))); | |
455 | Params[3] = wxAny(wxPoint( 10, 90 )); | |
456 | Params[4] = wxAny(wxSize(100,80)); | |
457 | Params[5] = wxAny((long)0); | |
458 | wxASSERT( info->Create(control, 6, Params )); | |
459 | ||
460 | info = wxClassInfo::FindClass("wxTextCtrl"); | |
461 | wxASSERT( info ); | |
462 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
463 | Params[0] = wxAny((wxWindow*)(panel)); | |
464 | Params[1] = wxAny(wxWindowID(baseID++)); | |
465 | Params[2] = wxAny(wxString(wxT("A Text Control"))); | |
466 | Params[3] = wxAny(wxPoint( 10, 200 )); | |
467 | Params[4] = wxAny(wxSize(-1,-1)); | |
468 | Params[5] = wxAny((long)0); | |
469 | wxASSERT( info->Create(control, 6, Params )); | |
470 | ||
471 | // spins and gauges page | |
472 | ||
473 | info = wxClassInfo::FindClass("wxPanel"); | |
474 | wxASSERT( info ); | |
475 | panel = wxDynamicCast( info->CreateObject(), wxPanel ); | |
476 | Params[0] = wxAny((wxWindow*)(notebook)); | |
477 | Params[1] = wxAny(wxWindowID(baseID++)); | |
478 | Params[2] = wxAny(wxPoint(-1,-1)); | |
479 | Params[3] = wxAny(wxSize(-1,-1)); | |
480 | Params[4] = wxAny((long)0); | |
481 | Params[5] = wxAny(wxString(wxT("Hello"))); | |
482 | wxASSERT( info->Create(panel, 6, Params )); | |
483 | notebook->AddPage( panel, "Spins and Sliders" ); | |
484 | ||
485 | wxENSURE_CLASS_IS_LINKED(wxSpinButton); | |
486 | ||
487 | info = wxClassInfo::FindClass("wxSpinButton"); | |
488 | wxASSERT( info ); | |
489 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
490 | Params[0] = wxAny((wxWindow*)(panel)); | |
491 | Params[1] = wxAny(wxWindowID(baseID++)); | |
492 | Params[2] = wxAny(wxPoint( 10, 10 )); | |
493 | Params[3] = wxAny(wxSize(-1,-1)); | |
494 | Params[4] = wxAny((long)wxSP_VERTICAL | wxSP_ARROW_KEYS); | |
495 | wxASSERT( info->Create(control, 5, Params )); | |
496 | ||
497 | wxENSURE_CLASS_IS_LINKED(wxSpinCtrl); | |
498 | ||
499 | info = wxClassInfo::FindClass("wxSpinCtrl"); | |
500 | wxASSERT( info ); | |
501 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
502 | Params[0] = wxAny((wxWindow*)(panel)); | |
503 | Params[1] = wxAny(wxWindowID(baseID++)); | |
504 | Params[2] = wxAny(wxString("20")); | |
505 | Params[3] = wxAny(wxPoint( 40, 10 )); | |
506 | Params[4] = wxAny(wxSize(40,-1)); | |
507 | Params[5] = wxAny((long) wxSP_ARROW_KEYS); | |
508 | wxASSERT( info->Create(control, 6, Params )); | |
509 | ||
510 | // MSVC likes to exclude from link wxGauge... | |
511 | wxENSURE_CLASS_IS_LINKED(wxGauge) | |
512 | wxENSURE_CLASS_IS_LINKED(wxCheckBox) | |
513 | wxENSURE_CLASS_IS_LINKED(wxSpinCtrl) | |
514 | ||
515 | info = wxClassInfo::FindClass("wxGauge"); | |
516 | ||
517 | wxASSERT( info ); | |
518 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
519 | Params[0] = wxAny((wxWindow*)(panel)); | |
520 | Params[1] = wxAny(wxWindowID(baseID++)); | |
521 | Params[2] = wxAny((int) 100); | |
522 | Params[3] = wxAny(wxPoint( 10, 50 )); | |
523 | Params[4] = wxAny(wxSize(-1,-1)); | |
524 | Params[5] = wxAny((long) wxGA_HORIZONTAL); | |
525 | wxASSERT( info->Create(control, 6, Params )); | |
526 | wx_dynamic_cast(wxGauge*, control)->SetValue(20); | |
527 | ||
528 | #endif | |
529 | return frameWrapper; | |
530 | } | |
531 | ||
532 | bool SaveFrameRTTI(const wxString &testFileName, wxDynamicObject *frame) | |
533 | { | |
534 | // setup the XML document | |
535 | wxXmlDocument xml; | |
536 | wxXmlNode *root = new wxXmlNode(wxXML_ELEMENT_NODE, | |
537 | "TestXTI", "This is the content"); | |
538 | xml.SetRoot(root); | |
539 | ||
540 | // setup the XTI writer and persister | |
541 | wxObjectXmlWriter writer(root); | |
542 | MyDesignerPersister persister(frame); | |
543 | ||
544 | // write the given wxObject into the XML document | |
545 | wxStringToAnyHashMap empty; | |
546 | writer.WriteObject( frame, frame->GetClassInfo(), &persister, | |
547 | wxString("myTestFrame"), empty ); | |
548 | ||
549 | return xml.Save(testFileName); | |
550 | } | |
551 | ||
552 | wxDynamicObject* LoadFrameRTTI(const wxString &fileName) | |
553 | { | |
554 | // load the XML document | |
555 | wxXmlDocument xml; | |
556 | if (!xml.Load(fileName)) | |
557 | return NULL; | |
558 | ||
559 | wxXmlNode *root = xml.GetRoot(); | |
560 | if (root->GetName() != "TestXTI") | |
561 | return NULL; | |
562 | ||
563 | // now depersist the wxFrame we saved into it using wxObjectRuntimeReaderCallback | |
564 | wxObjectRuntimeReaderCallback Callbacks; | |
565 | wxObjectXmlReader Reader( root ); | |
566 | int obj = Reader.ReadObject( wxString("myTestFrame"), &Callbacks ); | |
567 | return (wxDynamicObject*)Callbacks.GetObject( obj ); | |
568 | } | |
569 | ||
570 | bool GenerateFrameRTTICode(const wxString &inFileName, const wxString &outFileName) | |
571 | { | |
572 | // is loading the streamed out component from xml and writing code that | |
573 | // will create the same component | |
574 | ||
575 | wxFFileOutputStream fos( outFileName ); | |
576 | wxTextOutputStream tos( fos ); | |
577 | if (!fos.IsOk()) | |
578 | return false; | |
579 | ||
580 | wxXmlDocument xml; | |
581 | if (!xml.Load(inFileName)) | |
582 | return false; | |
583 | ||
584 | wxXmlNode *root = xml.GetRoot(); | |
585 | if (root->GetName() != "TestXTI") | |
586 | return false; | |
587 | ||
588 | // read the XML file using the wxObjectCodeReaderCallback | |
589 | ||
590 | wxString headerincludes; | |
591 | wxString sourcecode; | |
592 | wxObjectCodeReaderCallback Callbacks(headerincludes,sourcecode); | |
593 | wxObjectXmlReader Reader(root); | |
594 | ||
595 | // ReadObject will return the ID of the object read?? | |
596 | Reader.ReadObject( wxString("myTestFrame"), &Callbacks ); | |
597 | ||
598 | // header preamble | |
599 | tos << | |
600 | "#include \"wx/wxprec.h\" \n#ifdef __BORLANDC__\n#pragma hdrstop\n#endif\n#ifndef WX_PRECOMP\n#include \"wx/wx.h\" \n#endif\n\n"; | |
601 | // add object includes | |
602 | tos.WriteString( headerincludes ); | |
603 | ||
604 | tos << "\n\nvoid test()\n{"; | |
605 | tos.WriteString( sourcecode ); | |
606 | tos << "}"; | |
607 | return true; | |
608 | } | |
609 | ||
610 | ||
611 | ||
612 | ||
613 | // ---------------------------------------------------------------------------- | |
614 | // MyFrame event handlers | |
615 | // ---------------------------------------------------------------------------- | |
616 | ||
617 | void MyFrame::OnPersist(wxCommandEvent& WXUNUSED(event)) | |
618 | { | |
619 | // first create a frame using XTI calls | |
620 | wxDynamicObject *frame = CreateFrameRTTI(); | |
621 | if (!frame) | |
622 | { | |
623 | wxLogError(wxT("Cannot create the XTI frame!")); | |
624 | return; | |
625 | } | |
626 | ||
627 | // show the frame we're going to save to the user | |
628 | wxFrame *trueFrame = wx_dynamic_cast(wxFrame *, frame->GetSuperClassInstance() ); | |
629 | trueFrame->Show(); | |
630 | ||
631 | // ask the user where to save it | |
632 | wxFileDialog dlg(this, wxT("Where should the frame be saved?"), | |
633 | wxEmptyString, wxT("test.xml"), wxT("XML files (*.xml)|*.xml"), | |
634 | wxFD_SAVE); | |
635 | if (dlg.ShowModal() == wxID_CANCEL) | |
636 | return; | |
637 | ||
638 | // then save it to a test XML file | |
639 | if (!SaveFrameRTTI(dlg.GetPath(), frame)) | |
640 | { | |
641 | wxLogError(wxT("Cannot save the XTI frame into '%s'"), dlg.GetPath()); | |
642 | return; | |
643 | } | |
644 | ||
645 | // now simply delete it | |
646 | delete frame; | |
647 | } | |
648 | ||
649 | void MyFrame::OnDepersist(wxCommandEvent& WXUNUSED(event)) | |
650 | { | |
651 | // ask the user which file to load | |
652 | wxFileDialog dlg(this, wxT("Which file contains the frame to depersist?"), | |
653 | wxEmptyString, wxT("test.xml"), wxT("XML files (*.xml)|*.xml"), | |
654 | wxFD_OPEN); | |
655 | if (dlg.ShowModal() == wxID_CANCEL) | |
656 | return; | |
657 | ||
658 | wxObject *frame = LoadFrameRTTI(dlg.GetPath()); | |
659 | if (!frame) | |
660 | { | |
661 | wxLogError(wxT("Could not depersist the wxFrame from '%s'"), dlg.GetPath()); | |
662 | return; | |
663 | } | |
664 | ||
665 | wxFrame *trueFrame = wx_dynamic_cast(wxFrame*, frame ); | |
666 | if ( !trueFrame ) | |
667 | { | |
668 | wxDynamicObject* dyno = wx_dynamic_cast(wxDynamicObject*, frame ); | |
669 | if ( dyno ) | |
670 | trueFrame = wx_dynamic_cast(wxFrame *, dyno->GetSuperClassInstance() ); | |
671 | } | |
672 | ||
673 | if ( trueFrame ) | |
674 | trueFrame->Show(); | |
675 | else | |
676 | wxLogError(wxT("Could not show the frame")); | |
677 | } | |
678 | ||
679 | void MyFrame::OnGenerateCode(wxCommandEvent& WXUNUSED(event)) | |
680 | { | |
681 | // ask the user which file to load | |
682 | wxFileDialog dlg(this, wxT("Which file contains the frame to work on?"), | |
683 | wxEmptyString, wxT("test.xml"), wxT("XML files (*.xml)|*.xml"), | |
684 | wxFD_OPEN); | |
685 | if (dlg.ShowModal() == wxID_CANCEL) | |
686 | return; | |
687 | ||
688 | // ask the user which file to load | |
689 | wxFileDialog dlg2(this, wxT("Where should the C++ code be saved?"), | |
690 | wxEmptyString, wxT("test.cpp"), wxT("Source files (*.cpp)|*.cpp"), | |
691 | wxFD_SAVE); | |
692 | if (dlg2.ShowModal() == wxID_CANCEL) | |
693 | return; | |
694 | ||
695 | // do generate code | |
696 | if (!GenerateFrameRTTICode(dlg.GetPath(), dlg2.GetPath())) | |
697 | { | |
698 | wxLogError(wxT("Could not generate the code for the frame!")); | |
699 | return; | |
700 | } | |
701 | ||
702 | // show the generated code | |
703 | { | |
704 | wxFileInputStream f(dlg2.GetPath()); | |
705 | wxStringOutputStream str; | |
706 | f.Read(str); | |
707 | ||
708 | wxDialog dlg(this, wxID_ANY, wxT("Generated code"), | |
709 | wxDefaultPosition, wxDefaultSize, | |
710 | wxRESIZE_BORDER|wxDEFAULT_DIALOG_STYLE); | |
711 | wxPanel *panel = new wxPanel(&dlg); | |
712 | wxSizer *sz = new wxBoxSizer(wxVERTICAL); | |
713 | sz->Add(new wxTextCtrl(panel, wxID_ANY, str.GetString(), | |
714 | wxDefaultPosition, wxDefaultSize, | |
715 | wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP), | |
716 | 1, wxGROW|wxALL, 5); | |
717 | sz->Add(new wxButton(panel, wxID_OK), 0, wxALIGN_RIGHT|wxALL, 5); | |
718 | panel->SetSizerAndFit(sz); | |
719 | dlg.ShowModal(); | |
720 | } | |
721 | } | |
722 | ||
723 | void MyFrame::OnDumpClasses(wxCommandEvent& WXUNUSED(event)) | |
724 | { | |
725 | ClassListDialog dlg(this); | |
726 | dlg.ShowModal(); | |
727 | } | |
728 | ||
729 | void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) | |
730 | { | |
731 | // true is to force the frame to close | |
732 | Close(true); | |
733 | } | |
734 | ||
735 | void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) | |
736 | { | |
737 | wxMessageBox(wxString::Format( | |
738 | wxT("Welcome to %s!\n") | |
739 | wxT("\n") | |
740 | wxT("This sample demonstrates wxWidgets eXtended RTTI (XTI) system."), | |
741 | wxVERSION_STRING | |
742 | ), | |
743 | wxT("About wxWidgets XTI sample"), | |
744 | wxOK | wxICON_INFORMATION, | |
745 | this); | |
746 | } |