diff options
Diffstat (limited to 'src/quicktemplates2/qquickscrollbar.cpp')
-rw-r--r-- | src/quicktemplates2/qquickscrollbar.cpp | 1234 |
1 files changed, 0 insertions, 1234 deletions
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp deleted file mode 100644 index cc338b65..00000000 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ /dev/null @@ -1,1234 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickscrollbar_p.h" -#include "qquickscrollbar_p_p.h" -#include "qquickscrollview_p.h" - -#include <QtQml/qqmlinfo.h> -#include <QtQuick/private/qquickflickable_p.h> -#if QT_CONFIG(accessibility) -#include <QtQuick/private/qquickaccessibleattached_p.h> -#endif - -QT_BEGIN_NAMESPACE - -/*! - \qmltype ScrollBar - \inherits Control -//! \instantiates QQuickScrollBar - \inqmlmodule QtQuick.Controls - \since 5.7 - \ingroup qtquickcontrols2-indicators - \brief Vertical or horizontal interactive scroll bar. - - \image qtquickcontrols2-scrollbar.gif - - ScrollBar is an interactive bar that can be used to scroll to a specific - position. A scroll bar can be either \l vertical or \l horizontal, and can - be attached to any \l Flickable, such as \l ListView and \l GridView. - - \code - Flickable { - // ... - ScrollBar.vertical: ScrollBar { } - } - \endcode - - \section1 Attaching ScrollBar to a Flickable - - When ScrollBar is attached \l {ScrollBar::vertical}{vertically} or - \l {ScrollBar::horizontal}{horizontally} to a Flickable, its geometry and - the following properties are automatically set and updated as appropriate: - - \list - \li \l orientation - \li \l position - \li \l size - \li \l active - \endlist - - An attached ScrollBar re-parents itself to the target Flickable. A vertically - attached ScrollBar resizes itself to the height of the Flickable, and positions - itself to either side of it based on the \l {Control::mirrored}{layout direction}. - A horizontally attached ScrollBar resizes itself to the width of the Flickable, - and positions itself to the bottom. The automatic geometry management can be disabled - by specifying another parent for the attached ScrollBar. This can be useful, for - example, if the ScrollBar should be placed outside a clipping Flickable. This is - demonstrated by the following example: - - \code - Flickable { - id: flickable - clip: true - // ... - ScrollBar.vertical: ScrollBar { - parent: flickable.parent - anchors.top: flickable.top - anchors.left: flickable.right - anchors.bottom: flickable.bottom - } - } - \endcode - - Notice that ScrollBar does not filter key events of the Flickable it is - attached to. The following example illustrates how to implement scrolling - with up and down keys: - - \code - Flickable { - focus: true - - Keys.onUpPressed: scrollBar.decrease() - Keys.onDownPressed: scrollBar.increase() - - ScrollBar.vertical: ScrollBar { id: scrollBar } - } - \endcode - - \section1 Binding the Active State of Horizontal and Vertical Scroll Bars - - Horizontal and vertical scroll bars do not share the \l active state with - each other by default. In order to keep both bars visible whilst scrolling - to either direction, establish a two-way binding between the active states - as presented by the following example: - - \snippet qtquickcontrols2-scrollbar-active.qml 1 - - \section1 Non-attached Scroll Bars - - It is possible to create an instance of ScrollBar without using the - attached property API. This is useful when the behavior of the attached - scroll bar is not sufficient or a \l Flickable is not in use. In the - following example, horizontal and vertical scroll bars are used to - scroll over the text without using \l Flickable: - - \snippet qtquickcontrols2-scrollbar-non-attached.qml 1 - - \image qtquickcontrols2-scrollbar-non-attached.png - - When using a non-attached ScrollBar, the following must be done manually: - - \list - \li Layout the scroll bar (with the \l {Item::}{x} and \l {Item::}{y} or - \l {Item::}{anchors} property, for example). - \li Set the \l size and \l position properties to determine the size and position - of the scroll bar in relation to the scrolled item. - \li Set the \l active property to determine when the scroll bar will be - visible. - \endlist - - \sa ScrollIndicator, {Customizing ScrollBar}, {Indicator Controls} -*/ - -static const QQuickItemPrivate::ChangeTypes changeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed; -static const QQuickItemPrivate::ChangeTypes horizontalChangeTypes = changeTypes | QQuickItemPrivate::ImplicitHeight; -static const QQuickItemPrivate::ChangeTypes verticalChangeTypes = changeTypes | QQuickItemPrivate::ImplicitWidth; - -QQuickScrollBarPrivate::VisualArea QQuickScrollBarPrivate::visualArea() const -{ - qreal visualPos = position; - if (minimumSize > size) - visualPos = position / (1.0 - size) * (1.0 - minimumSize); - - qreal visualSize = qBound<qreal>(0, qMax(size, minimumSize) + qMin<qreal>(0, visualPos), 1.0 - visualPos); - - visualPos = qBound<qreal>(0, visualPos, 1.0 - visualSize); - - return VisualArea(visualPos, visualSize); -} - -qreal QQuickScrollBarPrivate::logicalPosition(qreal position) const -{ - if (minimumSize > size) - return position * (1.0 - size) / (1.0 - minimumSize); - return position; -} - -qreal QQuickScrollBarPrivate::snapPosition(qreal position) const -{ - const qreal effectiveStep = stepSize * (1.0 - size); - if (qFuzzyIsNull(effectiveStep)) - return position; - - return qRound(position / effectiveStep) * effectiveStep; -} - -qreal QQuickScrollBarPrivate::positionAt(const QPointF &point) const -{ - Q_Q(const QQuickScrollBar); - if (orientation == Qt::Horizontal) - return logicalPosition(point.x() - q->leftPadding()) / q->availableWidth(); - else - return logicalPosition(point.y() - q->topPadding()) / q->availableHeight(); -} - -void QQuickScrollBarPrivate::setInteractive(bool enabled) -{ - Q_Q(QQuickScrollBar); - if (interactive == enabled) - return; - - interactive = enabled; - if (interactive) { - q->setAcceptedMouseButtons(Qt::LeftButton); -#if QT_CONFIG(quicktemplates2_multitouch) - q->setAcceptTouchEvents(true); -#endif -#if QT_CONFIG(cursor) - q->setCursor(Qt::ArrowCursor); -#endif - } else { - q->setAcceptedMouseButtons(Qt::NoButton); -#if QT_CONFIG(quicktemplates2_multitouch) - q->setAcceptTouchEvents(false); -#endif -#if QT_CONFIG(cursor) - q->unsetCursor(); -#endif - q->ungrabMouse(); - } - emit q->interactiveChanged(); -} - -void QQuickScrollBarPrivate::updateActive() -{ - Q_Q(QQuickScrollBar); -#if QT_CONFIG(quicktemplates2_hover) - bool hover = hovered; -#else - bool hover = false; -#endif - q->setActive(moving || (interactive && (pressed || hover))); -} - -void QQuickScrollBarPrivate::resizeContent() -{ - Q_Q(QQuickScrollBar); - if (!contentItem) - return; - - // - negative overshoot (pos < 0): clamp the pos to 0, and deduct the overshoot from the size - // - positive overshoot (pos + size > 1): clamp the size to 1-pos - const VisualArea visual = visualArea(); - - if (orientation == Qt::Horizontal) { - contentItem->setPosition(QPointF(q->leftPadding() + visual.position * q->availableWidth(), q->topPadding())); - contentItem->setSize(QSizeF(q->availableWidth() * visual.size, q->availableHeight())); - } else { - contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + visual.position * q->availableHeight())); - contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * visual.size)); - } -} - -void QQuickScrollBarPrivate::itemImplicitWidthChanged(QQuickItem *item) -{ - Q_Q(QQuickScrollBar); - QQuickControlPrivate::itemImplicitWidthChanged(item); - QQuickIndicatorButton *indicatorButton = q->decreaseVisual(); - if (!indicatorButton || item != indicatorButton->indicator()) { - indicatorButton = q->increaseVisual(); - if (!indicatorButton || item != indicatorButton->indicator()) - return; - } - if (indicatorButton) - emit indicatorButton->implicitIndicatorWidthChanged(); -} - -void QQuickScrollBarPrivate::itemImplicitHeightChanged(QQuickItem *item) -{ - Q_Q(QQuickScrollBar); - QQuickControlPrivate::itemImplicitHeightChanged(item); - QQuickIndicatorButton *indicatorButton = q->decreaseVisual(); - if (!indicatorButton || item != indicatorButton->indicator()) { - indicatorButton = q->increaseVisual(); - if (!indicatorButton || item != indicatorButton->indicator()) - return; - } - if (indicatorButton) - emit indicatorButton->implicitIndicatorHeightChanged(); -} - -void QQuickScrollBarPrivate::handlePress(const QPointF &point) -{ - Q_Q(QQuickScrollBar); - QQuickControlPrivate::handlePress(point); - if (QQuickIndicatorButton *indicatorButton = q->decreaseVisual()) { - QQuickItem *decreaseArrow = indicatorButton->indicator(); - if (decreaseArrow && decreaseArrow->contains(q->mapToItem(decreaseArrow, point + QPointF(0.5, 0.5)))) { - indicatorButton->setPressed(true); - q->decrease(); - return; - } - } - - if (QQuickIndicatorButton *increaseObject = q->increaseVisual()) { - QQuickItem *increaseArrow = increaseObject->indicator(); - if (increaseArrow && increaseArrow->contains(q->mapToItem(increaseArrow, point + QPointF(0.5, 0.5)))) { - increaseObject->setPressed(true); - q->increase(); - return; - } - } - - offset = positionAt(point) - position; - qreal sz = qMax(size, logicalPosition(minimumSize)); - if (offset < 0 || offset > sz) - offset = sz / 2; - q->setPressed(true); -} - -void QQuickScrollBarPrivate::handleMove(const QPointF &point) -{ - Q_Q(QQuickScrollBar); - QQuickControlPrivate::handleMove(point); - - /* - * handleMove() will be called as soon as you hold the mouse button down *anywhere* on the - * ScrollBar, including the increase/decrease button indicator areas. So without the following - * early return, it would move the scrollbar handle to one of its extremeties. That would - * ruin the behavior we would like when clicking e.g. the "increase button": To step the - * scrollbar gently. - */ - if (!pressed) - return; - qreal pos = qBound<qreal>(0.0, positionAt(point) - offset, 1.0 - size); - if (snapMode == QQuickScrollBar::SnapAlways) - pos = snapPosition(pos); - q->setPosition(pos); -} - -void QQuickScrollBarPrivate::handleRelease(const QPointF &point) -{ - Q_Q(QQuickScrollBar); - QQuickControlPrivate::handleRelease(point); - - if (orientation == Qt::Vertical) { - if (point.y() < q->topPadding() || point.y() >= (q->height() - q->bottomPadding())) - return; - } else /* orientation == Qt::Horizontal */{ - if (point.x() < q->leftPadding() || point.x() >= (q->width() - q->rightPadding())) - return; - } - qreal pos = qBound<qreal>(0.0, positionAt(point) - offset, 1.0 - size); - if (snapMode != QQuickScrollBar::NoSnap) - pos = snapPosition(pos); - q->setPosition(pos); - offset = 0.0; - q->setPressed(false); -} - -void QQuickScrollBarPrivate::handleUngrab() -{ - Q_Q(QQuickScrollBar); - QQuickControlPrivate::handleUngrab(); - offset = 0.0; - q->setPressed(false); -} - -void QQuickScrollBarPrivate::visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea) -{ - Q_Q(QQuickScrollBar); - if (!qFuzzyCompare(newVisualArea.size, oldVisualArea.size)) - emit q->visualSizeChanged(); - if (!qFuzzyCompare(newVisualArea.position, oldVisualArea.position)) - emit q->visualPositionChanged(); -} - -void QQuickScrollBarPrivate::updateHover(const QPointF &pos, std::optional<bool> newHoverState) -{ - Q_Q(QQuickScrollBar); - auto updateHoverOnButton = [&](QQuickIndicatorButton *sbButton) { - if (sbButton) { - bool hovered = newHoverState.value_or(false); - if (!newHoverState.has_value()) { - if (QQuickItem *indicator = sbButton->indicator()) - hovered = indicator->contains(q->mapToItem(indicator, pos)); - } - sbButton->setHovered(hovered); - } - }; - updateHoverOnButton(q->decreaseVisual()); - updateHoverOnButton(q->increaseVisual()); -} - -QQuickScrollBar::QQuickScrollBar(QQuickItem *parent) - : QQuickControl(*(new QQuickScrollBarPrivate), parent) -{ - Q_D(QQuickScrollBar); - d->decreaseVisual = new QQuickIndicatorButton(this); - d->increaseVisual = new QQuickIndicatorButton(this); - setKeepMouseGrab(true); - setAcceptedMouseButtons(Qt::LeftButton); -#if QT_CONFIG(quicktemplates2_multitouch) - setAcceptTouchEvents(true); -#endif -#if QT_CONFIG(cursor) - setCursor(Qt::ArrowCursor); -#endif -} - -QQuickScrollBarAttached *QQuickScrollBar::qmlAttachedProperties(QObject *object) -{ - return new QQuickScrollBarAttached(object); -} - -/*! - \qmlproperty real QtQuick.Controls::ScrollBar::size - - This property holds the size of the scroll bar, scaled to \c {0.0 - 1.0}. - - \sa {Flickable::visibleArea.heightRatio}{Flickable::visibleArea} - - This property is automatically set when the scroll bar is - \l {Attaching ScrollBar to a Flickable}{attached to a flickable}. - - \sa minimumSize, visualSize -*/ -qreal QQuickScrollBar::size() const -{ - Q_D(const QQuickScrollBar); - return d->size; -} - -void QQuickScrollBar::setSize(qreal size) -{ - Q_D(QQuickScrollBar); - if (qFuzzyCompare(d->size, size)) - return; - - auto oldVisualArea = d->visualArea(); - d->size = size; - if (isComponentComplete()) - d->resizeContent(); - emit sizeChanged(); - d->visualAreaChange(d->visualArea(), oldVisualArea); -} - -/*! - \qmlproperty real QtQuick.Controls::ScrollBar::position - - This property holds the position of the scroll bar, scaled to \c {0.0 - 1.0}. - - \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea} - - This property is automatically set when the scroll bar is - \l {Attaching ScrollBar to a Flickable}{attached to a flickable}. - - \sa visualPosition -*/ -qreal QQuickScrollBar::position() const -{ - Q_D(const QQuickScrollBar); - return d->position; -} - -void QQuickScrollBar::setPosition(qreal position) -{ - Q_D(QQuickScrollBar); - if (qFuzzyCompare(d->position, position)) - return; - - auto oldVisualArea = d->visualArea(); - d->position = position; - if (isComponentComplete()) - d->resizeContent(); - emit positionChanged(); - d->visualAreaChange(d->visualArea(), oldVisualArea); -} - -/*! - \qmlproperty real QtQuick.Controls::ScrollBar::stepSize - - This property holds the step size. The default value is \c 0.0. - - \sa snapMode, increase(), decrease() -*/ -qreal QQuickScrollBar::stepSize() const -{ - Q_D(const QQuickScrollBar); - return d->stepSize; -} - -void QQuickScrollBar::setStepSize(qreal step) -{ - Q_D(QQuickScrollBar); - if (qFuzzyCompare(d->stepSize, step)) - return; - - d->stepSize = step; - emit stepSizeChanged(); -} - -/*! - \qmlproperty bool QtQuick.Controls::ScrollBar::active - - This property holds whether the scroll bar is active, i.e. when it's \l pressed - or the attached Flickable is \l {Flickable::moving}{moving}. - - It is possible to keep \l {Binding the Active State of Horizontal and Vertical Scroll Bars} - {both horizontal and vertical bars visible} while scrolling in either direction. - - This property is automatically set when the scroll bar is - \l {Attaching ScrollBar to a Flickable}{attached to a flickable}. -*/ -bool QQuickScrollBar::isActive() const -{ - Q_D(const QQuickScrollBar); - return d->active; -} - -void QQuickScrollBar::setActive(bool active) -{ - Q_D(QQuickScrollBar); - if (d->active == active) - return; - - d->active = active; - emit activeChanged(); -} - -/*! - \qmlproperty bool QtQuick.Controls::ScrollBar::pressed - - This property holds whether the scroll bar is pressed. -*/ -bool QQuickScrollBar::isPressed() const -{ - Q_D(const QQuickScrollBar); - return d->pressed; -} - -void QQuickScrollBar::setPressed(bool pressed) -{ - Q_D(QQuickScrollBar); - if (!pressed) { - if (QQuickIndicatorButton *button = decreaseVisual()) - button->setPressed(false); - if (QQuickIndicatorButton *button = increaseVisual()) - button->setPressed(false); - } - if (d->pressed == pressed) - return; - - d->pressed = pressed; - setAccessibleProperty("pressed", pressed); - d->updateActive(); - emit pressedChanged(); -} - -/*! - \qmlproperty enumeration QtQuick.Controls::ScrollBar::orientation - - This property holds the orientation of the scroll bar. - - Possible values: - \value Qt.Horizontal Horizontal - \value Qt.Vertical Vertical (default) - - This property is automatically set when the scroll bar is - \l {Attaching ScrollBar to a Flickable}{attached to a flickable}. - - \sa horizontal, vertical -*/ -Qt::Orientation QQuickScrollBar::orientation() const -{ - Q_D(const QQuickScrollBar); - return d->orientation; -} - -void QQuickScrollBar::setOrientation(Qt::Orientation orientation) -{ - Q_D(QQuickScrollBar); - if (d->orientation == orientation) - return; - - d->orientation = orientation; - if (isComponentComplete()) - d->resizeContent(); - emit orientationChanged(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty enumeration QtQuick.Controls::ScrollBar::snapMode - - This property holds the snap mode. - - Possible values: - \value ScrollBar.NoSnap The scrollbar does not snap (default). - \value ScrollBar.SnapAlways The scrollbar snaps while dragged. - \value ScrollBar.SnapOnRelease The scrollbar does not snap while being dragged, but only after released. - - In the following table, the various modes are illustrated with animations. - The movement and the \l stepSize (\c 0.25) are identical in each animation. - - \table - \header - \row \li \b Value \li \b Example - \row \li \c ScrollBar.NoSnap \li \image qtquickcontrols2-scrollbar-nosnap.gif - \row \li \c ScrollBar.SnapAlways \li \image qtquickcontrols2-scrollbar-snapalways.gif - \row \li \c ScrollBar.SnapOnRelease \li \image qtquickcontrols2-scrollbar-snaponrelease.gif - \endtable - - \sa stepSize -*/ -QQuickScrollBar::SnapMode QQuickScrollBar::snapMode() const -{ - Q_D(const QQuickScrollBar); - return d->snapMode; -} - -void QQuickScrollBar::setSnapMode(SnapMode mode) -{ - Q_D(QQuickScrollBar); - if (d->snapMode == mode) - return; - - d->snapMode = mode; - emit snapModeChanged(); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty bool QtQuick.Controls::ScrollBar::interactive - - This property holds whether the scroll bar is interactive. The default value is \c true. - - A non-interactive scroll bar is visually and behaviorally similar to \l ScrollIndicator. - This property is useful for switching between typical mouse- and touch-orientated UIs - with interactive and non-interactive scroll bars, respectively. -*/ -bool QQuickScrollBar::isInteractive() const -{ - Q_D(const QQuickScrollBar); - return d->interactive; -} - -void QQuickScrollBar::setInteractive(bool interactive) -{ - Q_D(QQuickScrollBar); - d->explicitInteractive = true; - d->setInteractive(interactive); -} - -void QQuickScrollBar::resetInteractive() -{ - Q_D(QQuickScrollBar); - d->explicitInteractive = false; - d->setInteractive(true); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlproperty enumeration QtQuick.Controls::ScrollBar::policy - - This property holds the policy of the scroll bar. The default policy is \c ScrollBar.AsNeeded. - - Possible values: - \value ScrollBar.AsNeeded The scroll bar is only shown when the content is too large to fit. - \value ScrollBar.AlwaysOff The scroll bar is never shown. - \value ScrollBar.AlwaysOn The scroll bar is always shown. - - The following example keeps the vertical scroll bar always visible: - - \snippet qtquickcontrols2-scrollbar-policy.qml 1 -*/ -QQuickScrollBar::Policy QQuickScrollBar::policy() const -{ - Q_D(const QQuickScrollBar); - return d->policy; -} - -void QQuickScrollBar::setPolicy(Policy policy) -{ - Q_D(QQuickScrollBar); - if (d->policy == policy) - return; - - d->policy = policy; - emit policyChanged(); -} - -/*! - \since QtQuick.Controls 2.3 (Qt 5.10) - \qmlproperty bool QtQuick.Controls::ScrollBar::horizontal - \readonly - - This property holds whether the scroll bar is horizontal. - - \sa orientation -*/ -bool QQuickScrollBar::isHorizontal() const -{ - Q_D(const QQuickScrollBar); - return d->orientation == Qt::Horizontal; -} - -/*! - \since QtQuick.Controls 2.3 (Qt 5.10) - \qmlproperty bool QtQuick.Controls::ScrollBar::vertical - \readonly - - This property holds whether the scroll bar is vertical. - - \sa orientation -*/ -bool QQuickScrollBar::isVertical() const -{ - Q_D(const QQuickScrollBar); - return d->orientation == Qt::Vertical; -} - -/*! - \since QtQuick.Controls 2.4 (Qt 5.11) - \qmlproperty real QtQuick.Controls::ScrollBar::minimumSize - - This property holds the minimum size of the scroll bar, scaled to \c {0.0 - 1.0}. - - \sa size, visualSize, visualPosition -*/ -qreal QQuickScrollBar::minimumSize() const -{ - Q_D(const QQuickScrollBar); - return d->minimumSize; -} - -void QQuickScrollBar::setMinimumSize(qreal minimumSize) -{ - Q_D(QQuickScrollBar); - if (qFuzzyCompare(d->minimumSize, minimumSize)) - return; - - auto oldVisualArea = d->visualArea(); - d->minimumSize = minimumSize; - if (isComponentComplete()) - d->resizeContent(); - emit minimumSizeChanged(); - d->visualAreaChange(d->visualArea(), oldVisualArea); -} - -/*! - \since QtQuick.Controls 2.4 (Qt 5.11) - \qmlproperty real QtQuick.Controls::ScrollBar::visualSize - - This property holds the effective visual size of the scroll bar, - which may be limited by the \l {minimumSize}{minimum size}. - - \sa size, minimumSize -*/ -qreal QQuickScrollBar::visualSize() const -{ - Q_D(const QQuickScrollBar); - return d->visualArea().size; -} - -/*! - \since QtQuick.Controls 2.4 (Qt 5.11) - \qmlproperty real QtQuick.Controls::ScrollBar::visualPosition - - This property holds the effective visual position of the scroll bar, - which may be limited by the \l {minimumSize}{minimum size}. - - \sa position, minimumSize -*/ -qreal QQuickScrollBar::visualPosition() const -{ - Q_D(const QQuickScrollBar); - return d->visualArea().position; -} - -QQuickIndicatorButton *QQuickScrollBar::decreaseVisual() -{ - Q_D(QQuickScrollBar); - return d->decreaseVisual; -} - -QQuickIndicatorButton *QQuickScrollBar::increaseVisual() -{ - Q_D(QQuickScrollBar); - return d->increaseVisual; -} - -/*! - \qmlmethod void QtQuick.Controls::ScrollBar::increase() - - Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0. - - \sa stepSize -*/ -void QQuickScrollBar::increase() -{ - Q_D(QQuickScrollBar); - qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; - bool wasActive = d->active; - setActive(true); - setPosition(qMin<qreal>(1.0 - d->size, d->position + step)); - setActive(wasActive); -} - -/*! - \qmlmethod void QtQuick.Controls::ScrollBar::decrease() - - Decreases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0. - - \sa stepSize -*/ -void QQuickScrollBar::decrease() -{ - Q_D(QQuickScrollBar); - qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; - bool wasActive = d->active; - setActive(true); - setPosition(qMax<qreal>(0.0, d->position - step)); - setActive(wasActive); -} - -void QQuickScrollBar::mousePressEvent(QMouseEvent *event) -{ - Q_D(QQuickScrollBar); - QQuickControl::mousePressEvent(event); - d->handleMove(event->position()); -} - -#if QT_CONFIG(quicktemplates2_hover) -void QQuickScrollBar::hoverChange() -{ - Q_D(QQuickScrollBar); - d->updateActive(); -} -#endif - -void QQuickScrollBar::hoverEnterEvent(QHoverEvent *event) -{ - Q_D(QQuickScrollBar); - QQuickControl::hoverEnterEvent(event); - d->updateHover(event->position()); -} - -void QQuickScrollBar::hoverMoveEvent(QHoverEvent *event) -{ - Q_D(QQuickScrollBar); - QQuickControl::hoverMoveEvent(event); - d->updateHover(event->position()); -} - -void QQuickScrollBar::hoverLeaveEvent(QHoverEvent *event) -{ - Q_D(QQuickScrollBar); - QQuickControl::hoverLeaveEvent(event); - - d->updateHover(QPoint(), false); //position is not needed when we force it to unhover -} - -void QQuickScrollBar::classBegin() -{ - Q_D(QQuickScrollBar); - QQuickControl::classBegin(); - - QQmlContext *context = qmlContext(this); - if (context) { - QQmlEngine::setContextForObject(d->decreaseVisual, context); - QQmlEngine::setContextForObject(d->increaseVisual, context); - } -} - -void QQuickScrollBar::componentComplete() -{ - Q_D(QQuickScrollBar); - QQuickIndicatorButtonPrivate::get(d->decreaseVisual)->executeIndicator(true); - QQuickIndicatorButtonPrivate::get(d->increaseVisual)->executeIndicator(true); - - QQuickControl::componentComplete(); -} - -#if QT_CONFIG(accessibility) -void QQuickScrollBar::accessibilityActiveChanged(bool active) -{ - QQuickControl::accessibilityActiveChanged(active); - - Q_D(QQuickScrollBar); - if (active) { - setAccessibleProperty("pressed", d->pressed); - - if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this)) { - connect(accessibleAttached, &QQuickAccessibleAttached::increaseAction, this, &QQuickScrollBar::increase); - connect(accessibleAttached, &QQuickAccessibleAttached::decreaseAction, this, &QQuickScrollBar::decrease); - } - } else { - if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this)) { - disconnect(accessibleAttached, &QQuickAccessibleAttached::increaseAction, this, &QQuickScrollBar::increase); - disconnect(accessibleAttached, &QQuickAccessibleAttached::decreaseAction, this, &QQuickScrollBar::decrease); - } - } -} - -QAccessible::Role QQuickScrollBar::accessibleRole() const -{ - return QAccessible::ScrollBar; -} -#endif - -void QQuickScrollBarAttachedPrivate::setFlickable(QQuickFlickable *item) -{ - if (flickable) { - // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size). - // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling - // pointer on destruction. - QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Geometry); - if (horizontal) - cleanupHorizontal(); - if (vertical) - cleanupVertical(); - } - - flickable = item; - - if (item) { - QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size); - if (horizontal) - initHorizontal(); - if (vertical) - initVertical(); - } -} - -void QQuickScrollBarAttachedPrivate::initHorizontal() -{ - Q_ASSERT(flickable && horizontal); - - connect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal); - - // TODO: export QQuickFlickableVisibleArea - QObject *area = flickable->property("visibleArea").value<QObject *>(); - QObject::connect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal))); - QObject::connect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal))); - - // ensure that the ScrollBar is stacked above the Flickable in a ScrollView - QQuickItem *parent = horizontal->parentItem(); - if (parent && parent == flickable->parentItem()) - horizontal->stackAfter(flickable); - - layoutHorizontal(); - horizontal->setSize(area->property("widthRatio").toReal()); - horizontal->setPosition(area->property("xPosition").toReal()); -} - -void QQuickScrollBarAttachedPrivate::initVertical() -{ - Q_ASSERT(flickable && vertical); - - connect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical); - - // TODO: export QQuickFlickableVisibleArea - QObject *area = flickable->property("visibleArea").value<QObject *>(); - QObject::connect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal))); - QObject::connect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal))); - - // ensure that the ScrollBar is stacked above the Flickable in a ScrollView - QQuickItem *parent = vertical->parentItem(); - if (parent && parent == flickable->parentItem()) - vertical->stackAfter(flickable); - - layoutVertical(); - vertical->setSize(area->property("heightRatio").toReal()); - vertical->setPosition(area->property("yPosition").toReal()); -} - -void QQuickScrollBarAttachedPrivate::cleanupHorizontal() -{ - Q_ASSERT(flickable && horizontal); - - disconnect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal); - - // TODO: export QQuickFlickableVisibleArea - QObject *area = flickable->property("visibleArea").value<QObject *>(); - QObject::disconnect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal))); - QObject::disconnect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal))); -} - -void QQuickScrollBarAttachedPrivate::cleanupVertical() -{ - Q_ASSERT(flickable && vertical); - - disconnect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical); - - // TODO: export QQuickFlickableVisibleArea - QObject *area = flickable->property("visibleArea").value<QObject *>(); - QObject::disconnect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal))); - QObject::disconnect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal))); -} - -void QQuickScrollBarAttachedPrivate::activateHorizontal() -{ - QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(horizontal); - p->moving = flickable->isMovingHorizontally(); - p->updateActive(); -} - -void QQuickScrollBarAttachedPrivate::activateVertical() -{ - QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(vertical); - p->moving = flickable->isMovingVertically(); - p->updateActive(); -} - -// TODO: QQuickFlickable::maxXYExtent() -class QQuickFriendlyFlickable : public QQuickFlickable -{ - friend class QQuickScrollBarAttachedPrivate; -}; - -void QQuickScrollBarAttachedPrivate::scrollHorizontal() -{ - QQuickFriendlyFlickable *f = reinterpret_cast<QQuickFriendlyFlickable *>(flickable); - - const qreal viewwidth = f->width(); - const qreal maxxextent = -f->maxXExtent() + f->minXExtent(); - const qreal cx = horizontal->position() * (maxxextent + viewwidth) - f->minXExtent(); - - if (!qIsNaN(cx) && !qFuzzyCompare(cx, flickable->contentX())) - flickable->setContentX(cx); -} - -void QQuickScrollBarAttachedPrivate::scrollVertical() -{ - QQuickFriendlyFlickable *f = reinterpret_cast<QQuickFriendlyFlickable *>(flickable); - - const qreal viewheight = f->height(); - const qreal maxyextent = -f->maxYExtent() + f->minYExtent(); - const qreal cy = vertical->position() * (maxyextent + viewheight) - f->minYExtent(); - - if (!qIsNaN(cy) && !qFuzzyCompare(cy, flickable->contentY())) - flickable->setContentY(cy); -} - -void QQuickScrollBarAttachedPrivate::mirrorVertical() -{ - layoutVertical(true); -} - -void QQuickScrollBarAttachedPrivate::layoutHorizontal(bool move) -{ - Q_ASSERT(horizontal && flickable); - if (horizontal->parentItem() != flickable) - return; - horizontal->setWidth(flickable->width()); - if (move) - horizontal->setY(flickable->height() - horizontal->height()); -} - -void QQuickScrollBarAttachedPrivate::layoutVertical(bool move) -{ - Q_ASSERT(vertical && flickable); - if (vertical->parentItem() != flickable) - return; - vertical->setHeight(flickable->height()); - if (move) - vertical->setX(vertical->isMirrored() ? 0 : flickable->width() - vertical->width()); -} - -void QQuickScrollBarAttachedPrivate::itemGeometryChanged(QQuickItem *item, const QQuickGeometryChange change, const QRectF &diff) -{ - Q_UNUSED(item); - Q_UNUSED(change); - if (horizontal && horizontal->height() > 0) { -#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry - bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), diff.height() - horizontal->height()); -#else - bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), item->height() - diff.height() - horizontal->height()); -#endif - if (flickable) - layoutHorizontal(move); - } - if (vertical && vertical->width() > 0) { -#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry - bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), diff.width() - vertical->width()); -#else - bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), item->width() - diff.width() - vertical->width()); -#endif - if (flickable) - layoutVertical(move); - } -} - -void QQuickScrollBarAttachedPrivate::itemImplicitWidthChanged(QQuickItem *item) -{ - if (item == vertical && flickable) - layoutVertical(true); -} - -void QQuickScrollBarAttachedPrivate::itemImplicitHeightChanged(QQuickItem *item) -{ - if (item == horizontal && flickable) - layoutHorizontal(true); -} - -void QQuickScrollBarAttachedPrivate::itemDestroyed(QQuickItem *item) -{ - if (item == horizontal) - horizontal = nullptr; - if (item == vertical) - vertical = nullptr; -} - -QQuickScrollBarAttached::QQuickScrollBarAttached(QObject *parent) - : QObject(*(new QQuickScrollBarAttachedPrivate), parent) -{ - Q_D(QQuickScrollBarAttached); - d->setFlickable(qobject_cast<QQuickFlickable *>(parent)); - - if (parent && !d->flickable && !qobject_cast<QQuickScrollView *>(parent)) - qmlWarning(parent) << "ScrollBar must be attached to a Flickable or ScrollView"; -} - -QQuickScrollBarAttached::~QQuickScrollBarAttached() -{ - Q_D(QQuickScrollBarAttached); - if (d->horizontal) { - QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes); - d->horizontal = nullptr; - } - if (d->vertical) { - QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, verticalChangeTypes); - d->vertical = nullptr; - } - d->setFlickable(nullptr); -} - -/*! - \qmlattachedproperty ScrollBar QtQuick.Controls::ScrollBar::horizontal - - This property attaches a horizontal scroll bar to a \l Flickable. - - \code - Flickable { - contentWidth: 2000 - ScrollBar.horizontal: ScrollBar { } - } - \endcode - - \sa {Attaching ScrollBar to a Flickable} -*/ -QQuickScrollBar *QQuickScrollBarAttached::horizontal() const -{ - Q_D(const QQuickScrollBarAttached); - return d->horizontal; -} - -void QQuickScrollBarAttached::setHorizontal(QQuickScrollBar *horizontal) -{ - Q_D(QQuickScrollBarAttached); - if (d->horizontal == horizontal) - return; - - if (d->horizontal) { - QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes); - QObjectPrivate::disconnect(d->horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal); - - if (d->flickable) - d->cleanupHorizontal(); - } - - d->horizontal = horizontal; - - if (horizontal) { - if (!horizontal->parentItem()) - horizontal->setParentItem(qobject_cast<QQuickItem *>(parent())); - horizontal->setOrientation(Qt::Horizontal); - - QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, horizontalChangeTypes); - QObjectPrivate::connect(horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal); - - if (d->flickable) - d->initHorizontal(); - } - emit horizontalChanged(); -} - -/*! - \qmlattachedproperty ScrollBar QtQuick.Controls::ScrollBar::vertical - - This property attaches a vertical scroll bar to a \l Flickable. - - \code - Flickable { - contentHeight: 2000 - ScrollBar.vertical: ScrollBar { } - } - \endcode - - \sa {Attaching ScrollBar to a Flickable} -*/ -QQuickScrollBar *QQuickScrollBarAttached::vertical() const -{ - Q_D(const QQuickScrollBarAttached); - return d->vertical; -} - -void QQuickScrollBarAttached::setVertical(QQuickScrollBar *vertical) -{ - Q_D(QQuickScrollBarAttached); - if (d->vertical == vertical) - return; - - if (d->vertical) { - QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, verticalChangeTypes); - QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical); - QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical); - - if (d->flickable) - d->cleanupVertical(); - } - - d->vertical = vertical; - - if (vertical) { - if (!vertical->parentItem()) - vertical->setParentItem(qobject_cast<QQuickItem *>(parent())); - vertical->setOrientation(Qt::Vertical); - - QQuickItemPrivate::get(vertical)->addItemChangeListener(d, verticalChangeTypes); - QObjectPrivate::connect(vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical); - QObjectPrivate::connect(vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical); - - if (d->flickable) - d->initVertical(); - } - emit verticalChanged(); -} - -QT_END_NAMESPACE |