Always link with expat in monolithic build.
[wxWidgets.git] / samples / widgets / toggle.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: toggle.cpp
4 // Purpose: Part of the widgets sample showing toggle control
5 // Author: Dimitri Schoolwerth, Vadim Zeitlin
6 // Created: 27 Sep 2003
7 // Id: $Id$
8 // Copyright: (c) 2006 Wlodzmierz Skiba
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_TOGGLEBTN
28
29 #include "wx/tglbtn.h"
30
31 #include "widgets.h"
32
33 // for all others, include the necessary headers
34 #ifndef WX_PRECOMP
35 #include "wx/button.h"
36 #include "wx/checkbox.h"
37 #include "wx/radiobox.h"
38 #include "wx/statbox.h"
39 #include "wx/textctrl.h"
40 #endif
41
42 #include "wx/artprov.h"
43 #include "wx/sizer.h"
44 #include "wx/dcmemory.h"
45
46 #include "icons/toggle.xpm"
47
48 // ----------------------------------------------------------------------------
49 // constants
50 // ----------------------------------------------------------------------------
51
52 // control ids
53 enum
54 {
55 TogglePage_Reset = wxID_HIGHEST,
56 TogglePage_ChangeLabel,
57 TogglePage_Picker
58 };
59
60 // radio boxes
61 enum
62 {
63 ToggleImagePos_Left,
64 ToggleImagePos_Right,
65 ToggleImagePos_Top,
66 ToggleImagePos_Bottom
67 };
68
69 enum
70 {
71 ToggleHAlign_Left,
72 ToggleHAlign_Centre,
73 ToggleHAlign_Right
74 };
75
76 enum
77 {
78 ToggleVAlign_Top,
79 ToggleVAlign_Centre,
80 ToggleVAlign_Bottom
81 };
82
83 // ----------------------------------------------------------------------------
84 // CheckBoxWidgetsPage
85 // ----------------------------------------------------------------------------
86
87 class ToggleWidgetsPage : public WidgetsPage
88 {
89 public:
90 ToggleWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
91 virtual ~ToggleWidgetsPage(){};
92
93 virtual wxControl *GetWidget() const { return m_toggle; }
94 virtual void RecreateWidget() { CreateToggle(); }
95
96 // lazy creation of the content
97 virtual void CreateContent();
98
99 protected:
100 // event handlers
101 void OnCheckOrRadioBox(wxCommandEvent& event);
102
103 // event handlers
104 void OnButtonReset(wxCommandEvent& event);
105 void OnButtonChangeLabel(wxCommandEvent& event);
106
107 // reset the toggle parameters
108 void Reset();
109
110 // (re)create the toggle
111 void CreateToggle();
112
113 // helper function: create a bitmap for wxBitmapToggleButton
114 wxBitmap CreateBitmap(const wxString& label);
115
116 // the controls
117 // ------------
118
119 #if wxUSE_MARKUP
120 wxCheckBox *m_chkUseMarkup;
121 #endif // wxUSE_MARKUP
122 #ifdef wxHAS_BITMAPTOGGLEBUTTON
123 // the check/radio boxes for styles
124 wxCheckBox *m_chkBitmapOnly,
125 *m_chkTextAndBitmap,
126 *m_chkFit,
127 *m_chkUseBitmapClass;
128
129 // more checkboxes for wxBitmapToggleButton only
130 wxCheckBox *m_chkUsePressed,
131 *m_chkUseFocused,
132 *m_chkUseCurrent,
133 *m_chkUseDisabled;
134
135 // and an image position choice used if m_chkTextAndBitmap is on
136 wxRadioBox *m_radioImagePos;
137
138 wxRadioBox *m_radioHAlign,
139 *m_radioVAlign;
140 #endif // wxHAS_BITMAPTOGGLEBUTTON
141
142 // the checkbox itself and the sizer it is in
143 #ifdef wxHAS_ANY_BUTTON
144 wxToggleButton *m_toggle;
145 #else
146 wxToggleButtonBase *m_toggle;
147 #endif // wxHAS_ANY_BUTTON
148 wxSizer *m_sizerToggle;
149
150 // the text entries for command parameters
151 wxTextCtrl *m_textLabel;
152
153 private:
154 DECLARE_EVENT_TABLE()
155 DECLARE_WIDGETS_PAGE(ToggleWidgetsPage)
156 };
157
158 // ----------------------------------------------------------------------------
159 // event tables
160 // ----------------------------------------------------------------------------
161
162 BEGIN_EVENT_TABLE(ToggleWidgetsPage, WidgetsPage)
163 EVT_BUTTON(TogglePage_Reset, ToggleWidgetsPage::OnButtonReset)
164 EVT_BUTTON(TogglePage_ChangeLabel, ToggleWidgetsPage::OnButtonChangeLabel)
165
166 EVT_CHECKBOX(wxID_ANY, ToggleWidgetsPage::OnCheckOrRadioBox)
167 EVT_RADIOBOX(wxID_ANY, ToggleWidgetsPage::OnCheckOrRadioBox)
168 END_EVENT_TABLE()
169
170 // ============================================================================
171 // implementation
172 // ============================================================================
173
174 #if defined(__WXUNIVERSAL__)
175 #define FAMILY_CTRLS UNIVERSAL_CTRLS
176 #else
177 #define FAMILY_CTRLS NATIVE_CTRLS
178 #endif
179
180 IMPLEMENT_WIDGETS_PAGE(ToggleWidgetsPage, wxT("ToggleButton"),
181 FAMILY_CTRLS
182 );
183
184 ToggleWidgetsPage::ToggleWidgetsPage(WidgetsBookCtrl *book,
185 wxImageList *imaglist)
186 :WidgetsPage(book, imaglist, toggle_xpm)
187 {
188 #if wxUSE_MARKUP
189 m_chkUseMarkup = (wxCheckBox *)NULL;
190 #endif // wxUSE_MARKUP
191 #ifdef wxHAS_BITMAPTOGGLEBUTTON
192 // init everything
193 m_chkBitmapOnly =
194 m_chkTextAndBitmap =
195 m_chkFit =
196 m_chkUseBitmapClass =
197 m_chkUsePressed =
198 m_chkUseFocused =
199 m_chkUseCurrent =
200 m_chkUseDisabled = (wxCheckBox *)NULL;
201
202 m_radioImagePos =
203 m_radioHAlign =
204 m_radioVAlign = (wxRadioBox *)NULL;
205 #endif // wxHAS_BITMAPTOGGLEBUTTON
206
207 m_textLabel = (wxTextCtrl *)NULL;
208
209 m_toggle = (wxToggleButton *)NULL;
210 m_sizerToggle = (wxSizer *)NULL;
211 }
212
213 void ToggleWidgetsPage::CreateContent()
214 {
215 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
216
217 // left pane
218 wxStaticBox *box = new wxStaticBox(this, wxID_ANY, wxT("Styles"));
219
220 wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
221
222 #ifdef wxHAS_BITMAPTOGGLEBUTTON
223 m_chkBitmapOnly = CreateCheckBoxAndAddToSizer(sizerLeft, "&Bitmap only");
224 m_chkTextAndBitmap = CreateCheckBoxAndAddToSizer(sizerLeft, "Text &and bitmap");
225 m_chkFit = CreateCheckBoxAndAddToSizer(sizerLeft, wxT("&Fit exactly"));
226 #endif // wxHAS_BITMAPTOGGLEBUTTON
227 #if wxUSE_MARKUP
228 m_chkUseMarkup = CreateCheckBoxAndAddToSizer(sizerLeft, "Interpret &markup");
229 #endif // wxUSE_MARKUP
230
231 #ifdef wxHAS_BITMAPTOGGLEBUTTON
232 m_chkUseBitmapClass = CreateCheckBoxAndAddToSizer(sizerLeft,
233 "Use wxBitmapToggleButton");
234 m_chkUseBitmapClass->SetValue(true);
235
236 sizerLeft->AddSpacer(5);
237
238 wxSizer *sizerUseLabels =
239 new wxStaticBoxSizer(wxVERTICAL, this,
240 "&Use the following bitmaps in addition to the normal one?");
241 m_chkUsePressed = CreateCheckBoxAndAddToSizer(sizerUseLabels,
242 "&Pressed (small help icon)");
243 m_chkUseFocused = CreateCheckBoxAndAddToSizer(sizerUseLabels,
244 "&Focused (small error icon)");
245 m_chkUseCurrent = CreateCheckBoxAndAddToSizer(sizerUseLabels,
246 "&Current (small warning icon)");
247 m_chkUseDisabled = CreateCheckBoxAndAddToSizer(sizerUseLabels,
248 "&Disabled (broken image icon)");
249 sizerLeft->Add(sizerUseLabels, wxSizerFlags().Expand().Border());
250
251 sizerLeft->AddSpacer(10);
252
253 static const wxString dirs[] =
254 {
255 "left", "right", "top", "bottom",
256 };
257 m_radioImagePos = new wxRadioBox(this, wxID_ANY, "Image &position",
258 wxDefaultPosition, wxDefaultSize,
259 WXSIZEOF(dirs), dirs);
260 sizerLeft->Add(m_radioImagePos, 0, wxGROW | wxALL, 5);
261 sizerLeft->AddSpacer(15);
262
263 // should be in sync with enums Toggle[HV]Align!
264 static const wxString halign[] =
265 {
266 wxT("left"),
267 wxT("centre"),
268 wxT("right"),
269 };
270
271 static const wxString valign[] =
272 {
273 wxT("top"),
274 wxT("centre"),
275 wxT("bottom"),
276 };
277
278 m_radioHAlign = new wxRadioBox(this, wxID_ANY, wxT("&Horz alignment"),
279 wxDefaultPosition, wxDefaultSize,
280 WXSIZEOF(halign), halign);
281 m_radioVAlign = new wxRadioBox(this, wxID_ANY, wxT("&Vert alignment"),
282 wxDefaultPosition, wxDefaultSize,
283 WXSIZEOF(valign), valign);
284
285 sizerLeft->Add(m_radioHAlign, 0, wxGROW | wxALL, 5);
286 sizerLeft->Add(m_radioVAlign, 0, wxGROW | wxALL, 5);
287 #endif // wxHAS_BITMAPTOGGLEBUTTON
288
289 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
290
291 wxButton *btn = new wxButton(this, TogglePage_Reset, wxT("&Reset"));
292 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
293
294 // middle pane
295 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, wxT("&Operations"));
296 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
297
298 wxSizer *sizerRow = CreateSizerWithTextAndButton(TogglePage_ChangeLabel,
299 wxT("Change label"),
300 wxID_ANY,
301 &m_textLabel);
302 m_textLabel->SetValue(wxT("&Toggle me!"));
303
304 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
305
306 // right pane
307 m_sizerToggle = new wxBoxSizer(wxHORIZONTAL);
308 m_sizerToggle->SetMinSize(150, 0);
309
310 // the 3 panes panes compose the window
311 sizerTop->Add(sizerLeft, 0, (wxALL & ~wxLEFT), 10);
312 sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
313 sizerTop->Add(m_sizerToggle, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
314
315 // do create the main control
316 Reset();
317 CreateToggle();
318
319 SetSizer(sizerTop);
320 }
321
322 void ToggleWidgetsPage::Reset()
323 {
324 #ifdef wxHAS_BITMAPTOGGLEBUTTON
325 m_chkBitmapOnly->SetValue(false);
326 m_chkFit->SetValue(true);
327 m_chkTextAndBitmap->SetValue(false);
328 #if wxUSE_MARKUP
329 m_chkUseMarkup->SetValue(false);
330 #endif // wxUSE_MARKUP
331 m_chkUseBitmapClass->SetValue(true);
332
333 m_chkUsePressed->SetValue(true);
334 m_chkUseFocused->SetValue(true);
335 m_chkUseCurrent->SetValue(true);
336 m_chkUseDisabled->SetValue(true);
337
338 m_radioImagePos->SetSelection(ToggleImagePos_Left);
339 m_radioHAlign->SetSelection(ToggleHAlign_Centre);
340 m_radioVAlign->SetSelection(ToggleVAlign_Centre);
341 #endif // wxHAS_BITMAPTOGGLEBUTTON
342
343 if ( m_toggle )
344 {
345 m_toggle->SetValue(false);
346 }
347 }
348
349 void ToggleWidgetsPage::CreateToggle()
350 {
351 wxString label;
352 bool value = false;
353
354 if ( m_toggle )
355 {
356 label = m_toggle->GetLabel();
357 value = m_toggle->GetValue();
358 size_t count = m_sizerToggle->GetChildren().GetCount();
359 for ( size_t n = 0; n < count; n++ )
360 {
361 m_sizerToggle->Remove(0);
362 }
363
364 delete m_toggle;
365 }
366
367 if ( label.empty() )
368 {
369 // creating for the first time or recreating a toggle button after bitmap
370 // button
371 label = m_textLabel->GetValue();
372 }
373
374 int flags = ms_defaultFlags;
375 #ifdef wxHAS_BITMAPTOGGLEBUTTON
376 switch ( m_radioHAlign->GetSelection() )
377 {
378 case ToggleHAlign_Left:
379 flags |= wxBU_LEFT;
380 break;
381
382 default:
383 wxFAIL_MSG(wxT("unexpected radiobox selection"));
384 // fall through
385
386 case ToggleHAlign_Centre:
387 break;
388
389 case ToggleHAlign_Right:
390 flags |= wxBU_RIGHT;
391 break;
392 }
393
394 switch ( m_radioVAlign->GetSelection() )
395 {
396 case ToggleVAlign_Top:
397 flags |= wxBU_TOP;
398 break;
399
400 default:
401 wxFAIL_MSG(wxT("unexpected radiobox selection"));
402 // fall through
403
404 case ToggleVAlign_Centre:
405 // centre vertical alignment is the default (no style)
406 break;
407
408 case ToggleVAlign_Bottom:
409 flags |= wxBU_BOTTOM;
410 break;
411 }
412 #endif // wxHAS_BITMAPTOGGLEBUTTON
413
414 #ifdef wxHAS_BITMAPTOGGLEBUTTON
415 bool showsBitmap = false;
416 if ( m_chkBitmapOnly->GetValue() )
417 {
418 showsBitmap = true;
419
420 wxToggleButton *btgl;
421 if ( m_chkUseBitmapClass->GetValue() )
422 {
423 btgl = new wxBitmapToggleButton(this, TogglePage_Picker,
424 CreateBitmap(wxT("normal")));
425 }
426 else
427 {
428 btgl = new wxToggleButton(this, TogglePage_Picker, wxT(""));
429 btgl->SetBitmapLabel(CreateBitmap(wxT("normal")));
430 }
431 #ifdef wxHAS_ANY_BUTTON
432 if ( m_chkUsePressed->GetValue() )
433 btgl->SetBitmapPressed(CreateBitmap(wxT("pushed")));
434 if ( m_chkUseFocused->GetValue() )
435 btgl->SetBitmapFocus(CreateBitmap(wxT("focused")));
436 if ( m_chkUseCurrent->GetValue() )
437 btgl->SetBitmapCurrent(CreateBitmap(wxT("hover")));
438 if ( m_chkUseDisabled->GetValue() )
439 btgl->SetBitmapDisabled(CreateBitmap(wxT("disabled")));
440 #endif // wxHAS_ANY_BUTTON
441 m_toggle = btgl;
442 }
443 else // normal button
444 #endif // wxHAS_BITMAPTOGGLEBUTTON
445 {
446 m_toggle = new wxToggleButton(this, TogglePage_Picker, label,
447 wxDefaultPosition, wxDefaultSize,
448 flags);
449 }
450 m_toggle->SetValue(value);
451
452 #ifdef wxHAS_BITMAPTOGGLEBUTTON
453 #ifdef wxHAS_ANY_BUTTON
454 if ( !showsBitmap && m_chkTextAndBitmap->GetValue() )
455 {
456 showsBitmap = true;
457
458 static const wxDirection positions[] =
459 {
460 wxLEFT, wxRIGHT, wxTOP, wxBOTTOM
461 };
462
463 m_toggle->SetBitmap(wxArtProvider::GetIcon(wxART_INFORMATION, wxART_BUTTON),
464 positions[m_radioImagePos->GetSelection()]);
465
466 if ( m_chkUsePressed->GetValue() )
467 m_toggle->SetBitmapPressed(wxArtProvider::GetIcon(wxART_HELP, wxART_BUTTON));
468 if ( m_chkUseFocused->GetValue() )
469 m_toggle->SetBitmapFocus(wxArtProvider::GetIcon(wxART_ERROR, wxART_BUTTON));
470 if ( m_chkUseCurrent->GetValue() )
471 m_toggle->SetBitmapCurrent(wxArtProvider::GetIcon(wxART_WARNING, wxART_BUTTON));
472 if ( m_chkUseDisabled->GetValue() )
473 m_toggle->SetBitmapDisabled(wxArtProvider::GetIcon(wxART_MISSING_IMAGE, wxART_BUTTON));
474 }
475 #endif // wxHAS_ANY_BUTTON
476
477 m_chkUseBitmapClass->Enable(showsBitmap);
478
479 m_chkUsePressed->Enable(showsBitmap);
480 m_chkUseFocused->Enable(showsBitmap);
481 m_chkUseCurrent->Enable(showsBitmap);
482 m_chkUseDisabled->Enable(showsBitmap);
483 #endif // wxHAS_BITMAPTOGGLEBUTTON
484
485 m_sizerToggle->Add(0, 0, 1, wxCENTRE);
486 m_sizerToggle->Add(m_toggle, 1, wxCENTRE);
487 m_sizerToggle->Add(0, 0, 1, wxCENTRE);
488 m_sizerToggle->Layout();
489 }
490
491 // ----------------------------------------------------------------------------
492 // event handlers
493 // ----------------------------------------------------------------------------
494
495 void ToggleWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
496 {
497 Reset();
498
499 CreateToggle();
500 }
501
502 void ToggleWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
503 {
504 CreateToggle();
505 }
506
507 void ToggleWidgetsPage::OnButtonChangeLabel(wxCommandEvent& WXUNUSED(event))
508 {
509 const wxString labelText = m_textLabel->GetValue();
510
511 #if wxUSE_MARKUP
512 if ( m_chkUseMarkup->GetValue() )
513 m_toggle->SetLabelMarkup(labelText);
514 else
515 #endif // wxUSE_MARKUP
516 m_toggle->SetLabel(labelText);
517 }
518
519 #ifdef wxHAS_BITMAPTOGGLEBUTTON
520 // ----------------------------------------------------------------------------
521 // bitmap toggle button stuff
522 // ----------------------------------------------------------------------------
523
524 wxBitmap ToggleWidgetsPage::CreateBitmap(const wxString& label)
525 {
526 wxBitmap bmp(180, 70); // shouldn't hardcode but it's simpler like this
527 wxMemoryDC dc;
528 dc.SelectObject(bmp);
529 dc.SetBackground(wxBrush(*wxCYAN));
530 dc.Clear();
531 dc.SetTextForeground(*wxBLACK);
532 dc.DrawLabel(wxStripMenuCodes(m_textLabel->GetValue()) + wxT("\n")
533 wxT("(") + label + wxT(" state)"),
534 wxArtProvider::GetBitmap(wxART_INFORMATION),
535 wxRect(10, 10, bmp.GetWidth() - 20, bmp.GetHeight() - 20),
536 wxALIGN_CENTRE);
537
538 return bmp;
539 }
540 #endif // wxHAS_BITMAPTOGGLEBUTTON
541
542 #endif // wxUSE_TOGGLEBTN