diff --git a/include/wx/private/rescale.h b/include/wx/private/rescale.h index e4266921c0..d5a8b81831 100644 --- a/include/wx/private/rescale.h +++ b/include/wx/private/rescale.h @@ -29,8 +29,9 @@ // order to allow calling To() on it. // // Another complication is that we want this to work for both wxSize and -// wxPoint, so wxRescaleCoord() is a overloaded and the helper classes are -// templates, with their template parameter being either one or the other. +// wxPoint, as well as for just plain coordinate values, so wxRescaleCoord() is +// an overloaded function and the helper classes are templates, with their +// template parameter being either wxSize, wxPoint or int. namespace wxPrivate { @@ -72,6 +73,31 @@ private: friend wxRescaleCoordWithValue; }; +// Specialization for just a single value. +template <> +class wxRescaleCoordWithFrom +{ +public: + int To(wxSize newScale) const + { + return m_value == wxDefaultCoord + ? wxDefaultCoord + : wxMulDivInt32(m_value, newScale.x, m_oldScale.x); + } + +private: + wxRescaleCoordWithFrom(int value, wxSize oldScale) + : m_value(value), m_oldScale(oldScale) + { + } + + const int m_value; + const wxSize m_oldScale; + + // Only it can create objects of this class. + friend wxRescaleCoordWithValue; +}; + template class wxRescaleCoordWithValue { @@ -97,6 +123,11 @@ private: } // namespace wxPrivate +inline wxPrivate::wxRescaleCoordWithValue wxRescaleCoord(int coord) +{ + return wxPrivate::wxRescaleCoordWithValue(coord); +} + inline wxPrivate::wxRescaleCoordWithValue wxRescaleCoord(wxSize sz) { return wxPrivate::wxRescaleCoordWithValue(sz); diff --git a/src/msw/window.cpp b/src/msw/window.cpp index e869d58539..cba433d6be 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -82,6 +82,7 @@ #include "wx/msw/dcclient.h" #include "wx/msw/seh.h" #include "wx/private/textmeasure.h" +#include "wx/private/rescale.h" #if wxUSE_TOOLTIPS #include "wx/tooltip.h" @@ -4891,20 +4892,9 @@ void wxWindowMSW::MSWUpdateFontOnDPIChange(const wxSize& newDPI) } } -// Helper function to update the given coordinate by the scaling factor if it -// is set, i.e. different from wxDefaultCoord. -static void ScaleCoordIfSet(int& coord, float scaleFactor) -{ - if ( coord != wxDefaultCoord ) - { - const float coordScaled = coord * scaleFactor; - coord = int(scaleFactor > 1 ? std::ceil(coordScaled) : std::floor(coordScaled)); - } -} - // Called from MSWUpdateonDPIChange() to recursively update the window // sizer and any child sizers and spacers. -static void UpdateSizerOnDPIChange(wxSizer* sizer, float scaleFactor) +static void UpdateSizerOnDPIChange(wxSizer* sizer, wxSize oldDPI, wxSize newDPI) { if ( !sizer ) { @@ -4919,27 +4909,25 @@ static void UpdateSizerOnDPIChange(wxSizer* sizer, float scaleFactor) wxSizerItem* sizerItem = node->GetData(); int border = sizerItem->GetBorder(); - ScaleCoordIfSet(border, scaleFactor); + border = wxRescaleCoord(border).From(oldDPI).To(newDPI); sizerItem->SetBorder(border); // only scale sizers and spacers, not windows if ( sizerItem->IsSizer() || sizerItem->IsSpacer() ) { wxSize min = sizerItem->GetMinSize(); - ScaleCoordIfSet(min.x, scaleFactor); - ScaleCoordIfSet(min.y, scaleFactor); + min = wxRescaleCoord(min).From(oldDPI).To(newDPI); sizerItem->SetMinSize(min); if ( sizerItem->IsSpacer() ) { wxSize size = sizerItem->GetSize(); - ScaleCoordIfSet(size.x, scaleFactor); - ScaleCoordIfSet(size.y, scaleFactor); + size = wxRescaleCoord(size).From(oldDPI).To(newDPI); sizerItem->SetDimension(wxDefaultPosition, size); } // Update any child sizers if this is a sizer - UpdateSizerOnDPIChange(sizerItem->GetSizer(), scaleFactor); + UpdateSizerOnDPIChange(sizerItem->GetSizer(), oldDPI, newDPI); } } } @@ -4948,12 +4936,10 @@ void wxWindowMSW::MSWUpdateOnDPIChange(const wxSize& oldDPI, const wxSize& newDPI) { // update min and max size if necessary - const float scaleFactor = (float)newDPI.y / oldDPI.y; - - ScaleCoordIfSet(m_minHeight, scaleFactor); - ScaleCoordIfSet(m_minWidth, scaleFactor); - ScaleCoordIfSet(m_maxHeight, scaleFactor); - ScaleCoordIfSet(m_maxWidth, scaleFactor); + m_minHeight = wxRescaleCoord(m_minHeight).From(oldDPI).To(newDPI); + m_minWidth = wxRescaleCoord(m_minWidth).From(oldDPI).To(newDPI); + m_maxHeight = wxRescaleCoord(m_maxHeight).From(oldDPI).To(newDPI); + m_maxWidth = wxRescaleCoord(m_maxWidth).From(oldDPI).To(newDPI); InvalidateBestSize(); @@ -4961,7 +4947,7 @@ wxWindowMSW::MSWUpdateOnDPIChange(const wxSize& oldDPI, const wxSize& newDPI) MSWUpdateFontOnDPIChange(newDPI); // update sizers - UpdateSizerOnDPIChange(GetSizer(), scaleFactor); + UpdateSizerOnDPIChange(GetSizer(), oldDPI, newDPI); // update children for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();