xti.cpp 25 KB

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