]>
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 | } | |
0526c8cc VZ |
141 | } |
142 | } | |
143 | ||
125c2fcc VZ |
144 | // There are undoubtedly simpler ways of doing all this, but we're |
145 | // demonstrating the use of ID ranges | |
0526c8cc VZ |
146 | void ObjrefDialog::OnUpdateUIFirst(wxUpdateUIEvent& event) |
147 | { | |
148 | // The checkbox with the XRCID 'check[0]' controls this row of icons | |
125c2fcc VZ |
149 | wxCheckBox * |
150 | chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[0]", wxCheckBox); | |
0526c8cc VZ |
151 | if (chk) |
152 | event.Enable(chk->IsChecked()); | |
153 | ||
154 | // Let's create a log-window entry | |
155 | static bool checked = true; | |
156 | if (chk->IsChecked() != checked) | |
157 | { | |
158 | checked = chk->IsChecked(); | |
125c2fcc VZ |
159 | wxLogMessage("Row one has been %s by check[0], XRCID = %i", |
160 | checked ? "enabled" : "disabled", XRCID("check[0]")); | |
161 | wxLogMessage("XRCIDs: first_row[start] = %i, first_row[0] = %i, " | |
162 | "first_row[1] = %i, first_row[2] = %i, " | |
163 | "first_row[end] = %i", | |
164 | XRCID("first_row[start]"), XRCID("first_row[0]"), | |
165 | XRCID("first_row[1]"), XRCID("first_row[2]"), | |
166 | XRCID("first_row[end]")); | |
0526c8cc VZ |
167 | } |
168 | } | |
169 | ||
170 | void ObjrefDialog::OnUpdateUISecond(wxUpdateUIEvent& event) | |
171 | { | |
172 | // The checkbox with the XRCID 'check[1]' controls this row of icons | |
125c2fcc VZ |
173 | wxCheckBox * |
174 | chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[1]", wxCheckBox); | |
0526c8cc VZ |
175 | if (chk) |
176 | event.Enable(chk->IsChecked()); | |
177 | ||
178 | // Let's create a log-window entry | |
179 | static bool checked = true; | |
180 | if (chk->IsChecked() != checked) | |
181 | { | |
182 | checked = chk->IsChecked(); | |
125c2fcc VZ |
183 | wxLogMessage("Row two has been %s by check[1], XRCID = %i", |
184 | checked ? "enabled" : "disabled", XRCID("check[1]")); | |
185 | wxLogMessage("XRCIDs: second_row[start] = %i, second_row[0] = %i, " | |
186 | "second_row[1] = %i, second_row[2] = %i, " | |
187 | "second_row[end] = %i", | |
188 | XRCID("second_row[start]"), XRCID("second_row[0]"), | |
189 | XRCID("second_row[1]"), XRCID("second_row[2]"), | |
190 | XRCID("second_row[end]")); | |
0526c8cc VZ |
191 | } |
192 | } | |
193 | ||
194 | void ObjrefDialog::OnUpdateUIThird(wxUpdateUIEvent& event) | |
195 | { | |
196 | // The checkbox with the XRCID 'check[2]' controls this row of icons | |
125c2fcc VZ |
197 | wxCheckBox * |
198 | chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[2]", wxCheckBox); | |
0526c8cc VZ |
199 | if (chk) |
200 | event.Enable(chk->IsChecked()); | |
201 | ||
202 | // Let's create a log-window entry | |
203 | static bool checked = true; | |
204 | if (chk->IsChecked() != checked) | |
205 | { | |
206 | checked = chk->IsChecked(); | |
125c2fcc VZ |
207 | wxLogMessage("Row three has been %s by check[2], XRCID = %i", |
208 | checked ? "enabled" : "disabled", XRCID("check[2]")); | |
209 | wxLogMessage("XRCIDs: third_row[start] = %i, third_row[0] = %i, " | |
210 | "third_row[1] = %i, third_row[2] = %i, " | |
211 | "third_row[end] = %i", | |
212 | XRCID("third_row[start]"), XRCID("third_row[0]"), | |
213 | XRCID("third_row[1]"), XRCID("third_row[2]"), | |
214 | XRCID("third_row[end]")); | |
0526c8cc VZ |
215 | } |
216 | } | |
217 | ||
218 | void ObjrefDialog::OnNumeralClick(wxCommandEvent& event) | |
219 | { | |
220 | // See how the id range simplifies determining which numeral was clicked | |
221 | int digit = event.GetId() - XRCID("digits[start]"); | |
222 | ||
223 | char c = '0' + digit; | |
224 | if (current==0 && previous==0) | |
225 | { | |
226 | // We're just starting a calculation, so get rid of the placeholder '0' | |
227 | result_txt->Clear(); | |
228 | } | |
229 | else if (operator_expected == true) | |
230 | { | |
125c2fcc VZ |
231 | // If we've just finished one calculation, and now a digit is entered, |
232 | // clear | |
0526c8cc VZ |
233 | ClearCalculator(); |
234 | result_txt->Clear(); | |
235 | } | |
236 | (*result_txt) << c; | |
237 | ||
238 | ||
239 | current = current*10 + digit; | |
240 | ||
241 | wxLogMessage("You clicked digits[%c], XRCID %i", c, event.GetId()); | |
242 | } | |
243 | ||
244 | void ObjrefDialog::OnOperatorClick(wxCommandEvent& event) | |
245 | { | |
246 | static const char symbols[] = "+-*/="; | |
247 | ||
248 | operator_expected = false; | |
249 | int ID = event.GetId() - XRCID("operators[start]"); | |
250 | ||
251 | // We carefully used "operators[end]" as the name of the Clear button | |
252 | if (event.GetId() == XRCID("operators[end]")) | |
253 | { | |
125c2fcc VZ |
254 | wxLogMessage("You clicked operators[%i], XRCID %d, 'Clear'", |
255 | ID, event.GetId()); | |
6ab66823 VZ |
256 | ClearCalculator(); |
257 | return; | |
0526c8cc VZ |
258 | } |
259 | ||
260 | switch(ID) | |
261 | { | |
262 | case operator_plus: | |
263 | case operator_minus: | |
264 | case operator_multiply: | |
265 | case operator_divide: | |
266 | if (current!=0 || previous!=0) | |
267 | { | |
125c2fcc VZ |
268 | // We're in the middle of a complex calculation, so do the |
269 | // first bit | |
0526c8cc VZ |
270 | Calculate(); |
271 | } | |
272 | curr_operator = (CalcOperator)ID; | |
273 | break; | |
274 | ||
275 | case operator_equals: | |
276 | Calculate(); | |
125c2fcc VZ |
277 | wxLogMessage("You clicked operators[%i], XRCID %i, giving a '%c'", |
278 | ID, event.GetId(), symbols[ID]); | |
0526c8cc VZ |
279 | curr_operator = operator_equals; |
280 | // Flag that the next entry should be an operator, not a digit | |
281 | operator_expected = true; | |
282 | return; | |
283 | } | |
284 | ||
285 | (*result_txt) << ' ' << symbols[ID] << ' '; | |
286 | ||
125c2fcc VZ |
287 | wxLogMessage("You clicked operators[%i], XRCID %i, giving a '%c'", |
288 | ID, event.GetId(), symbols[ID]); | |
0526c8cc VZ |
289 | } |
290 | ||
291 | void ObjrefDialog::Calculate() | |
292 | { | |
293 | switch(curr_operator) | |
294 | { | |
295 | case operator_plus: | |
296 | previous += current; break; | |
297 | case operator_minus: | |
298 | previous -= current; break; | |
299 | case operator_multiply: | |
300 | previous *= current; break; | |
301 | case operator_divide: | |
302 | if (current!=0) | |
303 | previous /= current; | |
304 | break; | |
305 | default: return; | |
306 | } | |
307 | ||
308 | curr_operator = operator_plus; | |
309 | current = 0; | |
310 | result_txt->Clear(); | |
311 | ||
312 | (*result_txt) << previous; | |
313 | } | |
314 | ||
315 | void ObjrefDialog::ClearCalculator() | |
316 | { | |
317 | current = previous = 0; | |
318 | curr_operator = operator_plus; | |
319 | operator_expected = false; | |
320 | result_txt->ChangeValue("0"); | |
321 | } |