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