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