From 0e824883009f7474f164b8224fdb28888f2d4f5c Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:13:11 +0100 Subject: [PATCH 1/9] Document wxSL_BOTH style of wxSlider --- interface/wx/slider.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/wx/slider.h b/interface/wx/slider.h index f35e3cf574..0c35d97224 100644 --- a/interface/wx/slider.h +++ b/interface/wx/slider.h @@ -57,6 +57,8 @@ Displays ticks on the top. @style{wxSL_BOTTOM} Displays ticks on the bottom (this is the default). + @style{wxSL_BOTH} + Displays ticks on both sides of the slider. Windows only. @style{wxSL_SELRANGE} Displays a highlighted selection range. Windows only. @style{wxSL_INVERSE} From 94f3d567c8c133eb60ecc98ecad2b61bf59d0839 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:19:12 +0100 Subject: [PATCH 2/9] Centre labels above and below vertical wxSlider Improve label position for specific combinations of wxSlider styles. --- src/msw/slider.cpp | 65 ++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/src/msw/slider.cpp b/src/msw/slider.cpp index cd99974bf5..dc24072b81 100644 --- a/src/msw/slider.cpp +++ b/src/msw/slider.cpp @@ -401,10 +401,10 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) } int tickOffset = 0; - if ( HasFlag(wxSL_TICKS)) - tickOffset = TICK; - if ( HasFlag(wxSL_BOTH)) - tickOffset *= 2; + if ( HasFlag(wxSL_TICKS) ) + tickOffset = TICK; + if ( HasFlag(wxSL_BOTH) ) + tickOffset *= 2; // be careful to position the slider itself after moving the labels as // otherwise our GetBoundingBox(), which is called from WM_SIZE handler, @@ -419,7 +419,7 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) sliderOffset += longestLabelWidth + HGAP; } - int labelHeightUsed = 0 ; + int labelHeightUsed = 0; if ( HasFlag(wxSL_MIN_MAX_LABELS) ) { @@ -429,9 +429,12 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) if ( HasFlag(wxSL_LEFT) ) { // Label aligned to the left edge of the slider. - xPos = sliderOffset + tickOffset; - holdTopX = xPos; - holdBottomX = xPos; + xPos = sliderOffset + THUMB / 2; + if ( HasFlag(wxSL_TICKS) ) + xPos += TICK; + + holdTopX = xPos - minLabelWidth / 2; + holdBottomX = xPos - maxLabelWidth / 2; if ( holdTopX + minLabelWidth > width ) holdTopX = width - minLabelWidth; if ( holdBottomX + maxLabelWidth > width ) @@ -440,24 +443,18 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) else // wxSL_RIGHT { // Label aligned to the right edge of the slider. - if ( HasFlag(wxSL_BOTH) ) - xPos = sliderOffset + THUMB + tickOffset/2; - else - xPos = sliderOffset + THUMB; + xPos = sliderOffset + THUMB / 2; + if ( HasFlag(wxSL_TICKS) && HasFlag(wxSL_BOTH) ) + xPos += TICK; - holdTopX = xPos - minLabelWidth; - holdBottomX = xPos - maxLabelWidth; + holdTopX = xPos - minLabelWidth / 2; + holdBottomX = xPos - maxLabelWidth / 2; if ( holdTopX < 0 ) holdTopX = 0; if ( holdBottomX < 0 ) holdBottomX = 0; } - if ( HasFlag(wxSL_INVERSE) ) - { - wxSwap(holdTopX, holdBottomX); - } - DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min], x + holdTopX, y, @@ -467,14 +464,14 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) y + height - labelHeight, maxLabelWidth, labelHeight); - labelHeightUsed = labelHeight ; + labelHeightUsed = labelHeight; } if ( HasFlag(wxSL_VALUE_LABEL) ) { DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value], x + ( HasFlag(wxSL_LEFT) ? THUMB + tickOffset + HGAP : 0 ), - y + (height - labelHeight)/2, + y + (height - labelHeight) / 2, longestLabelWidth, labelHeight); } @@ -488,20 +485,20 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) else // horizontal { int yLabelMinMax = - (y + ((THUMB + tickOffset) / 2)) - (labelHeight / 2); + ((THUMB + tickOffset) / 2) - (labelHeight / 2); int xLabelValue = - x + minLabelWidth + - ((width - (minLabelWidth + maxLabelWidth)) / 2) - + minLabelWidth + + ((width - (minLabelWidth + maxLabelWidth)) / 2) - (longestLabelWidth / 2); - int ySlider = y; - int minLabelWidthUsed = 0 ; - int maxLabelWidthUsed = 0 ; + int ySlider = 0; + int minLabelWidthUsed = 0; + int maxLabelWidthUsed = 0; if ( HasFlag(wxSL_VALUE_LABEL) ) { DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value], - xLabelValue, + x + xLabelValue, y + (HasFlag(wxSL_BOTTOM) ? 0 : THUMB + tickOffset), longestLabelWidth, labelHeight); @@ -516,21 +513,21 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) { DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min], x, - yLabelMinMax, + y + yLabelMinMax, minLabelWidth, labelHeight); DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max], x + width - maxLabelWidth, - yLabelMinMax, + y + yLabelMinMax, maxLabelWidth, labelHeight); - minLabelWidthUsed = minLabelWidth + VGAP ; - maxLabelWidthUsed = maxLabelWidth + VGAP ; + minLabelWidthUsed = minLabelWidth + VGAP; + maxLabelWidthUsed = maxLabelWidth + VGAP; } // position the slider itself along the top/bottom edge wxSliderBase::DoMoveWindow( x + minLabelWidthUsed, - ySlider, + y + ySlider, width - (minLabelWidthUsed + maxLabelWidthUsed), THUMB + tickOffset); } @@ -559,7 +556,7 @@ wxSize wxSlider::DoGetBestSize() const if ( HasFlag(wxSL_VALUE_LABEL) ) size.x += longestLabelWidth + HGAP; - if (HasFlag(wxSL_MIN_MAX_LABELS)) + if ( HasFlag(wxSL_MIN_MAX_LABELS) ) { size.x = wxMax(size.x, longestLabelWidth); size.y += hLabel * 2; From 5eaea0e43f88b30d464c638ca903f3519ea415fb Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:21:21 +0100 Subject: [PATCH 3/9] Improve wxSlider in high DPI Make thumb and tick size DPI dependent. --- src/msw/slider.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/msw/slider.cpp b/src/msw/slider.cpp index dc24072b81..cb6d8c8422 100644 --- a/src/msw/slider.cpp +++ b/src/msw/slider.cpp @@ -390,6 +390,9 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) return; } + const int thumbSize = FromDIP(THUMB); + const int tickSize = FromDIP(TICK); + int minLabelWidth, maxLabelWidth; const int labelHeight = GetLabelsSize(&minLabelWidth, &maxLabelWidth); @@ -402,7 +405,7 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) int tickOffset = 0; if ( HasFlag(wxSL_TICKS) ) - tickOffset = TICK; + tickOffset = tickSize; if ( HasFlag(wxSL_BOTH) ) tickOffset *= 2; @@ -429,9 +432,9 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) if ( HasFlag(wxSL_LEFT) ) { // Label aligned to the left edge of the slider. - xPos = sliderOffset + THUMB / 2; + xPos = sliderOffset + thumbSize / 2; if ( HasFlag(wxSL_TICKS) ) - xPos += TICK; + xPos += tickSize; holdTopX = xPos - minLabelWidth / 2; holdBottomX = xPos - maxLabelWidth / 2; @@ -443,9 +446,9 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) else // wxSL_RIGHT { // Label aligned to the right edge of the slider. - xPos = sliderOffset + THUMB / 2; + xPos = sliderOffset + thumbSize / 2; if ( HasFlag(wxSL_TICKS) && HasFlag(wxSL_BOTH) ) - xPos += TICK; + xPos += tickSize; holdTopX = xPos - minLabelWidth / 2; holdBottomX = xPos - maxLabelWidth / 2; @@ -470,7 +473,7 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) if ( HasFlag(wxSL_VALUE_LABEL) ) { DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value], - x + ( HasFlag(wxSL_LEFT) ? THUMB + tickOffset + HGAP : 0 ), + x + ( HasFlag(wxSL_LEFT) ? thumbSize + tickOffset + HGAP : 0 ), y + (height - labelHeight) / 2, longestLabelWidth, labelHeight); } @@ -479,13 +482,13 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) wxSliderBase::DoMoveWindow( x + sliderOffset, y + labelHeightUsed, - THUMB + tickOffset, + thumbSize + tickOffset, height - (labelHeightUsed * 2)); } else // horizontal { int yLabelMinMax = - ((THUMB + tickOffset) / 2) - (labelHeight / 2); + ((thumbSize + tickOffset) / 2) - (labelHeight / 2); int xLabelValue = minLabelWidth + ((width - (minLabelWidth + maxLabelWidth)) / 2) - @@ -499,7 +502,7 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) { DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value], x + xLabelValue, - y + (HasFlag(wxSL_BOTTOM) ? 0 : THUMB + tickOffset), + y + (HasFlag(wxSL_BOTTOM) ? 0 : thumbSize + tickOffset), longestLabelWidth, labelHeight); if ( HasFlag(wxSL_BOTTOM) ) @@ -529,20 +532,22 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) x + minLabelWidthUsed, y + ySlider, width - (minLabelWidthUsed + maxLabelWidthUsed), - THUMB + tickOffset); + thumbSize + tickOffset); } } wxSize wxSlider::DoGetBestSize() const { // this value is arbitrary: - static const int length = 100; + static const int length = FromDIP(100); + const int thumbSize = FromDIP(THUMB); + const int tickSize = FromDIP(TICK); int *width; wxSize size; if ( HasFlag(wxSL_VERTICAL) ) { - size.Set(THUMB, length); + size.Set(thumbSize, length); width = &size.x; if ( m_labels ) @@ -565,7 +570,7 @@ wxSize wxSlider::DoGetBestSize() const } else // horizontal { - size.Set(length, THUMB); + size.Set(length, thumbSize); width = &size.y; if ( m_labels ) @@ -585,10 +590,10 @@ wxSize wxSlider::DoGetBestSize() const // need extra space to show ticks if ( HasFlag(wxSL_TICKS) ) { - *width += TICK; + *width += tickSize; // and maybe twice as much if we show them on both sides if ( HasFlag(wxSL_BOTH) ) - *width += TICK; + *width += tickSize; } return size; } From 9f9bc40f83371b61c87aaf03f32f51296cb89d59 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:22:27 +0100 Subject: [PATCH 4/9] Better fix layout of wxSlider labels after changing value range Commit 0b821adf did not (always) trigger a call to DoMoveWindow. See #17093. --- src/msw/slider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/msw/slider.cpp b/src/msw/slider.cpp index cb6d8c8422..30eadaf490 100644 --- a/src/msw/slider.cpp +++ b/src/msw/slider.cpp @@ -651,7 +651,7 @@ void wxSlider::SetRange(int minValue, int maxValue) if ( m_labels ) { - Move(wxDefaultPosition); // Force a re-layout the labels. + Move(wxDefaultPosition, wxSIZE_FORCE); // Force a re-layout the labels. // Update the label with the value adjusted by the control as // old value can be out of the new range. From 8f3b87dce79a5b1a06864b1aa9d43e294becb567 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:23:38 +0100 Subject: [PATCH 5/9] Fix wxSlider::SetThumbLength() on wxMSW It requires TBS_FIXEDLENGTH style. Call InvalidateBestSize because the size of the control might change. Call Layout in the widgets sample to adjust to the changed size. Use GetThumbLength() instead of the arbitrary defined THUMB size. --- samples/widgets/slider.cpp | 8 ++++++++ src/msw/slider.cpp | 12 ++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/samples/widgets/slider.cpp b/samples/widgets/slider.cpp index 33edea188d..427e89a6ad 100644 --- a/samples/widgets/slider.cpp +++ b/samples/widgets/slider.cpp @@ -543,6 +543,14 @@ void SliderWidgetsPage::DoSetThumbLen() } m_slider->SetThumbLength(len); + + if ( m_slider->GetThumbLength() != len ) + { + wxLogWarning(wxString::Format("Invalid thumb length in slider: %d", + m_slider->GetThumbLength())); + } + + Layout(); } // ---------------------------------------------------------------------------- diff --git a/src/msw/slider.cpp b/src/msw/slider.cpp index 30eadaf490..558107053f 100644 --- a/src/msw/slider.cpp +++ b/src/msw/slider.cpp @@ -54,8 +54,7 @@ enum // the gaps between the slider and the labels, in pixels const int HGAP = 5; const int VGAP = 4; -// these 2 values are arbitrary: -const int THUMB = 24; +// this value is arbitrary: const int TICK = 8; } // anonymous namespace @@ -194,6 +193,9 @@ WXDWORD wxSlider::MSWGetStyle(long style, WXDWORD *exstyle) const // TBS_HORZ, TBS_RIGHT and TBS_BOTTOM are 0 but do include them for clarity msStyle |= style & wxSL_VERTICAL ? TBS_VERT : TBS_HORZ; + // allow setting thumb size + msStyle |= TBS_FIXEDLENGTH; + if ( style & wxSL_BOTH ) { // this fully specifies the style combined with TBS_VERT/HORZ above @@ -390,7 +392,7 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height) return; } - const int thumbSize = FromDIP(THUMB); + const int thumbSize = GetThumbLength(); const int tickSize = FromDIP(TICK); int minLabelWidth, @@ -540,7 +542,7 @@ wxSize wxSlider::DoGetBestSize() const { // this value is arbitrary: static const int length = FromDIP(100); - const int thumbSize = FromDIP(THUMB); + const int thumbSize = GetThumbLength(); const int tickSize = FromDIP(TICK); int *width; @@ -732,6 +734,8 @@ void wxSlider::SetSelection(int minPos, int maxPos) void wxSlider::SetThumbLength(int len) { ::SendMessage(GetHwnd(), TBM_SETTHUMBLENGTH, (WPARAM) len, (LPARAM) 0); + + InvalidateBestSize(); } int wxSlider::GetThumbLength() const From bf0a8ffd74b1e8f100641bb6b48789c6d5f1cf73 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:12:23 +0100 Subject: [PATCH 6/9] Improve guards in button pages of widgets sample Add guards for wxCommandLinkButton. Move CheckBoxes outside wxHAS_BITMAPTOGGLEBUTTON guard. Remove wxHAS_ANY_BUTTON check, this is always defined with wxUSE_TOGGLEBTN. --- samples/widgets/button.cpp | 4 ++++ samples/widgets/toggle.cpp | 47 +++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/samples/widgets/button.cpp b/samples/widgets/button.cpp index e5881ed46d..8b266c247c 100644 --- a/samples/widgets/button.cpp +++ b/samples/widgets/button.cpp @@ -456,7 +456,9 @@ void ButtonWidgetsPage::CreateButton() bool showsBitmap = false; if ( m_chkBitmapOnly->GetValue() ) { +#if wxUSE_COMMANDLINKBUTTON m_chkCommandLink->SetValue(false); // wxCommandLinkButton cannot be "Bitmap only" +#endif showsBitmap = true; @@ -537,7 +539,9 @@ void ButtonWidgetsPage::CreateButton() m_chkTextAndBitmap->Enable(!m_chkBitmapOnly->IsChecked()); m_chkBitmapOnly->Enable(!m_chkTextAndBitmap->IsChecked()); +#if wxUSE_COMMANDLINKBUTTON m_chkCommandLink->Enable(!m_chkBitmapOnly->IsChecked()); +#endif m_chkUseBitmapClass->Enable(showsBitmap); m_chkUsePressed->Enable(showsBitmap); diff --git a/samples/widgets/toggle.cpp b/samples/widgets/toggle.cpp index 52a4b6215c..43a4e3f103 100644 --- a/samples/widgets/toggle.cpp +++ b/samples/widgets/toggle.cpp @@ -117,16 +117,18 @@ protected: // the controls // ------------ + wxCheckBox *m_chkFit, + *m_chkDisable; + #if wxUSE_MARKUP wxCheckBox *m_chkUseMarkup; #endif // wxUSE_MARKUP + #ifdef wxHAS_BITMAPTOGGLEBUTTON // the check/radio boxes for styles wxCheckBox *m_chkBitmapOnly, *m_chkTextAndBitmap, - *m_chkFit, - *m_chkUseBitmapClass, - *m_chkDisable; + *m_chkUseBitmapClass; // more checkboxes for wxBitmapToggleButton only wxCheckBox *m_chkUsePressed, @@ -142,11 +144,7 @@ protected: #endif // wxHAS_BITMAPTOGGLEBUTTON // the checkbox itself and the sizer it is in -#ifdef wxHAS_ANY_BUTTON wxToggleButton *m_toggle; -#else - wxToggleButtonBase *m_toggle; -#endif // wxHAS_ANY_BUTTON wxSizer *m_sizerToggle; // the text entries for command parameters @@ -187,16 +185,18 @@ ToggleWidgetsPage::ToggleWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist) :WidgetsPage(book, imaglist, toggle_xpm) { + m_chkFit = + m_chkDisable = (wxCheckBox *)NULL; + #if wxUSE_MARKUP m_chkUseMarkup = (wxCheckBox *)NULL; #endif // wxUSE_MARKUP + #ifdef wxHAS_BITMAPTOGGLEBUTTON // init everything m_chkBitmapOnly = m_chkTextAndBitmap = - m_chkFit = m_chkUseBitmapClass = - m_chkDisable = m_chkUsePressed = m_chkUseFocused = m_chkUseCurrent = @@ -225,18 +225,20 @@ void ToggleWidgetsPage::CreateContent() #ifdef wxHAS_BITMAPTOGGLEBUTTON m_chkBitmapOnly = CreateCheckBoxAndAddToSizer(sizerLeft, "&Bitmap only"); m_chkTextAndBitmap = CreateCheckBoxAndAddToSizer(sizerLeft, "Text &and bitmap"); - m_chkFit = CreateCheckBoxAndAddToSizer(sizerLeft, "&Fit exactly"); #endif // wxHAS_BITMAPTOGGLEBUTTON + #if wxUSE_MARKUP m_chkUseMarkup = CreateCheckBoxAndAddToSizer(sizerLeft, "Interpret &markup"); #endif // wxUSE_MARKUP + m_chkFit = CreateCheckBoxAndAddToSizer(sizerLeft, "&Fit exactly"); + m_chkDisable = CreateCheckBoxAndAddToSizer(sizerLeft, "Disable"); + #ifdef wxHAS_BITMAPTOGGLEBUTTON m_chkUseBitmapClass = CreateCheckBoxAndAddToSizer(sizerLeft, "Use wxBitmapToggleButton"); m_chkUseBitmapClass->SetValue(true); - m_chkDisable = CreateCheckBoxAndAddToSizer(sizerLeft, "Disable"); sizerLeft->AddSpacer(5); @@ -329,15 +331,18 @@ void ToggleWidgetsPage::CreateContent() void ToggleWidgetsPage::Reset() { -#ifdef wxHAS_BITMAPTOGGLEBUTTON - m_chkBitmapOnly->SetValue(false); + m_chkFit->SetValue(true); - m_chkTextAndBitmap->SetValue(false); + m_chkDisable->SetValue(false); + #if wxUSE_MARKUP m_chkUseMarkup->SetValue(false); #endif // wxUSE_MARKUP + +#ifdef wxHAS_BITMAPTOGGLEBUTTON + m_chkBitmapOnly->SetValue(false); + m_chkTextAndBitmap->SetValue(false); m_chkUseBitmapClass->SetValue(true); - m_chkDisable->SetValue(false); m_chkUsePressed->SetValue(true); m_chkUseFocused->SetValue(true); @@ -381,6 +386,7 @@ void ToggleWidgetsPage::CreateToggle() } int flags = GetAttrs().m_defaultFlags; + #ifdef wxHAS_BITMAPTOGGLEBUTTON switch ( m_radioHAlign->GetSelection() ) { @@ -418,9 +424,7 @@ void ToggleWidgetsPage::CreateToggle() flags |= wxBU_BOTTOM; break; } -#endif // wxHAS_BITMAPTOGGLEBUTTON -#ifdef wxHAS_BITMAPTOGGLEBUTTON bool showsBitmap = false; if ( m_chkBitmapOnly->GetValue() ) { @@ -437,7 +441,6 @@ void ToggleWidgetsPage::CreateToggle() btgl = new wxToggleButton(this, TogglePage_Picker, ""); btgl->SetBitmapLabel(CreateBitmap("normal", wxART_INFORMATION)); } -#ifdef wxHAS_ANY_BUTTON if ( m_chkUsePressed->GetValue() ) btgl->SetBitmapPressed(CreateBitmap("pushed", wxART_HELP)); if ( m_chkUseFocused->GetValue() ) @@ -446,7 +449,6 @@ void ToggleWidgetsPage::CreateToggle() btgl->SetBitmapCurrent(CreateBitmap("hover", wxART_WARNING)); if ( m_chkUseDisabled->GetValue() ) btgl->SetBitmapDisabled(CreateBitmap("disabled", wxART_MISSING_IMAGE)); -#endif // wxHAS_ANY_BUTTON m_toggle = btgl; } else // normal button @@ -459,7 +461,6 @@ void ToggleWidgetsPage::CreateToggle() m_toggle->SetValue(value); #ifdef wxHAS_BITMAPTOGGLEBUTTON -#ifdef wxHAS_ANY_BUTTON if ( !showsBitmap && m_chkTextAndBitmap->GetValue() ) { showsBitmap = true; @@ -481,7 +482,6 @@ void ToggleWidgetsPage::CreateToggle() if ( m_chkUseDisabled->GetValue() ) m_toggle->SetBitmapDisabled(wxArtProvider::GetIcon(wxART_MISSING_IMAGE, wxART_BUTTON)); } -#endif // wxHAS_ANY_BUTTON m_chkUseBitmapClass->Enable(showsBitmap); m_chkTextAndBitmap->Enable(!m_chkBitmapOnly->IsChecked()); @@ -490,9 +490,10 @@ void ToggleWidgetsPage::CreateToggle() m_chkUseFocused->Enable(showsBitmap); m_chkUseCurrent->Enable(showsBitmap); m_chkUseDisabled->Enable(showsBitmap); - m_toggle->Enable(!m_chkDisable->IsChecked()); #endif // wxHAS_BITMAPTOGGLEBUTTON + m_toggle->Enable(!m_chkDisable->IsChecked()); + AddButtonToSizer(); m_sizerToggle->Layout(); @@ -500,7 +501,6 @@ void ToggleWidgetsPage::CreateToggle() void ToggleWidgetsPage::AddButtonToSizer() { -#ifdef wxHAS_BITMAPTOGGLEBUTTON if ( m_chkFit->GetValue() ) { m_sizerToggle->AddStretchSpacer(1); @@ -508,7 +508,6 @@ void ToggleWidgetsPage::AddButtonToSizer() m_sizerToggle->AddStretchSpacer(1); } else // take up the entire space -#endif // wxHAS_BITMAPTOGGLEBUTTON { m_sizerToggle->Add(m_toggle, wxSizerFlags(1).Expand().Border()); } From 56c7eadc0adad38f4d87608890e9b52c72167ca9 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:32:10 +0100 Subject: [PATCH 7/9] Use wxSizerFlags for slider page in widgets sample Don't set minimum size of right panel. --- samples/widgets/slider.cpp | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/samples/widgets/slider.cpp b/samples/widgets/slider.cpp index 427e89a6ad..40ff59430b 100644 --- a/samples/widgets/slider.cpp +++ b/samples/widgets/slider.cpp @@ -272,17 +272,17 @@ void SliderWidgetsPage::CreateContent() wxDefaultPosition, wxDefaultSize, WXSIZEOF(sides), sides, 1, wxRA_SPECIFY_COLS); - sizerLeft->Add(m_radioSides, 0, wxGROW | wxALL, 5); + sizerLeft->Add(m_radioSides, wxSizerFlags().Expand().Border()); m_chkBothSides = CreateCheckBoxAndAddToSizer (sizerLeft, "&Both sides", SliderPage_BothSides); #if wxUSE_TOOLTIPS m_chkBothSides->SetToolTip("\"Both sides\" is only supported \nin Universal"); #endif // wxUSE_TOOLTIPS - sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer + sizerLeft->AddSpacer(5); wxButton *btn = new wxButton(this, SliderPage_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, "&Change slider value"); @@ -294,13 +294,13 @@ void SliderWidgetsPage::CreateContent() &text); text->SetEditable(false); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); sizerRow = CreateSizerWithTextAndButton(SliderPage_SetValue, "Set &value", SliderPage_ValueText, &m_textValue); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); sizerRow = CreateSizerWithTextAndButton(SliderPage_SetMinAndMax, "&Min and max", @@ -308,26 +308,26 @@ void SliderWidgetsPage::CreateContent() &m_textMin); m_textMax = new wxTextCtrl(this, SliderPage_MaxText, wxEmptyString); - sizerRow->Add(m_textMax, 1, wxLEFT | wxALIGN_CENTRE_VERTICAL, 5); + sizerRow->Add(m_textMax, wxSizerFlags(1).CentreVertical().Border(wxLEFT)); m_textMin->SetValue( wxString::Format("%d", m_min) ); m_textMax->SetValue( wxString::Format("%d", m_max) ); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); sizerRow = CreateSizerWithTextAndButton(SliderPage_SetLineSize, "Li&ne size", SliderPage_LineSizeText, &m_textLineSize); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); sizerRow = CreateSizerWithTextAndButton(SliderPage_SetPageSize, "P&age size", SliderPage_PageSizeText, &m_textPageSize); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); sizerRow = CreateSizerWithTextAndButton(SliderPage_SetTickFreq, "Tick &frequency", @@ -336,18 +336,17 @@ void SliderWidgetsPage::CreateContent() m_textTickFreq->SetValue("10"); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); sizerRow = CreateSizerWithTextAndButton(SliderPage_SetThumbLen, "Thumb &length", SliderPage_ThumbLenText, &m_textThumbLen); - sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); // right pane wxSizer *sizerRight = new wxBoxSizer(wxHORIZONTAL); - sizerRight->SetMinSize(150, 40); m_sizerSlider = sizerRight; // save it to modify it later Reset(); @@ -357,9 +356,12 @@ void SliderWidgetsPage::CreateContent() m_textPageSize->SetValue(wxString::Format("%d", m_slider->GetPageSize())); // the 3 panes panes compose the window - sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10); - sizerTop->Add(sizerMiddle, 0, wxGROW | wxALL, 10); - sizerTop->Add(sizerRight, 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(sizerRight, + wxSizerFlags(1).Expand().Border((wxALL & ~wxRIGHT), 10)); // final initializations SetSizer(sizerTop); @@ -466,13 +468,13 @@ void SliderWidgetsPage::CreateSlider() if ( m_slider->HasFlag(wxSL_VERTICAL) ) { - m_sizerSlider->Add(0, 0, 1); - m_sizerSlider->Add(m_slider, 0, wxGROW | wxALL, 5); - m_sizerSlider->Add(0, 0, 1); + m_sizerSlider->AddStretchSpacer(1); + m_sizerSlider->Add(m_slider, wxSizerFlags(0).Expand().Border()); + m_sizerSlider->AddStretchSpacer(1); } else { - m_sizerSlider->Add(m_slider, 1, wxCENTRE | wxALL, 5); + m_sizerSlider->Add(m_slider, wxSizerFlags(1).Centre().Border()); } if ( m_chkTicks->GetValue() ) From 53af5cb2519d9e1b54948e4f85f286d2967eeb9b Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:39:15 +0100 Subject: [PATCH 8/9] Some fixes for wxSlider in widgets sample Correctly save the slider value before recreating the slider. Layout the entire page instead of only the slider sizer. Update the text controls after recreating the slider. Always enable 'both sides' checkbox. It has additional effects in wxMSW. --- samples/widgets/slider.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/samples/widgets/slider.cpp b/samples/widgets/slider.cpp index 40ff59430b..583ad15c5a 100644 --- a/samples/widgets/slider.cpp +++ b/samples/widgets/slider.cpp @@ -352,9 +352,6 @@ void SliderWidgetsPage::CreateContent() Reset(); CreateSlider(); - m_textLineSize->SetValue(wxString::Format("%d", m_slider->GetLineSize())); - m_textPageSize->SetValue(wxString::Format("%d", m_slider->GetPageSize())); - // the 3 panes panes compose the window sizerTop->Add(sizerLeft, wxSizerFlags(0).Expand().Border((wxALL & ~wxLEFT), 10)); @@ -444,7 +441,7 @@ void SliderWidgetsPage::CreateSlider() if ( m_slider ) { int valOld = m_slider->GetValue(); - if ( !IsValidValue(valOld) ) + if ( IsValidValue(valOld) ) { val = valOld; } @@ -477,12 +474,16 @@ void SliderWidgetsPage::CreateSlider() m_sizerSlider->Add(m_slider, wxSizerFlags(1).Centre().Border()); } + m_textLineSize->SetValue(wxString::Format("%d", m_slider->GetLineSize())); + m_textPageSize->SetValue(wxString::Format("%d", m_slider->GetPageSize())); + m_textThumbLen->SetValue(wxString::Format("%d", m_slider->GetThumbLength())); + if ( m_chkTicks->GetValue() ) { DoSetTickFreq(); } - m_sizerSlider->Layout(); + Layout(); } void SliderWidgetsPage::DoSetLineSize() @@ -694,7 +695,7 @@ void SliderWidgetsPage::OnUpdateUIRadioSides(wxUpdateUIEvent& event) void SliderWidgetsPage::OnUpdateUIBothSides(wxUpdateUIEvent& event) { #if defined(__WXMSW__) || defined(__WXUNIVERSAL__) - event.Enable( m_chkTicks->GetValue() ); + event.Enable( true ); #else event.Enable( false ); #endif // defined(__WXMSW__) || defined(__WXUNIVERSAL__) From 4aeb941c4c810b08f0d48579e935a7700aadcbf8 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 31 Jan 2019 20:36:25 +0100 Subject: [PATCH 9/9] Demonstrate wxSlider::SetSelection() in widgets sample --- samples/widgets/slider.cpp | 104 ++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/samples/widgets/slider.cpp b/samples/widgets/slider.cpp index 583ad15c5a..32bf2fad60 100644 --- a/samples/widgets/slider.cpp +++ b/samples/widgets/slider.cpp @@ -59,6 +59,7 @@ enum SliderPage_Clear, SliderPage_SetValue, SliderPage_SetMinAndMax, + SliderPage_SetRange, SliderPage_SetLineSize, SliderPage_SetPageSize, SliderPage_SetTickFreq, @@ -67,12 +68,15 @@ enum SliderPage_ValueText, SliderPage_MinText, SliderPage_MaxText, + SliderPage_RangeMinText, + SliderPage_RangeMaxText, SliderPage_LineSizeText, SliderPage_PageSizeText, SliderPage_TickFreqText, SliderPage_ThumbLenText, SliderPage_RadioSides, SliderPage_BothSides, + SliderPage_SelectRange, SliderPage_Slider }; @@ -107,6 +111,7 @@ protected: void OnButtonClear(wxCommandEvent& event); void OnButtonSetValue(wxCommandEvent& event); void OnButtonSetMinAndMax(wxCommandEvent& event); + void OnButtonSetRange(wxCommandEvent& event); void OnButtonSetLineSize(wxCommandEvent& event); void OnButtonSetPageSize(wxCommandEvent& event); void OnButtonSetTickFreq(wxCommandEvent& event); @@ -118,12 +123,14 @@ protected: void OnUpdateUIValueButton(wxUpdateUIEvent& event); void OnUpdateUIMinMaxButton(wxUpdateUIEvent& event); + void OnUpdateUIRangeButton(wxUpdateUIEvent& event); void OnUpdateUILineSize(wxUpdateUIEvent& event); void OnUpdateUIPageSize(wxUpdateUIEvent& event); void OnUpdateUITickFreq(wxUpdateUIEvent& event); void OnUpdateUIThumbLen(wxUpdateUIEvent& event); void OnUpdateUIRadioSides(wxUpdateUIEvent& event); void OnUpdateUIBothSides(wxUpdateUIEvent& event); + void OnUpdateUISelectRange(wxUpdateUIEvent& event); void OnUpdateUIResetButton(wxUpdateUIEvent& event); @@ -147,6 +154,9 @@ protected: // set the thumb len from the text field value void DoSetThumbLen(); + // set the selection range from the text field values + void DoSetSelectionRange(); + // is this slider value in range? bool IsValidValue(int val) const { return (val >= m_min) && (val <= m_max); } @@ -154,6 +164,9 @@ protected: // the slider range int m_min, m_max; + // the slider selection range + int m_rangeMin, m_rangeMax; + // the controls // ------------ @@ -162,7 +175,8 @@ protected: *m_chkValueLabel, *m_chkInverse, *m_chkTicks, - *m_chkBothSides; + *m_chkBothSides, + *m_chkSelectRange; wxRadioBox *m_radioSides; @@ -174,6 +188,8 @@ protected: wxTextCtrl *m_textValue, *m_textMin, *m_textMax, + *m_textRangeMin, + *m_textRangeMax, *m_textLineSize, *m_textPageSize, *m_textTickFreq, @@ -192,6 +208,7 @@ wxBEGIN_EVENT_TABLE(SliderWidgetsPage, WidgetsPage) EVT_BUTTON(SliderPage_Reset, SliderWidgetsPage::OnButtonReset) EVT_BUTTON(SliderPage_SetValue, SliderWidgetsPage::OnButtonSetValue) EVT_BUTTON(SliderPage_SetMinAndMax, SliderWidgetsPage::OnButtonSetMinAndMax) + EVT_BUTTON(SliderPage_SetRange, SliderWidgetsPage::OnButtonSetRange) EVT_BUTTON(SliderPage_SetLineSize, SliderWidgetsPage::OnButtonSetLineSize) EVT_BUTTON(SliderPage_SetPageSize, SliderWidgetsPage::OnButtonSetPageSize) EVT_BUTTON(SliderPage_SetTickFreq, SliderWidgetsPage::OnButtonSetTickFreq) @@ -199,12 +216,14 @@ wxBEGIN_EVENT_TABLE(SliderWidgetsPage, WidgetsPage) EVT_UPDATE_UI(SliderPage_SetValue, SliderWidgetsPage::OnUpdateUIValueButton) EVT_UPDATE_UI(SliderPage_SetMinAndMax, SliderWidgetsPage::OnUpdateUIMinMaxButton) + EVT_UPDATE_UI(SliderPage_SetRange, SliderWidgetsPage::OnUpdateUIRangeButton) EVT_UPDATE_UI(SliderPage_SetLineSize, SliderWidgetsPage::OnUpdateUILineSize) EVT_UPDATE_UI(SliderPage_SetPageSize, SliderWidgetsPage::OnUpdateUIPageSize) EVT_UPDATE_UI(SliderPage_SetTickFreq, SliderWidgetsPage::OnUpdateUITickFreq) EVT_UPDATE_UI(SliderPage_SetThumbLen, SliderWidgetsPage::OnUpdateUIThumbLen) EVT_UPDATE_UI(SliderPage_RadioSides, SliderWidgetsPage::OnUpdateUIRadioSides) EVT_UPDATE_UI(SliderPage_BothSides, SliderWidgetsPage::OnUpdateUIBothSides) + EVT_UPDATE_UI(SliderPage_SelectRange, SliderWidgetsPage::OnUpdateUISelectRange) EVT_UPDATE_UI(SliderPage_Reset, SliderWidgetsPage::OnUpdateUIResetButton) @@ -235,12 +254,15 @@ SliderWidgetsPage::SliderWidgetsPage(WidgetsBookCtrl *book, // init everything m_min = 0; m_max = 100; + m_rangeMin = 20; + m_rangeMax = 80; m_chkInverse = m_chkTicks = m_chkMinMaxLabels = m_chkValueLabel = - m_chkBothSides = (wxCheckBox *)NULL; + m_chkBothSides = + m_chkSelectRange =(wxCheckBox *)NULL; m_radioSides = (wxRadioBox *)NULL; @@ -275,8 +297,11 @@ void SliderWidgetsPage::CreateContent() sizerLeft->Add(m_radioSides, wxSizerFlags().Expand().Border()); m_chkBothSides = CreateCheckBoxAndAddToSizer (sizerLeft, "&Both sides", SliderPage_BothSides); + m_chkSelectRange = CreateCheckBoxAndAddToSizer + (sizerLeft, "&Selection range", SliderPage_SelectRange); #if wxUSE_TOOLTIPS m_chkBothSides->SetToolTip("\"Both sides\" is only supported \nin Universal"); + m_chkSelectRange->SetToolTip("\"Select range\" is only supported \nin wxMSW"); #endif // wxUSE_TOOLTIPS sizerLeft->AddSpacer(5); @@ -315,6 +340,19 @@ void SliderWidgetsPage::CreateContent() sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); + sizerRow = CreateSizerWithTextAndButton(SliderPage_SetRange, + "&Selection", + SliderPage_RangeMinText, + &m_textRangeMin); + + m_textRangeMax = new wxTextCtrl(this, SliderPage_RangeMaxText, wxEmptyString); + sizerRow->Add(m_textRangeMax, wxSizerFlags(1).CentreVertical().Border(wxLEFT)); + + m_textRangeMin->SetValue( wxString::Format("%d", m_rangeMin) ); + m_textRangeMax->SetValue( wxString::Format("%d", m_rangeMax) ); + + sizerMiddle->Add(sizerRow, wxSizerFlags().Expand().Border()); + sizerRow = CreateSizerWithTextAndButton(SliderPage_SetLineSize, "Li&ne size", SliderPage_LineSizeText, @@ -375,6 +413,7 @@ void SliderWidgetsPage::Reset() m_chkValueLabel->SetValue(true); m_chkMinMaxLabels->SetValue(true); m_chkBothSides->SetValue(false); + m_chkSelectRange->SetValue(false); m_radioSides->SetSelection(SliderTicks_None); } @@ -437,6 +476,11 @@ void SliderWidgetsPage::CreateSlider() flags |= wxSL_BOTH; } + if ( m_chkSelectRange->GetValue() ) + { + flags |= wxSL_SELRANGE; + } + int val = m_min; if ( m_slider ) { @@ -483,6 +527,11 @@ void SliderWidgetsPage::CreateSlider() DoSetTickFreq(); } + if ( m_chkSelectRange->GetValue() ) + { + DoSetSelectionRange(); + } + Layout(); } @@ -556,6 +605,31 @@ void SliderWidgetsPage::DoSetThumbLen() Layout(); } +void SliderWidgetsPage::DoSetSelectionRange() +{ + long minNew, + maxNew = 0; // init to suppress compiler warning + if ( !m_textRangeMin->GetValue().ToLong(&minNew) || + !m_textRangeMax->GetValue().ToLong(&maxNew) || + minNew >= maxNew || minNew < m_min || maxNew > m_max ) + { + wxLogWarning("Invalid selection range for the slider."); + + return; + } + + m_rangeMin = minNew; + m_rangeMax = maxNew; + + m_slider->SetSelection(m_rangeMin, m_rangeMax); + + if ( m_slider->GetSelStart() != m_rangeMin || + m_slider->GetSelEnd() != m_rangeMax ) + { + wxLogWarning("Invalid selection range in slider."); + } +} + // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- @@ -612,6 +686,11 @@ void SliderWidgetsPage::OnButtonSetMinAndMax(wxCommandEvent& WXUNUSED(event)) } } +void SliderWidgetsPage::OnButtonSetRange(wxCommandEvent& WXUNUSED(event)) +{ + DoSetSelectionRange(); +} + void SliderWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event)) { long val; @@ -667,6 +746,17 @@ void SliderWidgetsPage::OnUpdateUIMinMaxButton(wxUpdateUIEvent& event) mn < mx); } +void SliderWidgetsPage::OnUpdateUIRangeButton(wxUpdateUIEvent& event) +{ + long mn, mx; + event.Enable( m_chkSelectRange->GetValue() && + m_textRangeMin->GetValue().ToLong(&mn) && + m_textRangeMax->GetValue().ToLong(&mx) && + mn < mx && + mn >= m_min && mx <= m_max ); + +} + void SliderWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event) { event.Enable( m_chkInverse->GetValue() || @@ -674,6 +764,7 @@ void SliderWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event) !m_chkValueLabel->GetValue() || !m_chkMinMaxLabels->GetValue() || m_chkBothSides->GetValue() || + m_chkSelectRange->GetValue() || m_radioSides->GetSelection() != SliderTicks_None ); } @@ -701,6 +792,15 @@ void SliderWidgetsPage::OnUpdateUIBothSides(wxUpdateUIEvent& event) #endif // defined(__WXMSW__) || defined(__WXUNIVERSAL__) } +void SliderWidgetsPage::OnUpdateUISelectRange(wxUpdateUIEvent& event) +{ +#if defined(__WXMSW__) + event.Enable( true ); +#else + event.Enable( false ); +#endif // defined(__WXMSW__) +} + void SliderWidgetsPage::OnSlider(wxScrollEvent& event) { wxASSERT_MSG( event.GetInt() == m_slider->GetValue(),