objrefdlg.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. //-----------------------------------------------------------------------------
  2. // Name: objref.cpp
  3. // Purpose: XML resources sample: Object references and ID ranges dialog
  4. // Author: David Hart, Vaclav Slavik
  5. // Copyright: (c) Vaclav Slavik
  6. // Licence: wxWindows licence
  7. //-----------------------------------------------------------------------------
  8. //-----------------------------------------------------------------------------
  9. // Standard wxWidgets headers
  10. //-----------------------------------------------------------------------------
  11. // For compilers that support precompilation, includes "wx/wx.h".
  12. #include "wx/wxprec.h"
  13. #ifdef __BORLANDC__
  14. #pragma hdrstop
  15. #endif
  16. // For all others, include the necessary headers (this file is usually all you
  17. // need because it includes almost all "standard" wxWidgets headers)
  18. #ifndef WX_PRECOMP
  19. #include "wx/wx.h"
  20. #endif
  21. //-----------------------------------------------------------------------------
  22. // Header of this .cpp file
  23. //-----------------------------------------------------------------------------
  24. #include "objrefdlg.h"
  25. //-----------------------------------------------------------------------------
  26. // Needed wx headers,
  27. //-----------------------------------------------------------------------------
  28. #include "wx/xrc/xmlres.h" // XRC XML resouces
  29. //-----------------------------------------------------------------------------
  30. // Public members
  31. //-----------------------------------------------------------------------------
  32. ObjrefDialog::ObjrefDialog(wxWindow* parent)
  33. {
  34. wxXmlResource::Get()->LoadDialog(this, parent, wxT("objref_dialog"));
  35. nb = XRCCTRL(*this, "objref_notebook", wxNotebook);
  36. wxCHECK_RET(nb, "failed to find objref_notebook");
  37. // Connect different event handlers.
  38. nb->Connect(wxEVT_NOTEBOOK_PAGE_CHANGED,
  39. wxNotebookEventHandler(ObjrefDialog::OnNotebookPageChanged),
  40. NULL, this);
  41. // We want to direct UpdateUI events for the ID range 'first_row' to
  42. // OnUpdateUIFirst(). We could achieve this using first_row[0] and
  43. // first_row[2], but what if a fourth column were added? It's safer to use
  44. // the 'typedefs' for the two ends of the range:
  45. wxNotebookPage *page = nb->GetPage(icons_page);
  46. page->Connect(XRCID("first_row[start]"), XRCID("first_row[end]"),
  47. wxEVT_UPDATE_UI,
  48. wxUpdateUIEventHandler(ObjrefDialog::OnUpdateUIFirst),
  49. NULL, this);
  50. page->Connect(XRCID("second_row[start]"), XRCID("second_row[end]"),
  51. wxEVT_UPDATE_UI,
  52. wxUpdateUIEventHandler(ObjrefDialog::OnUpdateUISecond),
  53. NULL, this);
  54. page->Connect(XRCID("third_row[start]"), XRCID("third_row[end]"),
  55. wxEVT_UPDATE_UI,
  56. wxUpdateUIEventHandler(ObjrefDialog::OnUpdateUIThird),
  57. NULL, this);
  58. // Connect the id ranges, using the [start] and [end] 'typedefs'
  59. page = nb->GetPage(calc_page);
  60. page->Connect(XRCID("digits[start]"), XRCID("digits[end]"),
  61. wxEVT_BUTTON,
  62. wxCommandEventHandler(ObjrefDialog::OnNumeralClick),
  63. NULL, this);
  64. page->Connect(XRCID("operators[start]"), XRCID("operators[end]"),
  65. wxEVT_BUTTON,
  66. wxCommandEventHandler(ObjrefDialog::OnOperatorClick),
  67. NULL, this);
  68. }
  69. ObjrefDialog::~ObjrefDialog()
  70. {
  71. // Select page 0. Otherwise if the Calc page were selected, when it's
  72. // removed the Icons page is selected and sets the log target again in idle
  73. // time, *after* myframe restores the old one!
  74. nb->ChangeSelection(0);
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Private members (including the event handlers)
  78. //-----------------------------------------------------------------------------
  79. void ObjrefDialog::OnNotebookPageChanged( wxNotebookEvent &event )
  80. {
  81. switch(event.GetSelection())
  82. {
  83. case copy_page:
  84. {
  85. // This is a straight object reference to the first page
  86. // so change the text programmatically
  87. nb->SetPageText(copy_page, "Page 1 copy");
  88. wxNotebookPage *page = nb->GetPage(copy_page);
  89. wxTextCtrl *
  90. text = XRCCTRL(*page, "description_text", wxTextCtrl);
  91. text->ChangeValue(
  92. "This is a duplicate of page 1, using an object reference. "
  93. "It was created by this very simple xml:\n\n"
  94. "<object class=\"notebookpage\">\n\t<object_ref ref=\"page1\"/>\n"
  95. "\t<label>Page 1 copy</label>\n</object>"
  96. "\n\n(Then I'm cheating by inserting this text programmatically.)"
  97. );
  98. break;
  99. }
  100. case icons_page:
  101. {
  102. wxNotebookPage *page = nb->GetPage(icons_page);
  103. text = XRCCTRL(*page, "log_text", wxTextCtrl);
  104. if (text)
  105. delete wxLog::SetActiveTarget(new wxLogTextCtrl(text));
  106. break;
  107. }
  108. case calc_page:
  109. {
  110. wxNotebookPage *page = nb->GetPage(calc_page);
  111. result_txt = XRCCTRL(*page, "result", wxTextCtrl);
  112. text = XRCCTRL(*page, "log_text", wxTextCtrl);
  113. if (text)
  114. delete wxLog::SetActiveTarget(new wxLogTextCtrl(text));
  115. ClearCalculator();
  116. break;
  117. }
  118. }
  119. }
  120. // There are undoubtedly simpler ways of doing all this, but we're
  121. // demonstrating the use of ID ranges
  122. void ObjrefDialog::OnUpdateUIFirst(wxUpdateUIEvent& event)
  123. {
  124. // The checkbox with the XRCID 'check[0]' controls this row of icons
  125. wxCheckBox *
  126. chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[0]", wxCheckBox);
  127. if (chk)
  128. event.Enable(chk->IsChecked());
  129. // Let's create a log-window entry
  130. static bool checked = true;
  131. if (chk->IsChecked() != checked)
  132. {
  133. checked = chk->IsChecked();
  134. wxLogMessage("Row one has been %s by check[0], XRCID = %i",
  135. checked ? "enabled" : "disabled", XRCID("check[0]"));
  136. wxLogMessage("XRCIDs: first_row[start] = %i, first_row[0] = %i, "
  137. "first_row[1] = %i, first_row[2] = %i, "
  138. "first_row[end] = %i",
  139. XRCID("first_row[start]"), XRCID("first_row[0]"),
  140. XRCID("first_row[1]"), XRCID("first_row[2]"),
  141. XRCID("first_row[end]"));
  142. }
  143. }
  144. void ObjrefDialog::OnUpdateUISecond(wxUpdateUIEvent& event)
  145. {
  146. // The checkbox with the XRCID 'check[1]' controls this row of icons
  147. wxCheckBox *
  148. chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[1]", wxCheckBox);
  149. if (chk)
  150. event.Enable(chk->IsChecked());
  151. // Let's create a log-window entry
  152. static bool checked = true;
  153. if (chk->IsChecked() != checked)
  154. {
  155. checked = chk->IsChecked();
  156. wxLogMessage("Row two has been %s by check[1], XRCID = %i",
  157. checked ? "enabled" : "disabled", XRCID("check[1]"));
  158. wxLogMessage("XRCIDs: second_row[start] = %i, second_row[0] = %i, "
  159. "second_row[1] = %i, second_row[2] = %i, "
  160. "second_row[end] = %i",
  161. XRCID("second_row[start]"), XRCID("second_row[0]"),
  162. XRCID("second_row[1]"), XRCID("second_row[2]"),
  163. XRCID("second_row[end]"));
  164. }
  165. }
  166. void ObjrefDialog::OnUpdateUIThird(wxUpdateUIEvent& event)
  167. {
  168. // The checkbox with the XRCID 'check[2]' controls this row of icons
  169. wxCheckBox *
  170. chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[2]", wxCheckBox);
  171. if (chk)
  172. event.Enable(chk->IsChecked());
  173. // Let's create a log-window entry
  174. static bool checked = true;
  175. if (chk->IsChecked() != checked)
  176. {
  177. checked = chk->IsChecked();
  178. wxLogMessage("Row three has been %s by check[2], XRCID = %i",
  179. checked ? "enabled" : "disabled", XRCID("check[2]"));
  180. wxLogMessage("XRCIDs: third_row[start] = %i, third_row[0] = %i, "
  181. "third_row[1] = %i, third_row[2] = %i, "
  182. "third_row[end] = %i",
  183. XRCID("third_row[start]"), XRCID("third_row[0]"),
  184. XRCID("third_row[1]"), XRCID("third_row[2]"),
  185. XRCID("third_row[end]"));
  186. }
  187. }
  188. void ObjrefDialog::OnNumeralClick(wxCommandEvent& event)
  189. {
  190. // See how the id range simplifies determining which numeral was clicked
  191. int digit = event.GetId() - XRCID("digits[start]");
  192. char c = '0' + digit;
  193. if (current==0 && previous==0)
  194. {
  195. // We're just starting a calculation, so get rid of the placeholder '0'
  196. result_txt->Clear();
  197. }
  198. else if (operator_expected == true)
  199. {
  200. // If we've just finished one calculation, and now a digit is entered,
  201. // clear
  202. ClearCalculator();
  203. result_txt->Clear();
  204. }
  205. (*result_txt) << c;
  206. current = current*10 + digit;
  207. wxLogMessage("You clicked digits[%c], XRCID %i", c, event.GetId());
  208. }
  209. void ObjrefDialog::OnOperatorClick(wxCommandEvent& event)
  210. {
  211. static const char symbols[] = "+-*/=";
  212. operator_expected = false;
  213. int ID = event.GetId() - XRCID("operators[start]");
  214. // We carefully used "operators[end]" as the name of the Clear button
  215. if (event.GetId() == XRCID("operators[end]"))
  216. {
  217. wxLogMessage("You clicked operators[%i], XRCID %d, 'Clear'",
  218. ID, event.GetId());
  219. ClearCalculator();
  220. return;
  221. }
  222. switch(ID)
  223. {
  224. case operator_plus:
  225. case operator_minus:
  226. case operator_multiply:
  227. case operator_divide:
  228. if (current!=0 || previous!=0)
  229. {
  230. // We're in the middle of a complex calculation, so do the
  231. // first bit
  232. Calculate();
  233. }
  234. curr_operator = (CalcOperator)ID;
  235. break;
  236. case operator_equals:
  237. Calculate();
  238. wxLogMessage("You clicked operators[%i], XRCID %i, giving a '%c'",
  239. ID, event.GetId(), symbols[ID]);
  240. curr_operator = operator_equals;
  241. // Flag that the next entry should be an operator, not a digit
  242. operator_expected = true;
  243. return;
  244. }
  245. (*result_txt) << ' ' << symbols[ID] << ' ';
  246. wxLogMessage("You clicked operators[%i], XRCID %i, giving a '%c'",
  247. ID, event.GetId(), symbols[ID]);
  248. }
  249. void ObjrefDialog::Calculate()
  250. {
  251. switch(curr_operator)
  252. {
  253. case operator_plus:
  254. previous += current; break;
  255. case operator_minus:
  256. previous -= current; break;
  257. case operator_multiply:
  258. previous *= current; break;
  259. case operator_divide:
  260. if (current!=0)
  261. previous /= current;
  262. break;
  263. default: return;
  264. }
  265. curr_operator = operator_plus;
  266. current = 0;
  267. result_txt->Clear();
  268. (*result_txt) << previous;
  269. }
  270. void ObjrefDialog::ClearCalculator()
  271. {
  272. current = previous = 0;
  273. curr_operator = operator_plus;
  274. operator_expected = false;
  275. result_txt->ChangeValue("0");
  276. }