]> git.saurik.com Git - wxWidgets.git/blame - samples/xti/xti.cpp
prevent infinite loop if gtk_menu_popup() fails, fixes #15387
[wxWidgets.git] / samples / xti / xti.cpp
CommitLineData
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
cc3977bf
SC
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
e7092398 60#ifndef wxHAS_IMAGES_IN_RESOURCES
cc3977bf
SC
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
69class MyApp : public wxApp
70{
71public:
72 virtual bool OnInit();
73};
74
75// Define a new frame type: this is going to be our main frame
76class MyFrame : public wxFrame
77{
78public:
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
89private:
90 // any class wishing to process wxWidgets events must use this macro
1bf29304 91 wxDECLARE_EVENT_TABLE();
cc3977bf
SC
92};
93
94// ----------------------------------------------------------------------------
95// constants
96// ----------------------------------------------------------------------------
97
98// IDs for the controls and the menu commands
99enum
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
114BEGIN_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)
121END_EVENT_TABLE()
122
1bf29304 123wxIMPLEMENT_APP(MyApp);
cc3977bf
SC
124
125// ============================================================================
126// implementation
127// ============================================================================
128
129void RegisterFrameRTTI();
130
131// ----------------------------------------------------------------------------
132// the application class
133// ----------------------------------------------------------------------------
134
135bool MyApp::OnInit()
136{
137 if ( !wxApp::OnInit() )
138 return false;
139
140 RegisterFrameRTTI();
141
142 // create the main application window
ebfe373e 143 MyFrame *frame = new MyFrame(wxT("Extended RTTI sample"));
cc3977bf
SC
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
159MyFrame::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;
2d143b66 171 helpMenu->Append(Minimal_About, wxT("&About\tF1"), wxT("Show about dialog"));
ebfe373e
DS
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"));
cc3977bf 179 fileMenu->AppendSeparator();
ebfe373e
DS
180 fileMenu->Append(Minimal_DumpClasses, wxT("Dump registered classes..."),
181 wxT("Dumps the description of all wxWidgets classes registered in XTI"));
cc3977bf 182 fileMenu->AppendSeparator();
ebfe373e 183 fileMenu->Append(Minimal_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
cc3977bf
SC
184
185 // now append the freshly created menu to the menu bar...
186 wxMenuBar *menuBar = new wxMenuBar();
ebfe373e
DS
187 menuBar->Append(fileMenu, wxT("&File"));
188 menuBar->Append(helpMenu, wxT("&Help"));
cc3977bf
SC
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);
ebfe373e 197 SetStatusText(wxT("Welcome to wxWidgets!"));
cc3977bf
SC
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
1bf29304 265class MyDesignerPersister : public wxObjectWriterCallback
cc3977bf
SC
266{
267public:
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 {
1bf29304 280 // this approach would be used if the handler would not
cc3977bf
SC
281 // be connected really in the designer, so we have to supply
282 // the information
1bf29304
SC
283 const wxObject* but = wxAnyGetAsObjectPtr( m_frame->GetProperty(wxT("Button")) );
284 if ( object == but &&
285 propInfo == wxCLASSINFO( wxButton )->FindPropertyInfo(wxT("OnClick")) )
cc3977bf
SC
286 {
287 eventSink = m_frame;
288 handlerInfo = m_frame->GetClassInfo()->
1bf29304 289 FindHandlerInfo(wxT("ButtonClickHandler"));
cc3977bf
SC
290 return true;
291 }
292 return false;
293 }
294
295private:
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
313void 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:
1bf29304
SC
326 dyninfo->AddProperty(wxT("Button"), wxGetTypeInfo((wxButton**) NULL));
327 dyninfo->AddHandler(wxT("ButtonClickHandler"),
cc3977bf
SC
328 NULL /* no instance of the handler method */, CLASSINFO( wxEvent ) );
329 }
330}
331
332wxDynamicObject* CreateFrameRTTI()
333{
334 int baseID = 100;
1bf29304 335 wxAny Params[10];
cc3977bf
SC
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() );
1bf29304
SC
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);
cc3977bf
SC
350 wxASSERT( info->Create(frameWrapper, 6, Params ));
351 frame = wx_dynamic_cast(wxFrame*, frameWrapper->GetSuperClassInstance());
352
1bf29304 353#if 1
cc3977bf
SC
354 // now build a notebook inside it:
355 wxNotebook* notebook;
356 info = wxClassInfo::FindClass("wxNotebook");
357 wxASSERT( info );
358 notebook = wxDynamicCast( info->CreateObject(), wxNotebook );
1bf29304
SC
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);
cc3977bf
SC
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 );
1bf29304
SC
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")));
cc3977bf
SC
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 );
1bf29304
SC
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);
cc3977bf 391 wxASSERT( info->Create(button, 6, Params ));
1bf29304 392 frameWrapper->SetProperty( wxT("Button"), wxAny( button ) );
cc3977bf
SC
393
394 // other controls page
395
396 info = wxClassInfo::FindClass("wxPanel");
397 wxASSERT( info );
398 panel = wxDynamicCast( info->CreateObject(), wxPanel );
1bf29304
SC
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")));
cc3977bf
SC
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 );
1bf29304
SC
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);
cc3977bf
SC
418 wxASSERT( info->Create(control, 6, Params ));
419
420 info = wxClassInfo::FindClass("wxRadioButton");
421 wxASSERT( info );
422 control = wxDynamicCast( info->CreateObject(), wxControl );
1bf29304
SC
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);
cc3977bf
SC
429 wxASSERT( info->Create(control, 6, Params ));
430
431 control = wxDynamicCast( info->CreateObject(), wxControl );
1bf29304
SC
432 Params[1] = wxAny(wxWindowID(baseID++));
433 Params[2] = wxAny(wxString(wxT("Another One")));
434 Params[3] = wxAny(wxPoint( 10, 50 ));
cc3977bf
SC
435 wxASSERT( info->Create(control, 6, Params ));
436
437 info = wxClassInfo::FindClass("wxStaticText");
438 wxASSERT( info );
439 control = wxDynamicCast( info->CreateObject(), wxControl );
1bf29304
SC
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);
cc3977bf
SC
446 wxASSERT( info->Create(control, 6, Params ));
447
448 info = wxClassInfo::FindClass("wxStaticBox");
449 wxASSERT( info );
450 control = wxDynamicCast( info->CreateObject(), wxControl );
1bf29304
SC
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);
cc3977bf
SC
457 wxASSERT( info->Create(control, 6, Params ));
458
459 info = wxClassInfo::FindClass("wxTextCtrl");
460 wxASSERT( info );
461 control = wxDynamicCast( info->CreateObject(), wxControl );
1bf29304
SC
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);
cc3977bf
SC
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 );
1bf29304
SC
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")));
cc3977bf
SC
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 );
1bf29304
SC
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);
cc3977bf
SC
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 );
1bf29304
SC
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);
cc3977bf
SC
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
cc3977bf 514 info = wxClassInfo::FindClass("wxGauge");
1bf29304 515
cc3977bf
SC
516 wxASSERT( info );
517 control = wxDynamicCast( info->CreateObject(), wxControl );
1bf29304
SC
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);
cc3977bf
SC
524 wxASSERT( info->Create(control, 6, Params ));
525 wx_dynamic_cast(wxGauge*, control)->SetValue(20);
526
1bf29304 527#endif
cc3977bf
SC
528 return frameWrapper;
529}
530
531bool 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
1bf29304 544 wxStringToAnyHashMap empty;
cc3977bf
SC
545 writer.WriteObject( frame, frame->GetClassInfo(), &persister,
546 wxString("myTestFrame"), empty );
547
548 return xml.Save(testFileName);
549}
550
551wxDynamicObject* 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
569bool 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
1bf29304
SC
588
589 wxString headerincludes;
590 wxString sourcecode;
591 wxObjectCodeReaderCallback Callbacks(headerincludes,sourcecode);
cc3977bf
SC
592 wxObjectXmlReader Reader(root);
593
594 // ReadObject will return the ID of the object read??
595 Reader.ReadObject( wxString("myTestFrame"), &Callbacks );
596
1bf29304
SC
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 << "}";
cc3977bf
SC
606 return true;
607}
608
609
610
611
612// ----------------------------------------------------------------------------
613// MyFrame event handlers
614// ----------------------------------------------------------------------------
615
616void 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
648void 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
678void 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
722void MyFrame::OnDumpClasses(wxCommandEvent& WXUNUSED(event))
723{
724 ClassListDialog dlg(this);
725 dlg.ShowModal();
726}
727
728void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
729{
730 // true is to force the frame to close
731 Close(true);
732}
733
734void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
735{
736 wxMessageBox(wxString::Format(
ebfe373e
DS
737 wxT("Welcome to %s!\n")
738 wxT("\n")
739 wxT("This sample demonstrates wxWidgets eXtended RTTI (XTI) system."),
cc3977bf
SC
740 wxVERSION_STRING
741 ),
ebfe373e 742 wxT("About wxWidgets XTI sample"),
cc3977bf
SC
743 wxOK | wxICON_INFORMATION,
744 this);
745}