X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1e6feb95a79834836e88143b15d9f424ebe79621..c0e7c9a98bb5cdfaccf4df3d13da846d022957f8:/src/univ/slider.cpp diff --git a/src/univ/slider.cpp b/src/univ/slider.cpp index e1640dd87b..df73dc6951 100644 --- a/src/univ/slider.cpp +++ b/src/univ/slider.cpp @@ -5,7 +5,7 @@ // Modified by: // Created: 09.02.01 // RCS-ID: $Id$ -// Copyright: (c) 2001 Vadim Zeitlin +// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -42,7 +42,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "univslider.h" #endif @@ -143,7 +143,7 @@ bool wxSlider::Create(wxWindow *parent, { if ( !wxSliderBase::Create(parent, id, pos, size, style, validator, name) ) - return FALSE; + return false; SetRange(minValue, maxValue); SetValue(value); @@ -154,7 +154,7 @@ bool wxSlider::Create(wxWindow *parent, CreateInputHandler(wxINP_HANDLER_SLIDER); - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -183,21 +183,16 @@ bool wxSlider::ChangeValueBy(int inc) bool wxSlider::ChangeValueTo(int value) { - // this method is protected and we should only call it with normalized - // value! - wxCHECK_MSG( IsInRange(value), FALSE, _T("invalid slider value") ); - // check if the value is going to change at all - if ( value == m_value ) - return FALSE; + if (value == m_value) return false; - // refresh the old thumb position - RefreshThumb(); + // this method is protected and we should only call it with normalized + // value! + wxCHECK_MSG( IsInRange(value), false, _T("invalid slider value") ); m_value = value; - // and the new one - RefreshThumb(); + Refresh(); // generate the event wxCommandEvent event(wxEVT_COMMAND_SLIDER_UPDATED, GetId()); @@ -206,7 +201,7 @@ bool wxSlider::ChangeValueTo(int value) (void)GetEventHandler()->ProcessEvent(event); - return TRUE; + return true; } void wxSlider::SetValue(int value) @@ -266,14 +261,14 @@ int wxSlider::GetMax() const void wxSlider::SetLineSize(int lineSize) { - wxCHECK_RET( lineSize > 0, _T("invalid slider line size") ); + wxCHECK_RET( lineSize >= 0, _T("invalid slider line size") ); m_lineSize = lineSize; } void wxSlider::SetPageSize(int pageSize) { - wxCHECK_RET( pageSize > 0, _T("invalid slider page size") ); + wxCHECK_RET( pageSize >= 0, _T("invalid slider page size") ); m_pageSize = pageSize; } @@ -293,8 +288,8 @@ int wxSlider::GetPageSize() const { if ( !m_pageSize ) { - // the default page increment is 1/10 of the range - wxConstCast(this, wxSlider)->m_pageSize = (m_max - m_min) / 10; + // the default page increment is m_tickFreq + wxConstCast(this, wxSlider)->m_pageSize = m_tickFreq; } return m_pageSize; @@ -302,7 +297,7 @@ int wxSlider::GetPageSize() const void wxSlider::SetThumbLength(int lenPixels) { - wxCHECK_RET( lenPixels > 0, _T("invalid slider thumb size") ); + wxCHECK_RET( lenPixels >= 0, _T("invalid slider thumb size") ); // use m_thumbSize here directly and not GetThumbLength() to avoid setting // it to the default value as we don't need it @@ -316,13 +311,17 @@ void wxSlider::SetThumbLength(int lenPixels) int wxSlider::GetThumbLength() const { - if ( !m_thumbSize ) + wxSize sz = GetDefaultThumbSize(); + int len = (IsVert() ? sz.x : sz.y); + if (m_thumbSize > len) { - wxSize sz = GetDefaultThumbSize(); - return IsVert() ? sz.y : sz.x; + return m_thumbSize; + } + else + { + return len; } - return m_thumbSize; } // ---------------------------------------------------------------------------- @@ -331,6 +330,8 @@ int wxSlider::GetThumbLength() const void wxSlider::SetTickFreq(int n, int WXUNUSED(dummy)) { + wxCHECK_RET (n > 0, _T("invalid slider tick frequency")); + if ( n != m_tickFreq ) { m_tickFreq = n; @@ -364,7 +365,9 @@ wxSize wxSlider::CalcLabelSize() const wxSize wxSlider::DoGetBestClientSize() const { // this dimension is completely arbitrary - static const wxCoord SLIDER_WIDTH = 100; + static const wxCoord SLIDER_WIDTH = 40; + + long style = GetWindowStyle(); // first calculate the size of the slider itself: i.e. the shaft and the // thumb @@ -386,6 +389,10 @@ wxSize wxSlider::DoGetBestClientSize() const if ( HasTicks() ) { wxCoord lenTick = GetRenderer()->GetSliderTickLen(); + if (style & wxSL_BOTH) + { + lenTick = 2 * lenTick; + } if ( IsVert() ) size.x += lenTick; @@ -398,10 +405,14 @@ wxSize wxSlider::DoGetBestClientSize() const { wxSize sizeLabels = CalcLabelSize(); - if ( IsVert() ) + if (style & (wxSL_LEFT|wxSL_RIGHT)) + { size.x += sizeLabels.x + SLIDER_LABEL_MARGIN; - else + } + else if (style & (wxSL_TOP|wxSL_BOTTOM)) + { size.y += sizeLabels.y + SLIDER_LABEL_MARGIN; + } } return size; @@ -457,110 +468,102 @@ void wxSlider::CalcGeometry() | H *| ------ */ + long style = GetWindowStyle(); + // initialize to the full client rect wxRect rectTotal = GetClientRect(); + m_rectSlider = rectTotal; + wxSize sizeThumb = GetThumbSize(); + + // Labels reduce the size of the slider rect if ( HasLabels() ) { - wxSize sizeLabels = CalcLabelSize(); + wxSize sizeLabels = CalcLabelSize(); - m_rectSlider = rectTotal; m_rectLabel = wxRect(rectTotal.GetPosition(), sizeLabels); - // split the rect - if ( IsVert() ) + if (style & wxSL_TOP) { - sizeLabels.x += SLIDER_LABEL_MARGIN; - - if ( GetWindowStyle() & wxSL_LEFT ) - { - // shrink and offset the slider to the right - m_rectSlider.x += sizeLabels.x; - m_rectSlider.width -= sizeLabels.x; - } - else // wxSL_RIGHT - { - // just shrink the slider and move the label to the right - m_rectSlider.width -= sizeLabels.x; - - m_rectLabel.x += m_rectSlider.width + SLIDER_LABEL_MARGIN; - } + // shrink and offset the slider to the bottom + m_rectSlider.y += sizeLabels.y + SLIDER_LABEL_MARGIN; + m_rectSlider.height -= sizeLabels.y + SLIDER_LABEL_MARGIN; } - else // horizontal + else if (style & wxSL_BOTTOM) { - // same logic as above but x/y are trasnposed - sizeLabels.y += SLIDER_LABEL_MARGIN; - - if ( GetWindowStyle() & wxSL_TOP ) - { - m_rectSlider.y += sizeLabels.y; - m_rectSlider.height -= sizeLabels.y; - } - else // wxSL_BOTTOM - { - m_rectSlider.height -= sizeLabels.y; - - m_rectLabel.y += m_rectSlider.height + SLIDER_LABEL_MARGIN; - } + // shrink the slider and move the label to the bottom + m_rectSlider.height -= sizeLabels.y + SLIDER_LABEL_MARGIN; + m_rectLabel.y += m_rectSlider.height + SLIDER_LABEL_MARGIN; + } + else if (style & wxSL_LEFT) + { + // shrink and offset the slider to the right + m_rectSlider.x += sizeLabels.x + SLIDER_LABEL_MARGIN; + m_rectSlider.width -= sizeLabels.x + SLIDER_LABEL_MARGIN; + } + else if (style & wxSL_RIGHT) + { + // shrink the slider and move the label to the right + m_rectSlider.width -= sizeLabels.x + SLIDER_LABEL_MARGIN; + m_rectLabel.x += m_rectSlider.width + SLIDER_LABEL_MARGIN; } - } - else // no labels - { - // the slider takes the whole client rect - m_rectSlider = rectTotal; } - // now adjust for ticks too + // calculate ticks too if ( HasTicks() ) { wxCoord lenTick = GetRenderer()->GetSliderTickLen(); - if ( IsVert() ) - { - m_rectSlider.width -= lenTick; - } - else // horizontal - { - m_rectSlider.height -= lenTick; - } - - // note that we must compute m_rectSlider first as GetShaftRect() uses // it m_rectTicks = GetShaftRect(); if ( IsVert() ) { - m_rectTicks.x = m_rectSlider.x + m_rectSlider.width; + if (style & (wxSL_LEFT|wxSL_BOTH)) + { + m_rectTicks.x = m_rectSlider.x; + } + else + { // wxSL_RIGHT + m_rectTicks.x = m_rectSlider.x + m_rectSlider.width - lenTick; + } m_rectTicks.width = lenTick; } else // horizontal { - m_rectTicks.y = m_rectSlider.y + m_rectSlider.height; + if (style & (wxSL_TOP|wxSL_BOTH)) + { + m_rectTicks.y = m_rectSlider.y; + } + else + { // wxSL_BOTTOM + m_rectTicks.y = m_rectSlider.y + m_rectSlider.height - lenTick; + } m_rectTicks.height = lenTick; } + } + // slider is never smaller than thumb size unless rectTotal + if ( IsVert() ) + { + wxCoord width = wxMin ( rectTotal.width, sizeThumb.x ); + m_rectSlider.width = wxMax ( m_rectSlider.width, width ); + } + else + { + wxCoord height = wxMin ( rectTotal.height, sizeThumb.y ); + m_rectSlider.height = wxMax ( m_rectSlider.height, height ); } } wxSize wxSlider::GetDefaultThumbSize() const { - return GetRenderer()->GetSliderThumbSize(GetSliderRect(), GetOrientation()); + // Default size has no styles (arrows) + return GetRenderer()->GetSliderThumbSize(GetSliderRect(), 0, GetOrientation()); } wxSize wxSlider::GetThumbSize() const { - wxSize sizeThumb = GetDefaultThumbSize(); - - // if we have our own thumb length (set by the user), use it instead of the - // default value - if ( m_thumbSize ) - { - if ( IsVert() ) - sizeThumb.y = m_thumbSize; - else - sizeThumb.x = m_thumbSize; - } - - return sizeThumb; + return GetRenderer()->GetSliderThumbSize(GetSliderRect(), m_thumbSize, GetOrientation()); } // ---------------------------------------------------------------------------- @@ -569,7 +572,7 @@ wxSize wxSlider::GetThumbSize() const wxRect wxSlider::GetShaftRect() const { - return GetRenderer()->GetSliderShaftRect(m_rectSlider, GetOrientation()); + return GetRenderer()->GetSliderShaftRect(m_rectSlider, m_thumbSize, GetOrientation(), GetWindowStyle()); } void wxSlider::CalcThumbRect(const wxRect *rectShaftIn, @@ -596,8 +599,9 @@ void wxSlider::CalcThumbRect(const wxRect *rectShaftIn, } wxCoord lenShaft, - lenThumb, - *p; + lenThumb; + wxCoord *p; + wxRect rectThumb(rectShaft.GetPosition(), GetThumbSize()); if ( isVertical ) { @@ -620,30 +624,37 @@ void wxSlider::CalcThumbRect(const wxRect *rectShaftIn, // position is not at lenShaft but at lenShaft - thumbSize if ( m_max != m_min ) { - *p += ((lenShaft - lenThumb)*(value - m_min))/(m_max - m_min); + if ( isVertical ) + { + *p += ((lenShaft - lenThumb)*(m_max - value))/(m_max - m_min); + } + else + { // horz + *p += ((lenShaft - lenThumb)*(value - m_min))/(m_max - m_min); + } } // calc the label rect if ( HasLabels() && rectLabelOut ) { + long style = GetWindowStyle(); wxRect rectLabel = m_rectLabel; // centre the label relatively to the thumb position - if ( isVertical ) + if (style & (wxSL_TOP|wxSL_BOTTOM)) { - rectLabel.y = - rectThumb.y + (rectThumb.height - m_rectLabel.height)/2; + rectLabel.x = rectThumb.x + (rectThumb.width - m_rectLabel.width)/2; } - else // horz + else if (style & (wxSL_LEFT|wxSL_RIGHT)) { - rectLabel.x = - rectThumb.x + (rectThumb.width - m_rectLabel.width)/2; + rectLabel.y = rectThumb.y + (rectThumb.height - m_rectLabel.height)/2; } *rectLabelOut = rectLabel; } if ( rectThumbOut ) + *rectThumbOut = rectThumb; } @@ -662,47 +673,57 @@ void wxSlider::DoDraw(wxControlRenderer *renderer) wxDC& dc = renderer->GetDC(); wxRect rectUpdate = GetUpdateClientRect(); - bool isVertical = IsVert(); wxOrientation orient = GetOrientation(); int flags = GetStateFlags(); + long style = GetWindowStyle(); + + wxSize sz = GetThumbSize(); + int len = IsVert() ? sz.x : sz.y; // first draw the shaft - wxRect rectShaft = rend->GetSliderShaftRect(m_rectSlider, orient); + wxRect rectShaft = rend->GetSliderShaftRect(m_rectSlider, len, orient, style); if ( rectUpdate.Intersects(rectShaft) ) { - rend->DrawSliderShaft(dc, m_rectSlider, orient, flags); + rend->DrawSliderShaft(dc, m_rectSlider, len, orient, flags, style); } // calculate the thumb position in pixels and draw it wxRect rectThumb, rectLabel; CalcThumbRect(&rectShaft, &rectThumb, &rectLabel); - if ( rectUpdate.Intersects(rectThumb) ) + // then draw the ticks + if ( HasTicks() && rectUpdate.Intersects(m_rectTicks) ) { - rend->DrawSliderThumb(dc, rectThumb, orient, flags | m_thumbFlags); + rend->DrawSliderTicks(dc, m_rectSlider, len, orient, + m_min, m_max, m_tickFreq, flags, style); } - // then draw the ticks - if ( HasTicks() && rectUpdate.Intersects(m_rectTicks) ) + // then draw the thumb + if ( rectUpdate.Intersects(rectThumb) ) { - rend->DrawSliderTicks(dc, m_rectTicks, rectThumb.GetSize(), orient, - m_min, m_max, m_tickFreq); + rend->DrawSliderThumb(dc, rectThumb, orient, flags | m_thumbFlags, style); } // finally, draw the label near the thumb if ( HasLabels() && rectUpdate.Intersects(rectLabel) ) { // align it to be close to the shaft - int align; - if ( isVertical ) + int align = 0; + if (style & wxSL_TOP) + { + align = wxALIGN_CENTRE_HORIZONTAL|wxALIGN_TOP; + } + else if (style & wxSL_BOTTOM) + { + align = wxALIGN_CENTRE_HORIZONTAL|wxALIGN_BOTTOM; + } + else if (style & wxSL_LEFT) { - align = wxALIGN_CENTRE_VERTICAL | - (GetWindowStyle() & wxSL_RIGHT ? wxALIGN_LEFT - : wxALIGN_RIGHT); + align = wxALIGN_CENTRE_VERTICAL|wxALIGN_LEFT; } - else // horz + else if (style & wxSL_RIGHT) { - align = wxALIGN_CENTRE; + align = wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT; } dc.SetFont(GetFont()); @@ -714,18 +735,6 @@ void wxSlider::DoDraw(wxControlRenderer *renderer) } } -void wxSlider::RefreshThumb() -{ - wxRect rectThumb, rectLabel; - CalcThumbRect(NULL, &rectThumb, &rectLabel); - - Refresh(TRUE /* erase background */, &rectThumb); - if ( HasLabels() ) - { - Refresh(TRUE, &rectLabel); - } -} - // ---------------------------------------------------------------------------- // wxSlider input processing // ---------------------------------------------------------------------------- @@ -734,7 +743,7 @@ bool wxSlider::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) { - if ( action == wxACTION_SLIDER_START ) + if ( action == wxACTION_SLIDER_START ) { ChangeValueTo(m_min); } @@ -748,24 +757,24 @@ bool wxSlider::PerformAction(const wxControlAction& action, } else if ( action == wxACTION_SLIDER_LINE_UP ) { - ChangeValueBy(-GetLineSize()); + ChangeValueBy(+GetLineSize()); } - else if ( action == wxACTION_SLIDER_PAGE_UP ) + else if ( action == wxACTION_SLIDER_LINE_DOWN ) { - return PerformAction(wxACTION_SLIDER_PAGE_CHANGE, -1); + ChangeValueBy(-GetLineSize()); } - else if ( action == wxACTION_SLIDER_LINE_DOWN ) + else if ( action == wxACTION_SLIDER_PAGE_UP ) { - ChangeValueBy(GetLineSize()); + ChangeValueBy(+GetPageSize()); } else if ( action == wxACTION_SLIDER_PAGE_DOWN ) { - return PerformAction(wxACTION_SLIDER_PAGE_CHANGE, 1); + ChangeValueBy(-GetPageSize()); } else if ( action == wxACTION_SLIDER_THUMB_DRAG ) { // no special processing for it - return TRUE; + return true; } else if ( action == wxACTION_SLIDER_THUMB_MOVE || action == wxACTION_SLIDER_THUMB_RELEASE ) @@ -777,7 +786,7 @@ bool wxSlider::PerformAction(const wxControlAction& action, return wxControl::PerformAction(action, numArg, strArg); } - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -787,38 +796,40 @@ bool wxSlider::PerformAction(const wxControlAction& action, wxScrollThumb::Shaft wxSlider::HitTest(const wxPoint& pt) const { wxRect rectShaft = GetShaftRect(); - if ( !rectShaft.Inside(pt) ) + wxRect rectThumb; + CalcThumbRect(&rectShaft, &rectThumb, NULL); + + // check for possible shaft or thumb hit + if (!rectShaft.Inside(pt) && !rectThumb.Inside(pt)) { return wxScrollThumb::Shaft_None; } - // inside the shaft, where is it relatively to the thumb? - wxRect rectThumb; - CalcThumbRect(&rectShaft, &rectThumb, NULL); - // the position to test and the start and end of the thumb - wxCoord x, x1, x2; - if ( IsVert() ) + wxCoord x, x1, x2, x3, x4; + if (IsVert()) { x = pt.y; - x1 = rectThumb.GetTop(); - x2 = rectThumb.GetBottom(); + x1 = rectThumb.GetBottom(); + x2 = rectShaft.GetBottom(); + x3 = rectShaft.GetTop(); + x4 = rectThumb.GetTop(); } - else // horz - { + else + { // horz x = pt.x; - x1 = rectThumb.GetLeft(); - x2 = rectThumb.GetRight(); + x1 = rectShaft.GetLeft(); + x2 = rectThumb.GetLeft(); + x3 = rectThumb.GetRight(); + x4 = rectShaft.GetRight(); } - - if ( x < x1 ) + if ((x1 <= x) & (x < x2)) { // or to the left return wxScrollThumb::Shaft_Above; } - if ( x > x2 ) - { + if ((x3 < x) & (x <= x4)) { // or to the right return wxScrollThumb::Shaft_Below; } @@ -880,23 +891,44 @@ void wxSlider::SetShaftPartState(wxScrollThumb::Shaft shaftPart, else m_thumbFlags &= ~flag; - RefreshThumb(); + Refresh(); } } void wxSlider::OnThumbDragStart(int pos) { - PerformAction(wxACTION_SLIDER_THUMB_DRAG, pos); + if (IsVert()) + { + PerformAction(wxACTION_SLIDER_THUMB_DRAG, m_max - pos); + } + else + { + PerformAction(wxACTION_SLIDER_THUMB_DRAG, pos); + } } void wxSlider::OnThumbDrag(int pos) { - PerformAction(wxACTION_SLIDER_THUMB_MOVE, pos); + if (IsVert()) + { + PerformAction(wxACTION_SLIDER_THUMB_MOVE, m_max - pos); + } + else + { + PerformAction(wxACTION_SLIDER_THUMB_MOVE, pos); + } } void wxSlider::OnThumbDragEnd(int pos) { - PerformAction(wxACTION_SLIDER_THUMB_RELEASE, pos); + if (IsVert()) + { + PerformAction(wxACTION_SLIDER_THUMB_RELEASE, m_max - pos); + } + else + { + PerformAction(wxACTION_SLIDER_THUMB_RELEASE, pos); + } } void wxSlider::OnPageScrollStart() @@ -916,11 +948,11 @@ bool wxSlider::OnPageScroll(int pageInc) // wxStdSliderButtonInputHandler // ---------------------------------------------------------------------------- -bool wxStdSliderButtonInputHandler::HandleKey(wxControl *control, +bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer, const wxKeyEvent& event, bool pressed) { - if ( pressed ) + if ( pressed ) { int keycode = event.GetKeyCode(); @@ -928,76 +960,79 @@ bool wxStdSliderButtonInputHandler::HandleKey(wxControl *control, switch ( keycode ) { case WXK_HOME: - action = wxACTION_SLIDER_START; + action = wxACTION_SLIDER_END; break; case WXK_END: - action = wxACTION_SLIDER_END; + action = wxACTION_SLIDER_START; break; - case WXK_LEFT: + case WXK_RIGHT: case WXK_UP: action = wxACTION_SLIDER_LINE_UP; break; - case WXK_RIGHT: + case WXK_LEFT: case WXK_DOWN: action = wxACTION_SLIDER_LINE_DOWN; break; case WXK_PRIOR: + case WXK_PAGEUP: action = wxACTION_SLIDER_PAGE_UP; break; case WXK_NEXT: + case WXK_PAGEDOWN: action = wxACTION_SLIDER_PAGE_DOWN; break; } - if ( !!action ) + if ( !action.IsEmpty() ) { - control->PerformAction(action); + consumer->PerformAction(action); - return TRUE; + return true; } } - return wxStdInputHandler::HandleKey(control, event, pressed); + return wxStdInputHandler::HandleKey(consumer, event, pressed); } -bool wxStdSliderButtonInputHandler::HandleMouse(wxControl *control, +bool wxStdSliderButtonInputHandler::HandleMouse(wxInputConsumer *consumer, const wxMouseEvent& event) { - wxSlider *slider = wxStaticCast(control, wxSlider); + wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider); if ( slider->GetThumb().HandleMouse(event) ) { // processed by the thumb - return FALSE; + return false; } - return wxStdInputHandler::HandleMouse(control, event); + return wxStdInputHandler::HandleMouse(consumer, event); } -bool wxStdSliderButtonInputHandler::HandleMouseMove(wxControl *control, +bool wxStdSliderButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer, const wxMouseEvent& event) { - wxSlider *slider = wxStaticCast(control, wxSlider); + wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider); if ( slider->GetThumb().HandleMouseMove(event) ) { // processed by the thumb - return FALSE; + return false; } - return wxStdInputHandler::HandleMouseMove(control, event); + return wxStdInputHandler::HandleMouseMove(consumer, event); } -bool wxStdSliderButtonInputHandler::HandleFocus(wxControl *control, - const wxFocusEvent& event) +bool +wxStdSliderButtonInputHandler::HandleFocus(wxInputConsumer * WXUNUSED(consumer), + const wxFocusEvent& WXUNUSED(event)) { // slider's appearance changes when it gets/loses focus - return TRUE; + return true; } #endif // wxUSE_SLIDER