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