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