]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/slider95.cpp
Implement wxChoice::Insert.
[wxWidgets.git] / src / msw / slider95.cpp
index 78175544135780c082d5d2fe28900b60191c5d42..193017c84ab3678af047944e2fd083aca2703b74 100644 (file)
@@ -1,6 +1,6 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        msw/slider95.cpp
-// Purpose:     wxSlider95, using the Win95 trackbar control
+// Name:        msw/slider.cpp
+// Purpose:     wxSlider, using the Win95 (and later) trackbar control
 // Author:      Julian Smart
 // Modified by:
 // Created:     04/01/98
 // declarations
 // ============================================================================
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-#pragma implementation "slider95.h"
-#endif
-
 // ----------------------------------------------------------------------------
 // headers
 // ----------------------------------------------------------------------------
@@ -46,7 +42,7 @@
 // constants
 // ----------------------------------------------------------------------------
 
-// indices of labels in wxSlider95::m_labels
+// indices of labels in wxSlider::m_labels
 enum
 {
     SliderLabel_Min,
@@ -107,10 +103,10 @@ wxBEGIN_FLAGS( wxSliderStyle )
 
 wxEND_FLAGS( wxSliderStyle )
 
-IMPLEMENT_DYNAMIC_CLASS_XTI(wxSlider95, wxControl,"wx/scrolbar.h")
+IMPLEMENT_DYNAMIC_CLASS_XTI(wxSlider, wxControl,"wx/scrolbar.h")
 
-wxBEGIN_PROPERTIES_TABLE(wxSlider95)
-    wxEVENT_RANGE_PROPERTY( Scroll , wxEVT_SCROLL_TOP , wxEVT_SCROLL_ENDSCROLL , wxScrollEvent )
+wxBEGIN_PROPERTIES_TABLE(wxSlider)
+    wxEVENT_RANGE_PROPERTY( Scroll , wxEVT_SCROLL_TOP , wxEVT_SCROLL_CHANGED , wxScrollEvent )
     wxEVENT_PROPERTY( Updated , wxEVT_COMMAND_SLIDER_UPDATED , wxCommandEvent )
 
     wxPROPERTY( Value , int , SetValue, GetValue , 0, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
@@ -122,23 +118,23 @@ wxBEGIN_PROPERTIES_TABLE(wxSlider95)
     wxPROPERTY_FLAGS( WindowStyle , wxSliderStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
 wxEND_PROPERTIES_TABLE()
 
-wxBEGIN_HANDLERS_TABLE(wxSlider95)
+wxBEGIN_HANDLERS_TABLE(wxSlider)
 wxEND_HANDLERS_TABLE()
 
-wxCONSTRUCTOR_8( wxSlider95 , wxWindow* , Parent , wxWindowID , Id , int , Value , int , Minimum , int , Maximum , wxPoint , Position , wxSize , Size , long , WindowStyle )
+wxCONSTRUCTOR_8( wxSlider , wxWindow* , Parent , wxWindowID , Id , int , Value , int , Minimum , int , Maximum , wxPoint , Position , wxSize , Size , long , WindowStyle )
 #else
-IMPLEMENT_DYNAMIC_CLASS(wxSlider95, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
 #endif
 
 // ============================================================================
-// wxSlider95 implementation
+// wxSlider implementation
 // ============================================================================
 
 // ----------------------------------------------------------------------------
 // construction
 // ----------------------------------------------------------------------------
 
-void wxSlider95::Init()
+void wxSlider::Init()
 {
     m_labels = NULL;
 
@@ -147,20 +143,51 @@ void wxSlider95::Init()
     m_rangeMax = 0;
     m_rangeMin = 0;
     m_tickFreq = 0;
+
+    m_isDragging = false;
 }
 
 bool
-wxSlider95::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)
-{
+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)
+{
+    // 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
+    // from the flags given to us here
+    switch ( style & (wxSL_LEFT | wxSL_RIGHT | wxSL_TOP | wxSL_BOTTOM) )
+    {
+        case wxSL_LEFT:
+        case wxSL_RIGHT:
+            style |= wxSL_VERTICAL;
+            break;
+
+        case wxSL_TOP:
+        case wxSL_BOTTOM:
+            style |= wxSL_HORIZONTAL;
+            break;
+
+        case 0:
+            // no specific direction, do we have at least the orientation?
+            if ( !(style & (wxSL_HORIZONTAL | wxSL_VERTICAL)) )
+            {
+                // no, choose default
+                style |= wxSL_BOTTOM | wxSL_HORIZONTAL;
+            }
+    };
+
+    wxASSERT_MSG( !(style & wxSL_VERTICAL) || !(style & wxSL_HORIZONTAL),
+                    _T("incompatible slider direction and orientation") );
+
+
     // initialize everything
     if ( !CreateControl(parent, id, pos, size, style, validator, name) )
         return false;
@@ -219,28 +246,33 @@ wxSlider95::Create(wxWindow *parent,
     return true;
 }
 
-WXDWORD wxSlider95::MSWGetStyle(long style, WXDWORD *exstyle) const
+WXDWORD wxSlider::MSWGetStyle(long style, WXDWORD *exstyle) const
 {
     WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle);
 
-    // TBS_HORZ is 0 anyhow, but do mention it explicitly for clarity
+    // TBS_HORZ, TBS_RIGHT and TBS_BOTTOM are 0 but do include them for clarity
     msStyle |= style & wxSL_VERTICAL ? TBS_VERT : TBS_HORZ;
 
-    if ( style & wxSL_AUTOTICKS )
-        msStyle |= TBS_AUTOTICKS ;
-
-    // again, TBS_RIGHT is 0 but do include it for clarity
-    if ( style & wxSL_LEFT )
-        msStyle |= TBS_LEFT;
-    else if ( style & wxSL_RIGHT )
-        msStyle |= TBS_RIGHT;
-    else if ( style & wxSL_TOP )
-        msStyle |= TBS_TOP;
-    else if ( style & wxSL_BOTTOM )
-        msStyle |= TBS_BOTTOM;
-    else if ( style & wxSL_BOTH )
+    if ( style & wxSL_BOTH )
+    {
+        // this fully specifies the style combined with TBS_VERT/HORZ above
         msStyle |= TBS_BOTH;
-    else if ( !(style & wxSL_AUTOTICKS) )
+    }
+    else // choose one direction
+    {
+        if ( style & wxSL_LEFT )
+            msStyle |= TBS_LEFT;
+        else if ( style & wxSL_RIGHT )
+            msStyle |= TBS_RIGHT;
+        else if ( style & wxSL_TOP )
+            msStyle |= TBS_TOP;
+        else if ( style & wxSL_BOTTOM )
+            msStyle |= TBS_BOTTOM;
+    }
+
+    if ( style & wxSL_AUTOTICKS )
+        msStyle |= TBS_AUTOTICKS;
+    else
         msStyle |= TBS_NOTICKS;
 
     if ( style & wxSL_SELRANGE )
@@ -249,7 +281,7 @@ WXDWORD wxSlider95::MSWGetStyle(long style, WXDWORD *exstyle) const
     return msStyle;
 }
 
-wxSlider95::~wxSlider95()
+wxSlider::~wxSlider()
 {
     delete m_labels;
 }
@@ -258,10 +290,10 @@ wxSlider95::~wxSlider95()
 // event handling
 // ----------------------------------------------------------------------------
 
-bool wxSlider95::MSWOnScroll(int WXUNUSED(orientation),
-                             WXWORD wParam,
-                             WXWORD WXUNUSED(pos),
-                             WXHWND control)
+bool wxSlider::MSWOnScroll(int WXUNUSED(orientation),
+                           WXWORD wParam,
+                           WXWORD WXUNUSED(pos),
+                           WXHWND control)
 {
     wxEventType scrollEvent;
     switch ( wParam )
@@ -292,14 +324,29 @@ bool wxSlider95::MSWOnScroll(int WXUNUSED(orientation),
 
         case SB_THUMBTRACK:
             scrollEvent = wxEVT_SCROLL_THUMBTRACK;
+            m_isDragging = true;
             break;
 
         case SB_THUMBPOSITION:
-            scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
+            if ( m_isDragging )
+            {
+                scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
+                m_isDragging = false;
+            }
+            else
+            {
+                // this seems to only happen when the mouse wheel is used: in
+                // this case, as it might be unexpected to get THUMBRELEASE
+                // without preceding THUMBTRACKs, we don't generate it at all
+                // but generate CHANGED event because the control itself does
+                // not send us SB_ENDSCROLL for whatever reason when mouse
+                // wheel is used
+                scrollEvent = wxEVT_SCROLL_CHANGED;
+            }
             break;
 
         case SB_ENDSCROLL:
-            scrollEvent = wxEVT_SCROLL_ENDSCROLL;
+            scrollEvent = wxEVT_SCROLL_CHANGED;
             break;
 
         default:
@@ -307,7 +354,7 @@ bool wxSlider95::MSWOnScroll(int WXUNUSED(orientation),
             return false;
     }
 
-    int newPos = MSWInvertOrNot((int) ::SendMessage((HWND) control, TBM_GETPOS, 0, 0));
+    int newPos = ValueInvertOrNot((int) ::SendMessage((HWND) control, TBM_GETPOS, 0, 0));
     if ( (newPos < GetMin()) || (newPos > GetMax()) )
     {
         // out of range - but we did process it
@@ -328,7 +375,7 @@ bool wxSlider95::MSWOnScroll(int WXUNUSED(orientation),
     return GetEventHandler()->ProcessEvent( cevent );
 }
 
-void wxSlider95::Command (wxCommandEvent & event)
+void wxSlider::Command (wxCommandEvent & event)
 {
     SetValue (event.GetInt());
     ProcessCommand (event);
@@ -338,7 +385,7 @@ void wxSlider95::Command (wxCommandEvent & event)
 // geometry stuff
 // ----------------------------------------------------------------------------
 
-wxRect wxSlider95::GetBoundingBox() const
+wxRect wxSlider::GetBoundingBox() const
 {
     // take care not to call our own functions which would call us recursively
     int x, y, w, h;
@@ -356,7 +403,7 @@ wxRect wxSlider95::GetBoundingBox() const
     return rect;
 }
 
-void wxSlider95::DoGetSize(int *width, int *height) const
+void wxSlider::DoGetSize(int *width, int *height) const
 {
     wxRect rect = GetBoundingBox();
 
@@ -366,7 +413,7 @@ void wxSlider95::DoGetSize(int *width, int *height) const
         *height = rect.height;
 }
 
-void wxSlider95::DoGetPosition(int *x, int *y) const
+void wxSlider::DoGetPosition(int *x, int *y) const
 {
     wxRect rect = GetBoundingBox();
 
@@ -376,7 +423,7 @@ void wxSlider95::DoGetPosition(int *x, int *y) const
         *y = rect.y;
 }
 
-int wxSlider95::GetLabelsSize(int *width) const
+int wxSlider::GetLabelsSize(int *width) const
 {
     int cy;
 
@@ -397,7 +444,7 @@ int wxSlider95::GetLabelsSize(int *width) const
     return EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
 }
 
-void wxSlider95::DoMoveWindow(int x, int y, int width, int height)
+void wxSlider::DoMoveWindow(int x, int y, int width, int height)
 {
     // all complications below are because we need to position the labels,
     // without them everything is easy
@@ -419,22 +466,20 @@ void wxSlider95::DoMoveWindow(int x, int y, int width, int height)
 
         // position all labels: min at the top, value in the middle and max at
         // the bottom
-        ::MoveWindow((*m_labels)[SliderLabel_Min],
-                     xLabel, y, wLabel, hLabel, TRUE);
+        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+                     xLabel, y, wLabel, hLabel);
 
-        ::MoveWindow((*m_labels)[SliderLabel_Value],
-                     xLabel, y + (height - hLabel)/2, wLabel, hLabel, TRUE);
+        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+                     xLabel, y + (height - hLabel)/2, wLabel, hLabel);
 
-        ::MoveWindow((*m_labels)[SliderLabel_Max],
-                     xLabel, y + height - hLabel, wLabel, hLabel, TRUE);
+        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+                      xLabel, y + height - hLabel, wLabel, hLabel);
 
         // position the slider itself along the left/right edge
-        ::MoveWindow(GetHwnd(),
-                     HasFlag(wxSL_LEFT) ? x : x + wLabel + HGAP,
-                     y + hLabel/2,
-                     width - wLabel - HGAP,
-                     height - hLabel,
-                     TRUE);
+        wxSliderBase::DoMoveWindow(HasFlag(wxSL_LEFT) ? x : x + wLabel + HGAP,
+                                   y + hLabel/2,
+                                   width - wLabel - HGAP,
+                                   height - hLabel);
     }
     else // horizontal
     {
@@ -445,36 +490,37 @@ void wxSlider95::DoMoveWindow(int x, int y, int width, int height)
 
         // position all labels: min on the left, value in the middle and max to
         // the right
-        ::MoveWindow((*m_labels)[SliderLabel_Min],
-                     x, yLabel, wLabel, hLabel, TRUE);
+        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+                      x, yLabel, wLabel, hLabel);
 
-        ::MoveWindow((*m_labels)[SliderLabel_Value],
-                     x + (width - wLabel)/2, yLabel, wLabel, hLabel, TRUE);
+        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+                      x + (width - wLabel)/2, yLabel, wLabel, hLabel);
 
-        ::MoveWindow((*m_labels)[SliderLabel_Max],
-                     x + width - wLabel, yLabel, wLabel, hLabel, TRUE);
+        DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+                      x + width - wLabel, yLabel, wLabel, hLabel);
 
         // position the slider itself along the top/bottom edge
-        ::MoveWindow(GetHwnd(),
-                     x,
-                     HasFlag(wxSL_TOP) ? y : y + hLabel,
-                     width,
-                     height - hLabel,
-                     TRUE);
+        wxSliderBase::DoMoveWindow(x,
+                                   HasFlag(wxSL_TOP) ? y : y + hLabel,
+                                   width,
+                                   height - hLabel);
     }
 }
 
