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