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);
~ButtonWidgetsPage()92     virtual ~ButtonWidgetsPage(){};
93 
GetWidget() const94     virtual wxControl *GetWidget() const { return m_button; }
RecreateWidget()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     wxDECLARE_EVENT_TABLE();
173     DECLARE_WIDGETS_PAGE(ButtonWidgetsPage)
174 };
175 
176 // ----------------------------------------------------------------------------
177 // event tables
178 // ----------------------------------------------------------------------------
179 
180 wxBEGIN_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 wxEND_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 
ButtonWidgetsPage(WidgetsBookCtrl * book,wxImageList * imaglist)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 
CreateContent()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 
Reset()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 
CreateButton()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 
AddButtonToSizer()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 
OnButtonReset(wxCommandEvent & WXUNUSED (event))564 void ButtonWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
565 {
566     Reset();
567 
568     CreateButton();
569 }
570 
OnCheckOrRadioBox(wxCommandEvent & WXUNUSED (event))571 void ButtonWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
572 {
573     CreateButton();
574     Layout(); // make sure the text field for changing note displays correctly.
575 }
576 
OnButtonChangeLabel(wxCommandEvent & WXUNUSED (event))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 
OnButtonChangeNote(wxCommandEvent & WXUNUSED (event))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 
OnButton(wxCommandEvent & WXUNUSED (event))607 void ButtonWidgetsPage::OnButton(wxCommandEvent& WXUNUSED(event))
608 {
609     wxLogMessage(wxT("Test button clicked."));
610 }
611 
612 // ----------------------------------------------------------------------------
613 // bitmap button stuff
614 // ----------------------------------------------------------------------------
615 
CreateBitmap(const wxString & label)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 
633