]> git.saurik.com Git - wxWidgets.git/commitdiff
Improve positioning of wxSlider min/max labels in wxMSW.
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 28 Oct 2010 13:52:50 +0000 (13:52 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 28 Oct 2010 13:52:50 +0000 (13:52 +0000)
Put the min/max labels on the sides or a horizontal slider or above/below a
vertical one to make them visually more distinct from the current value label.

See #11427.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65941 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/slider.h
src/msw/slider.cpp

index a692c9905cc7ae9468170d15b9b1506efd8aece7..e84a0e146a09b6240d495a35cf06320cccf67bcb 100644 (file)
@@ -106,8 +106,8 @@ protected:
     // get the boundig box for the slider and possible labels
     wxRect GetBoundingBox() const;
 
     // get the boundig box for the slider and possible labels
     wxRect GetBoundingBox() const;
 
-    // get the height and, if the pointer is not NULL, width of our labels
-    int GetLabelsSize(int *width = NULL) const;
+    // Get the height and, if the pointers are non NULL, widths of both labels.
+    int GetLabelsSize(int *widthMin = NULL, int *widthMax = NULL) const;
 
 
     // overridden base class virtuals
 
 
     // overridden base class virtuals
@@ -124,6 +124,8 @@ protected:
     int           m_pageSize;
     int           m_lineSize;
     int           m_tickFreq;
     int           m_pageSize;
     int           m_lineSize;
     int           m_tickFreq;
+    int           m_minLabelWidth;
+    int           m_maxLabelWidth;
 
     // flag needed to detect whether we're getting THUMBRELEASE event because
     // of dragging the thumb or scrolling the mouse wheel
 
     // flag needed to detect whether we're getting THUMBRELEASE event because
     // of dragging the thumb or scrolling the mouse wheel
index 62643ec98655671311ee14c5ff179cb6926ae1b0..4d08687349438ff6635d975f4ce31475440b750b 100644 (file)
@@ -40,6 +40,9 @@
 // constants
 // ----------------------------------------------------------------------------
 
 // constants
 // ----------------------------------------------------------------------------
 
+namespace
+{
+
 // indices of labels in wxSlider::m_labels
 enum
 {
 // indices of labels in wxSlider::m_labels
 enum
 {
@@ -49,8 +52,16 @@ enum
     SliderLabel_Last
 };
 
     SliderLabel_Last
 };
 
-// the gap between the slider and the labels, in pixels
-static const int HGAP = 5;
+// the gaps between the slider and the labels, in pixels
+const int HGAP = 5;
+const int VGAP = 4;
+// the width of the borders including white space
+const int BORDERPAD = 8;
+// these 2 values are arbitrary:
+const int THUMB = 24;
+const int TICK = 8;
+
+} // anonymous namespace
 
 // ----------------------------------------------------------------------------
 // XTI
 
 // ----------------------------------------------------------------------------
 // XTI
@@ -90,7 +101,6 @@ wxBEGIN_FLAGS( wxSliderStyle )
     wxFLAGS_MEMBER(wxSL_HORIZONTAL)
     wxFLAGS_MEMBER(wxSL_VERTICAL)
     wxFLAGS_MEMBER(wxSL_AUTOTICKS)
     wxFLAGS_MEMBER(wxSL_HORIZONTAL)
     wxFLAGS_MEMBER(wxSL_VERTICAL)
     wxFLAGS_MEMBER(wxSL_AUTOTICKS)
-    wxFLAGS_MEMBER(wxSL_LABELS)
     wxFLAGS_MEMBER(wxSL_LEFT)
     wxFLAGS_MEMBER(wxSL_TOP)
     wxFLAGS_MEMBER(wxSL_RIGHT)
     wxFLAGS_MEMBER(wxSL_LEFT)
     wxFLAGS_MEMBER(wxSL_TOP)
     wxFLAGS_MEMBER(wxSL_RIGHT)
@@ -98,6 +108,9 @@ wxBEGIN_FLAGS( wxSliderStyle )
     wxFLAGS_MEMBER(wxSL_BOTH)
     wxFLAGS_MEMBER(wxSL_SELRANGE)
     wxFLAGS_MEMBER(wxSL_INVERSE)
     wxFLAGS_MEMBER(wxSL_BOTH)
     wxFLAGS_MEMBER(wxSL_SELRANGE)
     wxFLAGS_MEMBER(wxSL_INVERSE)
+    wxFLAGS_MEMBER(wxSL_MIN_MAX_LABELS)
+    wxFLAGS_MEMBER(wxSL_VALUE_LABEL)
+    wxFLAGS_MEMBER(wxSL_LABELS)
 
 wxEND_FLAGS( wxSliderStyle )
 
 
 wxEND_FLAGS( wxSliderStyle )
 
@@ -145,18 +158,20 @@ void wxSlider::Init()
     m_isDragging = false;
 }
 
     m_isDragging = false;
 }
 
