X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a290fa5a7deebe9d96c0c0089d18e27d4bd9b624..61f09f569358d7b2752733c4a24d1bd10daefae2:/src/univ/slider.cpp?ds=sidebyside diff --git a/src/univ/slider.cpp b/src/univ/slider.cpp index bd6eac32a2..8dbb9abf00 100644 --- a/src/univ/slider.cpp +++ b/src/univ/slider.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: univ/slider.cpp +// Name: src/univ/slider.cpp // Purpose: implementation of the universal version of wxSlider // Author: Vadim Zeitlin // Modified by: @@ -22,9 +22,9 @@ or right. What we really need is probably a more fine grain control on labels, i.e. we - should be able to select if we show nothign at all, the current value only + should be able to select if we show nothing at all, the current value only or the value and the limits - the current approach is just that of the - greatest common denominator. + lowest common denominator. TODO: @@ -42,28 +42,49 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "univslider.h" -#endif - #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif -#ifndef WX_PRECOMP - #include "wx/dc.h" -#endif +#if wxUSE_SLIDER #include "wx/slider.h" -#if wxUSE_SLIDER +#ifndef WX_PRECOMP + #include "wx/dc.h" +#endif #include "wx/univ/renderer.h" #include "wx/univ/inphand.h" #include "wx/univ/theme.h" +// ---------------------------------------------------------------------------- +// wxStdSliderInputHandler: default slider input handling +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxStdSliderInputHandler : public wxStdInputHandler +{ +public: + // default ctor + wxStdSliderInputHandler(wxInputHandler *inphand) + : wxStdInputHandler(inphand) + { + } + + // base class methods + virtual bool HandleKey(wxInputConsumer *consumer, + const wxKeyEvent& event, + bool pressed); + virtual bool HandleMouse(wxInputConsumer *consumer, + const wxMouseEvent& event); + virtual bool HandleMouseMove(wxInputConsumer *consumer, + const wxMouseEvent& event); + + virtual bool HandleFocus(wxInputConsumer *consumer, const wxFocusEvent& event); +}; + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -150,7 +171,7 @@ bool wxSlider::Create(wxWindow *parent, // call this after setting the range as the best size depends (at least if // we have wxSL_LABELS style) on the range - SetBestSize(size); + SetInitialSize(size); CreateInputHandler(wxINP_HANDLER_SLIDER); @@ -184,21 +205,26 @@ bool wxSlider::ChangeValueBy(int inc) bool wxSlider::ChangeValueTo(int value) { // check if the value is going to change at all - if (value == m_value) return false; + if (value == m_value) + return false; // this method is protected and we should only call it with normalized // value! - wxCHECK_MSG( IsInRange(value), false, _T("invalid slider value") ); + wxCHECK_MSG( IsInRange(value), false, wxT("invalid slider value") ); m_value = value; Refresh(); - // generate the event + // generate the events: both a specific scroll event and a command event + wxScrollEvent eventScroll(wxEVT_SCROLL_CHANGED, GetId()); + eventScroll.SetPosition(m_value); + eventScroll.SetEventObject( this ); + (void)GetEventHandler()->ProcessEvent(eventScroll); + wxCommandEvent event(wxEVT_COMMAND_SLIDER_UPDATED, GetId()); event.SetInt(m_value); event.SetEventObject(this); - (void)GetEventHandler()->ProcessEvent(event); return true; @@ -261,14 +287,14 @@ int wxSlider::GetMax() const void wxSlider::SetLineSize(int lineSize) { - wxCHECK_RET( lineSize >= 0, _T("invalid slider line size") ); + wxCHECK_RET( lineSize >= 0, wxT("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, wxT("invalid slider page size") ); m_pageSize = pageSize; } @@ -297,7 +323,7 @@ int wxSlider::GetPageSize() const void wxSlider::SetThumbLength(int lenPixels) { - wxCHECK_RET( lenPixels >= 0, _T("invalid slider thumb size") ); + wxCHECK_RET( lenPixels >= 0, wxT("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 @@ -313,7 +339,7 @@ int wxSlider::GetThumbLength() const { wxSize sz = GetDefaultThumbSize(); int len = (IsVert() ? sz.x : sz.y); - if (m_thumbSize > len) + if (m_thumbSize > len) { return m_thumbSize; } @@ -330,7 +356,7 @@ int wxSlider::GetThumbLength() const void wxSlider::SetTickFreq(int n, int WXUNUSED(dummy)) { - wxCHECK_RET (n > 0, _T("invalid slider tick frequency")); + wxCHECK_RET (n > 0, wxT("invalid slider tick frequency")); if ( n != m_tickFreq ) { @@ -350,7 +376,7 @@ wxSize wxSlider::CalcLabelSize() const // there is no sense in trying to calc the labels size if we haven't got // any, the caller must check for it - wxCHECK_MSG( HasLabels(), size, _T("shouldn't be called") ); + wxCHECK_MSG( HasLabels(), size, wxT("shouldn't be called") ); wxCoord w1, h1, w2, h2; GetTextExtent(FormatValue(m_min), &w1, &h1); @@ -389,7 +415,7 @@ wxSize wxSlider::DoGetBestClientSize() const if ( HasTicks() ) { wxCoord lenTick = GetRenderer()->GetSliderTickLen(); - if (style & wxSL_BOTH) + if (style & wxSL_BOTH) { lenTick = 2 * lenTick; } @@ -482,25 +508,25 @@ void wxSlider::CalcGeometry() m_rectLabel = wxRect(rectTotal.GetPosition(), sizeLabels); - if (style & wxSL_TOP) + if (style & wxSL_TOP) { // 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 if (style & wxSL_BOTTOM) + else if (style & wxSL_BOTTOM) { // 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) + 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) + else if (style & wxSL_RIGHT) { // shrink the slider and move the label to the right m_rectSlider.width -= sizeLabels.x + SLIDER_LABEL_MARGIN; @@ -518,7 +544,7 @@ void wxSlider::CalcGeometry() if ( IsVert() ) { - if (style & (wxSL_LEFT|wxSL_BOTH)) + if (style & (wxSL_LEFT|wxSL_BOTH)) { m_rectTicks.x = m_rectSlider.x; } @@ -530,7 +556,7 @@ void wxSlider::CalcGeometry() } else // horizontal { - if (style & (wxSL_TOP|wxSL_BOTH)) + if (style & (wxSL_TOP|wxSL_BOTH)) { m_rectTicks.y = m_rectSlider.y; } @@ -599,8 +625,9 @@ void wxSlider::CalcThumbRect(const wxRect *rectShaftIn, } wxCoord lenShaft, - lenThumb, - *p; + lenThumb; + wxCoord *p; + wxRect rectThumb(rectShaft.GetPosition(), GetThumbSize()); if ( isVertical ) { @@ -663,7 +690,7 @@ void wxSlider::CalcThumbRect(const wxRect *rectShaftIn, wxString wxSlider::FormatValue(int value) const { - return wxString::Format(_T("%d"), value); + return wxString::Format(wxT("%d"), value); } void wxSlider::DoDraw(wxControlRenderer *renderer) @@ -708,19 +735,19 @@ void wxSlider::DoDraw(wxControlRenderer *renderer) { // align it to be close to the shaft int align = 0; - if (style & wxSL_TOP) + if (style & wxSL_TOP) { align = wxALIGN_CENTRE_HORIZONTAL|wxALIGN_TOP; } - else if (style & wxSL_BOTTOM) + else if (style & wxSL_BOTTOM) { align = wxALIGN_CENTRE_HORIZONTAL|wxALIGN_BOTTOM; } - else if (style & wxSL_LEFT) + else if (style & wxSL_LEFT) { align = wxALIGN_CENTRE_VERTICAL|wxALIGN_LEFT; } - else if (style & wxSL_RIGHT) + else if (style & wxSL_RIGHT) { align = wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT; } @@ -742,52 +769,91 @@ bool wxSlider::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) { - if ( action == wxACTION_SLIDER_START ) + wxEventType scrollEvent = wxEVT_NULL; + int value; + bool valueChanged = true; + + if ( action == wxACTION_SLIDER_START ) { - ChangeValueTo(m_min); + scrollEvent = wxEVT_SCROLL_TOP; + value = m_min; } else if ( action == wxACTION_SLIDER_END ) { - ChangeValueTo(m_max); + scrollEvent = wxEVT_SCROLL_BOTTOM; + value = m_max; } else if ( action == wxACTION_SLIDER_PAGE_CHANGE ) { - ChangeValueBy(numArg * GetPageSize()); + value = NormalizeValue(m_value + numArg * GetPageSize()); } else if ( action == wxACTION_SLIDER_LINE_UP ) { - ChangeValueBy(+GetLineSize()); + scrollEvent = wxEVT_SCROLL_LINEUP; + value = NormalizeValue(m_value + +GetLineSize()); } else if ( action == wxACTION_SLIDER_LINE_DOWN ) { - ChangeValueBy(-GetLineSize()); + scrollEvent = wxEVT_SCROLL_LINEDOWN; + value = NormalizeValue(m_value + -GetLineSize()); } else if ( action == wxACTION_SLIDER_PAGE_UP ) { - ChangeValueBy(+GetPageSize()); + scrollEvent = wxEVT_SCROLL_PAGEUP; + value = NormalizeValue(m_value + +GetPageSize()); } else if ( action == wxACTION_SLIDER_PAGE_DOWN ) { - ChangeValueBy(-GetPageSize()); + scrollEvent = wxEVT_SCROLL_PAGEDOWN; + value = NormalizeValue(m_value + -GetPageSize()); } - else if ( action == wxACTION_SLIDER_THUMB_DRAG ) + else if ( action == wxACTION_SLIDER_THUMB_DRAG || + action == wxACTION_SLIDER_THUMB_MOVE ) { - // no special processing for it - return true; + scrollEvent = wxEVT_SCROLL_THUMBTRACK; + + // we shouldn't generate a command event about this change but we still + // should update our value and the slider appearance + valueChanged = false; + m_value = + value = (int)numArg; + Refresh(); } - else if ( action == wxACTION_SLIDER_THUMB_MOVE || - action == wxACTION_SLIDER_THUMB_RELEASE ) + else if ( action == wxACTION_SLIDER_THUMB_RELEASE ) { - ChangeValueTo((int)numArg); + scrollEvent = wxEVT_SCROLL_THUMBRELEASE; + value = (int)numArg; } else { return wxControl::PerformAction(action, numArg, strArg); } + // update wxSlider current value and generate wxCommandEvent, except while + // dragging the thumb + if ( valueChanged ) + ChangeValueTo(value); + + // also generate more precise wxScrollEvent if applicable + if ( scrollEvent != wxEVT_NULL ) + { + wxScrollEvent event(scrollEvent, GetId()); + event.SetPosition(value); + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event); + } + return true; } +/* static */ +wxInputHandler *wxSlider::GetStdInputHandler(wxInputHandler *handlerDef) +{ + static wxStdSliderInputHandler s_handler(handlerDef); + + return &s_handler; +} + // ---------------------------------------------------------------------------- // wxSlider implementation of wxControlWithThumb interface // ---------------------------------------------------------------------------- @@ -799,14 +865,14 @@ wxScrollThumb::Shaft wxSlider::HitTest(const wxPoint& pt) const CalcThumbRect(&rectShaft, &rectThumb, NULL); // check for possible shaft or thumb hit - if (!rectShaft.Inside(pt) && !rectThumb.Inside(pt)) + if (!rectShaft.Contains(pt) && !rectThumb.Contains(pt)) { return wxScrollThumb::Shaft_None; } // the position to test and the start and end of the thumb wxCoord x, x1, x2, x3, x4; - if (IsVert()) + if (IsVert()) { x = pt.y; x1 = rectThumb.GetBottom(); @@ -822,13 +888,13 @@ wxScrollThumb::Shaft wxSlider::HitTest(const wxPoint& pt) const x3 = rectThumb.GetRight(); x4 = rectShaft.GetRight(); } - if ((x1 <= x) & (x < x2)) + if ((x1 <= x) && (x < x2)) { // or to the left return wxScrollThumb::Shaft_Above; } - if ((x3 < x) & (x <= x4)) { + if ((x3 < x) && (x <= x4)) { // or to the right return wxScrollThumb::Shaft_Below; } @@ -896,7 +962,7 @@ void wxSlider::SetShaftPartState(wxScrollThumb::Shaft shaftPart, void wxSlider::OnThumbDragStart(int pos) { - if (IsVert()) + if (IsVert()) { PerformAction(wxACTION_SLIDER_THUMB_DRAG, m_max - pos); } @@ -908,7 +974,7 @@ void wxSlider::OnThumbDragStart(int pos) void wxSlider::OnThumbDrag(int pos) { - if (IsVert()) + if (IsVert()) { PerformAction(wxACTION_SLIDER_THUMB_MOVE, m_max - pos); } @@ -920,7 +986,7 @@ void wxSlider::OnThumbDrag(int pos) void wxSlider::OnThumbDragEnd(int pos) { - if (IsVert()) + if (IsVert()) { PerformAction(wxACTION_SLIDER_THUMB_RELEASE, m_max - pos); } @@ -944,14 +1010,14 @@ bool wxSlider::OnPageScroll(int pageInc) } // ---------------------------------------------------------------------------- -// wxStdSliderButtonInputHandler +// wxStdSliderInputHandler // ---------------------------------------------------------------------------- -bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer, +bool wxStdSliderInputHandler::HandleKey(wxInputConsumer *consumer, const wxKeyEvent& event, bool pressed) { - if ( pressed ) + if ( pressed ) { int keycode = event.GetKeyCode(); @@ -976,12 +1042,10 @@ bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer, 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; @@ -998,7 +1062,7 @@ bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer, return wxStdInputHandler::HandleKey(consumer, event, pressed); } -bool wxStdSliderButtonInputHandler::HandleMouse(wxInputConsumer *consumer, +bool wxStdSliderInputHandler::HandleMouse(wxInputConsumer *consumer, const wxMouseEvent& event) { wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider); @@ -1012,7 +1076,7 @@ bool wxStdSliderButtonInputHandler::HandleMouse(wxInputConsumer *consumer, return wxStdInputHandler::HandleMouse(consumer, event); } -bool wxStdSliderButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer, +bool wxStdSliderInputHandler::HandleMouseMove(wxInputConsumer *consumer, const wxMouseEvent& event) { wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider); @@ -1027,10 +1091,10 @@ bool wxStdSliderButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer, } bool -wxStdSliderButtonInputHandler::HandleFocus(wxInputConsumer * WXUNUSED(consumer), +wxStdSliderInputHandler::HandleFocus(wxInputConsumer * WXUNUSED(consumer), const wxFocusEvent& WXUNUSED(event)) { - // slider's appearance changes when it gets/loses focus + // slider appearance changes when it gets/loses focus return true; }