Beispiel #1
0
void PlatformScrollbar::handleMouseMoveEventWhenCapturing(const PlatformMouseEvent& e)
{
    IntPoint pos = convertFromContainingWindow(e.pos());
    updateMousePosition(pos.x(), pos.y());

    if (m_captureStart != Thumb) {
        // FIXME: Invalidate only the portions that actually changed
        invalidate();
        return;
    }

    int xCancelDistance, yCancelDistance, backgroundSpan, thumbGirth, delta;
    // NOTE: The cancel distance calculations are based on the behavior of the
    // MSVC8 main window scrollbar + some guessing/extrapolation
    if (orientation() == HorizontalScrollbar) {
        xCancelDistance = kOffEndMultiplier * horizontalScrollbarHeight();
        yCancelDistance = kOffSideMultiplier * horizontalScrollbarHeight();
        backgroundSpan = m_segmentRects[AfterThumb].right() -
            m_segmentRects[BeforeThumb].x();
        thumbGirth = m_segmentRects[Thumb].right() - m_segmentRects[Thumb].x();
        delta = pos.x() - m_dragOrigin.thumbPos;
    } else {
        xCancelDistance = kOffSideMultiplier * verticalScrollbarWidth();
        yCancelDistance = kOffEndMultiplier * verticalScrollbarWidth();
        backgroundSpan = m_segmentRects[AfterThumb].bottom() -
            m_segmentRects[BeforeThumb].y();
        thumbGirth = m_segmentRects[Thumb].bottom() - m_segmentRects[Thumb].y();
        delta = pos.y() - m_dragOrigin.thumbPos;
    }

    // Snap scrollbar back to drag origin if mouse gets too far away
    if ((m_lastNativePos.x() <
            (m_segmentRects[BeforeThumb].x() - xCancelDistance)) ||
        (m_lastNativePos.x() >
            (m_segmentRects[AfterThumb].right() + xCancelDistance)) ||
        (m_lastNativePos.y() <
            (m_segmentRects[BeforeThumb].y() - yCancelDistance)) ||
        (m_lastNativePos.y() >
            (m_segmentRects[AfterThumb].bottom() + yCancelDistance)))
        delta = 0;

    // Convert delta from pixel coords to scrollbar logical coords
    if (backgroundSpan > thumbGirth) {
        if (setValue(m_dragOrigin.scrollVal + (delta *
            (m_totalSize - m_visibleSize) / (backgroundSpan - thumbGirth)))) {
            m_needsLayout = true;
            // FIXME: Invalidate only the portions that actually changed
            invalidate();
        }
    }
}
PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size)
    : Scrollbar(client, orientation, size)
    , m_pressedPos(0)
    , m_pressedPart(QStyle::SC_None)
    , m_hoveredPart(QStyle::SC_None)
    , m_scrollTimer(this, &PlatformScrollbar::autoscrollTimerFired)
{
    QStyle *s = QApplication::style();

    m_opt.state = QStyle::State_Active | QStyle::State_Enabled;
    m_opt.sliderValue = m_opt.sliderPosition = 0;
    m_opt.upsideDown = false;
    setEnabled(true);
    if (size != RegularScrollbar)
        m_opt.state |= QStyle::State_Mini;
    if (orientation == HorizontalScrollbar) {
        m_opt.rect.setHeight(horizontalScrollbarHeight(size));
        m_opt.orientation = Qt::Horizontal;
        m_opt.state |= QStyle::State_Horizontal;
    } else {
        m_opt.rect.setWidth(verticalScrollbarWidth(size));
        m_opt.orientation = Qt::Vertical;
        m_opt.state &= ~QStyle::State_Horizontal;
    }
}
void PlatformScrollbar::paint(GraphicsContext* graphicsContext, const IntRect& damageRect)
{
    if (controlSize() != RegularScrollbar) {
        m_opt.state |= QStyle::State_Mini;
    } else {
        m_opt.state &= ~QStyle::State_Mini;
    }
    m_opt.orientation = (orientation() == VerticalScrollbar) ? Qt::Vertical : Qt::Horizontal;
    QStyle *s = QApplication::style();
    if (orientation() == HorizontalScrollbar) {
        m_opt.rect.setHeight(horizontalScrollbarHeight(controlSize()));
        m_opt.state |= QStyle::State_Horizontal;
    } else {
        m_opt.rect.setWidth(verticalScrollbarWidth(controlSize()));
        m_opt.state &= ~QStyle::State_Horizontal;
    }

    if (graphicsContext->paintingDisabled() || !m_opt.rect.isValid())
        return;

    QRect clip = m_opt.rect.intersected(damageRect);
    // Don't paint anything if the scrollbar doesn't intersect the damage rect.
    if (clip.isEmpty())
        return;

    QPainter *p = graphicsContext->platformContext();
    p->save();
    p->setClipRect(clip);
    m_opt.sliderValue = value();
    m_opt.sliderPosition = value();
    m_opt.pageStep = m_visibleSize;
    m_opt.singleStep = m_lineStep;
    m_opt.minimum = 0;
    m_opt.maximum = qMax(0, m_totalSize - m_visibleSize);
    if (m_pressedPart != QStyle::SC_None) {
        m_opt.activeSubControls = m_pressedPart;
    } else {
        m_opt.activeSubControls = m_hoveredPart;
    }

    const QPoint topLeft = m_opt.rect.topLeft();
#ifdef Q_WS_MAC
    QApplication::style()->drawComplexControl(QStyle::CC_ScrollBar, &m_opt, p, 0);
#else
    p->translate(topLeft);
    m_opt.rect.moveTo(QPoint(0, 0));

    // The QStyle expects the background to be already filled
    p->fillRect(m_opt.rect, m_opt.palette.background());

    QApplication::style()->drawComplexControl(QStyle::CC_ScrollBar, &m_opt, p, 0);
    m_opt.rect.moveTo(topLeft);
#endif
    p->restore();
}
Beispiel #4
0
void PlatformScrollbar::layout()
{
#if PLATFORM(WIN_OS)
    if (!m_needsLayout)
        return;
    m_needsLayout = false;

    const IntRect invalid(-1, -1, 0, 0);
    if (m_totalSize <= 0) {
        for (int i = 0; i < NumSegments; ++i)
            m_segmentRects[i] = invalid;
        return;
    }

    int buttonGirth, backgroundSpan, thumbGirth;
    RECT box = {0};
    LONG* changingCoord1, * changingCoord2;
    // For both orientations, we allow the buttonGirth to determine the
    // backgroundSpan directly, to avoid rounding errors.
    if (orientation() == HorizontalScrollbar) {
        buttonGirth = scrollButtonGirth(SM_CXHSCROLL, width(), &backgroundSpan);
        thumbGirth = scrollThumbGirth(SM_CXHTHUMB, backgroundSpan);
        box.bottom += horizontalScrollbarHeight();
        changingCoord1 = &box.left;
        changingCoord2 = &box.right;
    } else {
        buttonGirth = scrollButtonGirth(SM_CYVSCROLL, height(),
                                        &backgroundSpan);
        thumbGirth = scrollThumbGirth(SM_CYVTHUMB, backgroundSpan);
        box.right += verticalScrollbarWidth();
        changingCoord1 = &box.top;
        changingCoord2 = &box.bottom;
    }

    // Scrollbar:       |<|--------|XXX|------|>|
    // Start arrow:     |<|
    *changingCoord2 += buttonGirth;
    m_segmentRects[Arrow1] = gfx::RECTToSkIRect(box);

    if (thumbGirth >= backgroundSpan) {
        if (backgroundSpan == 0) {
            m_segmentRects[Track] = invalid;
        } else {
            // Track:     |-------------------|
            *changingCoord1 = *changingCoord2;
            *changingCoord2 += backgroundSpan;
            m_segmentRects[Track] = gfx::RECTToSkIRect(box);
        }

        m_segmentRects[BeforeThumb] = invalid;
        m_segmentRects[Thumb] = invalid;
        m_segmentRects[AfterThumb] = invalid;
    } else {
        m_segmentRects[Track] = invalid;

        const int thumbOffset = (m_totalSize <= m_visibleSize) ? 0 : (value() *
            (backgroundSpan - thumbGirth) / (m_totalSize - m_visibleSize));
        // Before thumb:  |--------|
        *changingCoord1 = *changingCoord2;
        *changingCoord2 += thumbOffset;
        m_segmentRects[BeforeThumb] = gfx::RECTToSkIRect(box);

        // Thumb:                  |XXX|
        *changingCoord1 = *changingCoord2;
        *changingCoord2 += thumbGirth;
        m_segmentRects[Thumb] = gfx::RECTToSkIRect(box);

        // After thumb:                |------|
        *changingCoord1 = *changingCoord2;
        *changingCoord2 += backgroundSpan - (thumbOffset + thumbGirth);
        m_segmentRects[AfterThumb] = gfx::RECTToSkIRect(box);
    }

    // End arrow:                             |>|
    *changingCoord1 = *changingCoord2;
    *changingCoord2 += buttonGirth;
    m_segmentRects[Arrow2] = gfx::RECTToSkIRect(box);

    // Changed layout, so need to update m_mouseOver and m_autorepeatTimer
    updateMousePositionInternal();

    // DO NOT invalidate() here.  We already invalidate()d for this layout when
    // setting m_needsLayout = true; by the time we reach this point, we're
    // called by paint(), so invalidate() is not only unnecessary but will
    // waste effort.
#endif
}
Beispiel #5
0
int PlatformScrollbar::height() const
{
    return orientation() == HorizontalScrollbar ?
        horizontalScrollbarHeight(controlSize()) : Widget::height();
}