-wxSize wxSlider95::DoGetBestSize() const
+wxSize wxSlider::DoGetBestSize() const
 {
     // these values are arbitrary
     static const int length = 100;
-    static const int thickness = 26;
+    static const int thumb = 24;
+    static const int ticks = 8;
 
+    int *width;
     wxSize size;
     if ( HasFlag(wxSL_VERTICAL) )
     {
-        size.x = thickness;
+        size.x = thumb;
         size.y = length;
+        width = &size.x;
 
         if ( m_labels )
         {
@@ -491,7 +537,8 @@ wxSize wxSlider95::DoGetBestSize() const
     else // horizontal
     {
         size.x = length;
-        size.y = thickness;
+        size.y = thumb;
+        width = &size.y;
 
         if ( m_labels )
         {
@@ -500,6 +547,16 @@ wxSize wxSlider95::DoGetBestSize() const
         }
     }
 
+    // need extra space to show ticks
+    if ( HasFlag(wxSL_TICKS) )
+    {
+        *width += ticks;
+
+        // and maybe twice as much if we show them on both sides
+        if ( HasFlag(wxSL_BOTH) )
+            *width += ticks;
+    }
+
     return size;
 }
 
@@ -507,22 +564,14 @@ wxSize wxSlider95::DoGetBestSize() const
 // slider-specific methods
 // ----------------------------------------------------------------------------
 
-int wxSlider95::MSWInvertOrNot(int value) const
-{
-    if (m_windowStyle & wxSL_INVERSE) 
-        return (m_rangeMax + m_rangeMin) - value; 
-    else 
-        return value; 
-}
-
-int wxSlider95::GetValue() const
+int wxSlider::GetValue() const
 {
-    return MSWInvertOrNot(::SendMessage(GetHwnd(), TBM_GETPOS, 0, 0));
+    return ValueInvertOrNot(::SendMessage(GetHwnd(), TBM_GETPOS, 0, 0));
 }
 
-void wxSlider95::SetValue(int value)
+void wxSlider::SetValue(int value)
 {
-    ::SendMessage(GetHwnd(), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)MSWInvertOrNot(value));
+    ::SendMessage(GetHwnd(), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)ValueInvertOrNot(value));
 
     if ( m_labels )
     {
@@ -530,86 +579,87 @@ void wxSlider95::SetValue(int value)
     }
 }
 
