// Author: Julian Smart
// Modified by:
// Created: 04/01/98
-// RCS-ID: $Id$
// Copyright: (c) Julian Smart 1998
// Vadim Zeitlin 2004
// Licence: wxWindows licence
} // anonymous namespace
-// ----------------------------------------------------------------------------
-// XTI
-// ----------------------------------------------------------------------------
-
-#if wxUSE_EXTENDED_RTTI
-WX_DEFINE_FLAGS( wxSliderStyle )
-
-wxBEGIN_FLAGS( wxSliderStyle )
- // new style border flags, we put them first to
- // use them for streaming out
- wxFLAGS_MEMBER(wxBORDER_SIMPLE)
- wxFLAGS_MEMBER(wxBORDER_SUNKEN)
- wxFLAGS_MEMBER(wxBORDER_DOUBLE)
- wxFLAGS_MEMBER(wxBORDER_RAISED)
- wxFLAGS_MEMBER(wxBORDER_STATIC)
- wxFLAGS_MEMBER(wxBORDER_NONE)
-
- // old style border flags
- wxFLAGS_MEMBER(wxSIMPLE_BORDER)
- wxFLAGS_MEMBER(wxSUNKEN_BORDER)
- wxFLAGS_MEMBER(wxDOUBLE_BORDER)
- wxFLAGS_MEMBER(wxRAISED_BORDER)
- wxFLAGS_MEMBER(wxSTATIC_BORDER)
- wxFLAGS_MEMBER(wxBORDER)
-
- // standard window styles
- wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
- wxFLAGS_MEMBER(wxCLIP_CHILDREN)
- wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
- wxFLAGS_MEMBER(wxWANTS_CHARS)
- wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
- wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
- wxFLAGS_MEMBER(wxVSCROLL)
- wxFLAGS_MEMBER(wxHSCROLL)
-
- wxFLAGS_MEMBER(wxSL_HORIZONTAL)
- wxFLAGS_MEMBER(wxSL_VERTICAL)
- wxFLAGS_MEMBER(wxSL_AUTOTICKS)
- wxFLAGS_MEMBER(wxSL_LEFT)
- wxFLAGS_MEMBER(wxSL_TOP)
- wxFLAGS_MEMBER(wxSL_RIGHT)
- wxFLAGS_MEMBER(wxSL_BOTTOM)
- wxFLAGS_MEMBER(wxSL_BOTH)
- wxFLAGS_MEMBER(wxSL_SELRANGE)
- wxFLAGS_MEMBER(wxSL_INVERSE)
- wxFLAGS_MEMBER(wxSL_MIN_MAX_LABELS)
- wxFLAGS_MEMBER(wxSL_VALUE_LABEL)
- wxFLAGS_MEMBER(wxSL_LABELS)
-
-wxEND_FLAGS( wxSliderStyle )
-
-IMPLEMENT_DYNAMIC_CLASS_XTI(wxSlider, wxControl,"wx/slider.h")
-
-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"))
- wxPROPERTY( Minimum , int , SetMin, GetMin, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( Maximum , int , SetMax, GetMax, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( PageSize , int , SetPageSize, GetLineSize, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( LineSize , int , SetLineSize, GetLineSize, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY( ThumbLength , int , SetThumbLength, GetThumbLength, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
- wxPROPERTY_FLAGS( WindowStyle , wxSliderStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
-wxEND_PROPERTIES_TABLE()
-
-wxBEGIN_HANDLERS_TABLE(wxSlider)
-wxEND_HANDLERS_TABLE()
-
-wxCONSTRUCTOR_8( wxSlider , wxWindow* , Parent , wxWindowID , Id , int , Value , int , Minimum , int , Maximum , wxPoint , Position , wxSize , Size , long , WindowStyle )
-#else
-IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
-#endif
-
// ============================================================================
// wxSlider implementation
// ============================================================================
// and initialize everything
SetRange(minValue, maxValue);
SetValue(value);
- SetPageSize((maxValue - minValue)/10);
+ SetPageSize( wxMax(1, (maxValue - minValue)/10) );
// we need to position the labels correctly if we have them and if
// SetSize() hadn't been called before (when best size was determined by
event.SetEventObject( this );
HandleWindowEvent(event);
- wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, GetId() );
+ wxCommandEvent cevent( wxEVT_SLIDER, GetId() );
cevent.SetInt( newPos );
cevent.SetEventObject( this );
{
if ( widthMin && widthMax )
{
- if ( HasFlag(wxSL_MIN_MAX_LABELS) )
- {
- *widthMin = GetTextExtent(Format(m_rangeMin)).x;
- *widthMax = GetTextExtent(Format(m_rangeMax)).x;
- }
- else
+ *widthMin = GetTextExtent(Format(m_rangeMin)).x;
+ *widthMax = GetTextExtent(Format(m_rangeMax)).x;
+
+ if ( HasFlag(wxSL_INVERSE) )
{
- *widthMin =
- *widthMax = 0;
+ wxSwap(*widthMin, *widthMax);
}
}
return;
}
- const int labelHeight = GetLabelsSize(&m_minLabelWidth, &m_maxLabelWidth);
- const int maxLabelWidth = wxMax(m_minLabelWidth, m_maxLabelWidth);
+ int minLabelWidth,
+ maxLabelWidth;
+ const int labelHeight = GetLabelsSize(&minLabelWidth, &maxLabelWidth);
+ const int longestLabelWidth = wxMax(minLabelWidth, maxLabelWidth);
+ if ( !HasFlag(wxSL_MIN_MAX_LABELS) )
+ {
+ minLabelWidth =
+ maxLabelWidth = 0;
+ }
- int labelOffset = 0;
int tickOffset = 0;
if ( HasFlag(wxSL_TICKS))
tickOffset = TICK;
// would return a wrong result and wrong size would be cached internally
if ( HasFlag(wxSL_VERTICAL) )
{
- int holdTopWidth;
+ int labelOffset = 0;
int holdTopX;
- int holdBottomWidth;
int holdBottomX;
- int xLabel = (wxMax((THUMB + (BORDERPAD * 2)), maxLabelWidth) / 2) -
- (maxLabelWidth / 2) + x;
+ int xLabel = (wxMax((THUMB + (BORDERPAD * 2)), longestLabelWidth) / 2) -
+ (longestLabelWidth / 2) + x;
if ( HasFlag(wxSL_LEFT) )
{
- if ( HasFlag(wxSL_MIN_MAX_LABELS) )
- {
- holdTopX = xLabel;
- holdTopWidth = m_minLabelWidth;
- holdBottomX = xLabel - ((m_maxLabelWidth - m_minLabelWidth) / 2);
- holdBottomWidth = m_maxLabelWidth;
- if ( HasFlag(wxSL_INVERSE) )
- {
- wxSwap(holdTopWidth, holdBottomWidth);
- wxSwap(holdTopX, holdBottomX);
- }
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
- holdTopX,
- y,
- holdTopWidth, labelHeight);
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
- holdBottomX,
- y + height - labelHeight,
- holdBottomWidth, labelHeight);
- }
- if ( HasFlag(wxSL_VALUE_LABEL) )
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
- x + THUMB + tickOffset + HGAP,
- y + (height - labelHeight)/2,
- maxLabelWidth, labelHeight);
+ holdTopX = xLabel;
+ holdBottomX = xLabel - (abs(maxLabelWidth - minLabelWidth) / 2);
}
else // wxSL_RIGHT
{
- if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+ holdTopX = xLabel + longestLabelWidth + (abs(maxLabelWidth - minLabelWidth) / 2);
+ holdBottomX = xLabel + longestLabelWidth;
+
+ labelOffset = longestLabelWidth + HGAP;
+ }
+
+ if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+ {
+ if ( HasFlag(wxSL_INVERSE) )
{
- holdTopX = xLabel + maxLabelWidth + ((m_maxLabelWidth - m_minLabelWidth) / 2);
- holdTopWidth = m_minLabelWidth;
- holdBottomX = xLabel + maxLabelWidth;
- holdBottomWidth = m_maxLabelWidth;
- if ( HasFlag(wxSL_INVERSE) )
- {
- wxSwap(holdTopWidth, holdBottomWidth);
- wxSwap(holdTopX, holdBottomX);
- }
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
- holdTopX,
- y,
- holdTopWidth, labelHeight);
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
- holdBottomX,
- y + height - labelHeight,
- holdBottomWidth, labelHeight);
+ wxSwap(holdTopX, holdBottomX);
}
- if ( HasFlag(wxSL_VALUE_LABEL) )
- labelOffset = maxLabelWidth + HGAP;
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
- x,
- y + (height - labelHeight)/2,
+
+ DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+ holdTopX,
+ y,
+ minLabelWidth, labelHeight);
+ DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+ holdBottomX,
+ y + height - labelHeight,
maxLabelWidth, labelHeight);
}
+ if ( HasFlag(wxSL_VALUE_LABEL) )
+ {
+ DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+ x + ( HasFlag(wxSL_LEFT) ? THUMB + tickOffset + HGAP : 0 ),
+ y + (height - labelHeight)/2,
+ longestLabelWidth, labelHeight);
+ }
+
// position the slider itself along the left/right edge
wxSliderBase::DoMoveWindow(
x + labelOffset,
}
else // horizontal
{
- int holdLeftWidth;
- int holdLeftX;
- int holdRightWidth;
- int holdRightX;
int yLabelMinMax =
(y + ((THUMB + tickOffset) / 2)) - (labelHeight / 2);
int xLabelValue =
- x + m_minLabelWidth +
- ((width - (m_minLabelWidth + m_maxLabelWidth)) / 2) -
- (m_maxLabelWidth / 2);
+ x + minLabelWidth +
+ ((width - (minLabelWidth + maxLabelWidth)) / 2) -
+ (longestLabelWidth / 2);
+
+ int ySlider = y;
- if ( HasFlag(wxSL_BOTTOM) )
+ if ( HasFlag(wxSL_VALUE_LABEL) )
{
- if ( HasFlag(wxSL_MIN_MAX_LABELS) )
- {
- holdLeftX = x;
- holdLeftWidth = m_minLabelWidth;
- holdRightX = x + width - m_maxLabelWidth;
- holdRightWidth = m_maxLabelWidth;
- if ( HasFlag(wxSL_INVERSE) )
- {
- wxSwap(holdLeftWidth, holdRightWidth);
- wxSwap(holdLeftX, holdRightX);
- }
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
- holdLeftX,
- yLabelMinMax,
- holdLeftWidth, labelHeight);
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
- holdRightX,
- yLabelMinMax,
- holdRightWidth, labelHeight);
- }
- if ( HasFlag(wxSL_VALUE_LABEL) )
+ DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
+ xLabelValue,
+ y + (HasFlag(wxSL_BOTTOM) ? 0 : THUMB + tickOffset),
+ longestLabelWidth, labelHeight);
+
+ if ( HasFlag(wxSL_BOTTOM) )
{
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
- xLabelValue,
- y - labelHeight,
- maxLabelWidth, labelHeight);
+ ySlider += labelHeight;
+ yLabelMinMax += labelHeight;
}
}
- else // wxSL_TOP
+
+ if ( HasFlag(wxSL_MIN_MAX_LABELS) )
{
- if ( HasFlag(wxSL_MIN_MAX_LABELS) )
- {
- holdLeftX = x;
- holdLeftWidth = m_minLabelWidth;
- holdRightX = x + width - m_maxLabelWidth;
- holdRightWidth = m_maxLabelWidth;
- if ( HasFlag(wxSL_INVERSE) )
- {
- wxSwap(holdLeftWidth, holdRightWidth);
- wxSwap(holdLeftX, holdRightX);
- }
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
- holdLeftX,
- yLabelMinMax,
- holdLeftWidth, labelHeight);
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
- holdRightX,
- yLabelMinMax,
- holdRightWidth, labelHeight);
- }
- if ( HasFlag(wxSL_VALUE_LABEL) )
- DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
- xLabelValue,
- y + THUMB + tickOffset,
- maxLabelWidth, labelHeight);
+ DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
+ x,
+ yLabelMinMax,
+ minLabelWidth, labelHeight);
+ DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
+ x + width - maxLabelWidth,
+ yLabelMinMax,
+ maxLabelWidth, labelHeight);
}
// position the slider itself along the top/bottom edge
- if ( HasFlag(wxSL_MIN_MAX_LABELS) || HasFlag(wxSL_VALUE_LABEL) )
- labelOffset = labelHeight;
wxSliderBase::DoMoveWindow(
- x + m_minLabelWidth + VGAP,
- y,
- width - (m_minLabelWidth + m_maxLabelWidth + (VGAP*2)),
+ x + minLabelWidth + VGAP,
+ ySlider,
+ width - (minLabelWidth + maxLabelWidth + (VGAP*2)),
THUMB + tickOffset);
}
}
int hLabel = GetLabelsSize(&widthMin, &widthMax);
// account for the labels
- size.x += HGAP + wxMax(widthMin, widthMax);
+ if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+ size.x += HGAP + wxMax(widthMin, widthMax);
// labels are indented relative to the slider itself
size.y += hLabel;
if ( m_labels )
{
- // labels add extra height
int labelSize = GetLabelsSize();
- if ( HasFlag(wxSL_MIN_MAX_LABELS) )
+
+ // Min/max labels are compensated by the ticks so we don't need
+ // extra space for them if we're also showing ticks.
+ if ( HasFlag(wxSL_MIN_MAX_LABELS) && !HasFlag(wxSL_TICKS) )
size.y += labelSize;
+
+ // The value label is always on top of the control and so does need
+ // extra space in any case.
if ( HasFlag(wxSL_VALUE_LABEL) )
- size.y += labelSize*2.75;
+ size.y += labelSize;
}
}
if ( m_labels )
{
- ::SetWindowText((*m_labels)[SliderLabel_Value], Format(value).wx_str());
+ ::SetWindowText((*m_labels)[SliderLabel_Value], Format(value).t_str());
}
}
void wxSlider::SetRange(int minValue, int maxValue)
{
+ // Remember the old logical value if we need to update the physical control
+ // value after changing its range in wxSL_INVERSE case (and avoid an
+ // unnecessary call to GetValue() otherwise as it's just not needed).
+ const int valueOld = HasFlag(wxSL_INVERSE) ? GetValue() : 0;
+
m_rangeMin = minValue;
m_rangeMax = maxValue;
if ( m_labels )
{
::SetWindowText((*m_labels)[SliderLabel_Min],
- Format(ValueInvertOrNot(m_rangeMin)).wx_str());
+ Format(ValueInvertOrNot(m_rangeMin)).t_str());
::SetWindowText((*m_labels)[SliderLabel_Max],
- Format(ValueInvertOrNot(m_rangeMax)).wx_str());
+ Format(ValueInvertOrNot(m_rangeMax)).t_str());
+ }
+
+ // When emulating wxSL_INVERSE style in wxWidgets, we need to update the
+ // value after changing the range to ensure that the value seen by the user
+ // code, i.e. the one returned by GetValue(), does not change.
+ if ( HasFlag(wxSL_INVERSE) )
+ {
+ ::SendMessage(GetHwnd(), TBM_SETPOS, TRUE, ValueInvertOrNot(valueOld));
}
}
-void wxSlider::SetTickFreq(int n, int pos)
+void wxSlider::DoSetTickFreq(int n)
{
m_tickFreq = n;
- ::SendMessage( GetHwnd(), TBM_SETTICFREQ, (WPARAM) n, (LPARAM) pos );
+ ::SendMessage( GetHwnd(), TBM_SETTICFREQ, (WPARAM) n, (LPARAM) 0 );
}
void wxSlider::SetPageSize(int pageSize)