+wxHitTest wxScrollBar::HitTestBar(const wxPoint& pt) const
+{
+ // we only need to work with either x or y coord depending on the
+ // orientation, choose one (but still check the other one to verify if the
+ // mouse is in the window at all)
+ const wxSize sizeArrowSB = m_renderer->GetScrollbarArrowSize();
+
+ wxCoord coord, sizeArrow, sizeTotal;
+ wxSize size = GetSize();
+ if ( GetWindowStyle() & wxVERTICAL )
+ {
+ if ( pt.x < 0 || pt.x > size.x )
+ return wxHT_NOWHERE;
+
+ coord = pt.y;
+ sizeArrow = sizeArrowSB.y;
+ sizeTotal = size.y;
+ }
+ else // horizontal
+ {
+ if ( pt.y < 0 || pt.y > size.y )
+ return wxHT_NOWHERE;
+
+ coord = pt.x;
+ sizeArrow = sizeArrowSB.x;
+ sizeTotal = size.x;
+ }
+
+ // test for the arrows first as it's faster
+ if ( coord < 0 || coord > sizeTotal )
+ {
+ return wxHT_NOWHERE;
+ }
+ else if ( coord < sizeArrow )
+ {
+ return wxHT_SCROLLBAR_ARROW_LINE_1;
+ }
+ else if ( coord > sizeTotal - sizeArrow )
+ {
+ return wxHT_SCROLLBAR_ARROW_LINE_2;
+ }
+ else
+ {
+ // calculate the thumb position in pixels
+ sizeTotal -= 2*sizeArrow;
+ wxCoord thumbStart, thumbEnd;
+ int range = GetRange();
+ if ( !range )
+ {
+ // clicking the scrollbar without range has no effect
+ return wxHT_NOWHERE;
+ }
+ else
+ {
+ GetScrollBarThumbSize(sizeTotal,
+ GetThumbPosition(),
+ GetThumbSize(),
+ range,
+ &thumbStart,
+ &thumbEnd);
+ }
+
+ // now compare with the thumb position
+ coord -= sizeArrow;
+ if ( coord < thumbStart )
+ return wxHT_SCROLLBAR_BAR_1;
+ else if ( coord > thumbEnd )
+ return wxHT_SCROLLBAR_BAR_2;
+ else
+ return wxHT_SCROLLBAR_THUMB;
+ }
+}
+
+/* static */
+void wxScrollBar::GetScrollBarThumbSize(wxCoord length,
+ int thumbPos,
+ int thumbSize,
+ int range,
+ wxCoord *thumbStart,
+ wxCoord *thumbEnd)
+{
+ // the thumb can't be made less than this number of pixels
+ static const wxCoord thumbMinWidth = 8; // FIXME: should be configurable
+
+ *thumbStart = (length*thumbPos) / range;
+ *thumbEnd = (length*(thumbPos + thumbSize)) / range;
+
+ if ( *thumbEnd - *thumbStart < thumbMinWidth )
+ {
+ // adjust the end if possible
+ if ( *thumbStart <= length - thumbMinWidth )
+ {
+ // yes, just make it wider
+ *thumbEnd = *thumbStart + thumbMinWidth;
+ }
+ else // it is at the bottom of the scrollbar
+ {
+ // so move it a bit up
+ *thumbStart = length - thumbMinWidth;
+ *thumbEnd = length;
+ }
+ }
+}
+
+wxRect wxScrollBar::GetScrollbarRect(wxScrollBar::Element elem,
+ int thumbPos) const
+{
+ if ( thumbPos == -1 )
+ {
+ thumbPos = GetThumbPosition();
+ }
+
+ const wxSize sizeArrow = m_renderer->GetScrollbarArrowSize();
+
+ wxSize sizeTotal = GetClientSize();
+ wxCoord *start, *width;
+ wxCoord length, arrow;
+ wxRect rect;
+ if ( IsVertical() )
+ {
+ rect.x = 0;
+ rect.width = sizeTotal.x;
+ length = sizeTotal.y;
+ start = &rect.y;
+ width = &rect.height;
+ arrow = sizeArrow.y;
+ }
+ else // horizontal
+ {
+ rect.y = 0;
+ rect.height = sizeTotal.y;
+ length = sizeTotal.x;
+ start = &rect.x;
+ width = &rect.width;
+ arrow = sizeArrow.x;
+ }
+
+ switch ( elem )
+ {
+ case wxScrollBar::Element_Arrow_Line_1:
+ *start = 0;
+ *width = arrow;
+ break;
+
+ case wxScrollBar::Element_Arrow_Line_2:
+ *start = length - arrow;
+ *width = arrow;
+ break;
+
+ case wxScrollBar::Element_Arrow_Page_1:
+ case wxScrollBar::Element_Arrow_Page_2:
+ // we don't have them at all
+ break;
+
+ case wxScrollBar::Element_Thumb:
+ case wxScrollBar::Element_Bar_1:
+ case wxScrollBar::Element_Bar_2:
+ // we need to calculate the thumb position - do it
+ {
+ length -= 2*arrow;
+ wxCoord thumbStart, thumbEnd;
+ int range = GetRange();
+ if ( !range )
+ {
+ thumbStart =
+ thumbEnd = 0;
+ }
+ else
+ {
+ GetScrollBarThumbSize(length,
+ thumbPos,
+ GetThumbSize(),
+ range,
+ &thumbStart,
+ &thumbEnd);
+ }
+
+ if ( elem == wxScrollBar::Element_Thumb )
+ {
+ *start = thumbStart;
+ *width = thumbEnd - thumbStart;
+ }
+ else if ( elem == wxScrollBar::Element_Bar_1 )
+ {
+ *start = 0;
+ *width = thumbStart;
+ }
+ else // elem == wxScrollBar::Element_Bar_2
+ {
+ *start = thumbEnd;
+ *width = length - thumbEnd;
+ }
+
+ // everything is relative to the start of the shaft so far
+ *start += arrow;
+ }
+ break;
+
+ case wxScrollBar::Element_Max:
+ default:
+ wxFAIL_MSG( wxT("unknown scrollbar element") );
+ }
+
+ return rect;
+}
+
+wxCoord wxScrollBar::GetScrollbarSize() const
+{
+ const wxSize sizeArrowSB = m_renderer->GetScrollbarArrowSize();
+
+ wxCoord sizeArrow, sizeTotal;
+ if ( GetWindowStyle() & wxVERTICAL )
+ {
+ sizeArrow = sizeArrowSB.y;
+ sizeTotal = GetSize().y;
+ }
+ else // horizontal
+ {
+ sizeArrow = sizeArrowSB.x;
+ sizeTotal = GetSize().x;
+ }
+
+ return sizeTotal - 2*sizeArrow;
+}
+
+
+wxCoord wxScrollBar::ScrollbarToPixel(int thumbPos)
+{
+ int range = GetRange();
+ if ( !range )
+ {
+ // the only valid position anyhow
+ return 0;
+ }
+
+ if ( thumbPos == -1 )
+ {
+ // by default use the current thumb position
+ thumbPos = GetThumbPosition();
+ }
+
+ const wxSize sizeArrow = m_renderer->GetScrollbarArrowSize();
+ return (thumbPos * GetScrollbarSize()) / range
+ + (IsVertical() ? sizeArrow.y : sizeArrow.x);
+}
+
+int wxScrollBar::PixelToScrollbar(wxCoord coord)
+{
+ const wxSize sizeArrow = m_renderer->GetScrollbarArrowSize();
+ return ((coord - (IsVertical() ? sizeArrow.y : sizeArrow.x)) *
+ GetRange() ) / GetScrollbarSize();
+}
+