Always link with expat in monolithic build.
[wxWidgets.git] / samples / widgets / radiobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: radiobox.cpp
4 // Purpose: Part of the widgets sample showing wxRadioBox
5 // Author: Vadim Zeitlin
6 // Created: 15.04.01
7 // Id: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // for compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_RADIOBOX
28
29 // for all others, include the necessary headers
30 #ifndef WX_PRECOMP
31 #include "wx/log.h"
32
33 #include "wx/bitmap.h"
34 #include "wx/button.h"
35 #include "wx/checkbox.h"
36 #include "wx/radiobox.h"
37 #include "wx/statbox.h"
38 #include "wx/textctrl.h"
39 #endif
40
41 #include "wx/sizer.h"
42
43 #include "widgets.h"
44
45 #include "icons/radiobox.xpm"
46
47 // ----------------------------------------------------------------------------
48 // constants
49 // ----------------------------------------------------------------------------
50
51 // control ids
52 enum
53 {
54 RadioPage_Reset = wxID_HIGHEST,
55 RadioPage_Update,
56 RadioPage_Selection,
57 RadioPage_Label,
58 RadioPage_LabelBtn,
59 RadioPage_EnableItem,
60 RadioPage_ShowItem,
61 RadioPage_Radio
62 };
63
64 // layout direction radiobox selections
65 enum
66 {
67 RadioDir_Default,
68 RadioDir_LtoR,
69 RadioDir_TtoB
70 };
71
72 // default values for the number of radiobox items
73 static const unsigned int DEFAULT_NUM_ENTRIES = 12;
74 static const unsigned int DEFAULT_MAJOR_DIM = 3;
75
76 // this item is enabled/disabled shown/hidden by the test checkboxes
77 static const int TEST_BUTTON = 1;
78
79 // ----------------------------------------------------------------------------
80 // RadioWidgetsPage
81 // ----------------------------------------------------------------------------
82
83 class RadioWidgetsPage : public WidgetsPage
84 {
85 public:
86 RadioWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
87 virtual ~RadioWidgetsPage(){};
88
89 virtual wxControl *GetWidget() const { return m_radio; }
90 virtual void RecreateWidget() { CreateRadio(); }
91
92 // lazy creation of the content
93 virtual void CreateContent();
94
95 protected:
96 // event handlers
97 void OnCheckOrRadioBox(wxCommandEvent& event);
98 void OnRadioBox(wxCommandEvent& event);
99
100 void OnButtonReset(wxCommandEvent& event);
101 void OnButtonRecreate(wxCommandEvent& event);
102
103 void OnButtonSelection(wxCommandEvent& event);
104 void OnButtonSetLabel(wxCommandEvent& event);
105
106 void OnEnableItem(wxCommandEvent& event);
107 void OnShowItem(wxCommandEvent& event);
108
109 void OnUpdateUIReset(wxUpdateUIEvent& event);
110 void OnUpdateUIUpdate(wxUpdateUIEvent& event);
111 void OnUpdateUISelection(wxUpdateUIEvent& event);
112 void OnUpdateUIEnableItem(wxUpdateUIEvent& event);
113 void OnUpdateUIShowItem(wxUpdateUIEvent& event);
114
115 // reset the wxRadioBox parameters
116 void Reset();
117
118 // (re)create the wxRadioBox
119 void CreateRadio();
120
121 // the controls
122 // ------------
123
124 // the check/radio boxes for styles
125 wxCheckBox *m_chkSpecifyRows;
126 wxCheckBox *m_chkEnableItem;
127 wxCheckBox *m_chkShowItem;
128 wxRadioBox *m_radioDir;
129
130 // the gauge itself and the sizer it is in
131 wxRadioBox *m_radio;
132 wxSizer *m_sizerRadio;
133
134 // the text entries for command parameters
135 wxTextCtrl *m_textNumBtns,
136 *m_textMajorDim,
137 *m_textCurSel,
138 *m_textSel,
139 *m_textLabel,
140 *m_textLabelBtns;
141
142 private:
143 DECLARE_EVENT_TABLE()
144 DECLARE_WIDGETS_PAGE(RadioWidgetsPage)
145 };
146
147 // ----------------------------------------------------------------------------
148 // event tables
149 // ----------------------------------------------------------------------------
150
151 BEGIN_EVENT_TABLE(RadioWidgetsPage, WidgetsPage)
152 EVT_BUTTON(RadioPage_Reset, RadioWidgetsPage::OnButtonReset)
153
154 EVT_BUTTON(RadioPage_Update, RadioWidgetsPage::OnButtonRecreate)
155 EVT_BUTTON(RadioPage_LabelBtn, RadioWidgetsPage::OnButtonRecreate)
156
157 EVT_BUTTON(RadioPage_Selection, RadioWidgetsPage::OnButtonSelection)
158 EVT_BUTTON(RadioPage_Label, RadioWidgetsPage::OnButtonSetLabel)
159
160 EVT_UPDATE_UI(RadioPage_Update, RadioWidgetsPage::OnUpdateUIUpdate)
161 EVT_UPDATE_UI(RadioPage_Selection, RadioWidgetsPage::OnUpdateUISelection)
162
163 EVT_RADIOBOX(RadioPage_Radio, RadioWidgetsPage::OnRadioBox)
164
165 EVT_CHECKBOX(RadioPage_EnableItem, RadioWidgetsPage::OnEnableItem)
166 EVT_CHECKBOX(RadioPage_ShowItem, RadioWidgetsPage::OnShowItem)
167
168 EVT_UPDATE_UI(RadioPage_EnableItem, RadioWidgetsPage::OnUpdateUIEnableItem)
169 EVT_UPDATE_UI(RadioPage_ShowItem, RadioWidgetsPage::OnUpdateUIShowItem)
170
171 EVT_CHECKBOX(wxID_ANY, RadioWidgetsPage::OnCheckOrRadioBox)
172 EVT_RADIOBOX(wxID_ANY, RadioWidgetsPage::OnCheckOrRadioBox)
173 END_EVENT_TABLE()
174
175 // ============================================================================
176 // implementation
177 // ============================================================================
178
179 #if defined(__WXUNIVERSAL__)
180 #define FAMILY_CTRLS UNIVERSAL_CTRLS
181 #else
182 #define FAMILY_CTRLS NATIVE_CTRLS
183 #endif
184
185 IMPLEMENT_WIDGETS_PAGE(RadioWidgetsPage, wxT("Radio"),
186 FAMILY_CTRLS | WITH_ITEMS_CTRLS
187 );
188
189 RadioWidgetsPage::RadioWidgetsPage(WidgetsBookCtrl *book,
190 wxImageList *imaglist)
191 : WidgetsPage(book, imaglist, radio_xpm)
192 {
193 // init everything
194 m_chkSpecifyRows = (wxCheckBox *)NULL;
195 m_chkEnableItem = (wxCheckBox *)NULL;
196 m_chkShowItem = (wxCheckBox *)NULL;
197
198 m_textNumBtns =
199 m_textLabelBtns =
200 m_textLabel = (wxTextCtrl *)NULL;
201
202 m_radio =
203 m_radioDir = (wxRadioBox *)NULL;
204 m_sizerRadio = (wxSizer *)NULL;
205 }
206
207 void RadioWidgetsPage::CreateContent()
208 {
209 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
210
211 // left pane
212 wxStaticBox *box = new wxStaticBox(this, wxID_ANY, wxT("&Set style"));
213
214 wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
215
216 m_chkSpecifyRows = CreateCheckBoxAndAddToSizer
217 (
218 sizerLeft,
219 "Major specifies &rows count"
220 );
221
222 static const wxString layoutDir[] =
223 {
224 wxT("default"),
225 wxT("left to right"),
226 wxT("top to bottom")
227 };
228
229 m_radioDir = new wxRadioBox(this, wxID_ANY, wxT("Numbering:"),
230 wxDefaultPosition, wxDefaultSize,
231 WXSIZEOF(layoutDir), layoutDir,
232 1, wxRA_SPECIFY_COLS);
233 sizerLeft->Add(m_radioDir, 0, wxGROW | wxALL, 5);
234
235 // if it's not defined, we can't change the radiobox direction
236 #ifndef wxRA_LEFTTORIGHT
237 m_radioDir->Disable();
238 #endif // wxRA_LEFTTORIGHT
239
240 wxSizer *sizerRow;
241 sizerRow = CreateSizerWithTextAndLabel(wxT("&Major dimension:"),
242 wxID_ANY,
243 &m_textMajorDim);
244 sizerLeft->Add(sizerRow, 0, wxGROW | wxALL, 5);
245
246 sizerRow = CreateSizerWithTextAndLabel(wxT("&Number of buttons:"),
247 wxID_ANY,
248 &m_textNumBtns);
249 sizerLeft->Add(sizerRow, 0, wxGROW | wxALL, 5);
250
251 wxButton *btn;
252 btn = new wxButton(this, RadioPage_Update, wxT("&Update"));
253 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 5);
254
255 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
256
257 btn = new wxButton(this, RadioPage_Reset, wxT("&Reset"));
258 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
259
260 // middle pane
261 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, wxT("&Change parameters"));
262 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
263
264 sizerRow = CreateSizerWithTextAndLabel(wxT("Current selection:"),
265 wxID_ANY,
266 &m_textCurSel);
267 sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
268
269 sizerRow = CreateSizerWithTextAndButton(RadioPage_Selection,
270 wxT("&Change selection:"),
271 wxID_ANY,
272 &m_textSel);
273 sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
274
275 sizerRow = CreateSizerWithTextAndButton(RadioPage_Label,
276 wxT("&Label for box:"),
277 wxID_ANY,
278 &m_textLabel);
279 sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
280
281 sizerRow = CreateSizerWithTextAndButton(RadioPage_LabelBtn,
282 wxT("&Label for buttons:"),
283 wxID_ANY,
284 &m_textLabelBtns);
285 sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
286
287 m_chkEnableItem = CreateCheckBoxAndAddToSizer(sizerMiddle,
288 wxT("Disable &2nd item"),
289 RadioPage_EnableItem);
290 m_chkShowItem = CreateCheckBoxAndAddToSizer(sizerMiddle,
291 wxT("Hide 2nd &item"),
292 RadioPage_ShowItem);
293
294 // right pane
295 wxSizer *sizerRight = new wxBoxSizer(wxHORIZONTAL);
296 sizerRight->SetMinSize(150, 0);
297 m_sizerRadio = sizerRight; // save it to modify it later
298
299 Reset();
300 CreateRadio();
301
302 // the 3 panes panes compose the window
303 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
304 sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
305 sizerTop->Add(sizerRight, 0, wxGROW | (wxALL & ~wxRIGHT), 10);
306
307 // final initializations
308 SetSizer(sizerTop);
309 }
310
311 // ----------------------------------------------------------------------------
312 // operations
313 // ----------------------------------------------------------------------------
314
315 void RadioWidgetsPage::Reset()
316 {
317 m_textMajorDim->SetValue(wxString::Format(wxT("%u"), DEFAULT_MAJOR_DIM));
318 m_textNumBtns->SetValue(wxString::Format(wxT("%u"), DEFAULT_NUM_ENTRIES));
319 m_textLabel->SetValue(wxT("I'm a radiobox"));
320 m_textLabelBtns->SetValue(wxT("item"));
321
322 m_chkSpecifyRows->SetValue(false);
323 m_chkEnableItem->SetValue(true);
324 m_chkShowItem->SetValue(true);
325 m_radioDir->SetSelection(RadioDir_Default);
326 }
327
328 void RadioWidgetsPage::CreateRadio()
329 {
330 int sel;
331 if ( m_radio )
332 {
333 sel = m_radio->GetSelection();
334
335 m_sizerRadio->Detach( m_radio );
336
337 delete m_radio;
338 }
339 else // first time creation, no old selection to preserve
340 {
341 sel = -1;
342 }
343
344 unsigned long count;
345 if ( !m_textNumBtns->GetValue().ToULong(&count) )
346 {
347 wxLogWarning(wxT("Should have a valid number for number of items."));
348
349 // fall back to default
350 count = DEFAULT_NUM_ENTRIES;
351 }
352
353 unsigned long majorDim;
354 if ( !m_textMajorDim->GetValue().ToULong(&majorDim) )
355 {
356 wxLogWarning(wxT("Should have a valid major dimension number."));
357
358 // fall back to default
359 majorDim = DEFAULT_MAJOR_DIM;
360 }
361
362 wxString *items = new wxString[count];
363
364 wxString labelBtn = m_textLabelBtns->GetValue();
365 for ( size_t n = 0; n < count; n++ )
366 {
367 items[n] = wxString::Format(wxT("%s %lu"),
368 labelBtn.c_str(), (unsigned long)n + 1);
369 }
370
371 int flags = m_chkSpecifyRows->GetValue() ? wxRA_SPECIFY_ROWS
372 : wxRA_SPECIFY_COLS;
373
374 flags |= ms_defaultFlags;
375
376 #ifdef wxRA_LEFTTORIGHT
377 switch ( m_radioDir->GetSelection() )
378 {
379 default:
380 wxFAIL_MSG( wxT("unexpected wxRadioBox layout direction") );
381 // fall through
382
383 case RadioDir_Default:
384 break;
385
386 case RadioDir_LtoR:
387 flags |= wxRA_LEFTTORIGHT;
388 break;
389
390 case RadioDir_TtoB:
391 flags |= wxRA_TOPTOBOTTOM;
392 break;
393 }
394 #endif // wxRA_LEFTTORIGHT
395
396 m_radio = new wxRadioBox(this, RadioPage_Radio,
397 m_textLabel->GetValue(),
398 wxDefaultPosition, wxDefaultSize,
399 count, items,
400 majorDim,
401 flags);
402
403 delete [] items;
404
405 if ( sel >= 0 && (size_t)sel < count )
406 {
407 m_radio->SetSelection(sel);
408 }
409
410 m_sizerRadio->Add(m_radio, 1, wxGROW);
411 m_sizerRadio->Layout();
412
413 m_chkEnableItem->SetValue(true);
414 m_chkEnableItem->SetValue(true);
415 }
416
417 // ----------------------------------------------------------------------------
418 // event handlers
419 // ----------------------------------------------------------------------------
420
421 void RadioWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
422 {
423 Reset();
424
425 CreateRadio();
426 }
427
428 void RadioWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
429 {
430 CreateRadio();
431 }
432
433 void RadioWidgetsPage::OnRadioBox(wxCommandEvent& event)
434 {
435 int sel = m_radio->GetSelection();
436 int event_sel = event.GetSelection();
437 wxUnusedVar(event_sel);
438
439 wxLogMessage(wxT("Radiobox selection changed, now %d"), sel);
440
441 wxASSERT_MSG( sel == event_sel,
442 wxT("selection should be the same in event and radiobox") );
443
444 m_textCurSel->SetValue(wxString::Format(wxT("%d"), sel));
445 }
446
447 void RadioWidgetsPage::OnButtonRecreate(wxCommandEvent& WXUNUSED(event))
448 {
449 CreateRadio();
450 }
451
452 void RadioWidgetsPage::OnButtonSetLabel(wxCommandEvent& WXUNUSED(event))
453 {
454 m_radio->wxControl::SetLabel(m_textLabel->GetValue());
455 }
456
457 void RadioWidgetsPage::OnButtonSelection(wxCommandEvent& WXUNUSED(event))
458 {
459 unsigned long sel;
460 if ( !m_textSel->GetValue().ToULong(&sel) ||
461 (sel >= (size_t)m_radio->GetCount()) )
462 {
463 wxLogWarning(wxT("Invalid number specified as new selection."));
464 }
465 else
466 {
467 m_radio->SetSelection(sel);
468 }
469 }
470
471 void RadioWidgetsPage::OnEnableItem(wxCommandEvent& event)
472 {
473 m_radio->Enable(TEST_BUTTON, event.IsChecked());
474 }
475
476 void RadioWidgetsPage::OnShowItem(wxCommandEvent& event)
477 {
478 m_radio->Show(TEST_BUTTON, event.IsChecked());
479 }
480
481 void RadioWidgetsPage::OnUpdateUIUpdate(wxUpdateUIEvent& event)
482 {
483 unsigned long n;
484 event.Enable( m_textNumBtns->GetValue().ToULong(&n) &&
485 m_textMajorDim->GetValue().ToULong(&n) );
486 }
487
488 void RadioWidgetsPage::OnUpdateUISelection(wxUpdateUIEvent& event)
489 {
490 unsigned long n;
491 event.Enable( m_textSel->GetValue().ToULong(&n) &&
492 (n < (size_t)m_radio->GetCount()) );
493 }
494
495 void RadioWidgetsPage::OnUpdateUIReset(wxUpdateUIEvent& event)
496 {
497 // only enable it if something is not set to default
498 bool enable = m_chkSpecifyRows->GetValue();
499
500 if ( !enable )
501 {
502 unsigned long numEntries;
503
504 enable = !m_textNumBtns->GetValue().ToULong(&numEntries) ||
505 numEntries != DEFAULT_NUM_ENTRIES;
506
507 if ( !enable )
508 {
509 unsigned long majorDim;
510
511 enable = !m_textMajorDim->GetValue().ToULong(&majorDim) ||
512 majorDim != DEFAULT_MAJOR_DIM;
513 }
514 }
515
516 event.Enable(enable);
517 }
518
519 void RadioWidgetsPage::OnUpdateUIEnableItem(wxUpdateUIEvent& event)
520 {
521 event.SetText(m_radio->IsItemEnabled(TEST_BUTTON) ? wxT("Disable &2nd item")
522 : wxT("Enable &2nd item"));
523 }
524
525 void RadioWidgetsPage::OnUpdateUIShowItem(wxUpdateUIEvent& event)
526 {
527 event.SetText(m_radio->IsItemShown(TEST_BUTTON) ? wxT("Hide 2nd &item")
528 : wxT("Show 2nd &item"));
529 }
530
531 #endif // wxUSE_RADIOBOX