implement images support for wxButton under XP and later
[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_chkBitmap,
125 *m_chkImage,
126 *m_chkFit,
127 *m_chkDefault;
128
129 // more checkboxes for wxBitmapButton only
130 wxCheckBox *m_chkUseSelected,
131 *m_chkUseFocused,
132 *m_chkUseHover,
133 *m_chkUseDisabled;
134
135 // and an image position choice used if m_chkImage 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_chkBitmap =
185 m_chkImage =
186 m_chkFit =
187 m_chkDefault =
188 m_chkUseSelected =
189 m_chkUseFocused =
190 m_chkUseHover =
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_chkBitmap = CreateCheckBoxAndAddToSizer(sizerLeft, _T("&Bitmap button"));
213 m_chkImage = CreateCheckBoxAndAddToSizer(sizerLeft, _T("With &image"));
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, _T("&Use the following bitmaps?"));
221 m_chkUseSelected = CreateCheckBoxAndAddToSizer(sizerUseLabels, _T("&Pushed"));
222 m_chkUseFocused = CreateCheckBoxAndAddToSizer(sizerUseLabels, _T("&Focused"));
223 m_chkUseHover = CreateCheckBoxAndAddToSizer(sizerUseLabels, _T("&Hover"));
224 m_chkUseDisabled = CreateCheckBoxAndAddToSizer(sizerUseLabels, _T("&Disabled"));
225 sizerLeft->Add(sizerUseLabels, wxSizerFlags().Expand().Border());
226
227 sizerLeft->AddSpacer(10);
228
229 static const wxString dirs[] =
230 {
231 "left", "right", "top", "bottom",
232 };
233 m_radioImagePos = new wxRadioBox(this, wxID_ANY, "Image &position",
234 wxDefaultPosition, wxDefaultSize,
235 WXSIZEOF(dirs), dirs);
236 sizerLeft->Add(m_radioImagePos, 0, wxGROW | wxALL, 5);
237 sizerLeft->AddSpacer(15);
238
239 // should be in sync with enums Button[HV]Align!
240 static const wxString halign[] =
241 {
242 _T("left"),
243 _T("centre"),
244 _T("right"),
245 };
246
247 static const wxString valign[] =
248 {
249 _T("top"),
250 _T("centre"),
251 _T("bottom"),
252 };
253
254 m_radioHAlign = new wxRadioBox(this, wxID_ANY, _T("&Horz alignment"),
255 wxDefaultPosition, wxDefaultSize,
256 WXSIZEOF(halign), halign);
257 m_radioVAlign = new wxRadioBox(this, wxID_ANY, _T("&Vert alignment"),
258 wxDefaultPosition, wxDefaultSize,
259 WXSIZEOF(valign), valign);
260
261 sizerLeft->Add(m_radioHAlign, 0, wxGROW | wxALL, 5);
262 sizerLeft->Add(m_radioVAlign, 0, wxGROW | wxALL, 5);
263
264 sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
265
266 wxButton *btn = new wxButton(this, ButtonPage_Reset, _T("&Reset"));
267 sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
268
269 // middle pane
270 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, _T("&Operations"));
271 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
272
273 wxSizer *sizerRow = CreateSizerWithTextAndButton(ButtonPage_ChangeLabel,
274 _T("Change label"),
275 wxID_ANY,
276 &m_textLabel);
277 m_textLabel->SetValue(_T("&Press me!"));
278
279 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
280
281 // right pane
282 m_sizerButton = new wxBoxSizer(wxHORIZONTAL);
283 m_sizerButton->SetMinSize(150, 0);
284
285 // the 3 panes panes compose the window
286 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
287 sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10);
288 sizerTop->Add(m_sizerButton, 1, wxGROW | (wxALL & ~wxRIGHT), 10);
289
290 // do create the main control
291 Reset();
292 CreateButton();
293
294 SetSizer(sizerTop);
295 }
296
297 // ----------------------------------------------------------------------------
298 // operations
299 // ----------------------------------------------------------------------------
300
301 void ButtonWidgetsPage::Reset()
302 {
303 m_chkBitmap->SetValue(false);
304 m_chkFit->SetValue(true);
305 m_chkImage->SetValue(false);
306 m_chkDefault->SetValue(false);
307
308 m_chkUseSelected->SetValue(true);
309 m_chkUseFocused->SetValue(true);
310 m_chkUseHover->SetValue(true);
311 m_chkUseDisabled->SetValue(true);
312
313 m_radioImagePos->SetSelection(ButtonImagePos_Left);
314 m_radioHAlign->SetSelection(ButtonHAlign_Centre);
315 m_radioVAlign->SetSelection(ButtonVAlign_Centre);
316 }
317
318 void ButtonWidgetsPage::CreateButton()
319 {
320 wxString label;
321 if ( m_button )
322 {
323 label = m_button->GetLabel();
324
325 size_t count = m_sizerButton->GetChildren().GetCount();
326 for ( size_t n = 0; n < count; n++ )
327 {
328 m_sizerButton->Remove( 0 );
329 }
330
331 delete m_button;
332 }
333
334 if ( label.empty() )
335 {
336 // creating for the first time or recreating a button after bitmap
337 // button
338 label = m_textLabel->GetValue();
339 }
340
341 int flags = ms_defaultFlags;
342 switch ( m_radioHAlign->GetSelection() )
343 {
344 case ButtonHAlign_Left:
345 flags |= wxBU_LEFT;
346 break;
347
348 default:
349 wxFAIL_MSG(_T("unexpected radiobox selection"));
350 // fall through
351
352 case ButtonHAlign_Centre:
353 break;
354
355 case ButtonHAlign_Right:
356 flags |= wxBU_RIGHT;
357 break;
358 }
359
360 switch ( m_radioVAlign->GetSelection() )
361 {
362 case ButtonVAlign_Top:
363 flags |= wxBU_TOP;
364 break;
365
366 default:
367 wxFAIL_MSG(_T("unexpected radiobox selection"));
368 // fall through
369
370 case ButtonVAlign_Centre:
371 // centre vertical alignment is the default (no style)
372 break;
373
374 case ButtonVAlign_Bottom:
375 flags |= wxBU_BOTTOM;
376 break;
377 }
378
379 const bool isBitmapButton = m_chkBitmap->GetValue();
380 if ( isBitmapButton )
381 {
382 wxBitmapButton *bbtn = new wxBitmapButton(this, ButtonPage_Button,
383 CreateBitmap(_T("normal")));
384 if ( m_chkUseSelected->GetValue() )
385 bbtn->SetBitmapSelected(CreateBitmap(_T("pushed")));
386 if ( m_chkUseFocused->GetValue() )
387 bbtn->SetBitmapFocus(CreateBitmap(_T("focused")));
388 if ( m_chkUseHover->GetValue() )
389 bbtn->SetBitmapHover(CreateBitmap(_T("hover")));
390 if ( m_chkUseDisabled->GetValue() )
391 bbtn->SetBitmapDisabled(CreateBitmap(_T("disabled")));
392 m_button = bbtn;
393 }
394 else // normal button
395 {
396 m_button = new wxButton(this, ButtonPage_Button, label,
397 wxDefaultPosition, wxDefaultSize,
398 flags);
399 }
400
401 m_chkUseSelected->Enable(isBitmapButton);
402 m_chkUseFocused->Enable(isBitmapButton);
403 m_chkUseHover->Enable(isBitmapButton);
404 m_chkUseDisabled->Enable(isBitmapButton);
405
406 if ( m_chkImage->GetValue() )
407 {
408 static const wxDirection positions[] =
409 {
410 wxLEFT, wxRIGHT, wxTOP, wxBOTTOM
411 };
412
413 m_button->SetBitmap(wxArtProvider::GetIcon(wxART_INFORMATION),
414 positions[m_radioImagePos->GetSelection()]);
415 }
416
417 if ( m_chkDefault->GetValue() )
418 {
419 m_button->SetDefault();
420 }
421
422 AddButtonToSizer();
423
424 m_sizerButton->Layout();
425 }
426
427 void ButtonWidgetsPage::AddButtonToSizer()
428 {
429 if ( m_chkFit->GetValue() )
430 {
431 m_sizerButton->AddStretchSpacer(1);
432 m_sizerButton->Add(m_button, wxSizerFlags(0).Centre().Border());
433 m_sizerButton->AddStretchSpacer(1);
434 }
435 else // take up the entire space
436 {
437 m_sizerButton->Add(m_button, wxSizerFlags(1).Expand().Border());
438 }
439 }
440
441 // ----------------------------------------------------------------------------
442 // event handlers
443 // ----------------------------------------------------------------------------
444
445 void ButtonWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
446 {
447 Reset();
448
449 CreateButton();
450 }
451
452 void ButtonWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
453 {
454 CreateButton();
455 }
456
457 void ButtonWidgetsPage::OnButtonChangeLabel(wxCommandEvent& WXUNUSED(event))
458 {
459 m_button->SetLabel(m_textLabel->GetValue());
460 }
461
462 void ButtonWidgetsPage::OnButton(wxCommandEvent& WXUNUSED(event))
463 {
464 wxLogMessage(_T("Test button clicked."));
465 }
466
467 // ----------------------------------------------------------------------------
468 // bitmap button stuff
469 // ----------------------------------------------------------------------------
470
471 wxBitmap ButtonWidgetsPage::CreateBitmap(const wxString& label)
472 {
473 wxBitmap bmp(180, 70); // shouldn't hardcode but it's simpler like this
474 wxMemoryDC dc;
475 dc.SelectObject(bmp);
476 dc.SetBackground(wxBrush(*wxWHITE));
477 dc.Clear();
478 dc.SetTextForeground(*wxBLUE);
479 dc.DrawLabel(wxStripMenuCodes(m_textLabel->GetValue()) + _T("\n")
480 _T("(") + label + _T(" state)"),
481 wxArtProvider::GetBitmap(wxART_INFORMATION),
482 wxRect(10, 10, bmp.GetWidth() - 20, bmp.GetHeight() - 20),
483 wxALIGN_CENTRE);
484
485 return bmp;
486 }
487