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