-bool
-wxSlider::Create(wxWindow *parent,
-                 wxWindowID id,
-                 int value,
-                 int minValue,
-                 int maxValue,
-                 const wxPoint& pos,
-                 const wxSize& size,
-                 long style,
-                 const wxValidator& validator,
-                 const wxString& name)
+bool wxSlider::Create(wxWindow *parent,
+                      wxWindowID id,
+                      int value,
+                      int minValue,
+                      int maxValue,
+                      const wxPoint& pos,
+                      const wxSize& size,
+                      long style,
+                      const wxValidator& validator,
+                      const wxString& name)
 {
 {
+    wxCHECK_MSG( minValue < maxValue, false,
+        wxT("Slider minimum must be strictly less than the maximum.") );
+
     // our styles are redundant: wxSL_LEFT/RIGHT imply wxSL_VERTICAL and
     // wxSL_TOP/BOTTOM imply wxSL_HORIZONTAL, but for backwards compatibility
     // reasons we can't really change it, instead try to infer the orientation
     // our styles are redundant: wxSL_LEFT/RIGHT imply wxSL_VERTICAL and
     // wxSL_TOP/BOTTOM imply wxSL_HORIZONTAL, but for backwards compatibility
     // reasons we can't really change it, instead try to infer the orientation
@@ -224,7 +239,6 @@ wxSlider::Create(wxWindow *parent,
 
             m_labels->Set(n, wnd, lblid);
         }
 
             m_labels->Set(n, wnd, lblid);
         }
-
         m_labels->SetFont(GetFont());
     }
 
         m_labels->SetFont(GetFont());
     }
 
@@ -425,25 +439,23 @@ void wxSlider::DoGetPosition(int *x, int *y) const
         *y = rect.y;
 }
 
         *y = rect.y;
 }
 
-int wxSlider::GetLabelsSize(int *width) const
+int wxSlider::GetLabelsSize(int *widthMin, int *widthMax) const
 {
 {
-    int cy;
-
-    if ( width )
-    {
-        // find the max label width
-        int wLabelMin, wLabelMax;
-        GetTextExtent(Format(m_rangeMin), &wLabelMin, &cy);
-        GetTextExtent(Format(m_rangeMax), &wLabelMax, &cy);
-
-        *width = wxMax(wLabelMin, wLabelMax);
-    }
-    else
+    if ( widthMin && widthMax )
     {
     {
-        cy = GetCharHeight();
+        if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+        {
+            *widthMin = GetTextExtent(Format(m_rangeMin)).x;
+            *widthMax = GetTextExtent(Format(m_rangeMax)).x;
+        }
+        else
+        {
+            *widthMin =
+            *widthMax = 0;
+        }
     }
 
     }
 
-    return EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
+    return HasFlag(wxSL_LABELS) ? GetCharHeight() : 0;
 }
 
 void wxSlider::DoMoveWindow(int x, int y, int width, int height)
 }
 
 void wxSlider::DoMoveWindow(int x, int y, int width, int height)
