wizard.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: wizard.cpp
  3. // Purpose: wxWidgets sample demonstrating wxWizard control
  4. // Author: Vadim Zeitlin
  5. // Modified by: Robert Vazan (sizers)
  6. // Created: 15.08.99
  7. // Copyright: (c) Vadim Zeitlin
  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
  22. #ifndef WX_PRECOMP
  23. #include "wx/frame.h"
  24. #include "wx/stattext.h"
  25. #include "wx/log.h"
  26. #include "wx/app.h"
  27. #include "wx/checkbox.h"
  28. #include "wx/checklst.h"
  29. #include "wx/msgdlg.h"
  30. #include "wx/radiobox.h"
  31. #include "wx/menu.h"
  32. #include "wx/sizer.h"
  33. #endif
  34. #include "wx/textctrl.h"
  35. #include "wx/wizard.h"
  36. #include "wiztest.xpm"
  37. #include "wiztest2.xpm"
  38. #include "../sample.xpm"
  39. // ----------------------------------------------------------------------------
  40. // constants
  41. // ----------------------------------------------------------------------------
  42. // ids for menu items
  43. enum
  44. {
  45. Wizard_About = wxID_ABOUT,
  46. Wizard_Quit = wxID_EXIT,
  47. Wizard_RunModal = wxID_HIGHEST,
  48. Wizard_RunNoSizer,
  49. Wizard_RunModeless,
  50. Wizard_LargeWizard,
  51. Wizard_ExpandBitmap
  52. };
  53. // ----------------------------------------------------------------------------
  54. // private classes
  55. // ----------------------------------------------------------------------------
  56. // Define a new application type, each program should derive a class from wxApp
  57. class MyApp : public wxApp
  58. {
  59. public:
  60. // override base class virtuals
  61. virtual bool OnInit();
  62. };
  63. class MyFrame : public wxFrame
  64. {
  65. public:
  66. // ctor(s)
  67. MyFrame(const wxString& title);
  68. // event handlers (these functions should _not_ be virtual)
  69. void OnQuit(wxCommandEvent& event);
  70. void OnAbout(wxCommandEvent& event);
  71. void OnRunWizard(wxCommandEvent& event);
  72. void OnRunWizardNoSizer(wxCommandEvent& event);
  73. void OnRunWizardModeless(wxCommandEvent& event);
  74. void OnWizardCancel(wxWizardEvent& event);
  75. void OnWizardFinished(wxWizardEvent& event);
  76. private:
  77. // any class wishing to process wxWidgets events must use this macro
  78. wxDECLARE_EVENT_TABLE();
  79. };
  80. // ----------------------------------------------------------------------------
  81. // our wizard
  82. // ----------------------------------------------------------------------------
  83. class MyWizard : public wxWizard
  84. {
  85. public:
  86. MyWizard(wxFrame *frame, bool useSizer = true);
  87. wxWizardPage *GetFirstPage() const { return m_page1; }
  88. private:
  89. wxWizardPageSimple *m_page1;
  90. };
  91. // ----------------------------------------------------------------------------
  92. // some pages for our wizard
  93. // ----------------------------------------------------------------------------
  94. // This shows how to simply control the validity of the user input by just
  95. // overriding TransferDataFromWindow() - of course, in a real program, the
  96. // check wouldn't be so trivial and the data will be probably saved somewhere
  97. // too.
  98. //
  99. // It also shows how to use a different bitmap for one of the pages.
  100. class wxValidationPage : public wxWizardPageSimple
  101. {
  102. public:
  103. wxValidationPage(wxWizard *parent) : wxWizardPageSimple(parent)
  104. {
  105. m_bitmap = wxBitmap(wiztest2_xpm);
  106. m_checkbox = new wxCheckBox(this, wxID_ANY, wxT("&Check me"));
  107. wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
  108. mainSizer->Add(
  109. new wxStaticText(this, wxID_ANY,
  110. wxT("You need to check the checkbox\n")
  111. wxT("below before going to the next page\n")),
  112. 0,
  113. wxALL,
  114. 5
  115. );
  116. mainSizer->Add(
  117. m_checkbox,
  118. 0, // No stretching
  119. wxALL,
  120. 5 // Border
  121. );
  122. SetSizerAndFit(mainSizer);
  123. }
  124. virtual bool TransferDataFromWindow()
  125. {
  126. if ( !m_checkbox->GetValue() )
  127. {
  128. wxMessageBox(wxT("Check the checkbox first!"), wxT("No way"),
  129. wxICON_WARNING | wxOK, this);
  130. return false;
  131. }
  132. return true;
  133. }
  134. private:
  135. wxCheckBox *m_checkbox;
  136. };
  137. // This is a more complicated example of validity checking: using events we may
  138. // allow to return to the previous page, but not to proceed. It also
  139. // demonstrates how to intercept [Cancel] button press.
  140. class wxRadioboxPage : public wxWizardPageSimple
  141. {
  142. public:
  143. // directions in which we allow the user to proceed from this page
  144. enum
  145. {
  146. Forward, Backward, Both, Neither
  147. };
  148. wxRadioboxPage(wxWizard *parent) : wxWizardPageSimple(parent)
  149. {
  150. // should correspond to the enum above
  151. // static wxString choices[] = { "forward", "backward", "both", "neither" };
  152. // The above syntax can cause an internal compiler error with gcc.
  153. wxString choices[4];
  154. choices[0] = wxT("forward");
  155. choices[1] = wxT("backward");
  156. choices[2] = wxT("both");
  157. choices[3] = wxT("neither");
  158. m_radio = new wxRadioBox(this, wxID_ANY, wxT("Allow to proceed:"),
  159. wxDefaultPosition, wxDefaultSize,
  160. WXSIZEOF(choices), choices,
  161. 1, wxRA_SPECIFY_COLS);
  162. m_radio->SetSelection(Both);
  163. wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
  164. mainSizer->Add(
  165. m_radio,
  166. 0, // No stretching
  167. wxALL,
  168. 5 // Border
  169. );
  170. SetSizerAndFit(mainSizer);
  171. }
  172. // wizard event handlers
  173. void OnWizardCancel(wxWizardEvent& event)
  174. {
  175. if ( wxMessageBox(wxT("Do you really want to cancel?"), wxT("Question"),
  176. wxICON_QUESTION | wxYES_NO, this) != wxYES )
  177. {
  178. // not confirmed
  179. event.Veto();
  180. }
  181. }
  182. void OnWizardPageChanging(wxWizardEvent& event)
  183. {
  184. int sel = m_radio->GetSelection();
  185. if ( sel == Both )
  186. return;
  187. if ( event.GetDirection() && sel == Forward )
  188. return;
  189. if ( !event.GetDirection() && sel == Backward )
  190. return;
  191. wxMessageBox(wxT("You can't go there"), wxT("Not allowed"),
  192. wxICON_WARNING | wxOK, this);
  193. event.Veto();
  194. }
  195. private:
  196. wxRadioBox *m_radio;
  197. wxDECLARE_EVENT_TABLE();
  198. };
  199. // This shows how to dynamically (i.e. during run-time) arrange the page order.
  200. class wxCheckboxPage : public wxWizardPage
  201. {
  202. public:
  203. wxCheckboxPage(wxWizard *parent,
  204. wxWizardPage *prev,
  205. wxWizardPage *next)
  206. : wxWizardPage(parent)
  207. {
  208. m_prev = prev;
  209. m_next = next;
  210. wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
  211. mainSizer->Add(
  212. new wxStaticText(this, wxID_ANY, wxT("Try checking the box below and\n")
  213. wxT("then going back and clearing it")),
  214. 0, // No vertical stretching
  215. wxALL,
  216. 5 // Border width
  217. );
  218. m_checkbox = new wxCheckBox(this, wxID_ANY, wxT("&Skip the next page"));
  219. mainSizer->Add(
  220. m_checkbox,
  221. 0, // No vertical stretching
  222. wxALL,
  223. 5 // Border width
  224. );
  225. #if wxUSE_CHECKLISTBOX
  226. static const wxChar *aszChoices[] =
  227. {
  228. wxT("Zeroth"),
  229. wxT("First"),
  230. wxT("Second"),
  231. wxT("Third"),
  232. wxT("Fourth"),
  233. wxT("Fifth"),
  234. wxT("Sixth"),
  235. wxT("Seventh"),
  236. wxT("Eighth"),
  237. wxT("Nineth")
  238. };
  239. m_checklistbox = new wxCheckListBox
  240. (
  241. this,
  242. wxID_ANY,
  243. wxDefaultPosition,
  244. wxSize(100,100),
  245. wxArrayString(WXSIZEOF(aszChoices), aszChoices)
  246. );
  247. mainSizer->Add(
  248. m_checklistbox,
  249. 0, // No vertical stretching
  250. wxALL,
  251. 5 // Border width
  252. );
  253. #endif // wxUSE_CHECKLISTBOX
  254. wxSize textSize = wxSize(150, 200);
  255. if (((wxFrame*) wxTheApp->GetTopWindow())->GetMenuBar()->IsChecked(Wizard_LargeWizard))
  256. textSize = wxSize(150, wxGetClientDisplayRect().GetHeight() - 200);
  257. wxTextCtrl* textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, textSize, wxTE_MULTILINE);
  258. mainSizer->Add(textCtrl, 0, wxALL|wxEXPAND, 5);
  259. SetSizerAndFit(mainSizer);
  260. }
  261. // implement wxWizardPage functions
  262. virtual wxWizardPage *GetPrev() const { return m_prev; }
  263. virtual wxWizardPage *GetNext() const
  264. {
  265. return m_checkbox->GetValue() ? m_next->GetNext() : m_next;
  266. }
  267. private:
  268. wxWizardPage *m_prev,
  269. *m_next;
  270. wxCheckBox *m_checkbox;
  271. #if wxUSE_CHECKLISTBOX
  272. wxCheckListBox *m_checklistbox;
  273. #endif
  274. };
  275. // ============================================================================
  276. // implementation
  277. // ============================================================================
  278. // ----------------------------------------------------------------------------
  279. // event tables and such
  280. // ----------------------------------------------------------------------------
  281. wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
  282. EVT_MENU(Wizard_Quit, MyFrame::OnQuit)
  283. EVT_MENU(Wizard_About, MyFrame::OnAbout)
  284. EVT_MENU(Wizard_RunModal, MyFrame::OnRunWizard)
  285. EVT_MENU(Wizard_RunNoSizer, MyFrame::OnRunWizardNoSizer)
  286. EVT_MENU(Wizard_RunModeless, MyFrame::OnRunWizardModeless)
  287. EVT_WIZARD_CANCEL(wxID_ANY, MyFrame::OnWizardCancel)
  288. EVT_WIZARD_FINISHED(wxID_ANY, MyFrame::OnWizardFinished)
  289. wxEND_EVENT_TABLE()
  290. wxBEGIN_EVENT_TABLE(wxRadioboxPage, wxWizardPageSimple)
  291. EVT_WIZARD_PAGE_CHANGING(wxID_ANY, wxRadioboxPage::OnWizardPageChanging)
  292. EVT_WIZARD_CANCEL(wxID_ANY, wxRadioboxPage::OnWizardCancel)
  293. wxEND_EVENT_TABLE()
  294. IMPLEMENT_APP(MyApp)
  295. // ----------------------------------------------------------------------------
  296. // the application class
  297. // ----------------------------------------------------------------------------
  298. // `Main program' equivalent: the program execution "starts" here
  299. bool MyApp::OnInit()
  300. {
  301. if ( !wxApp::OnInit() )
  302. return false;
  303. MyFrame *frame = new MyFrame(wxT("wxWizard Sample"));
  304. // and show it (the frames, unlike simple controls, are not shown when
  305. // created initially)
  306. frame->Show(true);
  307. // we're done
  308. return true;
  309. }
  310. // ----------------------------------------------------------------------------
  311. // MyWizard
  312. // ----------------------------------------------------------------------------
  313. MyWizard::MyWizard(wxFrame *frame, bool useSizer)
  314. {
  315. SetExtraStyle(wxWIZARD_EX_HELPBUTTON);
  316. Create(frame,wxID_ANY,wxT("Absolutely Useless Wizard"),
  317. wxBitmap(wiztest_xpm),wxDefaultPosition,
  318. wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
  319. SetIcon(wxICON(sample));
  320. // Allow the bitmap to be expanded to fit the page height
  321. if (frame->GetMenuBar()->IsChecked(Wizard_ExpandBitmap))
  322. SetBitmapPlacement(wxWIZARD_VALIGN_CENTRE);
  323. // Enable scrolling adaptation
  324. if (frame->GetMenuBar()->IsChecked(Wizard_LargeWizard))
  325. SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
  326. // a wizard page may be either an object of predefined class
  327. m_page1 = new wxWizardPageSimple(this);
  328. /* wxStaticText *text = */ new wxStaticText(m_page1, wxID_ANY,
  329. wxT("This wizard doesn't help you\nto do anything at all.\n")
  330. wxT("\n")
  331. wxT("The next pages will present you\nwith more useless controls."),
  332. wxPoint(5,5)
  333. );
  334. // ... or a derived class
  335. wxRadioboxPage *page3 = new wxRadioboxPage(this);
  336. wxValidationPage *page4 = new wxValidationPage(this);
  337. // set the page order using a convenience function - could also use
  338. // SetNext/Prev directly as below, but Chain() is shorter, avoids the risk
  339. // of an error and can itself be chained, e.g. you could write
  340. // page3.Chain(page4).Chain(page5) and so on.
  341. page3->Chain(page4);
  342. // this page is not a wxWizardPageSimple, so we use SetNext/Prev to insert
  343. // it into the chain of pages
  344. wxCheckboxPage *page2 = new wxCheckboxPage(this, m_page1, page3);
  345. m_page1->SetNext(page2);
  346. page3->SetPrev(page2);
  347. if ( useSizer )
  348. {
  349. // allow the wizard to size itself around the pages
  350. GetPageAreaSizer()->Add(m_page1);
  351. }
  352. }
  353. // ----------------------------------------------------------------------------
  354. // MyFrame
  355. // ----------------------------------------------------------------------------
  356. MyFrame::MyFrame(const wxString& title)
  357. :wxFrame((wxFrame *)NULL, wxID_ANY, title,
  358. wxDefaultPosition, wxSize(250, 150)) // small frame
  359. {
  360. wxMenu *menuFile = new wxMenu;
  361. menuFile->Append(Wizard_RunModal, wxT("&Run wizard modal...\tCtrl-R"));
  362. menuFile->Append(Wizard_RunNoSizer, wxT("Run wizard &without sizer..."));
  363. menuFile->Append(Wizard_RunModeless, wxT("Run wizard &modeless..."));
  364. menuFile->AppendSeparator();
  365. menuFile->Append(Wizard_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
  366. wxMenu *menuOptions = new wxMenu;
  367. menuOptions->AppendCheckItem(Wizard_LargeWizard, wxT("&Scroll Wizard Pages"));
  368. menuOptions->AppendCheckItem(Wizard_ExpandBitmap, wxT("Si&ze Bitmap To Page"));
  369. wxMenu *helpMenu = new wxMenu;
  370. helpMenu->Append(Wizard_About, wxT("&About\tF1"), wxT("Show about dialog"));
  371. // now append the freshly created menu to the menu bar...
  372. wxMenuBar *menuBar = new wxMenuBar();
  373. menuBar->Append(menuFile, wxT("&File"));
  374. menuBar->Append(menuOptions, wxT("&Options"));
  375. menuBar->Append(helpMenu, wxT("&Help"));
  376. // ... and attach this menu bar to the frame
  377. SetMenuBar(menuBar);
  378. // also create status bar which we use in OnWizardCancel
  379. #if wxUSE_STATUSBAR
  380. CreateStatusBar();
  381. #endif // wxUSE_STATUSBAR
  382. }
  383. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  384. {
  385. // true is to force the frame to close
  386. Close(true);
  387. }
  388. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  389. {
  390. wxMessageBox(wxT("Demo of wxWizard class\n")
  391. wxT("(c) 1999, 2000 Vadim Zeitlin"),
  392. wxT("About wxWizard sample"), wxOK | wxICON_INFORMATION, this);
  393. }
  394. void MyFrame::OnRunWizard(wxCommandEvent& WXUNUSED(event))
  395. {
  396. MyWizard wizard(this);
  397. wizard.RunWizard(wizard.GetFirstPage());
  398. }
  399. void MyFrame::OnRunWizardNoSizer(wxCommandEvent& WXUNUSED(event))
  400. {
  401. MyWizard wizard(this, false);
  402. wizard.RunWizard(wizard.GetFirstPage());
  403. }
  404. void MyFrame::OnRunWizardModeless(wxCommandEvent& WXUNUSED(event))
  405. {
  406. MyWizard *wizard = new MyWizard(this);
  407. wizard->ShowPage(wizard->GetFirstPage());
  408. wizard->Show(true);
  409. }
  410. void MyFrame::OnWizardFinished(wxWizardEvent& WXUNUSED(event))
  411. {
  412. wxMessageBox(wxT("The wizard finished successfully."), wxT("Wizard notification"));
  413. }
  414. void MyFrame::OnWizardCancel(wxWizardEvent& WXUNUSED(event))
  415. {
  416. wxMessageBox(wxT("The wizard was cancelled."), wxT("Wizard notification"));
  417. }