]>
Commit | Line | Data |
---|---|---|
cc3977bf SC |
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: xti.cpp 48407 2007-08-26 23:17:23Z FM $ | |
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 | #if !defined(__WXMSW__) && !defined(__WXPM__) | |
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(_T("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, _T("&About...\tF1"), _T("Show about dialog")); | |
173 | ||
174 | fileMenu->Append(Minimal_Persist, _T("Persist a wxFrame to XML..."), | |
175 | _T("Creates a wxFrame using wxXTI and saves its description as XML")); | |
176 | fileMenu->Append(Minimal_Depersist, _T("Depersist XML file..."), | |
177 | _T("Loads the description of wxFrame from XML")); | |
178 | fileMenu->Append(Minimal_GenerateCode, _T("Generate code for a wxFrame saved to XML..."), | |
179 | _T("Generates the C++ code which belong to a persisted wxFrame")); | |
180 | fileMenu->AppendSeparator(); | |
181 | fileMenu->Append(Minimal_DumpClasses, _T("Dump registered classes..."), | |
182 | _T("Dumps the description of all wxWidgets classes registered in XTI")); | |
183 | fileMenu->AppendSeparator(); | |
184 | fileMenu->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program")); | |
185 | ||
186 | // now append the freshly created menu to the menu bar... | |
187 | wxMenuBar *menuBar = new wxMenuBar(); | |
188 | menuBar->Append(fileMenu, _T("&File")); | |
189 | menuBar->Append(helpMenu, _T("&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(_T("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 wxObjectReaderCallback | |
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 it the handler would not | |
282 | // be connected really in the designer, so we have to supply | |
283 | // the information | |
284 | if ( object == m_frame->GetProperty(wxT("Button")).GetAsObject() && | |
285 | propInfo == wxCLASSINFO( wxButton )->FindPropertyInfo("OnClick") ) | |
286 | { | |
287 | eventSink = m_frame; | |
288 | handlerInfo = m_frame->GetClassInfo()-> | |
289 | FindHandlerInfo("ButtonClickHandler"); | |
290 | return true; | |
291 | } | |
292 | return false; | |
293 | } | |
294 | ||
295 | private: | |
296 | wxDynamicObject *m_frame; | |
297 | }; | |
298 | ||
299 | // sometimes linkers (at least MSVC and GCC ones) optimize the final EXE | |
300 | // even in debug mode pruning the object files which he "thinks" are useless; | |
301 | // thus the classes defined in those files won't be available in the XTI | |
302 | // table and the program will fail to allocate them. | |
303 | // The following macro implements a simple hack to ensure that a given | |
304 | // class is linked in. | |
305 | // | |
306 | // TODO: in wx/link.h there are already similar macros (also more "optimized": | |
307 | // don't need the creation of fake object) which however require to use | |
308 | // the wxFORCE_LINK_THIS_MODULE() macro inside the source files corresponding | |
309 | // to the class being discarded. | |
310 | // | |
311 | #define wxENSURE_CLASS_IS_LINKED(x) { x test; } | |
312 | ||
313 | void RegisterFrameRTTI() | |
314 | { | |
315 | // set up the RTTI info for a class (MyXTIFrame) which | |
316 | // is not defined anywhere in this program | |
317 | wxDynamicClassInfo *dyninfo = | |
318 | wx_dynamic_cast( wxDynamicClassInfo *, wxClassInfo::FindClass(wxT("MyXTIFrame"))); | |
319 | if ( dyninfo == NULL ) | |
320 | { | |
321 | dyninfo = new wxDynamicClassInfo(wxT("myxtiframe.h"), | |
322 | wxT("MyXTIFrame"), | |
323 | CLASSINFO(wxFrame) ); | |
324 | ||
325 | // this class has a property named "Button" and the relative handler: | |
326 | dyninfo->AddProperty("Button", wxGetTypeInfo((wxButton**) NULL)); | |
327 | dyninfo->AddHandler("ButtonClickHandler", | |
328 | NULL /* no instance of the handler method */, CLASSINFO( wxEvent ) ); | |
329 | } | |
330 | } | |
331 | ||
332 | wxDynamicObject* CreateFrameRTTI() | |
333 | { | |
334 | int baseID = 100; | |
335 | wxVariantBase Params[10]; | |
336 | ||
337 | // the class is now part of XTI internal table so that we can | |
338 | // get a pointer to it just searching it like any other class: | |
339 | wxFrame* frame; | |
340 | wxClassInfo *info = wxClassInfo::FindClass(wxT("MyXTIFrame")); | |
341 | wxASSERT( info ); | |
342 | wxDynamicObject* frameWrapper = | |
343 | wx_dynamic_cast(wxDynamicObject*, info->CreateObject() ); | |
344 | Params[0] = wxVariantBase((wxWindow*)(NULL)); | |
345 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
346 | Params[2] = wxVariantBase(wxString(wxT("This is a frame created from XTI"))); | |
347 | Params[3] = wxVariantBase(wxPoint(-1,-1)); | |
348 | Params[4] = wxVariantBase(wxSize(400,300)); | |
349 | Params[5] = wxVariantBase((long)wxDEFAULT_FRAME_STYLE); | |
350 | wxASSERT( info->Create(frameWrapper, 6, Params )); | |
351 | frame = wx_dynamic_cast(wxFrame*, frameWrapper->GetSuperClassInstance()); | |
352 | ||
353 | // now build a notebook inside it: | |
354 | wxNotebook* notebook; | |
355 | info = wxClassInfo::FindClass("wxNotebook"); | |
356 | wxASSERT( info ); | |
357 | notebook = wxDynamicCast( info->CreateObject(), wxNotebook ); | |
358 | Params[0] = wxVariantBase((wxWindow*)frame); | |
359 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
360 | Params[2] = wxVariantBase(wxPoint( 10, 10 )); | |
361 | Params[3] = wxVariantBase(wxDefaultSize); | |
362 | Params[4] = wxVariantBase((long)0); | |
363 | wxASSERT( info->Create(notebook, 5, Params )); | |
364 | ||
365 | // button page | |
366 | ||
367 | wxPanel* panel; | |
368 | info = wxClassInfo::FindClass("wxPanel"); | |
369 | wxASSERT( info ); | |
370 | panel = wxDynamicCast( info->CreateObject(), wxPanel ); | |
371 | Params[0] = wxVariantBase((wxWindow*)(notebook)); | |
372 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
373 | Params[2] = wxVariantBase(wxPoint(-1,-1)); | |
374 | Params[3] = wxVariantBase(wxSize(-1,-1)); | |
375 | Params[4] = wxVariantBase((long)0); | |
376 | Params[5] = wxVariantBase(wxString(wxT("Hello"))); | |
377 | wxASSERT( info->Create(panel, 6, Params )); | |
378 | notebook->AddPage( panel, "Buttons" ); | |
379 | ||
380 | wxButton* button; | |
381 | info = wxClassInfo::FindClass("wxButton"); | |
382 | wxASSERT( info ); | |
383 | button = wxDynamicCast( info->CreateObject(), wxButton ); | |
384 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
385 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
386 | Params[2] = wxVariantBase(wxString(wxT("Click Me!"))); | |
387 | Params[3] = wxVariantBase(wxPoint( 10, 10 )); | |
388 | Params[4] = wxVariantBase(wxSize(-1,-1)); | |
389 | Params[5] = wxVariantBase((long)0); | |
390 | wxASSERT( info->Create(button, 6, Params )); | |
391 | frameWrapper->SetProperty( "Button", wxVariantBase( button ) ); | |
392 | ||
393 | // other controls page | |
394 | ||
395 | info = wxClassInfo::FindClass("wxPanel"); | |
396 | wxASSERT( info ); | |
397 | panel = wxDynamicCast( info->CreateObject(), wxPanel ); | |
398 | Params[0] = wxVariantBase((wxWindow*)(notebook)); | |
399 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
400 | Params[2] = wxVariantBase(wxPoint(-1,-1)); | |
401 | Params[3] = wxVariantBase(wxSize(-1,-1)); | |
402 | Params[4] = wxVariantBase((long)0); | |
403 | Params[5] = wxVariantBase(wxString(wxT("Hello"))); | |
404 | wxASSERT( info->Create(panel, 6, Params )); | |
405 | notebook->AddPage( panel, "Other Standard controls" ); | |
406 | ||
407 | wxControl* control; | |
408 | info = wxClassInfo::FindClass("wxCheckBox"); | |
409 | wxASSERT( info ); | |
410 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
411 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
412 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
413 | Params[2] = wxVariantBase(wxString(wxT("A Checkbox"))); | |
414 | Params[3] = wxVariantBase(wxPoint( 10, 10 )); | |
415 | Params[4] = wxVariantBase(wxSize(-1,-1)); | |
416 | Params[5] = wxVariantBase((long)0); | |
417 | wxASSERT( info->Create(control, 6, Params )); | |
418 | ||
419 | info = wxClassInfo::FindClass("wxRadioButton"); | |
420 | wxASSERT( info ); | |
421 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
422 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
423 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
424 | Params[2] = wxVariantBase(wxString(wxT("A Radiobutton"))); | |
425 | Params[3] = wxVariantBase(wxPoint( 10, 30 )); | |
426 | Params[4] = wxVariantBase(wxSize(-1,-1)); | |
427 | Params[5] = wxVariantBase((long)0); | |
428 | wxASSERT( info->Create(control, 6, Params )); | |
429 | ||
430 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
431 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
432 | Params[2] = wxVariantBase(wxString(wxT("Another One"))); | |
433 | Params[3] = wxVariantBase(wxPoint( 10, 50 )); | |
434 | wxASSERT( info->Create(control, 6, Params )); | |
435 | ||
436 | info = wxClassInfo::FindClass("wxStaticText"); | |
437 | wxASSERT( info ); | |
438 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
439 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
440 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
441 | Params[2] = wxVariantBase(wxString(wxT("A Static Text!"))); | |
442 | Params[3] = wxVariantBase(wxPoint( 10, 70 )); | |
443 | Params[4] = wxVariantBase(wxSize(-1,-1)); | |
444 | Params[5] = wxVariantBase((long)0); | |
445 | wxASSERT( info->Create(control, 6, Params )); | |
446 | ||
447 | info = wxClassInfo::FindClass("wxStaticBox"); | |
448 | wxASSERT( info ); | |
449 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
450 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
451 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
452 | Params[2] = wxVariantBase(wxString(wxT("A Static Box"))); | |
453 | Params[3] = wxVariantBase(wxPoint( 10, 90 )); | |
454 | Params[4] = wxVariantBase(wxSize(100,80)); | |
455 | Params[5] = wxVariantBase((long)0); | |
456 | wxASSERT( info->Create(control, 6, Params )); | |
457 | ||
458 | info = wxClassInfo::FindClass("wxTextCtrl"); | |
459 | wxASSERT( info ); | |
460 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
461 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
462 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
463 | Params[2] = wxVariantBase(wxString(wxT("A Text Control"))); | |
464 | Params[3] = wxVariantBase(wxPoint( 10, 200 )); | |
465 | Params[4] = wxVariantBase(wxSize(-1,-1)); | |
466 | Params[5] = wxVariantBase((long)0); | |
467 | wxASSERT( info->Create(control, 6, Params )); | |
468 | ||
469 | // spins and gauges page | |
470 | ||
471 | info = wxClassInfo::FindClass("wxPanel"); | |
472 | wxASSERT( info ); | |
473 | panel = wxDynamicCast( info->CreateObject(), wxPanel ); | |
474 | Params[0] = wxVariantBase((wxWindow*)(notebook)); | |
475 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
476 | Params[2] = wxVariantBase(wxPoint(-1,-1)); | |
477 | Params[3] = wxVariantBase(wxSize(-1,-1)); | |
478 | Params[4] = wxVariantBase((long)0); | |
479 | Params[5] = wxVariantBase(wxString(wxT("Hello"))); | |
480 | wxASSERT( info->Create(panel, 6, Params )); | |
481 | notebook->AddPage( panel, "Spins and Sliders" ); | |
482 | ||
483 | wxENSURE_CLASS_IS_LINKED(wxSpinButton); | |
484 | ||
485 | info = wxClassInfo::FindClass("wxSpinButton"); | |
486 | wxASSERT( info ); | |
487 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
488 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
489 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
490 | Params[2] = wxVariantBase(wxPoint( 10, 10 )); | |
491 | Params[3] = wxVariantBase(wxSize(-1,-1)); | |
492 | Params[4] = wxVariantBase((long)wxSP_VERTICAL | wxSP_ARROW_KEYS); | |
493 | wxASSERT( info->Create(control, 5, Params )); | |
494 | ||
495 | wxENSURE_CLASS_IS_LINKED(wxSpinCtrl); | |
496 | ||
497 | info = wxClassInfo::FindClass("wxSpinCtrl"); | |
498 | wxASSERT( info ); | |
499 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
500 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
501 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
502 | Params[2] = wxVariantBase(wxString("20")); | |
503 | Params[3] = wxVariantBase(wxPoint( 40, 10 )); | |
504 | Params[4] = wxVariantBase(wxSize(40,-1)); | |
505 | Params[5] = wxVariantBase((long) wxSP_ARROW_KEYS); | |
506 | wxASSERT( info->Create(control, 6, Params )); | |
507 | ||
508 | // MSVC likes to exclude from link wxGauge... | |
509 | wxENSURE_CLASS_IS_LINKED(wxGauge) | |
510 | wxENSURE_CLASS_IS_LINKED(wxCheckBox) | |
511 | wxENSURE_CLASS_IS_LINKED(wxSpinCtrl) | |
512 | ||
513 | #ifdef __WXMSW__ | |
514 | // under wxMSW wxGauge is simply #defined to wxGauge95 | |
515 | info = wxClassInfo::FindClass("wxGauge95"); | |
516 | #else | |
517 | info = wxClassInfo::FindClass("wxGauge"); | |
518 | #endif | |
519 | wxASSERT( info ); | |
520 | control = wxDynamicCast( info->CreateObject(), wxControl ); | |
521 | Params[0] = wxVariantBase((wxWindow*)(panel)); | |
522 | Params[1] = wxVariantBase(wxWindowID(baseID++)); | |
523 | Params[2] = wxVariantBase((int) 100); | |
524 | Params[3] = wxVariantBase(wxPoint( 10, 50 )); | |
525 | Params[4] = wxVariantBase(wxSize(-1,-1)); | |
526 | Params[5] = wxVariantBase((long) wxGA_HORIZONTAL); | |
527 | wxASSERT( info->Create(control, 6, Params )); | |
528 | wx_dynamic_cast(wxGauge*, control)->SetValue(20); | |
529 | ||
530 | return frameWrapper; | |
531 | } | |
532 | ||
533 | bool SaveFrameRTTI(const wxString &testFileName, wxDynamicObject *frame) | |
534 | { | |
535 | // setup the XML document | |
536 | wxXmlDocument xml; | |
537 | wxXmlNode *root = new wxXmlNode(wxXML_ELEMENT_NODE, | |
538 | "TestXTI", "This is the content"); | |
539 | xml.SetRoot(root); | |
540 | ||
541 | // setup the XTI writer and persister | |
542 | wxObjectXmlWriter writer(root); | |
543 | MyDesignerPersister persister(frame); | |
544 | ||
545 | // write the given wxObject into the XML document | |
546 | wxVariantBaseArray empty; | |
547 | writer.WriteObject( frame, frame->GetClassInfo(), &persister, | |
548 | wxString("myTestFrame"), empty ); | |
549 | ||
550 | return xml.Save(testFileName); | |
551 | } | |
552 | ||
553 | wxDynamicObject* LoadFrameRTTI(const wxString &fileName) | |
554 | { | |
555 | // load the XML document | |
556 | wxXmlDocument xml; | |
557 | if (!xml.Load(fileName)) | |
558 | return NULL; | |
559 | ||
560 | wxXmlNode *root = xml.GetRoot(); | |
561 | if (root->GetName() != "TestXTI") | |
562 | return NULL; | |
563 | ||
564 | // now depersist the wxFrame we saved into it using wxObjectRuntimeReaderCallback | |
565 | wxObjectRuntimeReaderCallback Callbacks; | |
566 | wxObjectXmlReader Reader( root ); | |
567 | int obj = Reader.ReadObject( wxString("myTestFrame"), &Callbacks ); | |
568 | return (wxDynamicObject*)Callbacks.GetObject( obj ); | |
569 | } | |
570 | ||
571 | bool GenerateFrameRTTICode(const wxString &inFileName, const wxString &outFileName) | |
572 | { | |
573 | // is loading the streamed out component from xml and writing code that | |
574 | // will create the same component | |
575 | ||
576 | wxFFileOutputStream fos( outFileName ); | |
577 | wxTextOutputStream tos( fos ); | |
578 | if (!fos.IsOk()) | |
579 | return false; | |
580 | ||
581 | wxXmlDocument xml; | |
582 | if (!xml.Load(inFileName)) | |
583 | return false; | |
584 | ||
585 | wxXmlNode *root = xml.GetRoot(); | |
586 | if (root->GetName() != "TestXTI") | |
587 | return false; | |
588 | ||
589 | // read the XML file using the wxObjectCodeReaderCallback | |
590 | wxObjectCodeReaderCallback Callbacks(&tos); | |
591 | wxObjectXmlReader Reader(root); | |
592 | ||
593 | // ReadObject will return the ID of the object read?? | |
594 | Reader.ReadObject( wxString("myTestFrame"), &Callbacks ); | |
595 | ||
596 | return true; | |
597 | } | |
598 | ||
599 | ||
600 | ||
601 | ||
602 | // ---------------------------------------------------------------------------- | |
603 | // MyFrame event handlers | |
604 | // ---------------------------------------------------------------------------- | |
605 | ||
606 | void MyFrame::OnPersist(wxCommandEvent& WXUNUSED(event)) | |
607 | { | |
608 | // first create a frame using XTI calls | |
609 | wxDynamicObject *frame = CreateFrameRTTI(); | |
610 | if (!frame) | |
611 | { | |
612 | wxLogError(wxT("Cannot create the XTI frame!")); | |
613 | return; | |
614 | } | |
615 | ||
616 | // show the frame we're going to save to the user | |
617 | wxFrame *trueFrame = wx_dynamic_cast(wxFrame *, frame->GetSuperClassInstance() ); | |
618 | trueFrame->Show(); | |
619 | ||
620 | // ask the user where to save it | |
621 | wxFileDialog dlg(this, wxT("Where should the frame be saved?"), | |
622 | wxEmptyString, wxT("test.xml"), wxT("XML files (*.xml)|*.xml"), | |
623 | wxFD_SAVE); | |
624 | if (dlg.ShowModal() == wxID_CANCEL) | |
625 | return; | |
626 | ||
627 | // then save it to a test XML file | |
628 | if (!SaveFrameRTTI(dlg.GetPath(), frame)) | |
629 | { | |
630 | wxLogError(wxT("Cannot save the XTI frame into '%s'"), dlg.GetPath()); | |
631 | return; | |
632 | } | |
633 | ||
634 | // now simply delete it | |
635 | delete frame; | |
636 | } | |
637 | ||
638 | void MyFrame::OnDepersist(wxCommandEvent& WXUNUSED(event)) | |
639 | { | |
640 | // ask the user which file to load | |
641 | wxFileDialog dlg(this, wxT("Which file contains the frame to depersist?"), | |
642 | wxEmptyString, wxT("test.xml"), wxT("XML files (*.xml)|*.xml"), | |
643 | wxFD_OPEN); | |
644 | if (dlg.ShowModal() == wxID_CANCEL) | |
645 | return; | |
646 | ||
647 | wxObject *frame = LoadFrameRTTI(dlg.GetPath()); | |
648 | if (!frame) | |
649 | { | |
650 | wxLogError(wxT("Could not depersist the wxFrame from '%s'"), dlg.GetPath()); | |
651 | return; | |
652 | } | |
653 | ||
654 | wxFrame *trueFrame = wx_dynamic_cast(wxFrame*, frame ); | |
655 | if ( !trueFrame ) | |
656 | { | |
657 | wxDynamicObject* dyno = wx_dynamic_cast(wxDynamicObject*, frame ); | |
658 | if ( dyno ) | |
659 | trueFrame = wx_dynamic_cast(wxFrame *, dyno->GetSuperClassInstance() ); | |
660 | } | |
661 | ||
662 | if ( trueFrame ) | |
663 | trueFrame->Show(); | |
664 | else | |
665 | wxLogError(wxT("Could not show the frame")); | |
666 | } | |
667 | ||
668 | void MyFrame::OnGenerateCode(wxCommandEvent& WXUNUSED(event)) | |
669 | { | |
670 | // ask the user which file to load | |
671 | wxFileDialog dlg(this, wxT("Which file contains the frame to work on?"), | |
672 | wxEmptyString, wxT("test.xml"), wxT("XML files (*.xml)|*.xml"), | |
673 | wxFD_OPEN); | |
674 | if (dlg.ShowModal() == wxID_CANCEL) | |
675 | return; | |
676 | ||
677 | // ask the user which file to load | |
678 | wxFileDialog dlg2(this, wxT("Where should the C++ code be saved?"), | |
679 | wxEmptyString, wxT("test.cpp"), wxT("Source files (*.cpp)|*.cpp"), | |
680 | wxFD_SAVE); | |
681 | if (dlg2.ShowModal() == wxID_CANCEL) | |
682 | return; | |
683 | ||
684 | // do generate code | |
685 | if (!GenerateFrameRTTICode(dlg.GetPath(), dlg2.GetPath())) | |
686 | { | |
687 | wxLogError(wxT("Could not generate the code for the frame!")); | |
688 | return; | |
689 | } | |
690 | ||
691 | // show the generated code | |
692 | { | |
693 | wxFileInputStream f(dlg2.GetPath()); | |
694 | wxStringOutputStream str; | |
695 | f.Read(str); | |
696 | ||
697 | wxDialog dlg(this, wxID_ANY, wxT("Generated code"), | |
698 | wxDefaultPosition, wxDefaultSize, | |
699 | wxRESIZE_BORDER|wxDEFAULT_DIALOG_STYLE); | |
700 | wxPanel *panel = new wxPanel(&dlg); | |
701 | wxSizer *sz = new wxBoxSizer(wxVERTICAL); | |
702 | sz->Add(new wxTextCtrl(panel, wxID_ANY, str.GetString(), | |
703 | wxDefaultPosition, wxDefaultSize, | |
704 | wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP), | |
705 | 1, wxGROW|wxALL, 5); | |
706 | sz->Add(new wxButton(panel, wxID_OK), 0, wxALIGN_RIGHT|wxALL, 5); | |
707 | panel->SetSizerAndFit(sz); | |
708 | dlg.ShowModal(); | |
709 | } | |
710 | } | |
711 | ||
712 | void MyFrame::OnDumpClasses(wxCommandEvent& WXUNUSED(event)) | |
713 | { | |
714 | ClassListDialog dlg(this); | |
715 | dlg.ShowModal(); | |
716 | } | |
717 | ||
718 | void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) | |
719 | { | |
720 | // true is to force the frame to close | |
721 | Close(true); | |
722 | } | |
723 | ||
724 | void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) | |
725 | { | |
726 | wxMessageBox(wxString::Format( | |
727 | _T("Welcome to %s!\n") | |
728 | _T("\n") | |
729 | _T("This sample demonstrates wxWidgets eXtended RTTI (XTI) system."), | |
730 | wxVERSION_STRING | |
731 | ), | |
732 | _T("About wxWidgets XTI sample"), | |
733 | wxOK | wxICON_INFORMATION, | |
734 | this); | |
735 | } |