]> git.saurik.com Git - wxWidgets.git/blob - samples/xrc/objrefdlg.cpp
Make storing non-trivial data in wxThreadSpecificInfo possible.
[wxWidgets.git] / samples / xrc / objrefdlg.cpp
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 }