-void wxSlider95::SetRange(int minValue, int maxValue)
+void wxSlider::SetRange(int minValue, int maxValue)
 {
     m_rangeMin = minValue;
     m_rangeMax = maxValue;
 
-    ::SendMessage(GetHwnd(), TBM_SETRANGE, TRUE, MAKELONG(minValue, maxValue));
+    ::SendMessage(GetHwnd(), TBM_SETRANGEMIN, TRUE, m_rangeMin);
+    ::SendMessage(GetHwnd(), TBM_SETRANGEMAX, TRUE, m_rangeMax);
 
     if ( m_labels )
     {
-        ::SetWindowText((*m_labels)[SliderLabel_Min], Format(MSWInvertOrNot(m_rangeMin)));
-        ::SetWindowText((*m_labels)[SliderLabel_Max], Format(MSWInvertOrNot(m_rangeMax)));
+        ::SetWindowText((*m_labels)[SliderLabel_Min], Format(ValueInvertOrNot(m_rangeMin)));
+        ::SetWindowText((*m_labels)[SliderLabel_Max], Format(ValueInvertOrNot(m_rangeMax)));
     }
 }
 
-void wxSlider95::SetTickFreq(int n, int pos)
+void wxSlider::SetTickFreq(int n, int pos)
 {
     m_tickFreq = n;
     ::SendMessage( GetHwnd(), TBM_SETTICFREQ, (WPARAM) n, (LPARAM) pos );
 }
 
