///////////////////////////////////////////////////////////////////////////////
-// Name: univ/slider.cpp
+// Name: src/univ/slider.cpp
// Purpose: implementation of the universal version of wxSlider
// Author: Vadim Zeitlin
// Modified by:
// Created: 09.02.01
-// RCS-ID: $Id$
// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
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:
// 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
// ----------------------------------------------------------------------------
// implementation of wxSlider
// ============================================================================
-IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
-
BEGIN_EVENT_TABLE(wxSlider, wxControl)
EVT_SIZE(wxSlider::OnSize)
END_EVENT_TABLE()
// 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);
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
- wxCommandEvent event(wxEVT_COMMAND_SLIDER_UPDATED, GetId());
+ // 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_SLIDER, GetId());
event.SetInt(m_value);
event.SetEventObject(this);
-
(void)GetEventHandler()->ProcessEvent(event);
return true;
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;
}
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
{
wxSize sz = GetDefaultThumbSize();
int len = (IsVert() ? sz.x : sz.y);
- if (m_thumbSize > len)
+ if (m_thumbSize > len)
{
return m_thumbSize;
}
// wxSlider ticks
// ----------------------------------------------------------------------------
-void wxSlider::SetTickFreq(int n, int WXUNUSED(dummy))
+void wxSlider::DoSetTickFreq(int n)
{
- wxCHECK_RET (n > 0, _T("invalid slider tick frequency"));
+ wxCHECK_RET (n > 0, wxT("invalid slider tick frequency"));
if ( n != m_tickFreq )
{
// 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);
if ( HasTicks() )
{
wxCoord lenTick = GetRenderer()->GetSliderTickLen();
- if (style & wxSL_BOTH)
+ if (style & wxSL_BOTH)
{
lenTick = 2 * lenTick;
}
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;
if ( IsVert() )
{
- if (style & (wxSL_LEFT|wxSL_BOTH))
+ if (style & (wxSL_LEFT|wxSL_BOTH))
{
m_rectTicks.x = m_rectSlider.x;
}
}
else // horizontal
{
- if (style & (wxSL_TOP|wxSL_BOTH))
+ if (style & (wxSL_TOP|wxSL_BOTH))
{
m_rectTicks.y = m_rectSlider.y;
}
}
wxCoord lenShaft,
- lenThumb,
- *p;
+ lenThumb;
+ wxCoord *p;
+
wxRect rectThumb(rectShaft.GetPosition(), GetThumbSize());
if ( isVertical )
{
wxString wxSlider::FormatValue(int value) const
{
- return wxString::Format(_T("%d"), value);
+ return wxString::Format(wxT("%d"), value);
}
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;
}
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
// ----------------------------------------------------------------------------
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();
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;
}
void wxSlider::OnThumbDragStart(int pos)
{
- if (IsVert())
+ if (IsVert())
{
PerformAction(wxACTION_SLIDER_THUMB_DRAG, m_max - pos);
}
void wxSlider::OnThumbDrag(int pos)
{
- if (IsVert())
+ if (IsVert())
{
PerformAction(wxACTION_SLIDER_THUMB_MOVE, m_max - pos);
}
void wxSlider::OnThumbDragEnd(int pos)
{
- if (IsVert())
+ if (IsVert())
{
PerformAction(wxACTION_SLIDER_THUMB_RELEASE, m_max - pos);
}
}
// ----------------------------------------------------------------------------
-// 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();
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;
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);
return wxStdInputHandler::HandleMouse(consumer, event);
}
-bool wxStdSliderButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer,
+bool wxStdSliderInputHandler::HandleMouseMove(wxInputConsumer *consumer,
const wxMouseEvent& event)
{
wxSlider *slider = wxStaticCast(consumer->GetInputWindow(), wxSlider);
}
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;
}