Applied patch [ 621451 ] Fixed version of wxSlider class

Otto Wyss

This patch corrects several bugs in the wxSlider class
for the wxUniversal/MSW port. It affects the files
"slider.h", "slider.cpp", "win32.cpp" and "gtk.cpp"
(and others). The slider should now work as expected. A simple test
program can be downloaded from

"http://dpartialmirror.sourceforge.net/Test/".


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18897 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart 2003-01-24 11:23:52 +00:00
parent 350777b68f
commit 6766e5d136
5 changed files with 486 additions and 314 deletions

View File

@ -228,25 +228,29 @@ public:
// draw the slider shaft
virtual void DrawSliderShaft(wxDC& dc,
const wxRect& rect,
int lenThumb,
wxOrientation orient,
int flags = 0,
long style = 0,
wxRect *rectShaft = NULL) = 0;
// draw the slider thumb
virtual void DrawSliderThumb(wxDC& dc,
const wxRect& rect,
wxOrientation orient,
int flags = 0) = 0;
int flags = 0,
long style = 0) = 0;
// draw the slider ticks
virtual void DrawSliderTicks(wxDC& dc,
const wxRect& rect,
const wxSize& sizeThumb,
int lenThumb,
wxOrientation orient,
int start,
int end,
int step = 1,
int flags = 0) = 0;
int flags = 0,
long style = 0) = 0;
// draw a menu bar item
virtual void DrawMenuBarItem(wxDC& dc,
@ -405,10 +409,13 @@ public:
// get the slider shaft rect from the total slider rect
virtual wxRect GetSliderShaftRect(const wxRect& rect,
wxOrientation orient) const = 0;
int lenThumb,
wxOrientation orient,
long style = 0) const = 0;
// get the size of the slider thumb for the given total slider rect
virtual wxSize GetSliderThumbSize(const wxRect& rect,
int lenThumb,
wxOrientation orient) const = 0;
// get the size of one progress bar step (in horz and vertical directions)
@ -637,25 +644,29 @@ public:
virtual void DrawSliderShaft(wxDC& dc,
const wxRect& rect,
int lenThumb,
wxOrientation orient,
int flags = 0,
long style = 0,
wxRect *rectShaft = NULL)
{ m_renderer->DrawSliderShaft(dc, rect, orient, flags, rectShaft); }
{ m_renderer->DrawSliderShaft(dc, rect, lenThumb, orient, flags, style, rectShaft); }
virtual void DrawSliderThumb(wxDC& dc,
const wxRect& rect,
wxOrientation orient,
int flags = 0)
{ m_renderer->DrawSliderThumb(dc, rect, orient, flags); }
int flags = 0,
long style = 0)
{ m_renderer->DrawSliderThumb(dc, rect, orient, flags, style); }
virtual void DrawSliderTicks(wxDC& dc,
const wxRect& rect,
const wxSize& sizeThumb,
int lenThumb,
wxOrientation orient,
int start,
int end,
int step = 1,
int flags = 0)
{ m_renderer->DrawSliderTicks(dc, rect, sizeThumb, orient,
start, end, step, flags); }
int flags = 0,
long style = 0)
{ m_renderer->DrawSliderTicks(dc, rect, lenThumb, orient,
start, end, start, flags, style); }
virtual void DrawMenuBarItem(wxDC& dc,
const wxRect& rect,
@ -778,11 +789,14 @@ public:
virtual wxCoord GetSliderTickLen() const
{ return m_renderer->GetSliderTickLen(); }
virtual wxRect GetSliderShaftRect(const wxRect& rect,
wxOrientation orient) const
{ return m_renderer->GetSliderShaftRect(rect, orient); }
int lenThumb,
wxOrientation orient,
long style = 0) const
{ return m_renderer->GetSliderShaftRect(rect, lenThumb, orient, style); }
virtual wxSize GetSliderThumbSize(const wxRect& rect,
int lenThumb,
wxOrientation orient) const
{ return m_renderer->GetSliderThumbSize(rect, orient); }
{ return m_renderer->GetSliderThumbSize(rect, lenThumb, orient); }
virtual wxSize GetProgressBarStep() const
{ return m_renderer->GetProgressBarStep(); }
virtual wxSize GetMenuBarItemSize(const wxSize& sizeText) const

