From a6fbfacc62a483a448c489a4534a80800b38e40d Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sun, 27 Jan 2019 15:10:32 +0100 Subject: [PATCH 1/2] Improve wxButton and wxToggleButton with bitmap in widgets sample Use a valid font when creating the bitmap. Create the bitmap with a DPI independent size. Use different images for different button states, as described by the checkbox options. Add a checkbox to disable the bitmap. Recreate the button when changing label, so the bitmap is updated. Implement the 'fit exactly' option on ToggleButton page. --- samples/widgets/button.cpp | 33 ++++++++++++++-------- samples/widgets/toggle.cpp | 56 ++++++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/samples/widgets/button.cpp b/samples/widgets/button.cpp index 98d9473a39..2fa95866a7 100644 --- a/samples/widgets/button.cpp +++ b/samples/widgets/button.cpp @@ -115,7 +115,7 @@ protected: void AddButtonToSizer(); // helper function: create a bitmap for wxBitmapButton - wxBitmap CreateBitmap(const wxString& label); + wxBitmap CreateBitmap(const wxString& label, const wxArtID& type); // the controls @@ -133,7 +133,8 @@ protected: *m_chkUseMarkup, #endif // wxUSE_MARKUP *m_chkDefault, - *m_chkUseBitmapClass; + *m_chkUseBitmapClass, + *m_chkDisable; // more checkboxes for wxBitmapButton only wxCheckBox *m_chkUsePressed, @@ -216,6 +217,7 @@ ButtonWidgetsPage::ButtonWidgetsPage(WidgetsBookCtrl *book, #endif // wxUSE_MARKUP m_chkDefault = m_chkUseBitmapClass = + m_chkDisable = m_chkUsePressed = m_chkUseFocused = m_chkUseCurrent = @@ -256,6 +258,8 @@ void ButtonWidgetsPage::CreateContent() "Use wxBitmapButton"); m_chkUseBitmapClass->SetValue(true); + m_chkDisable = CreateCheckBoxAndAddToSizer(sizerLeft, "Disable"); + sizerLeft->AddSpacer(5); wxSizer *sizerUseLabels = @@ -368,6 +372,7 @@ void ButtonWidgetsPage::Reset() m_chkUseMarkup->SetValue(false); #endif // wxUSE_MARKUP m_chkUseBitmapClass->SetValue(true); + m_chkDisable->SetValue(false); m_chkUsePressed->SetValue(true); m_chkUseFocused->SetValue(true); @@ -456,22 +461,22 @@ void ButtonWidgetsPage::CreateButton() if ( m_chkUseBitmapClass->GetValue() ) { bbtn = new wxBitmapButton(this, ButtonPage_Button, - CreateBitmap("normal"), + CreateBitmap("normal", wxART_INFORMATION), wxDefaultPosition, wxDefaultSize, flags); } else { bbtn = new wxButton(this, ButtonPage_Button); - bbtn->SetBitmapLabel(CreateBitmap("normal")); + bbtn->SetBitmapLabel(CreateBitmap("normal", wxART_INFORMATION)); } if ( m_chkUsePressed->GetValue() ) - bbtn->SetBitmapPressed(CreateBitmap("pushed")); + bbtn->SetBitmapPressed(CreateBitmap("pushed", wxART_HELP)); if ( m_chkUseFocused->GetValue() ) - bbtn->SetBitmapFocus(CreateBitmap("focused")); + bbtn->SetBitmapFocus(CreateBitmap("focused", wxART_ERROR)); if ( m_chkUseCurrent->GetValue() ) - bbtn->SetBitmapCurrent(CreateBitmap("hover")); + bbtn->SetBitmapCurrent(CreateBitmap("hover", wxART_WARNING)); if ( m_chkUseDisabled->GetValue() ) - bbtn->SetBitmapDisabled(CreateBitmap("disabled")); + bbtn->SetBitmapDisabled(CreateBitmap("disabled", wxART_MISSING_IMAGE)); m_button = bbtn; #if wxUSE_COMMANDLINKBUTTON m_cmdLnkButton = NULL; @@ -543,6 +548,8 @@ void ButtonWidgetsPage::CreateButton() if ( m_chkDefault->GetValue() ) m_button->SetDefault(); + m_button->Enable(!m_chkDisable->IsChecked()); + AddButtonToSizer(); m_sizerButton->Layout(); @@ -597,6 +604,9 @@ void ButtonWidgetsPage::OnButtonChangeLabel(wxCommandEvent& WXUNUSED(event)) m_button->SetLabel(labelText); } + if ( m_chkBitmapOnly->IsChecked() ) + CreateButton(); + m_sizerButton->Layout(); } @@ -618,17 +628,18 @@ void ButtonWidgetsPage::OnButton(wxCommandEvent& WXUNUSED(event)) // bitmap button stuff // ---------------------------------------------------------------------------- -wxBitmap ButtonWidgetsPage::CreateBitmap(const wxString& label) +wxBitmap ButtonWidgetsPage::CreateBitmap(const wxString& label, const wxArtID& type) { - wxBitmap bmp(180, 70); // shouldn't hardcode but it's simpler like this + wxBitmap bmp(FromDIP(wxSize(180, 70))); // shouldn't hardcode but it's simpler like this wxMemoryDC dc; dc.SelectObject(bmp); + dc.SetFont(GetFont()); dc.SetBackground(*wxCYAN_BRUSH); dc.Clear(); dc.SetTextForeground(*wxBLACK); dc.DrawLabel(wxStripMenuCodes(m_textLabel->GetValue()) + "\n" "(" + label + " state)", - wxArtProvider::GetBitmap(wxART_INFORMATION), + wxArtProvider::GetBitmap(type), wxRect(10, 10, bmp.GetWidth() - 20, bmp.GetHeight() - 20), wxALIGN_CENTRE); diff --git a/samples/widgets/toggle.cpp b/samples/widgets/toggle.cpp index d435642951..ecfeaeb0c9 100644 --- a/samples/widgets/toggle.cpp +++ b/samples/widgets/toggle.cpp @@ -108,8 +108,11 @@ protected: // (re)create the toggle void CreateToggle(); + // add m_button to m_sizerButton using current value of m_chkFit + void AddButtonToSizer(); + // helper function: create a bitmap for wxBitmapToggleButton - wxBitmap CreateBitmap(const wxString& label); + wxBitmap CreateBitmap(const wxString& label, const wxArtID& type); // the controls // ------------ @@ -122,7 +125,8 @@ protected: wxCheckBox *m_chkBitmapOnly, *m_chkTextAndBitmap, *m_chkFit, - *m_chkUseBitmapClass; + *m_chkUseBitmapClass, + *m_chkDisable; // more checkboxes for wxBitmapToggleButton only wxCheckBox *m_chkUsePressed, @@ -192,6 +196,7 @@ ToggleWidgetsPage::ToggleWidgetsPage(WidgetsBookCtrl *book, m_chkTextAndBitmap = m_chkFit = m_chkUseBitmapClass = + m_chkDisable = m_chkUsePressed = m_chkUseFocused = m_chkUseCurrent = @@ -231,6 +236,8 @@ void ToggleWidgetsPage::CreateContent() "Use wxBitmapToggleButton"); m_chkUseBitmapClass->SetValue(true); + m_chkDisable = CreateCheckBoxAndAddToSizer(sizerLeft, "Disable"); + sizerLeft->AddSpacer(5); wxSizer *sizerUseLabels = @@ -327,6 +334,7 @@ void ToggleWidgetsPage::Reset() m_chkUseMarkup->SetValue(false); #endif // wxUSE_MARKUP m_chkUseBitmapClass->SetValue(true); + m_chkDisable->SetValue(false); m_chkUsePressed->SetValue(true); m_chkUseFocused->SetValue(true); @@ -419,22 +427,22 @@ void ToggleWidgetsPage::CreateToggle() if ( m_chkUseBitmapClass->GetValue() ) { btgl = new wxBitmapToggleButton(this, TogglePage_Picker, - CreateBitmap("normal")); + CreateBitmap("normal", wxART_INFORMATION)); } else { btgl = new wxToggleButton(this, TogglePage_Picker, ""); - btgl->SetBitmapLabel(CreateBitmap("normal")); + btgl->SetBitmapLabel(CreateBitmap("normal", wxART_INFORMATION)); } #ifdef wxHAS_ANY_BUTTON if ( m_chkUsePressed->GetValue() ) - btgl->SetBitmapPressed(CreateBitmap("pushed")); + btgl->SetBitmapPressed(CreateBitmap("pushed", wxART_HELP)); if ( m_chkUseFocused->GetValue() ) - btgl->SetBitmapFocus(CreateBitmap("focused")); + btgl->SetBitmapFocus(CreateBitmap("focused", wxART_ERROR)); if ( m_chkUseCurrent->GetValue() ) - btgl->SetBitmapCurrent(CreateBitmap("hover")); + btgl->SetBitmapCurrent(CreateBitmap("hover", wxART_WARNING)); if ( m_chkUseDisabled->GetValue() ) - btgl->SetBitmapDisabled(CreateBitmap("disabled")); + btgl->SetBitmapDisabled(CreateBitmap("disabled", wxART_MISSING_IMAGE)); #endif // wxHAS_ANY_BUTTON m_toggle = btgl; } @@ -473,6 +481,7 @@ void ToggleWidgetsPage::CreateToggle() #endif // wxHAS_ANY_BUTTON m_chkUseBitmapClass->Enable(showsBitmap); + m_chkTextAndBitmap->Enable(!m_chkBitmapOnly->IsChecked()); m_chkUsePressed->Enable(showsBitmap); m_chkUseFocused->Enable(showsBitmap); @@ -480,12 +489,27 @@ void ToggleWidgetsPage::CreateToggle() m_chkUseDisabled->Enable(showsBitmap); #endif // wxHAS_BITMAPTOGGLEBUTTON - m_sizerToggle->Add(0, 0, 1, wxCENTRE); - m_sizerToggle->Add(m_toggle, 1, wxCENTRE); - m_sizerToggle->Add(0, 0, 1, wxCENTRE); + m_toggle->Enable(!m_chkDisable->IsChecked()); + + AddButtonToSizer(); + m_sizerToggle->Layout(); } +void ToggleWidgetsPage::AddButtonToSizer() +{ + if ( m_chkFit->GetValue() ) + { + m_sizerToggle->AddStretchSpacer(1); + m_sizerToggle->Add(m_toggle, wxSizerFlags(0).Centre().Border()); + m_sizerToggle->AddStretchSpacer(1); + } + else // take up the entire space + { + m_sizerToggle->Add(m_toggle, wxSizerFlags(1).Expand().Border()); + } +} + // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- @@ -512,6 +536,9 @@ void ToggleWidgetsPage::OnButtonChangeLabel(wxCommandEvent& WXUNUSED(event)) else #endif // wxUSE_MARKUP m_toggle->SetLabel(labelText); + + if ( m_chkBitmapOnly->IsChecked() ) + CreateToggle(); } #ifdef wxHAS_BITMAPTOGGLEBUTTON @@ -519,17 +546,18 @@ void ToggleWidgetsPage::OnButtonChangeLabel(wxCommandEvent& WXUNUSED(event)) // bitmap toggle button stuff // ---------------------------------------------------------------------------- -wxBitmap ToggleWidgetsPage::CreateBitmap(const wxString& label) +wxBitmap ToggleWidgetsPage::CreateBitmap(const wxString& label, const wxArtID& type) { - wxBitmap bmp(180, 70); // shouldn't hardcode but it's simpler like this + wxBitmap bmp(FromDIP(wxSize(180, 70))); // shouldn't hardcode but it's simpler like this wxMemoryDC dc; dc.SelectObject(bmp); + dc.SetFont(GetFont()); dc.SetBackground(*wxCYAN_BRUSH); dc.Clear(); dc.SetTextForeground(*wxBLACK); dc.DrawLabel(wxStripMenuCodes(m_textLabel->GetValue()) + "\n" "(" + label + " state)", - wxArtProvider::GetBitmap(wxART_INFORMATION), + wxArtProvider::GetBitmap(type), wxRect(10, 10, bmp.GetWidth() - 20, bmp.GetHeight() - 20), wxALIGN_CENTRE); From ee752e24396d7540b8363ce80fad02c045b665c6 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sun, 27 Jan 2019 15:23:02 +0100 Subject: [PATCH 2/2] Use more wxSizerFlags in widgets sample --- samples/widgets/button.cpp | 23 +++++++++++++---------- samples/widgets/toggle.cpp | 21 ++++++++++++--------- samples/widgets/widgets.cpp | 20 ++++++++++---------- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/samples/widgets/button.cpp b/samples/widgets/button.cpp index 2fa95866a7..e5881ed46d 100644 --- a/samples/widgets/button.cpp +++ b/samples/widgets/button.cpp @@ -284,7 +284,7 @@ void ButtonWidgetsPage::CreateContent() m_radioImagePos = new wxRadioBox(this, wxID_ANY, "Image &position", wxDefaultPosition, wxDefaultSize, WXSIZEOF(dirs), dirs); - sizerLeft->Add(m_radioImagePos, 0, wxGROW | wxALL, 5); + sizerLeft->Add(m_radioImagePos, wxSizerFlags().Expand().Border()); sizerLeft->AddSpacer(15); // should be in sync with enums Button[HV]Align! @@ -309,13 +309,13 @@ void ButtonWidgetsPage::CreateContent() wxDefaultPosition, wxDefaultSize, WXSIZEOF(valign), valign); - sizerLeft->Add(m_radioHAlign, 0, wxGROW | wxALL, 5); - sizerLeft->Add(m_radioVAlign, 0, wxGROW | wxALL, 5); + sizerLeft->Add(m_radioHAlign, wxSizerFlags().Expand().Border()); + sizerLeft->Add(m_radioVAlign, wxSizerFlags().Expand().Border()); - sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer + sizerLeft->AddSpacer(5); wxButton *btn = new wxButton(this, ButtonPage_Reset, "&Reset"); - sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); + sizerLeft->Add(btn, wxSizerFlags().CentreHorizontal().Border(wxALL, 15)); // middle pane wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, "&Operations"); @@ -326,7 +326,7 @@ void ButtonWidgetsPage::CreateContent() wxID_ANY, &m_textLabel); m_textLabel->SetValue("&Press me!"); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); #if wxUSE_COMMANDLINKBUTTON m_sizerNote = CreateSizerWithTextAndButton(ButtonPage_ChangeNote, @@ -335,7 +335,7 @@ void ButtonWidgetsPage::CreateContent() &m_textNote); m_textNote->SetValue("Writes down button clicks in the log."); - sizerMiddle->Add(m_sizerNote, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(m_sizerNote, wxSizerFlags().Expand().Border()); #endif // right pane @@ -343,9 +343,12 @@ void ButtonWidgetsPage::CreateContent() m_sizerButton->SetMinSize(150, 0); // the 3 panes panes compose the window - sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10); - sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10); - sizerTop->Add(m_sizerButton, 1, wxGROW | (wxALL & ~wxRIGHT), 10); + sizerTop->Add(sizerLeft, + wxSizerFlags(0).Expand().Border((wxALL & ~wxLEFT), 10)); + sizerTop->Add(sizerMiddle, + wxSizerFlags(1).Expand().Border(wxALL, 10)); + sizerTop->Add(m_sizerButton, + wxSizerFlags(1).Expand().Border((wxALL & ~wxRIGHT), 10)); // do create the main control Reset(); diff --git a/samples/widgets/toggle.cpp b/samples/widgets/toggle.cpp index ecfeaeb0c9..2f61d261b3 100644 --- a/samples/widgets/toggle.cpp +++ b/samples/widgets/toggle.cpp @@ -262,7 +262,7 @@ void ToggleWidgetsPage::CreateContent() m_radioImagePos = new wxRadioBox(this, wxID_ANY, "Image &position", wxDefaultPosition, wxDefaultSize, WXSIZEOF(dirs), dirs); - sizerLeft->Add(m_radioImagePos, 0, wxGROW | wxALL, 5); + sizerLeft->Add(m_radioImagePos, wxSizerFlags().Expand().Border()); sizerLeft->AddSpacer(15); // should be in sync with enums Toggle[HV]Align! @@ -287,14 +287,14 @@ void ToggleWidgetsPage::CreateContent() wxDefaultPosition, wxDefaultSize, WXSIZEOF(valign), valign); - sizerLeft->Add(m_radioHAlign, 0, wxGROW | wxALL, 5); - sizerLeft->Add(m_radioVAlign, 0, wxGROW | wxALL, 5); + sizerLeft->Add(m_radioHAlign, wxSizerFlags().Expand().Border()); + sizerLeft->Add(m_radioVAlign, wxSizerFlags().Expand().Border()); #endif // wxHAS_BITMAPTOGGLEBUTTON - sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer + sizerLeft->AddSpacer(5); wxButton *btn = new wxButton(this, TogglePage_Reset, "&Reset"); - sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); + sizerLeft->Add(btn, wxSizerFlags().CentreHorizontal().Border(wxALL, 15)); // middle pane wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, "&Operations"); @@ -306,16 +306,19 @@ void ToggleWidgetsPage::CreateContent() &m_textLabel); m_textLabel->SetValue("&Toggle me!"); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); // right pane m_sizerToggle = new wxBoxSizer(wxHORIZONTAL); m_sizerToggle->SetMinSize(150, 0); // the 3 panes panes compose the window - sizerTop->Add(sizerLeft, 0, (wxALL & ~wxLEFT), 10); - sizerTop->Add(sizerMiddle, 1, wxGROW | wxALL, 10); - sizerTop->Add(m_sizerToggle, 1, wxGROW | (wxALL & ~wxRIGHT), 10); + sizerTop->Add(sizerLeft, + wxSizerFlags(0).Expand().Border((wxALL & ~wxLEFT), 10)); + sizerTop->Add(sizerMiddle, + wxSizerFlags(1).Expand().Border(wxALL, 10)); + sizerTop->Add(m_sizerToggle, + wxSizerFlags(1).Expand().Border((wxALL & ~wxRIGHT), 10)); // do create the main control Reset(); diff --git a/samples/widgets/widgets.cpp b/samples/widgets/widgets.cpp index 381011490d..c2e44da45f 100644 --- a/samples/widgets/widgets.cpp +++ b/samples/widgets/widgets.cpp @@ -492,7 +492,7 @@ WidgetsFrame::WidgetsFrame(const wxString& title) wxVERTICAL); m_lboxLog = new wxListBox(m_panel, wxID_ANY); - sizerDown->Add(m_lboxLog, 1, wxGROW | wxALL, 5); + sizerDown->Add(m_lboxLog, wxSizerFlags(1).Expand().Border()); sizerDown->SetMinSize(100, 150); #else wxSizer *sizerDown = new wxBoxSizer(wxVERTICAL); @@ -503,16 +503,16 @@ WidgetsFrame::WidgetsFrame(const wxString& title) #if USE_LOG btn = new wxButton(m_panel, Widgets_ClearLog, "Clear &log"); sizerBtns->Add(btn); - sizerBtns->Add(10, 0); // spacer + sizerBtns->AddSpacer(10); #endif // USE_LOG btn = new wxButton(m_panel, Widgets_Quit, "E&xit"); sizerBtns->Add(btn); - sizerDown->Add(sizerBtns, 0, wxALL | wxALIGN_RIGHT, 5); + sizerDown->Add(sizerBtns, wxSizerFlags().Border().Right()); // put everything together - sizerTop->Add(m_book, 1, wxGROW | (wxALL & ~(wxTOP | wxBOTTOM)), 10); - sizerTop->Add(0, 5, 0, wxGROW); // spacer in between - sizerTop->Add(sizerDown, 0, wxGROW | (wxALL & ~wxTOP), 10); + sizerTop->Add(m_book, wxSizerFlags(1).Expand().DoubleBorder(wxALL & ~(wxTOP | wxBOTTOM))); + sizerTop->AddSpacer(5); + sizerTop->Add(sizerDown, wxSizerFlags(0).Expand().DoubleBorder(wxALL & ~wxTOP)); m_panel->SetSizer(sizerTop); @@ -1347,8 +1347,8 @@ wxSizer *WidgetsPage::CreateSizerWithText(wxControl *control, wxTextCtrl *text = new wxTextCtrl(this, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); - sizerRow->Add(control, 0, wxRIGHT | wxALIGN_CENTRE_VERTICAL, 5); - sizerRow->Add(text, 1, wxLEFT | wxALIGN_CENTRE_VERTICAL, 5); + sizerRow->Add(control, wxSizerFlags(0).Border(wxRIGHT).CentreVertical()); + sizerRow->Add(text, wxSizerFlags(1).Border(wxLEFT).CentreVertical()); if ( ppText ) *ppText = text; @@ -1379,8 +1379,8 @@ wxCheckBox *WidgetsPage::CreateCheckBoxAndAddToSizer(wxSizer *sizer, wxWindowID id) { wxCheckBox *checkbox = new wxCheckBox(this, id, label); - sizer->Add(checkbox, 0, wxLEFT | wxRIGHT, 5); - sizer->Add(0, 2, 0, wxGROW); // spacer + sizer->Add(checkbox, wxSizerFlags().HorzBorder()); + sizer->AddSpacer(2); return checkbox; }