aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2017-11-03 16:42:14 +0100
committerJ-P Nurmi <jpnurmi@qt.io>2017-11-08 10:13:49 +0000
commitf246314b21604c5fe2a2abe0aec8af89f06eb610 (patch)
treeb66ed350b4a1ba96b0b1c90bc64f923b1ae74e66
parent501d45012f746d843e0144c78202297a577758bc (diff)
ScrollIndicator: allow configuring the minimum size
Same as 9e1b044 for ScrollBar. The existing size and position properties cannot be changed, because then they won't match with Flickable::visibleArea and we get major problems connecting the two. Thus, the effective visible position and size are provided as separate properties. [ChangeLog][Controls][ScrollIndicator] Added minimumSize, visualSize, and visualPosition properties. Task-number: QTBUG-56557 Change-Id: I7deda3bea7a5a020bda79af433bfa38f326952d8 Reviewed-by: Liang Qi <liang.qi@qt.io>
-rw-r--r--src/imports/templates/qtquicktemplates2plugin.cpp1
-rw-r--r--src/quicktemplates2/qquickscrollindicator.cpp111
-rw-r--r--src/quicktemplates2/qquickscrollindicator_p.h15
-rw-r--r--tests/auto/controls/data/tst_scrollindicator.qml48
4 files changed, 168 insertions, 7 deletions
diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp
index f5d1118f..3564f957 100644
--- a/src/imports/templates/qtquicktemplates2plugin.cpp
+++ b/src/imports/templates/qtquicktemplates2plugin.cpp
@@ -324,6 +324,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
qmlRegisterType<QQuickButtonGroup, 4>(uri, 2, 4, "ButtonGroup");
qmlRegisterType<QQuickCheckBox, 4>(uri, 2, 4, "CheckBox");
qmlRegisterType<QQuickScrollBar, 4>(uri, 2, 4, "ScrollBar");
+ qmlRegisterType<QQuickScrollIndicator, 4>(uri, 2, 4, "ScrollIndicator");
qmlRegisterType<QQuickSpinBox, 4>(uri, 2, 4, "SpinBox");
}
diff --git a/src/quicktemplates2/qquickscrollindicator.cpp b/src/quicktemplates2/qquickscrollindicator.cpp
index ee1078e4..511a8311 100644
--- a/src/quicktemplates2/qquickscrollindicator.cpp
+++ b/src/quicktemplates2/qquickscrollindicator.cpp
@@ -137,20 +137,54 @@ class QQuickScrollIndicatorPrivate : public QQuickControlPrivate
public:
QQuickScrollIndicatorPrivate()
: size(0),
+ minimumSize(0),
position(0),
active(false),
orientation(Qt::Vertical)
{
}
+ struct VisualArea
+ {
+ VisualArea(qreal pos, qreal sz)
+ : position(pos), size(sz) { }
+ qreal position;
+ qreal size;
+ };
+ VisualArea visualArea() const;
+ void visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea);
+
void resizeContent() override;
qreal size;
+ qreal minimumSize;
qreal position;
bool active;
Qt::Orientation orientation;
};
+QQuickScrollIndicatorPrivate::VisualArea QQuickScrollIndicatorPrivate::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);
+}
+
+void QQuickScrollIndicatorPrivate::visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea)
+{
+ Q_Q(QQuickScrollIndicator);
+ if (!qFuzzyCompare(newVisualArea.size, oldVisualArea.size))
+ emit q->visualSizeChanged();
+ if (!qFuzzyCompare(newVisualArea.position, oldVisualArea.position))
+ emit q->visualPositionChanged();
+}
+
void QQuickScrollIndicatorPrivate::resizeContent()
{
Q_Q(QQuickScrollIndicator);
@@ -159,15 +193,14 @@ void QQuickScrollIndicatorPrivate::resizeContent()
// - 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 qreal clampedSize = qBound<qreal>(0, size + qMin<qreal>(0, position), 1.0 - position);
- const qreal clampedPos = qBound<qreal>(0, position, 1.0 - clampedSize);
+ const VisualArea visual = visualArea();
if (orientation == Qt::Horizontal) {
- contentItem->setPosition(QPointF(q->leftPadding() + clampedPos * q->availableWidth(), q->topPadding()));
- contentItem->setSize(QSizeF(q->availableWidth() * clampedSize, q->availableHeight()));
+ 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() + clampedPos * q->availableHeight()));
- contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * clampedSize));
+ contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + visual.position * q->availableHeight()));
+ contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * visual.size));
}
}
@@ -190,6 +223,8 @@ QQuickScrollIndicatorAttached *QQuickScrollIndicator::qmlAttachedProperties(QObj
This property is automatically set when the scroll indicator is
\l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
+
+ \sa minimumSize, visualSize
*/
qreal QQuickScrollIndicator::size() const
{
@@ -203,10 +238,12 @@ void QQuickScrollIndicator::setSize(qreal size)
if (qFuzzyCompare(d->size, size))
return;
+ auto oldVisualArea = d->visualArea();
d->size = size;
if (isComponentComplete())
d->resizeContent();
emit sizeChanged();
+ d->visualAreaChange(d->visualArea(), oldVisualArea);
}
/*!
@@ -217,7 +254,7 @@ void QQuickScrollIndicator::setSize(qreal size)
This property is automatically set when the scroll indicator is
\l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
- \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea}
+ \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea}, visualPosition
*/
qreal QQuickScrollIndicator::position() const
{
@@ -231,10 +268,12 @@ void QQuickScrollIndicator::setPosition(qreal position)
if (qFuzzyCompare(d->position, position))
return;
+ auto oldVisualArea = d->visualArea();
d->position = position;
if (isComponentComplete())
d->resizeContent();
emit positionChanged();
+ d->visualAreaChange(d->visualArea(), oldVisualArea);
}
/*!
@@ -327,6 +366,64 @@ bool QQuickScrollIndicator::isVertical() const
return d->orientation == Qt::Vertical;
}
+/*!
+ \since QtQuick.Controls 2.4 (Qt 5.11)
+ \qmlproperty real QtQuick.Controls::ScrollIndicator::minimumSize
+
+ This property holds the minimum size of the indicator, scaled to \c {0.0 - 1.0}.
+
+ \sa size, visualSize, visualPosition
+*/
+qreal QQuickScrollIndicator::minimumSize() const
+{
+ Q_D(const QQuickScrollIndicator);
+ return d->minimumSize;
+}
+
+void QQuickScrollIndicator::setMinimumSize(qreal minimumSize)
+{
+ Q_D(QQuickScrollIndicator);
+ 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::ScrollIndicator::visualSize
+
+ This property holds the effective visual size of the indicator,
+ which may be limited by the \l {minimumSize}{minimum size}.
+
+ \sa size, minimumSize
+*/
+qreal QQuickScrollIndicator::visualSize() const
+{
+ Q_D(const QQuickScrollIndicator);
+ return d->visualArea().size;
+}
+
+/*!
+ \since QtQuick.Controls 2.4 (Qt 5.11)
+ \qmlproperty real QtQuick.Controls::ScrollIndicator::visualPosition
+
+ This property holds the effective visual position of the indicator,
+ which may be limited by the \l {minimumSize}{minimum size}.
+
+ \sa position, minimumSize
+*/
+qreal QQuickScrollIndicator::visualPosition() const
+{
+ Q_D(const QQuickScrollIndicator);
+ return d->visualArea().position;
+}
+
class QQuickScrollIndicatorAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
public:
diff --git a/src/quicktemplates2/qquickscrollindicator_p.h b/src/quicktemplates2/qquickscrollindicator_p.h
index d679cf74..4fa06a33 100644
--- a/src/quicktemplates2/qquickscrollindicator_p.h
+++ b/src/quicktemplates2/qquickscrollindicator_p.h
@@ -66,6 +66,10 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollIndicator : public QQuickCont
// 2.3 (Qt 5.10)
Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3)
Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3)
+ // 2.4 (Qt 5.11)
+ Q_PROPERTY(qreal minimumSize READ minimumSize WRITE setMinimumSize NOTIFY minimumSizeChanged FINAL REVISION 4)
+ Q_PROPERTY(qreal visualSize READ visualSize NOTIFY visualSizeChanged FINAL REVISION 4)
+ Q_PROPERTY(qreal visualPosition READ visualPosition NOTIFY visualPositionChanged FINAL REVISION 4)
public:
explicit QQuickScrollIndicator(QQuickItem *parent = nullptr);
@@ -85,6 +89,13 @@ public:
bool isHorizontal() const;
bool isVertical() const;
+ // 2.4 (Qt 5.11)
+ qreal minimumSize() const;
+ void setMinimumSize(qreal minimumSize);
+
+ qreal visualSize() const;
+ qreal visualPosition() const;
+
public Q_SLOTS:
void setSize(qreal size);
void setPosition(qreal position);
@@ -94,6 +105,10 @@ Q_SIGNALS:
void positionChanged();
void activeChanged();
void orientationChanged();
+ // 2.4 (Qt 5.11)
+ Q_REVISION(4) void minimumSizeChanged();
+ Q_REVISION(4) void visualSizeChanged();
+ Q_REVISION(4) void visualPositionChanged();
protected:
#if QT_CONFIG(quicktemplates2_multitouch)
diff --git a/tests/auto/controls/data/tst_scrollindicator.qml b/tests/auto/controls/data/tst_scrollindicator.qml
index a6275f91..9435ec3b 100644
--- a/tests/auto/controls/data/tst_scrollindicator.qml
+++ b/tests/auto/controls/data/tst_scrollindicator.qml
@@ -258,4 +258,52 @@ TestCase {
touch.release(0, control).commit()
verify(!ma.pressed)
}
+
+ function test_minimumSize() {
+ var container = createTemporaryObject(flickable, testCase)
+ verify(container)
+ waitForRendering(container)
+
+ var vertical = scrollIndicator.createObject(container, {minimumSize: 0.1})
+ container.ScrollIndicator.vertical = vertical
+
+ compare(container.visibleArea.heightRatio, 0.5)
+ compare(vertical.size, 0.5)
+ compare(vertical.visualSize, 0.5)
+ compare(vertical.contentItem.height, 0.5 * vertical.availableHeight)
+
+ container.contentHeight = 2000
+
+ compare(container.visibleArea.heightRatio, 0.05)
+ compare(vertical.size, 0.05)
+ compare(vertical.visualSize, 0.1)
+ compare(vertical.contentItem.height, 0.1 * vertical.availableHeight)
+
+ verify(container.atYBeginning)
+ compare(container.visibleArea.yPosition, 0.0)
+ compare(vertical.position, 0.0)
+ compare(vertical.visualPosition, 0.0)
+ compare(vertical.contentItem.y, vertical.topPadding)
+
+ container.contentY = 1900
+
+ verify(container.atYEnd)
+ compare(container.visibleArea.yPosition, 0.95)
+ compare(vertical.position, 0.95)
+ compare(vertical.visualPosition, 0.9)
+ compare(vertical.contentItem.y, vertical.topPadding + 0.9 * vertical.availableHeight)
+
+ container.contentHeight = 125
+
+ compare(container.visibleArea.heightRatio, 0.8)
+ compare(vertical.size, 0.8)
+ compare(vertical.visualSize, 0.8)
+ compare(vertical.contentItem.height, 0.8 * vertical.availableHeight)
+
+ verify(container.atYEnd)
+ compare(container.visibleArea.yPosition, 0.2)
+ compare(vertical.position, 0.2)
+ compare(vertical.visualPosition, 0.2)
+ compare(vertical.contentItem.y, vertical.topPadding + 0.2 * vertical.availableHeight)
+ }
}