-void wxSlider95::SetPageSize(int pageSize)
+void wxSlider::SetPageSize(int pageSize)
 {
     ::SendMessage( GetHwnd(), TBM_SETPAGESIZE, (WPARAM) 0, (LPARAM) pageSize );
     m_pageSize = pageSize;
 }
 
-int wxSlider95::GetPageSize() const
+int wxSlider::GetPageSize() const
 {
     return m_pageSize;
 }
 
-void wxSlider95::ClearSel()
+void wxSlider::ClearSel()
 {
     ::SendMessage(GetHwnd(), TBM_CLEARSEL, (WPARAM) TRUE, (LPARAM) 0);
 }
 
-void wxSlider95::ClearTicks()
+void wxSlider::ClearTicks()
 {
     ::SendMessage(GetHwnd(), TBM_CLEARTICS, (WPARAM) TRUE, (LPARAM) 0);
 }
 
-void wxSlider95::SetLineSize(int lineSize)
+void wxSlider::SetLineSize(int lineSize)
 {
     m_lineSize = lineSize;
     ::SendMessage(GetHwnd(), TBM_SETLINESIZE, (WPARAM) 0, (LPARAM) lineSize);
 }
 
-int wxSlider95::GetLineSize() const
+int wxSlider::GetLineSize() const
 {
     return (int)::SendMessage(GetHwnd(), TBM_GETLINESIZE, 0, 0);
 }
 
