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