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: radiobox.cpp 43755 2006-12-03 13:43:44Z VZ $
8 // Copyright:   (c) 2001 Vadim Zeitlin
9 // License:     wxWindows license
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);
~RadioWidgetsPage()87     virtual ~RadioWidgetsPage(){};
88 
GetWidget() const89     virtual wxControl *GetWidget() const { return m_radio; }
RecreateWidget()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_chkVert;
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, _T("Radio"),
186                        FAMILY_CTRLS | WITH_ITEMS_CTRLS
187                        );
188 
RadioWidgetsPage(WidgetsBookCtrl * book,wxImageList * imaglist)189 RadioWidgetsPage::RadioWidgetsPage(WidgetsBookCtrl *book,
190                                    wxImageList *imaglist)
191                   : WidgetsPage(book, imaglist, radio_xpm)
192 {
193     // init everything
194     m_chkVert = (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 
CreateContent()207 void RadioWidgetsPage::CreateContent()
208 {
209     wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
210 
211     // left pane
212     wxStaticBox *box = new wxStaticBox(this, wxID_ANY, _T("&Set style"));
213 
214     wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
215 
216     m_chkVert = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Vertical layout"));
217 
218     static const wxString layoutDir[] =
219     {
220         _T("default"),
221         _T("left to right"),
222         _T("top to bottom")
223     };
224 
225     m_radioDir = new wxRadioBox(this, wxID_ANY, _T("Numbering:"),
226                                 wxDefaultPosition, wxDefaultSize,
227                                 WXSIZEOF(layoutDir), layoutDir,
228                                 1, wxRA_SPECIFY_COLS);
229     sizerLeft->Add(m_radioDir, 0, wxGROW | wxALL, 5);
230 
231     // if it's not defined, we can't change the radiobox direction
232 #ifndef wxRA_LEFTTORIGHT
233     m_radioDir->Disable();
234 #endif // wxRA_LEFTTORIGHT
235 
236     wxSizer *sizerRow;
237     sizerRow = CreateSizerWithTextAndLabel(_T("&Major dimension:"),
238                                            wxID_ANY,
239                                            &m_textMajorDim);
240     sizerLeft->Add(sizerRow, 0, wxGROW | wxALL, 5);
241 
242     sizerRow = CreateSizerWithTextAndLabel(_T("&Number of buttons:"),
243                                            wxID_ANY,
244                                            &m_textNumBtns);
245     sizerLeft->Add(sizerRow, 0, wxGROW | wxALL, 5);
246 
247     wxButton *btn;
248     btn = new wxButton(this, RadioPage_Update, _T("&Update"));
249     sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 5);
250 
251     sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
252 
253     btn = new wxButton(this, RadioPage_Reset, _T("&Reset"));
254     sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
255 
256     // middle pane
257     wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, _T("&Change parameters"));
258     wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
259 
260     sizerRow = CreateSizerWithTextAndLabel(_T("Current selection:"),
261                                            wxID_ANY,
262                                            &m_textCurSel);
263     sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
264 
265     sizerRow = CreateSizerWithTextAndButton(RadioPage_Selection,
266                                             _T("&Change selection:"),
267                                            wxID_ANY,
268                                            &m_textSel);
269     sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
270 
271     sizerRow = CreateSizerWithTextAndButton(RadioPage_Label,
272                                             _T("&Label for box:"),
273                                             wxID_ANY,
274                                             &m_textLabel);
275     sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
276 
277     sizerRow = CreateSizerWithTextAndButton(RadioPage_LabelBtn,
278                                             _T("&Label for buttons:"),
279                                             wxID_ANY,
280                                             &m_textLabelBtns);
281     sizerMiddle->Add(sizerRow, 0, wxGROW | wxALL, 5);
282 
283     m_chkEnableItem = CreateCheckBoxAndAddToSizer(sizerMiddle,
284                                                   _T("Disable &2nd item"),
285                                                   RadioPage_EnableItem);
286     m_chkShowItem = CreateCheckBoxAndAddToSizer(sizerMiddle,
287                                                 _T("Hide 2nd &item"),
288                                                 RadioPage_ShowItem);
289 
290     // right pane
291     wxSizer *sizerRight = new wxBoxSizer(wxHORIZONTAL);
292     sizerRight->SetMinSize(150, 0);
293     m_sizerRadio = sizerRight; // save it to modify it later
294 
295     Reset();
296     CreateRadio();
297 
298     // the 3 panes panes compose the window
299     sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
300     sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
301     sizerTop->Add(sizerRight, 0, wxGROW | (wxALL & ~wxRIGHT), 10);
302 
303     // final initializations
304     SetSizer(sizerTop);
305 }
306 
307 // ----------------------------------------------------------------------------
308 // operations
309 // ----------------------------------------------------------------------------
310 
Reset()311 void RadioWidgetsPage::Reset()
312 {
313     m_textMajorDim->SetValue(wxString::Format(_T("%u"), DEFAULT_MAJOR_DIM));
314     m_textNumBtns->SetValue(wxString::Format(_T("%u"), DEFAULT_NUM_ENTRIES));
315     m_textLabel->SetValue(_T("I'm a radiobox"));
316     m_textLabelBtns->SetValue(_T("item"));
317 
318     m_chkVert->SetValue(false);
319     m_chkEnableItem->SetValue(true);
320     m_chkShowItem->SetValue(true);
321     m_radioDir->SetSelection(RadioDir_Default);
322 }
323 
CreateRadio()324 void RadioWidgetsPage::CreateRadio()
325 {
326     int sel;
327     if ( m_radio )
328     {
329         sel = m_radio->GetSelection();
330 
331         m_sizerRadio->Detach( m_radio );
332 
333         delete m_radio;
334     }
335     else // first time creation, no old selection to preserve
336     {
337         sel = -1;
338     }
339 
340     unsigned long count;
341     if ( !m_textNumBtns->GetValue().ToULong(&count) )
342     {
343         wxLogWarning(_T("Should have a valid number for number of items."));
344 
345         // fall back to default
346         count = DEFAULT_NUM_ENTRIES;
347     }
348 
349     unsigned long majorDim;
350     if ( !m_textMajorDim->GetValue().ToULong(&majorDim) )
351     {
352         wxLogWarning(_T("Should have a valid major dimension number."));
353 
354         // fall back to default
355         majorDim = DEFAULT_MAJOR_DIM;
356     }
357 
358     wxString *items = new wxString[count];
359 
360     wxString labelBtn = m_textLabelBtns->GetValue();
361     for ( size_t n = 0; n < count; n++ )
362     {
363         items[n] = wxString::Format(_T("%s %lu"),
364                                     labelBtn.c_str(), (unsigned long)n + 1);
365     }
366 
367     int flags = m_chkVert->GetValue() ? wxRA_VERTICAL
368                                       : wxRA_HORIZONTAL;
369 
370     flags |= ms_defaultFlags;
371 
372 #ifdef wxRA_LEFTTORIGHT
373     switch ( m_radioDir->GetSelection() )
374     {
375         default:
376             wxFAIL_MSG( _T("unexpected wxRadioBox layout direction") );
377             // fall through
378 
379         case RadioDir_Default:
380             break;
381 
382         case RadioDir_LtoR:
383             flags |= wxRA_LEFTTORIGHT;
384             break;
385 
386         case RadioDir_TtoB:
387             flags |= wxRA_TOPTOBOTTOM;
388             break;
389     }
390 #endif // wxRA_LEFTTORIGHT
391 
392     m_radio = new wxRadioBox(this, RadioPage_Radio,
393                              m_textLabel->GetValue(),
394                              wxDefaultPosition, wxDefaultSize,
395                              count, items,
396                              majorDim,
397                              flags);
398 
399     delete [] items;
400 
401     if ( sel >= 0 && (size_t)sel < count )
402     {
403         m_radio->SetSelection(sel);
404     }
405 
406     m_sizerRadio->Add(m_radio, 1, wxGROW);
407     m_sizerRadio->Layout();
408 
409     m_chkEnableItem->SetValue(true);
410     m_chkEnableItem->SetValue(true);
411 }
412 
413 // ----------------------------------------------------------------------------
414 // event handlers
415 // ----------------------------------------------------------------------------
416 
OnButtonReset(wxCommandEvent & WXUNUSED (event))417 void RadioWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
418 {
419     Reset();
420 
421     CreateRadio();
422 }
423 
OnCheckOrRadioBox(wxCommandEvent & WXUNUSED (event))424 void RadioWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
425 {
426     CreateRadio();
427 }
428 
OnRadioBox(wxCommandEvent & event)429 void RadioWidgetsPage::OnRadioBox(wxCommandEvent& event)
430 {
431     int sel = m_radio->GetSelection();
432     int event_sel = event.GetSelection();
433     wxUnusedVar(event_sel);
434 
435     wxLogMessage(_T("Radiobox selection changed, now %d"), sel);
436 
437     wxASSERT_MSG( sel == event_sel,
438                   _T("selection should be the same in event and radiobox") );
439 
440     m_textCurSel->SetValue(wxString::Format(_T("%d"), sel));
441 }
442 
OnButtonRecreate(wxCommandEvent & WXUNUSED (event))443 void RadioWidgetsPage::OnButtonRecreate(wxCommandEvent& WXUNUSED(event))
444 {
445     CreateRadio();
446 }
447 
OnButtonSetLabel(wxCommandEvent & WXUNUSED (event))448 void RadioWidgetsPage::OnButtonSetLabel(wxCommandEvent& WXUNUSED(event))
449 {
450     m_radio->wxControl::SetLabel(m_textLabel->GetValue());
451 }
452 
OnButtonSelection(wxCommandEvent & WXUNUSED (event))453 void RadioWidgetsPage::OnButtonSelection(wxCommandEvent& WXUNUSED(event))
454 {
455     unsigned long sel;
456     if ( !m_textSel->GetValue().ToULong(&sel) ||
457             (sel >= (size_t)m_radio->GetCount()) )
458     {
459         wxLogWarning(_T("Invalid number specified as new selection."));
460     }
461     else
462     {
463         m_radio->SetSelection(sel);
464     }
465 }
466 
OnEnableItem(wxCommandEvent & event)467 void RadioWidgetsPage::OnEnableItem(wxCommandEvent& event)
468 {
469     m_radio->Enable(TEST_BUTTON, event.IsChecked());
470 }
471 
OnShowItem(wxCommandEvent & event)472 void RadioWidgetsPage::OnShowItem(wxCommandEvent& event)
473 {
474     m_radio->Show(TEST_BUTTON, event.IsChecked());
475 }
476 
OnUpdateUIUpdate(wxUpdateUIEvent & event)477 void RadioWidgetsPage::OnUpdateUIUpdate(wxUpdateUIEvent& event)
478 {
479     unsigned long n;
480     event.Enable( m_textNumBtns->GetValue().ToULong(&n) &&
481                   m_textMajorDim->GetValue().ToULong(&n) );
482 }
483 
OnUpdateUISelection(wxUpdateUIEvent & event)484 void RadioWidgetsPage::OnUpdateUISelection(wxUpdateUIEvent& event)
485 {
486     unsigned long n;
487     event.Enable( m_textSel->GetValue().ToULong(&n) &&
488                    (n < (size_t)m_radio->GetCount()) );
489 }
490 
OnUpdateUIReset(wxUpdateUIEvent & event)491 void RadioWidgetsPage::OnUpdateUIReset(wxUpdateUIEvent& event)
492 {
493     // only enable it if something is not set to default
494     bool enable = m_chkVert->GetValue();
495 
496     if ( !enable )
497     {
498         unsigned long numEntries;
499 
500         enable = !m_textNumBtns->GetValue().ToULong(&numEntries) ||
501                     numEntries != DEFAULT_NUM_ENTRIES;
502 
503         if ( !enable )
504         {
505             unsigned long majorDim;
506 
507             enable = !m_textMajorDim->GetValue().ToULong(&majorDim) ||
508                         majorDim != DEFAULT_MAJOR_DIM;
509         }
510     }
511 
512     event.Enable(enable);
513 }
514 
OnUpdateUIEnableItem(wxUpdateUIEvent & event)515 void RadioWidgetsPage::OnUpdateUIEnableItem(wxUpdateUIEvent& event)
516 {
517     event.SetText(m_radio->IsItemEnabled(TEST_BUTTON) ? _T("Disable &2nd item")
518                                                       : _T("Enable &2nd item"));
519 }
520 
OnUpdateUIShowItem(wxUpdateUIEvent & event)521 void RadioWidgetsPage::OnUpdateUIShowItem(wxUpdateUIEvent& event)
522 {
523     event.SetText(m_radio->IsItemShown(TEST_BUTTON) ? _T("Hide 2nd &item")
524                                                     : _T("Show 2nd &item"));
525 }
526 
527 #endif // wxUSE_RADIOBOX
528