View File

@ -95,10 +95,14 @@ public:
{ return IsVert() ? wxVERTICAL : wxHORIZONTAL; }
// do we have labels?
bool HasLabels() const { return (GetWindowStyle() & wxSL_LABELS) != 0; }
bool HasLabels() const
{ return ((GetWindowStyle() & wxSL_LABELS) != 0) &
((GetWindowStyle() & (wxSL_TOP|wxSL_BOTTOM|wxSL_LEFT|wxSL_RIGHT)) != 0); }
// do we have ticks?
bool HasTicks() const { return (GetWindowStyle() & wxSL_TICKS) != 0; }
bool HasTicks() const
{ return ((GetWindowStyle() & wxSL_TICKS) != 0) &
((GetWindowStyle() & (wxSL_TOP|wxSL_BOTTOM|wxSL_LEFT|wxSL_RIGHT|wxSL_BOTH)) != 0); }
// implement wxControlWithThumb interface
virtual wxWindow *GetWindow() { return this; }

View File

@ -183,21 +183,16 @@ 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;
// 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;
// refresh the old thumb position
RefreshThumb();
m_value = value;
// and the new one
RefreshThumb();
Refresh();
// generate the event
wxCommandEvent event(wxEVT_COMMAND_SLIDER_UPDATED, GetId());
@ -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,
@ -620,30 +623,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 +672,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) )
{
rend->DrawSliderThumb(dc, rectThumb, orient, flags | m_thumbFlags);
}
// then draw the ticks
if ( HasTicks() && rectUpdate.Intersects(m_rectTicks) )
{
rend->DrawSliderTicks(dc, m_rectTicks, rectThumb.GetSize(), orient,
m_min, m_max, m_tickFreq);
rend->DrawSliderTicks(dc, m_rectSlider, len, orient,
m_min, m_max, m_tickFreq, flags, style);
}
// then draw the thumb
if ( rectUpdate.Intersects(rectThumb) )
{
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_VERTICAL |
(GetWindowStyle() & wxSL_RIGHT ? wxALIGN_LEFT
: wxALIGN_RIGHT);
align = wxALIGN_CENTRE_HORIZONTAL|wxALIGN_TOP;
}
else // horz
else if (style & wxSL_BOTTOM)
{
align = wxALIGN_CENTRE;
align = wxALIGN_CENTRE_HORIZONTAL|wxALIGN_BOTTOM;
}
else if (style & wxSL_LEFT)
{
align = wxALIGN_CENTRE_VERTICAL|wxALIGN_LEFT;
}
else if (style & wxSL_RIGHT)
{
align = wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT;
}
dc.SetFont(GetFont());
@ -714,18 +734,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 +742,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);
}
@ -747,20 +755,20 @@ bool wxSlider::PerformAction(const wxControlAction& action,
ChangeValueBy(numArg * GetPageSize());
}
else if ( action == wxACTION_SLIDER_LINE_UP )
{
ChangeValueBy(+GetLineSize());
}
else if ( action == wxACTION_SLIDER_LINE_DOWN )
{
ChangeValueBy(-GetLineSize());
}
else if ( action == wxACTION_SLIDER_PAGE_UP )
{
return PerformAction(wxACTION_SLIDER_PAGE_CHANGE, -1);
}
else if ( action == wxACTION_SLIDER_LINE_DOWN )
{
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 )
{
@ -790,36 +798,37 @@ wxScrollThumb::Shaft wxSlider::HitTest(const wxPoint& pt) const
wxRect rectThumb;
CalcThumbRect(&rectShaft, &rectThumb, NULL);
// check for possible shaft or thumb hit
// check for possible shaft or thumb hit
if (!rectShaft.Inside(pt) && !rectThumb.Inside(pt))
{
return wxScrollThumb::Shaft_None;
}
// 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;
}
@ -881,23 +890,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()
@ -921,7 +951,7 @@ bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer,
const wxKeyEvent& event,
bool pressed)
{
if ( pressed )
if ( pressed )
{
int keycode = event.GetKeyCode();
@ -929,19 +959,19 @@ bool wxStdSliderButtonInputHandler::HandleKey(wxInputConsumer *consumer,
switch ( keycode )
{
case WXK_HOME:
action = wxACTION_SLIDER_START;
break;
case WXK_END:
action = wxACTION_SLIDER_END;
break;
case WXK_LEFT:
case WXK_END:
action = wxACTION_SLIDER_START;
break;
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;

View File

@ -184,21 +184,25 @@ public:
virtual void DrawSliderShaft(wxDC& dc,
const wxRect& rect,
int lenThumb,
wxOrientation orient,
int flags = 0,
long style = 0,
wxRect *rectShaft = NULL);
virtual void DrawSliderThumb(wxDC& dc,
const wxRect& rect,
wxOrientation orient,
int flags = 0);
int flags = 0,
long style = 0);
virtual void DrawSliderTicks(wxDC& dc,
const wxRect& rect,
const wxSize& sizeThumb,
int lenThumb,
wxOrientation orient,
int start,
int end,
int step,
int flags)
int step = 1,
int flags = 0,
long style = 0)
{
// we don't have the ticks in GTK version
}
@ -305,8 +309,11 @@ public:
virtual wxCoord GetSliderDim() const { return 15; }
virtual wxCoord GetSliderTickLen() const { return 0; }
virtual wxRect GetSliderShaftRect(const wxRect& rect,
wxOrientation orient) const;
int lenThumb,
wxOrientation orient,
long style = 0) const;
virtual wxSize GetSliderThumbSize(const wxRect& rect,
int lenThumb,
wxOrientation orient) const;
virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
@ -1865,13 +1872,14 @@ void wxGTKRenderer::DrawTab(wxDC& dc,
// ----------------------------------------------------------------------------
wxSize wxGTKRenderer::GetSliderThumbSize(const wxRect& rect,
int lenThumb,
wxOrientation orient) const
{
static const wxCoord SLIDER_THUMB_LENGTH = 30;
wxSize size;
wxRect rectShaft = GetSliderShaftRect(rect, orient);
wxRect rectShaft = GetSliderShaftRect(rect, lenThumb, orient);
if ( orient == wxHORIZONTAL )
{
size.x = wxMin(SLIDER_THUMB_LENGTH, rectShaft.width);
@ -1887,15 +1895,19 @@ wxSize wxGTKRenderer::GetSliderThumbSize(const wxRect& rect,
}
wxRect wxGTKRenderer::GetSliderShaftRect(const wxRect& rect,
wxOrientation WXUNUSED(orient)) const
int lenThumb,
wxOrientation WXUNUSED(orient),
long style) const
{
return rect.Deflate(2*BORDER_THICKNESS, 2*BORDER_THICKNESS);
}
void wxGTKRenderer::DrawSliderShaft(wxDC& dc,
const wxRect& rectOrig,
int lenThumb,
wxOrientation orient,
int flags,
long style,
wxRect *rectShaft)
{
wxRect rect = rectOrig;
@ -1922,7 +1934,8 @@ void wxGTKRenderer::DrawSliderShaft(wxDC& dc,
void wxGTKRenderer::DrawSliderThumb(wxDC& dc,
const wxRect& rectOrig,
wxOrientation orient,
int flags)
int flags,
long style)
{
// draw the thumb border
wxRect rect = rectOrig;

View File

@ -80,6 +80,10 @@ static const size_t WIDTH_STATUSBAR_GRIP_BAND = 4;
static const size_t STATUSBAR_GRIP_SIZE =
WIDTH_STATUSBAR_GRIP_BAND*NUM_STATUSBAR_GRIP_BANDS;
static const wxCoord SLIDER_MARGIN = 6; // margin around slider
static const wxCoord SLIDER_THUMB_LENGTH = 18;
static const wxCoord SLIDER_TICK_LENGTH = 6;
enum IndicatorType
{
IndicatorType_Check,
@ -253,21 +257,25 @@ public:
virtual void DrawSliderShaft(wxDC& dc,
const wxRect& rect,
int lenThumb,
wxOrientation orient,
int flags = 0,
long style = 0,
wxRect *rectShaft = NULL);
virtual void DrawSliderThumb(wxDC& dc,
const wxRect& rect,
wxOrientation orient,
int flags = 0);
int flags = 0,
long style = 0);
virtual void DrawSliderTicks(wxDC& dc,
const wxRect& rect,
const wxSize& sizeThumb,
int lenThumb,
wxOrientation orient,
int start,
int end,
int step = 1,
int flags = 0);
int flags = 0,
long style = 0);
virtual void DrawMenuBarItem(wxDC& dc,
const wxRect& rect,
@ -366,11 +374,14 @@ public:
virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
virtual wxSize GetTabPadding() const { return wxSize(6, 5); }
virtual wxCoord GetSliderDim() const { return 20; }
virtual wxCoord GetSliderTickLen() const { return 4; }
virtual wxCoord GetSliderDim() const { return SLIDER_THUMB_LENGTH + 2*BORDER_THICKNESS; }
virtual wxCoord GetSliderTickLen() const { return SLIDER_TICK_LENGTH; }
virtual wxRect GetSliderShaftRect(const wxRect& rect,
wxOrientation orient) const;
int lenThumb,
wxOrientation orient,
long style = 0) const;
virtual wxSize GetSliderThumbSize(const wxRect& rect,
int lenThumb,
wxOrientation orient) const;
virtual wxSize GetProgressBarStep() const { return wxSize(16, 32); }
@ -2571,52 +2582,80 @@ void wxWin32Renderer::DrawTab(wxDC& dc,
// ----------------------------------------------------------------------------
wxSize wxWin32Renderer::GetSliderThumbSize(const wxRect& rect,
int lenThumb,
wxOrientation orient) const
{
wxSize size;
wxCoord width = wxMax (lenThumb, SLIDER_THUMB_LENGTH) / 2;
wxCoord height = wxMax (lenThumb, SLIDER_THUMB_LENGTH);
wxRect rectShaft = GetSliderShaftRect(rect, orient);
if ( orient == wxHORIZONTAL )
if (orient == wxHORIZONTAL)
{
size.y = rect.height - 6;
size.x = wxMin(size.y / 2, rectShaft.width);
size.x = width;
size.y = height;
}
else // vertical
{
size.x = rect.width - 6;
size.y = wxMin(size.x / 2, rectShaft.height);
else
{ // == wxVERTICAL
size.x = height;
size.y = width;
}
return size;
}
wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
wxOrientation orient) const
int lenThumb,
wxOrientation orient,
long style) const
{
static const wxCoord SLIDER_MARGIN = 6;
bool transpose = (orient == wxVERTICAL);
bool left = ((style & wxSL_AUTOTICKS) != 0) &
(((style & wxSL_TOP) != 0) & !transpose |
((style & wxSL_LEFT) != 0) & transpose |
((style & wxSL_BOTH) != 0));
bool right = ((style & wxSL_AUTOTICKS) != 0) &
(((style & wxSL_BOTTOM) != 0) & !transpose |
((style & wxSL_RIGHT) != 0) & transpose |
((style & wxSL_BOTH) != 0));
wxRect rect = rectOrig;
if ( orient == wxHORIZONTAL )
{
// make the rect of minimal width and centre it
wxSize sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
if (orient == wxHORIZONTAL) {
rect.x += SLIDER_MARGIN;
if (left & right)
{
rect.y += wxMax ((rect.height - 2*BORDER_THICKNESS) / 2, sizeThumb.y/2);
}
else if (left)
{
rect.y += wxMax ((rect.height - 2*BORDER_THICKNESS - sizeThumb.y/2), sizeThumb.y/2);
}
else
{
rect.y += sizeThumb.y/2;
}
rect.width -= 2*SLIDER_MARGIN;
rect.height = 2*BORDER_THICKNESS;
rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
if ( rect.y < 0 )
rect.y = 0;
// leave margins on the sides
rect.Deflate(SLIDER_MARGIN, 0);
}
else // vertical
{
// same as above but in other direction
else
{ // == wxVERTICAL
rect.y += SLIDER_MARGIN;
if (left & right)
{
rect.x += wxMax ((rect.width - 2*BORDER_THICKNESS) / 2, sizeThumb.x/2);
}
else if (left)
{
rect.x += wxMax ((rect.width - 2*BORDER_THICKNESS - sizeThumb.x/2), sizeThumb.x/2);
}
else
{
rect.x += sizeThumb.x/2;
}
rect.width = 2*BORDER_THICKNESS;
rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
if ( rect.x < 0 )
rect.x = 0;
rect.Deflate(0, SLIDER_MARGIN);
rect.height -= 2*SLIDER_MARGIN;
}
return rect;
@ -2624,19 +2663,37 @@ wxRect wxWin32Renderer::GetSliderShaftRect(const wxRect& rectOrig,
void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
const wxRect& rectOrig,
int lenThumb,
wxOrientation orient,
int flags,
long style,
wxRect *rectShaft)
{
if ( flags & wxCONTROL_FOCUSED )
{
/* show shaft geometry
shaft
+-------------+
| |
| XXX | <-- x1
| XXX |
| XXX |
| XXX |
| XXX | <-- x2
| |
+-------------+
^ ^
| |
y1 y2
*/
if (flags & wxCONTROL_FOCUSED) {
DrawFocusRect(dc, rectOrig);
}
wxRect rect = GetSliderShaftRect(rectOrig, orient);
wxRect rect = GetSliderShaftRect(rectOrig, lenThumb, orient, style);
if ( rectShaft )
*rectShaft = rect;
if (rectShaft) *rectShaft = rect;
DrawSunkenBorder(dc, &rect);
}
@ -2644,26 +2701,31 @@ void wxWin32Renderer::DrawSliderShaft(wxDC& dc,
void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
const wxRect& rect,
wxOrientation orient,
int flags)
int flags,
long style)
{
/*
we are drawing a shape of this form
/* show thumb geometry
HHHHHHB <--- y
H DB
H DB
H DB where H is hightlight colour
H DB D dark grey
H DB B black
H DB
H DB <--- y3
H DB
HDB
B <--- y2
H <--- y1
H H B
H H B
H H B <--- y3
H D B
H D B
H D B
H D B where H is hightlight colour
H D B D dark grey
H D B B black
H D B
H D B
H D B <--- y4
H D B
H D B
B <--- y2
^ ^ ^
| | |
x x3 x2
^ ^ ^
| | |
x1 x3 x2
The interior of this shape is filled with the hatched brush if the thumb
is pressed.
@ -2671,51 +2733,81 @@ void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
DrawBackground(dc, wxNullColour, rect, flags);
bool transpose = orient == wxVERTICAL;
bool transpose = (orient == wxVERTICAL);
bool left = ((style & wxSL_AUTOTICKS) != 0) &
(((style & wxSL_TOP) != 0) & !transpose |
((style & wxSL_LEFT) != 0) & transpose) &
((style & wxSL_BOTH) == 0);
bool right = ((style & wxSL_AUTOTICKS) != 0) &
(((style & wxSL_BOTTOM) != 0) & !transpose |
((style & wxSL_RIGHT) != 0) & transpose) &
((style & wxSL_BOTH) == 0);
wxCoord x, y, x2, y2;
if ( transpose )
wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
wxCoord c = ((transpose ? rect.height : rect.width) - 2*sizeArrow);
wxCoord x1, x2, x3, y1, y2, y3, y4;
x1 = (transpose ? rect.y : rect.x);
x2 = (transpose ? rect.GetBottom() : rect.GetRight());
x3 = (x1-1+c) + sizeArrow;
y1 = (transpose ? rect.x : rect.y);
y2 = (transpose ? rect.GetRight() : rect.GetBottom());
y3 = (left ? (y1-1+c) + sizeArrow : y1);
y4 = (right ? (y2+1-c) - sizeArrow : y2);
dc.SetPen(m_penBlack);
if (left) {
DrawLine(dc, x3+1-c, y1, x2, y3, transpose);
}
DrawLine(dc, x2, y3, x2, y4, transpose);
if (right)
{
x = rect.y;
y = rect.x;
x2 = rect.GetBottom();
y2 = rect.GetRight();
DrawLine(dc, x3+1-c, y2, x2, y4, transpose);
}
else
{
x = rect.x;
y = rect.y;
x2 = rect.GetRight();
y2 = rect.GetBottom();
DrawLine(dc, x1, y2, x2, y2, transpose);
}
// the size of the pointed part of the thumb
wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
wxCoord x3 = x + sizeArrow,
y3 = y2 - sizeArrow;
dc.SetPen(m_penDarkGrey);
DrawLine(dc, x2-1, y3+1, x2-1, y4-1, transpose);
if (right) {
DrawLine(dc, x3+1-c, y2-1, x2-1, y4, transpose);
}
else
{
DrawLine(dc, x1+1, y2-1, x2-1, y2-1, transpose);
}
dc.SetPen(m_penHighlight);
DrawLine(dc, x, y, x2, y, transpose);
DrawLine(dc, x, y + 1, x, y2 - sizeArrow, transpose);
DrawLine(dc, x, y3, x3, y2, transpose);
dc.SetPen(m_penBlack);
DrawLine(dc, x3, y2, x2, y3, transpose);
DrawLine(dc, x2, y3, x2, y - 1, transpose);
dc.SetPen(m_penDarkGrey);
DrawLine(dc, x3, y2 - 1, x2 - 1, y3, transpose);
DrawLine(dc, x2 - 1, y3, x2 - 1, y, transpose);
if ( flags & wxCONTROL_PRESSED )
if (left)
{
DrawLine(dc, x1, y3, x3, y1, transpose);
DrawLine(dc, x3+1-c, y1+1, x2-1, y3, transpose);
}
else
{
DrawLine(dc, x1, y1, x2, y1, transpose);
}
DrawLine(dc, x1, y3, x1, y4, transpose);
if (right)
{
DrawLine(dc, x1, y4, x3+c, y2+c, transpose);
}
if (flags & wxCONTROL_PRESSED) {
// TODO: MSW fills the entire area inside, not just the rect
wxRect rectInt = rect;
if ( transpose )
rectInt.SetRight(y3);
{
rectInt.SetLeft(y3);
rectInt.SetRight(y4);
}
else
rectInt.SetBottom(y3);
{
rectInt.SetTop(y3);
rectInt.SetBottom(y4);
}
rectInt.Deflate(2);
#if !defined(__WXMGL__)
@ -2757,73 +2849,80 @@ void wxWin32Renderer::DrawSliderThumb(wxDC& dc,
void wxWin32Renderer::DrawSliderTicks(wxDC& dc,
const wxRect& rect,
const wxSize& sizeThumb,
int lenThumb,
wxOrientation orient,
int start,
int end,
int step,
int flags)
int flags,
long style)
{
if ( end == start )
{
// empty slider?
return;
}
/* show ticks geometry
// this would lead to an infinite loop below
wxCHECK_RET( step > 1, _T("invalid step in wxRenderer::DrawSliderTicks") );
left right
ticks shaft ticks
---- XX ---- <-- x1
---- XX ----
---- XX ----
---- XX ---- <-- x2
// the variable names correspond to horizontal case, but they can be used
// for both orientations
wxCoord x1, x2, y1, y2, len, widthThumb;
if ( orient == wxHORIZONTAL )
{
x1 = rect.GetLeft();
x2 = rect.GetRight();
^ ^ ^ ^
| | | |
y3 y1 y2 y4
*/
// draw from bottom to top to leave one pixel space between the ticks
// and the slider as Windows do
y1 = rect.GetBottom();
y2 = rect.GetTop();
// empty slider?
if (end == start) return;
len = rect.width;
bool transpose = (orient == wxVERTICAL);
bool left = ((style & wxSL_AUTOTICKS) != 0) &
(((style & wxSL_TOP) != 0) & !transpose |
((style & wxSL_LEFT) != 0) & transpose |
((style & wxSL_BOTH) != 0));
bool right = ((style & wxSL_AUTOTICKS) != 0) &
(((style & wxSL_BOTTOM) != 0) & !transpose |
((style & wxSL_RIGHT) != 0) & transpose |
((style & wxSL_BOTH) != 0));
widthThumb = sizeThumb.x;
}
else // vertical
{
x1 = rect.GetTop();
x2 = rect.GetBottom();
// default thumb size
wxSize sizeThumb = GetSliderThumbSize (rect, 0, orient);
wxCoord defaultLen = (transpose ? sizeThumb.x : sizeThumb.y);
y1 = rect.GetRight();
y2 = rect.GetLeft();
// normal thumb size
sizeThumb = GetSliderThumbSize (rect, lenThumb, orient);
wxCoord widthThumb = (transpose ? sizeThumb.y : sizeThumb.x);
len = rect.height;
wxRect rectShaft = GetSliderShaftRect (rect, lenThumb, orient, style);
widthThumb = sizeThumb.y;
}
// the first tick should be positioned in such way that a thumb drawn in
// the first position points down directly to it
x1 += widthThumb / 2;
x2 -= widthThumb / 2;
// this also means that we have slightly less space for the ticks in
// between the first and the last
len -= widthThumb;
wxCoord x1, x2, y1, y2, y3, y4 , len;
x1 = (transpose ? rectShaft.y : rectShaft.x) + widthThumb/2;
x2 = (transpose ? rectShaft.GetBottom() : rectShaft.GetRight()) - widthThumb/2;
y1 = (transpose ? rectShaft.x : rectShaft.y) - defaultLen/2;
y2 = (transpose ? rectShaft.GetRight() : rectShaft.GetBottom()) + defaultLen/2;
y3 = (transpose ? rect.x : rect.y);
y4 = (transpose ? rect.GetRight() : rect.GetBottom());
len = x2 - x1;
dc.SetPen(m_penBlack);
int range = end - start;
for ( int n = 0; n < range; n += step )
{
for ( int n = 0; n < range; n += step ) {
wxCoord x = x1 + (len*n) / range;
DrawLine(dc, x, y1, x, y2, orient == wxVERTICAL);
if (left & (y1 > y3)) {
DrawLine(dc, x, y1, x, y3, orient == wxVERTICAL);
}
if (right & (y4 > y2)) {
DrawLine(dc, x, y2, x, y4, orient == wxVERTICAL);
}
}
// always draw the line at the end position
DrawLine(dc, x2, y1, x2, y2, orient == wxVERTICAL);
if (left & (y1 > y3)) {
DrawLine(dc, x2, y1, x2, y3, orient == wxVERTICAL);
}
if (right & (y4 > y2)) {
DrawLine(dc, x2, y2, x2, y4, orient == wxVERTICAL);
}
}
// ----------------------------------------------------------------------------
@ -3987,6 +4086,18 @@ void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
size->y += 9;
}
// for compatibility with other ports, the buttons default size is never
// less than the standard one, but not when display not PDAs.
if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA)
{
if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
{
wxSize szDef = wxButton::GetDefaultSize();
if ( size->x < szDef.x )
size->x = szDef.x;
}
}
// no border width adjustments for buttons
return;
}