@@ -456,81 +468,196 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height)
         return;
     }
 
         return;
     }
 
+    const int labelHeight = GetLabelsSize(&m_minLabelWidth, &m_maxLabelWidth);
+    const int maxLabelWidth = wxMax(m_minLabelWidth, m_maxLabelWidth);
+
+    int labelOffset =  0;
+    int tickOffset = 0;
+    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,
     // would return a wrong result and wrong size would be cached internally
     if ( HasFlag(wxSL_VERTICAL) )
     {
     // be careful to position the slider itself after moving the labels as
     // otherwise our GetBoundingBox(), which is called from WM_SIZE handler,
     // would return a wrong result and wrong size would be cached internally
     if ( HasFlag(wxSL_VERTICAL) )
     {
-        int wLabel;
-        int hLabel = GetLabelsSize(&wLabel);
-
-        int xLabel = HasFlag(wxSL_LEFT) ? x + width - wLabel : x;
-
-        // position all labels: min at the top, value in the middle and max at
-        // the bottom
-        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
-                     xLabel, y, wLabel, hLabel);
-
-        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
-                     xLabel, y + (height - hLabel)/2, wLabel, hLabel);
-
-        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
-                      xLabel, y + height - hLabel, wLabel, hLabel);
+        int holdTopWidth;
+        int holdTopX;
+        int holdBottomWidth;
+        int holdBottomX;
+        int xLabel = (wxMax((THUMB + (BORDERPAD * 2)), maxLabelWidth) / 2) -
+            (maxLabelWidth / 2) + x;
+        if ( HasFlag(wxSL_LEFT) )
+        {
+            if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+            {
+                holdTopX = xLabel;
+                holdTopWidth = m_minLabelWidth;
+                holdBottomX = xLabel - ((m_maxLabelWidth - m_minLabelWidth) / 2);
+                holdBottomWidth = m_maxLabelWidth;
+                if ( HasFlag(wxSL_INVERSE) )
+                {
+                    wxSwap(holdTopWidth, holdBottomWidth);
+                    wxSwap(holdTopX, holdBottomX);
+                }
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+                    holdTopX,
+                    y,
+                    holdTopWidth, labelHeight);
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+                    holdBottomX,
+                    y + height - labelHeight,
+                    holdBottomWidth, labelHeight);
+            }
+            if ( HasFlag(wxSL_VALUE_LABEL) )
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+                    x + THUMB + tickOffset + HGAP,
+                    y + (height - labelHeight)/2,
+                    maxLabelWidth, labelHeight);
+        }
+        else // wxSL_RIGHT
+        {
+            if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+            {
+                holdTopX = xLabel + maxLabelWidth + ((m_maxLabelWidth - m_minLabelWidth) / 2);
+                holdTopWidth = m_minLabelWidth;
+                holdBottomX = xLabel + maxLabelWidth;
+                holdBottomWidth = m_maxLabelWidth;
+                if ( HasFlag(wxSL_INVERSE) )
+                {
+                    wxSwap(holdTopWidth, holdBottomWidth);
+                    wxSwap(holdTopX, holdBottomX);
+                }
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+                    holdTopX,
+                    y,
+                    holdTopWidth, labelHeight);
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+                    holdBottomX,
+                    y + height - labelHeight,
+                    holdBottomWidth, labelHeight);
+            }
+            if ( HasFlag(wxSL_VALUE_LABEL) )
+                labelOffset = maxLabelWidth + HGAP;
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+                x,
+                y + (height - labelHeight)/2,
+                maxLabelWidth, labelHeight);
+        }
 
         // position the slider itself along the left/right edge
 
         // position the slider itself along the left/right edge
