]> git.saurik.com Git - wxWidgets.git/blob - samples/widgets/button.cpp
Make storing non-trivial data in wxThreadSpecificInfo possible.
[wxWidgets.git] / samples / widgets / button.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: button.cpp
4 // Purpose: Part of the widgets sample showing wxButton
5 // Author: Vadim Zeitlin
6 // Created: 10.04.01
7 // Copyright: (c) 2001 Vadim Zeitlin
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 // for all others, include the necessary headers
27 #ifndef WX_PRECOMP
28 #include "wx/app.h"
29 #include "wx/log.h"
30
31 #include "wx/bmpbuttn.h"
32 #include "wx/button.h"
33 #include "wx/checkbox.h"
34 #include "wx/radiobox.h"
35 #include "wx/statbox.h"
36 #include "wx/textctrl.h"
37 #endif
38
39 #include "wx/artprov.h"
40 #include "wx/sizer.h"
41 #include "wx/dcmemory.h"
42 #include "wx/commandlinkbutton.h"
43
44 #include "widgets.h"
45
46 #include "icons/button.xpm"
47
48 // ----------------------------------------------------------------------------
49 // constants
50 // ----------------------------------------------------------------------------
51
52 // control ids
53 enum
54 {
55 ButtonPage_Reset = wxID_HIGHEST,
56 ButtonPage_ChangeLabel,
57 ButtonPage_ChangeNote,
58 ButtonPage_Button
59 };
60
61 // radio boxes
62 enum
63 {
64 ButtonImagePos_Left,
65 ButtonImagePos_Right,
66 ButtonImagePos_Top,
67 ButtonImagePos_Bottom
68 };
69
70 enum
71 {
72 ButtonHAlign_Left,
73 ButtonHAlign_Centre,
74 ButtonHAlign_Right
75 };
76
77 enum
78 {
79 ButtonVAlign_Top,
80 ButtonVAlign_Centre,
81 ButtonVAlign_Bottom
82 };
83
84 // ----------------------------------------------------------------------------
85 // ButtonWidgetsPage
86 // ----------------------------------------------------------------------------
87
88 class ButtonWidgetsPage : public WidgetsPage
89 {
90 public:
91 ButtonWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
92 virtual ~ButtonWidgetsPage(){};
93
94 virtual wxControl *GetWidget() const { return m_button; }
95 virtual void RecreateWidget() { CreateButton(); }
96
97 // lazy creation of the content
98 virtual void CreateContent();
99
100 protected:
101 // event handlers
102 void OnCheckOrRadioBox(wxCommandEvent& event);
103
104 void OnButton(wxCommandEvent& event);
105 void OnButtonReset(wxCommandEvent& event);
106 void OnButtonChangeLabel(wxCommandEvent& event);
107 void OnButtonChangeNote(wxCommandEvent& event);
108
109 // reset the wxButton parameters
110 void Reset();
111
112 // (re)create the wxButton
113 void CreateButton();
114
115 // add m_button to m_sizerButton using current value of m_chkFit
116 void AddButtonToSizer();
117
118 // helper function: create a bitmap for wxBitmapButton
119 wxBitmap CreateBitmap(const wxString& label);
120
121
122 // the controls
123 // ------------
124
125 // the check/radio boxes for styles
126 wxCheckBox *m_chkBitmapOnly,
127 *m_chkTextAndBitmap,
128 *m_chkFit,
129 *m_chkAuthNeeded,
130 #if wxUSE_COMMANDLINKBUTTON
131 *m_chkCommandLink,
132 #endif // wxUSE_COMMANDLINKBUTTON
133 #if wxUSE_MARKUP
134 *m_chkUseMarkup,
135 #endif // wxUSE_MARKUP
136 *m_chkDefault,
137 *m_chkUseBitmapClass;
138
139 // more checkboxes for wxBitmapButton only
140 wxCheckBox *m_chkUsePressed,
141 *m_chkUseFocused,
142 *m_chkUseCurrent,
143 *m_chkUseDisabled;
144
145 // and an image position choice used if m_chkTextAndBitmap is on
146 wxRadioBox *m_radioImagePos;
147
148 wxRadioBox *m_radioHAlign,
149 *m_radioVAlign;
150
151 // the button itself and the sizer it is in
152 wxButton *m_button;
153
154 #if wxUSE_COMMANDLINKBUTTON
155 // same as m_button or NULL if not showing a command link button currently
156 wxCommandLinkButton *m_cmdLnkButton;
157 #endif // wxUSE_COMMANDLINKBUTTON
158
159 wxSizer *m_sizerButton;
160
161 // the text entries for command parameters
162 wxTextCtrl *m_textLabel;
163
164 #if wxUSE_COMMANDLINKBUTTON
165 wxTextCtrl *m_textNote;
166
167 // used to hide or show button for changing note
168 wxSizer *m_sizerNote;
169 #endif // wxUSE_COMMANDLINKBUTTON
170
171 private:
172 DECLARE_EVENT_TABLE()
173 DECLARE_WIDGETS_PAGE(ButtonWidgetsPage)
174 };
175
176 // ----------------------------------------------------------------------------
177 // event tables
178 // ----------------------------------------------------------------------------
179
180 BEGIN_EVENT_TABLE(ButtonWidgetsPage, WidgetsPage)
181 EVT_BUTTON(ButtonPage_Button, ButtonWidgetsPage::OnButton)
182
183 EVT_BUTTON(ButtonPage_Reset, ButtonWidgetsPage::OnButtonReset)
184 EVT_BUTTON(ButtonPage_ChangeLabel, ButtonWidgetsPage::OnButtonChangeLabel)
185 EVT_BUTTON(ButtonPage_ChangeNote, ButtonWidgetsPage::OnButtonChangeNote)
186
187 EVT_CHECKBOX(wxID_ANY, ButtonWidgetsPage::OnCheckOrRadioBox)
188 EVT_RADIOBOX(wxID_ANY, ButtonWidgetsPage::OnCheckOrRadioBox)
189 END_EVENT_TABLE()
190
191 // ============================================================================
192 // implementation
193 // ============================================================================
194
195 #if defined(__WXUNIVERSAL__)
196 #define FAMILY_CTRLS UNIVERSAL_CTRLS
197 #else
198 #define FAMILY_CTRLS NATIVE_CTRLS
199 #endif
200
201 IMPLEMENT_WIDGETS_PAGE(ButtonWidgetsPage, wxT("Button"), FAMILY_CTRLS );
202
203 ButtonWidgetsPage::ButtonWidgetsPage(WidgetsBookCtrl *book,
204 wxImageList *imaglist)
205 : WidgetsPage(book, imaglist, button_xpm)
206 {
207 // init everything
208 m_chkBitmapOnly =
209 m_chkTextAndBitmap =
210 m_chkFit =
211 m_chkAuthNeeded =
212 #if wxUSE_COMMANDLINKBUTTON
213 m_chkCommandLink =
214 #endif // wxUSE_COMMANDLINKBUTTON
215 #if wxUSE_MARKUP
216 m_chkUseMarkup =
217 #endif // wxUSE_MARKUP
218 m_chkDefault =
219 m_chkUseBitmapClass =
220 m_chkUsePressed =
221 m_chkUseFocused =
222 m_chkUseCurrent =
223 m_chkUseDisabled = (wxCheckBox *)NULL;
224
225 m_radioImagePos =
226 m_radioHAlign =
227 m_radioVAlign = (wxRadioBox *)NULL;
228
229 m_textLabel = (wxTextCtrl *)NULL;
230
231 m_button = (wxButton *)NULL;
232 m_sizerButton = (wxSizer *)NULL;
233 }
234
235 void ButtonWidgetsPage::CreateContent()
236 {
237 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
238
239 // left pane
240 wxStaticBox *box = new wxStaticBox(this, wxID_ANY, wxT("&Set style"));
241
242 wxSizer *sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL);
243
244 m_chkBitmapOnly = CreateCheckBoxAndAddToSizer(sizerLeft, "&Bitmap only");
245 m_chkTextAndBitmap = CreateCheckBoxAndAddToSizer(sizerLeft, "Text &and bitmap");
246 m_chkFit = CreateCheckBoxAndAddToSizer(sizerLeft, wxT("&Fit exactly"));
247 m_chkAuthNeeded = CreateCheckBoxAndAddToSizer(sizerLeft, wxT("Require a&uth"));
248 #if wxUSE_COMMANDLINKBUTTON
249 m_chkCommandLink = CreateCheckBoxAndAddToSizer(sizerLeft, wxT("Use command &link button"));
250 #endif
251 #if wxUSE_MARKUP
252 m_chkUseMarkup = CreateCheckBoxAndAddToSizer(sizerLeft, "Interpret &markup");
253 #endif // wxUSE_MARKUP
254 m_chkDefault = CreateCheckBoxAndAddToSizer(sizerLeft, wxT("&Default"));
255
256 m_chkUseBitmapClass = CreateCheckBoxAndAddToSizer(sizerLeft,
257 "Use wxBitmapButton");
258 m_chkUseBitmapClass->SetValue(true);
259
260 sizerLeft->AddSpacer(5);
261
262 wxSizer *sizerUseLabels =
263 new wxStaticBoxSizer(wxVERTICAL, this,
264 "&Use the following bitmaps in addition to the normal one?");
265 m_chkUsePressed = CreateCheckBoxAndAddToSizer(sizerUseLabels,
266 "&Pressed (small help icon)");
267 m_chkUseFocused = CreateCheckBoxAndAddToSizer(sizerUseLabels,
268 "&Focused (small error icon)");
269 m_chkUseCurrent = CreateCheckBoxAndAddToSizer(sizerUseLabels,
270 "&Current (small warning icon)");
271 m_chkUseDisabled = CreateCheckBoxAndAddToSizer(sizerUseLabels,
272 "&Disabled (broken image icon)");
273 sizerLeft->Add(sizerUseLabels, wxSizerFlags().Expand().Border());
274
275 sizerLeft->AddSpacer(10);
276
277 static const wxString dirs[] =
278 {
279 "left", "right", "top", "bottom",
280 };
281 m_radioImagePos = new wxRadioBox(this, wxID_ANY, "Image &position",
282 wxDefaultPosition, wxDefaultSize,
283 WXSIZEOF(dirs), dirs);
284 sizerLeft->Add(m_radioImagePos, 0, wxGROW | wxALL, 5);
285 sizerLeft->AddSpacer(15);
286
287 // should be in sync with enums Button[HV]Align!
288 static const wxString halign[] =
289 {
290 wxT("left"),
291 wxT("centre"),
292 wxT("right"),
293 };
294
295 static const wxString valign[] =
296 {
297 wxT("top"),
298 wxT("centre"),
299 wxT("bottom"),
300 };
301
302 m_radioHAlign = new wxRadioBox(this, wxID_ANY, wxT("&Horz alignment"),
303 wxDefaultPosition, wxDefaultSize,
304 WXSIZEOF(halign), halign);
305 m_radioVAlign = new wxRadioBox(this, wxID_ANY, wxT("&Vert alignment"),
306 wxDefaultPosition, wxDefaultSize,
307 WXSIZEOF(valign), valign);
308
309 sizerLeft->Add(m_radioHAlign, 0, wxGROW | wxALL, 5);
310 sizerLeft->Add(m_radioVAlign, 0, wxGROW | wxALL, 5);
311
312 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
313
314 wxButton *btn = new wxButton(this, ButtonPage_Reset, wxT("&Reset"));
315 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
316
317 // middle pane
318 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, wxT("&Operations"));
319 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
320
321 wxSizer *sizerRow = CreateSizerWithTextAndButton(ButtonPage_ChangeLabel,
322 wxT("Change label"),
323 wxID_ANY,
324 &m_textLabel);
325 m_textLabel->SetValue(wxT("&Press me!"));
326 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
327
328 #if wxUSE_COMMANDLINKBUTTON
329 m_sizerNote = CreateSizerWithTextAndButton(ButtonPage_ChangeNote,
330 wxT("Change note"),
331 wxID_ANY,
332 &m_textNote);
333 m_textNote->SetValue(wxT("Writes down button clicks in the log."));
334
335 sizerMiddle->Add(m_sizerNote, 0, wxALL | wxGROW, 5);
336 #endif
337
338 // right pane
339 m_sizerButton = new wxBoxSizer(wxHORIZONTAL);
340 m_sizerButton->SetMinSize(150, 0);
341
342 // the 3 panes panes compose the window
343 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
344 sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
345 sizerTop->Add(m_sizerButton, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
346
347 // do create the main control
348 Reset();
349 CreateButton();
350
351 SetSizer(sizerTop);
352 }
353
354 // ----------------------------------------------------------------------------
355 // operations
356 // ----------------------------------------------------------------------------
357
358 void ButtonWidgetsPage::Reset()
359 {
360 m_chkBitmapOnly->SetValue(false);
361 m_chkFit->SetValue(true);
362 m_chkAuthNeeded->SetValue(false);
363 m_chkTextAndBitmap->SetValue(false);
364 m_chkDefault->SetValue(false);
365 #if wxUSE_COMMANDLINKBUTTON
366 m_chkCommandLink->SetValue(false);
367 #endif
368 #if wxUSE_MARKUP
369 m_chkUseMarkup->SetValue(false);
370 #endif // wxUSE_MARKUP
371 m_chkUseBitmapClass->SetValue(true);
372
373 m_chkUsePressed->SetValue(true);
374 m_chkUseFocused->SetValue(true);
375 m_chkUseCurrent->SetValue(true);
376 m_chkUseDisabled->SetValue(true);
377
378 m_radioImagePos->SetSelection(ButtonImagePos_Left);
379 m_radioHAlign->SetSelection(ButtonHAlign_Centre);
380 m_radioVAlign->SetSelection(ButtonVAlign_Centre);
381 }
382
383 void ButtonWidgetsPage::CreateButton()
384 {
385 wxString label;
386 if ( m_button )
387 {
388 #if wxUSE_COMMANDLINKBUTTON
389 if ( m_cmdLnkButton )
390 label = m_cmdLnkButton->GetMainLabel();
391 else
392 #endif
393 label = m_button->GetLabel();
394
395 size_t count = m_sizerButton->GetChildren().GetCount();
396 for ( size_t n = 0; n < count; n++ )
397 {
398 m_sizerButton->Remove( 0 );
399 }
400
401 delete m_button;
402 }
403
404 if ( label.empty() )
405 {
406 // creating for the first time or recreating a button after bitmap
407 // button
408 label = m_textLabel->GetValue();
409 }
410
411 int flags = ms_defaultFlags;
412 switch ( m_radioHAlign->GetSelection() )
413 {
414 case ButtonHAlign_Left:
415 flags |= wxBU_LEFT;
416 break;
417
418 default:
419 wxFAIL_MSG(wxT("unexpected radiobox selection"));
420 // fall through
421
422 case ButtonHAlign_Centre:
423 break;
424
425 case ButtonHAlign_Right:
426 flags |= wxBU_RIGHT;
427 break;
428 }
429
430 switch ( m_radioVAlign->GetSelection() )
431 {
432 case ButtonVAlign_Top:
433 flags |= wxBU_TOP;
434 break;
435
436 default:
437 wxFAIL_MSG(wxT("unexpected radiobox selection"));
438 // fall through
439
440 case ButtonVAlign_Centre:
441 // centre vertical alignment is the default (no style)
442 break;
443
444 case ButtonVAlign_Bottom:
445 flags |= wxBU_BOTTOM;
446 break;
447 }
448
449 #if wxUSE_COMMANDLINKBUTTON
450 m_sizerNote->Show(m_chkCommandLink->GetValue());
451 #endif
452
453 bool showsBitmap = false;
454 if ( m_chkBitmapOnly->GetValue() )
455 {
456 showsBitmap = true;
457
458 wxButton *bbtn;
459 if ( m_chkUseBitmapClass->GetValue() )
460 {
461 bbtn = new wxBitmapButton(this, ButtonPage_Button,
462 CreateBitmap(wxT("normal")));
463 }
464 else
465 {
466 bbtn = new wxButton(this, ButtonPage_Button);
467 bbtn->SetBitmapLabel(CreateBitmap(wxT("normal")));
468 }
469 if ( m_chkUsePressed->GetValue() )
470 bbtn->SetBitmapPressed(CreateBitmap(wxT("pushed")));
471 if ( m_chkUseFocused->GetValue() )
472 bbtn->SetBitmapFocus(CreateBitmap(wxT("focused")));
473 if ( m_chkUseCurrent->GetValue() )
474 bbtn->SetBitmapCurrent(CreateBitmap(wxT("hover")));
475 if ( m_chkUseDisabled->GetValue() )
476 bbtn->SetBitmapDisabled(CreateBitmap(wxT("disabled")));
477 m_button = bbtn;
478 #if wxUSE_COMMANDLINKBUTTON
479 m_cmdLnkButton = NULL;
480 #endif
481 }
482 else // normal button
483 {
484 #if wxUSE_COMMANDLINKBUTTON
485 m_cmdLnkButton = NULL;
486
487 if ( m_chkCommandLink->GetValue() )
488 {
489 m_cmdLnkButton = new wxCommandLinkButton(this, ButtonPage_Button,
490 label,
491 m_textNote->GetValue(),
492 wxDefaultPosition,
493 wxDefaultSize,
494 flags);
495 m_button = m_cmdLnkButton;
496 }
497 else
498 #endif // wxUSE_COMMANDLINKBUTTON
499 {
500 m_button = new wxButton(this, ButtonPage_Button, label,
501 wxDefaultPosition, wxDefaultSize,
502 flags);
503 }
504 }
505
506 if ( !showsBitmap && m_chkTextAndBitmap->GetValue() )
507 {
508 showsBitmap = true;
509
510 static const wxDirection positions[] =
511 {
512 wxLEFT, wxRIGHT, wxTOP, wxBOTTOM
513 };
514
515 m_button->SetBitmap(wxArtProvider::GetIcon(wxART_INFORMATION, wxART_BUTTON),
516 positions[m_radioImagePos->GetSelection()]);
517
518 if ( m_chkUsePressed->GetValue() )
519 m_button->SetBitmapPressed(wxArtProvider::GetIcon(wxART_HELP, wxART_BUTTON));
520 if ( m_chkUseFocused->GetValue() )
521 m_button->SetBitmapFocus(wxArtProvider::GetIcon(wxART_ERROR, wxART_BUTTON));
522 if ( m_chkUseCurrent->GetValue() )
523 m_button->SetBitmapCurrent(wxArtProvider::GetIcon(wxART_WARNING, wxART_BUTTON));
524 if ( m_chkUseDisabled->GetValue() )
525 m_button->SetBitmapDisabled(wxArtProvider::GetIcon(wxART_MISSING_IMAGE, wxART_BUTTON));
526 }
527
528 m_chkUseBitmapClass->Enable(showsBitmap);
529
530 m_chkUsePressed->Enable(showsBitmap);
531 m_chkUseFocused->Enable(showsBitmap);
532 m_chkUseCurrent->Enable(showsBitmap);
533 m_chkUseDisabled->Enable(showsBitmap);
534
535 if ( m_chkAuthNeeded->GetValue() )
536 m_button->SetAuthNeeded();
537
538 if ( m_chkDefault->GetValue() )
539 m_button->SetDefault();
540
541 AddButtonToSizer();
542
543 m_sizerButton->Layout();
544 }
545
546 void ButtonWidgetsPage::AddButtonToSizer()
547 {
548 if ( m_chkFit->GetValue() )
549 {
550 m_sizerButton->AddStretchSpacer(1);
551 m_sizerButton->Add(m_button, wxSizerFlags(0).Centre().Border());
552 m_sizerButton->AddStretchSpacer(1);
553 }
554 else // take up the entire space
555 {
556 m_sizerButton->Add(m_button, wxSizerFlags(1).Expand().Border());
557 }
558 }
559
560 // ----------------------------------------------------------------------------
561 // event handlers
562 // ----------------------------------------------------------------------------
563
564 void ButtonWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
565 {
566 Reset();
567
568 CreateButton();
569 }
570
571 void ButtonWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
572 {
573 CreateButton();
574 Layout(); // make sure the text field for changing note displays correctly.
575 }
576
577 void ButtonWidgetsPage::OnButtonChangeLabel(wxCommandEvent& WXUNUSED(event))
578 {
579 const wxString labelText = m_textLabel->GetValue();
580
581 #if wxUSE_COMMANDLINKBUTTON
582 if ( m_cmdLnkButton )
583 m_cmdLnkButton->SetMainLabel(labelText);
584 else
585 #endif // wxUSE_COMMANDLINKBUTTON
586 {
587 #if wxUSE_MARKUP
588 if ( m_chkUseMarkup->GetValue() )
589 m_button->SetLabelMarkup(labelText);
590 else
591 #endif // wxUSE_MARKUP
592 m_button->SetLabel(labelText);
593 }
594
595 m_sizerButton->Layout();
596 }
597
598 void ButtonWidgetsPage::OnButtonChangeNote(wxCommandEvent& WXUNUSED(event))
599 {
600 #if wxUSE_COMMANDLINKBUTTON
601 m_cmdLnkButton->SetNote(m_textNote->GetValue());
602
603 m_sizerButton->Layout();
604 #endif // wxUSE_COMMANDLINKBUTTON
605 }
606
607 void ButtonWidgetsPage::OnButton(wxCommandEvent& WXUNUSED(event))
608 {
609 wxLogMessage(wxT("Test button clicked."));
610 }
611
612 // ----------------------------------------------------------------------------
613 // bitmap button stuff
614 // ----------------------------------------------------------------------------
615
616 wxBitmap ButtonWidgetsPage::CreateBitmap(const wxString& label)
617 {
618 wxBitmap bmp(180, 70); // shouldn't hardcode but it's simpler like this
619 wxMemoryDC dc;
620 dc.SelectObject(bmp);
621 dc.SetBackground(*wxCYAN_BRUSH);
622 dc.Clear();
623 dc.SetTextForeground(*wxBLACK);
624 dc.DrawLabel(wxStripMenuCodes(m_textLabel->GetValue()) + wxT("\n")
625 wxT("(") + label + wxT(" state)"),
626 wxArtProvider::GetBitmap(wxART_INFORMATION),
627 wxRect(10, 10, bmp.GetWidth() - 20, bmp.GetHeight() - 20),
628 wxALIGN_CENTRE);
629
630 return bmp;
631 }
632