-int wxSlider95::GetSelEnd() const
+int wxSlider::GetSelEnd() const
 {
-    return (int)::SendMessage(GetHwnd(), TBM_SETSELEND, 0, 0);
+    return (int)::SendMessage(GetHwnd(), TBM_GETSELEND, 0, 0);
 }
 
-int wxSlider95::GetSelStart() const
+int wxSlider::GetSelStart() const
 {
     return (int)::SendMessage(GetHwnd(), TBM_GETSELSTART, 0, 0);
 }
 
-void wxSlider95::SetSelection(int minPos, int maxPos)
+void wxSlider::SetSelection(int minPos, int maxPos)
 {
     ::SendMessage(GetHwnd(), TBM_SETSEL,
                   (WPARAM) TRUE /* redraw */,
                   (LPARAM) MAKELONG( minPos, maxPos) );
 }
 
-void wxSlider95::SetThumbLength(int len)
+void wxSlider::SetThumbLength(int len)
 {
     ::SendMessage(GetHwnd(), TBM_SETTHUMBLENGTH, (WPARAM) len, (LPARAM) 0);
 }
 
-int wxSlider95::GetThumbLength() const
+int wxSlider::GetThumbLength() const
 {
     return (int)::SendMessage( GetHwnd(), TBM_GETTHUMBLENGTH, 0, 0);
 }
 
-void wxSlider95::SetTick(int tickPos)
+void wxSlider::SetTick(int tickPos)
 {
     ::SendMessage( GetHwnd(), TBM_SETTIC, (WPARAM) 0, (LPARAM) tickPos );
 }
@@ -618,21 +668,21 @@ void wxSlider95::SetTick(int tickPos)
 // composite control methods
 // ----------------------------------------------------------------------------
 
-WXHWND wxSlider95::GetStaticMin() const
+WXHWND wxSlider::GetStaticMin() const
 {
     return m_labels ? (WXHWND)(*m_labels)[SliderLabel_Min] : NULL;
 }
 
-WXHWND wxSlider95::GetStaticMax() const
+WXHWND wxSlider::GetStaticMax() const
 {
     return m_labels ? (WXHWND)(*m_labels)[SliderLabel_Max] : NULL;
 }
 
-WXHWND wxSlider95::GetEditValue() const
+WXHWND wxSlider::GetEditValue() const
 {
     return m_labels ? (WXHWND)(*m_labels)[SliderLabel_Value] : NULL;
 }
 
-WX_FORWARD_STD_METHODS_TO_SUBWINDOWS(wxSlider95, wxSliderBase, m_labels)
+WX_FORWARD_STD_METHODS_TO_SUBWINDOWS(wxSlider, wxSliderBase, m_labels)
 
 #endif // wxUSE_SLIDER