-        wxSliderBase::DoMoveWindow(HasFlag(wxSL_LEFT) ? x : x + wLabel + HGAP,
-                                   y + hLabel/2,
-                                   width - wLabel - HGAP,
-                                   height - hLabel);
+        wxSliderBase::DoMoveWindow(
+            x + labelOffset,
+            y + labelHeight,
+            THUMB + tickOffset + HGAP,
+            height - (labelHeight * 2));
     }
     else // horizontal
     {
     }
     else // horizontal
     {
-        int wLabel;
-        int hLabel = GetLabelsSize(&wLabel);
-
-        int yLabel = HasFlag(wxSL_TOP) ? y + height - hLabel : y;
-
-        // position all labels: min on the left, value in the middle and max to
-        // the right
-        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
-                      x, yLabel, wLabel, hLabel);
-
-        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
-                      x + (width - wLabel)/2, yLabel, wLabel, hLabel);
-
-        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
-                      x + width - wLabel, yLabel, wLabel, hLabel);
+        int holdLeftWidth;
+        int holdLeftX;
+        int holdRightWidth;
+        int holdRightX;
+        int yLabelMinMax =
+            (y + ((THUMB + tickOffset) / 2)) - (labelHeight / 2);
+        int xLabelValue =
+            x + m_minLabelWidth +
+            ((width  - (m_minLabelWidth + m_maxLabelWidth)) / 2) -
+            (m_maxLabelWidth / 2);
+
+        if ( HasFlag(wxSL_BOTTOM) )
+        {
+            if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+            {
+                holdLeftX = x;
+                holdLeftWidth = m_minLabelWidth;
+                holdRightX = x + width - m_maxLabelWidth;
+                holdRightWidth = m_maxLabelWidth;
+                if ( HasFlag(wxSL_INVERSE) )
+                {
+                    wxSwap(holdLeftWidth, holdRightWidth);
+                    wxSwap(holdLeftX, holdRightX);
+                }
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+                    holdLeftX,
+                    yLabelMinMax,
+                    holdLeftWidth, labelHeight);
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+                    holdRightX,
+                    yLabelMinMax,
+                    holdRightWidth, labelHeight);
+            }
+            if ( HasFlag(wxSL_VALUE_LABEL) )
+            {
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+                    xLabelValue,
+                    y - labelHeight,
+                    maxLabelWidth, labelHeight);
+            }
+        }
+        else // wxSL_TOP
+        {
+            if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+            {
+                holdLeftX = x;
+                holdLeftWidth = m_minLabelWidth;
+                holdRightX = x + width - m_maxLabelWidth;
+                holdRightWidth = m_maxLabelWidth;
+                if ( HasFlag(wxSL_INVERSE) )
+                {
+                    wxSwap(holdLeftWidth, holdRightWidth);
+                    wxSwap(holdLeftX, holdRightX);
+                }
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+                    holdLeftX,
+                    yLabelMinMax,
+                    holdLeftWidth, labelHeight);
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+                    holdRightX,
+                    yLabelMinMax,
+                    holdRightWidth, labelHeight);
+            }
+            if ( HasFlag(wxSL_VALUE_LABEL) )
+                DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+                    xLabelValue,
+                    y + THUMB + tickOffset,
+                    maxLabelWidth, labelHeight);
+        }
 
         // position the slider itself along the top/bottom edge
 
         // position the slider itself along the top/bottom edge
