]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/scrolbar.cpp
don't try to add emission hook if GtkWidget type is not loaded
[wxWidgets.git] / src / univ / scrolbar.cpp
index f446c73f340bdb26b8656f0d271e60522253d7e9..b5e1253f3dcc38df73050a3bb1d5ccd880afa2ae 100644 (file)
@@ -298,9 +298,9 @@ wxSize wxScrollBar::DoGetBestClientSize() const
     return size;
 }
 
-wxScrollArrows::Arrow wxScrollBar::HitTest(const wxPoint& pt) const
+wxScrollArrows::Arrow wxScrollBar::HitTestArrow(const wxPoint& pt) const
 {
-    switch ( m_renderer->HitTestScrollbar(this, pt) )
+    switch ( HitTestBar(pt) )
     {
         case wxHT_SCROLLBAR_ARROW_LINE_1:
             return wxScrollArrows::Arrow_First;
@@ -313,6 +313,259 @@ wxScrollArrows::Arrow wxScrollBar::HitTest(const wxPoint& pt) const
     }
 }
 
+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( _T("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();
+}
+
 // ----------------------------------------------------------------------------
 // drawing
 // ----------------------------------------------------------------------------
@@ -331,7 +584,7 @@ void wxScrollBar::UpdateThumb()
         {
             if ( m_elementsState[n] & wxCONTROL_DIRTY )
             {
-                wxRect rect = GetRenderer()->GetScrollbarRect(this, (Element)n);
+                wxRect rect = GetScrollbarRect((Element)n);
 
                 if ( rect.width && rect.height )
                 {
@@ -365,9 +618,7 @@ void wxScrollBar::UpdateThumb()
                         }
 #else                   // efficient version: only repaint the area occupied by
                         // the thumb previously - we can't do better than this
-                        rect = GetRenderer()->GetScrollbarRect(this,
-                                                               Element_Thumb,
-                                                               m_thumbPosOld);
+                        rect = GetScrollbarRect(Element_Thumb, m_thumbPosOld);
 #endif // 0/1
                     }
 
@@ -589,6 +840,15 @@ bool wxScrollBar::ScrollPages(int nPages)
     return true;
 }
 
+/* static */
+wxInputHandler *wxScrollBar::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+    static wxStdScrollBarInputHandler
+        s_handler(wxTheme::Get()->GetRenderer(), handlerDef);
+
+    return &s_handler;
+}
+
 // ============================================================================
 // scroll bar input handler
 // ============================================================================
@@ -697,7 +957,7 @@ void wxStdScrollBarInputHandler::HandleThumbMove(wxScrollBar *scrollbar,
                                                  const wxMouseEvent& event)
 {
     int thumbPos = GetMouseCoord(scrollbar, event) - m_ofsMouse;
-    thumbPos = m_renderer->PixelToScrollbar(scrollbar, thumbPos);
+    thumbPos = scrollbar->PixelToScrollbar(thumbPos);
     scrollbar->PerformAction(wxACTION_SCROLL_THUMB_MOVE, thumbPos);
 }
 
@@ -737,15 +997,11 @@ bool wxStdScrollBarInputHandler::HandleMouse(wxInputConsumer *consumer,
 {
     // is this a click event from an acceptable button?
     int btn = event.GetButton();
-    if ( (btn != -1) && IsAllowedButton(btn) )
+    if ( btn == wxMOUSE_BTN_LEFT )
     {
         // determine which part of the window mouse is in
         wxScrollBar *scrollbar = wxStaticCast(consumer->GetInputWindow(), wxScrollBar);
-        wxHitTest ht = m_renderer->HitTestScrollbar
-                                   (
-                                    scrollbar,
-                                    event.GetPosition()
-                                   );
+        wxHitTest ht = scrollbar->HitTest(event.GetPosition());
 
         // when the mouse is pressed on any scrollbar element, we capture it
         // and hold capture until the same mouse button is released
@@ -783,7 +1039,7 @@ bool wxStdScrollBarInputHandler::HandleMouse(wxInputConsumer *consumer,
                     case wxHT_SCROLLBAR_THUMB:
                         consumer->PerformAction(wxACTION_SCROLL_THUMB_DRAG);
                         m_ofsMouse = GetMouseCoord(scrollbar, event) -
-                                     m_renderer->ScrollbarToPixel(scrollbar);
+                                     scrollbar->ScrollbarToPixel();
 
                         // fall through: there is no immediate action
 
@@ -866,11 +1122,7 @@ bool wxStdScrollBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
 
     if ( event.Dragging() )
     {
-        wxHitTest ht = m_renderer->HitTestScrollbar
-                                   (
-                                    scrollbar,
-                                    event.GetPosition()
-                                   );
+        wxHitTest ht = scrollbar->HitTestBar(event.GetPosition());
         if ( ht == m_htLast )
         {
             // nothing changed