-        wxSliderBase::DoMoveWindow(x,
-                                   HasFlag(wxSL_TOP) ? y : y + hLabel,
-                                   width,
-                                   height - hLabel);
+        if ( HasFlag(wxSL_MIN_MAX_LABELS) || HasFlag(wxSL_VALUE_LABEL) )
+            labelOffset = labelHeight;
+        wxSliderBase::DoMoveWindow(
+            x + m_minLabelWidth + VGAP,
+            y,
+            width  - (m_minLabelWidth + m_maxLabelWidth  + (VGAP*2)),
+            THUMB + tickOffset);
     }
 }
 
 wxSize wxSlider::DoGetBestSize() const
 {
     }
 }
 
 wxSize wxSlider::DoGetBestSize() const
 {
-    // these values are arbitrary
+    // this value is arbitrary:
     static const int length = 100;
     static const int length = 100;
-    static const int thumb = 24;
-    static const int ticks = 8;
 
     int *width;
     wxSize size;
     if ( HasFlag(wxSL_VERTICAL) )
     {
 
     int *width;
     wxSize size;
     if ( HasFlag(wxSL_VERTICAL) )
     {
-        size.x = thumb;
+        size.x = THUMB;
         size.y = length;
         width = &size.x;
 
         if ( m_labels )
         {
         size.y = length;
         width = &size.x;
 
         if ( m_labels )
         {
-            int wLabel;
-            int hLabel = GetLabelsSize(&wLabel);
+            int widthMin,
+                widthMax;
+            int hLabel = GetLabelsSize(&widthMin, &widthMax);
 
             // account for the labels
 
             // account for the labels
-            size.x += HGAP + wLabel;
+            size.x += HGAP + wxMax(widthMin, widthMax);
 
             // labels are indented relative to the slider itself
             size.y += hLabel;
 
             // labels are indented relative to the slider itself
             size.y += hLabel;
@@ -539,26 +666,28 @@ wxSize wxSlider::DoGetBestSize() const
     else // horizontal
     {
         size.x = length;
     else // horizontal
     {
         size.x = length;
-        size.y = thumb;
+        size.y = THUMB;
         width = &size.y;
 
         if ( m_labels )
         {
             // labels add extra height
         width = &size.y;
 
         if ( m_labels )
         {
             // labels add extra height
-            size.y += GetLabelsSize();
+            int labelSize = GetLabelsSize();
+            if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+                size.y += labelSize;
+            if ( HasFlag(wxSL_VALUE_LABEL) )
+                size.y += labelSize*2.75;
         }
     }
 
     // need extra space to show ticks
     if ( HasFlag(wxSL_TICKS) )
     {
         }
     }
 
     // need extra space to show ticks
     if ( HasFlag(wxSL_TICKS) )
     {
-        *width += ticks;
-
+        *width += TICK;
         // and maybe twice as much if we show them on both sides
         if ( HasFlag(wxSL_BOTH) )
         // and maybe twice as much if we show them on both sides
         if ( HasFlag(wxSL_BOTH) )
-            *width += ticks;
+            *width += TICK;
     }
     }
-
     return size;
 }
 
     return size;
 }
 
@@ -575,7 +704,7 @@ void wxSlider::SetValue(int value)
 {
     ::SendMessage(GetHwnd(), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)ValueInvertOrNot(value));
 
 {
     ::SendMessage(GetHwnd(), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)ValueInvertOrNot(value));
 
-    if ( HasFlag(wxSL_VALUE_LABEL) )
+    if ( m_labels )
     {
         ::SetWindowText((*m_labels)[SliderLabel_Value], Format(value).wx_str());
     }
     {
         ::SetWindowText((*m_labels)[SliderLabel_Value], Format(value).wx_str());
     }
@@ -589,7 +718,7 @@ void wxSlider::SetRange(int minValue, int maxValue)
     ::SendMessage(GetHwnd(), TBM_SETRANGEMIN, TRUE, m_rangeMin);
     ::SendMessage(GetHwnd(), TBM_SETRANGEMAX, TRUE, m_rangeMax);
 
     ::SendMessage(GetHwnd(), TBM_SETRANGEMIN, TRUE, m_rangeMin);
     ::SendMessage(GetHwnd(), TBM_SETRANGEMAX, TRUE, m_rangeMax);
 
-    if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+    if ( m_labels )
     {
         ::SetWindowText((*m_labels)[SliderLabel_Min],
                         Format(ValueInvertOrNot(m_rangeMin)).wx_str());
     {
         ::SetWindowText((*m_labels)[SliderLabel_Min],
                         Format(ValueInvertOrNot(m_rangeMin)).wx_str());