aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/controls/SwipeDelegate.qml18
-rw-r--r--src/imports/controls/material/SwipeDelegate.qml18
-rw-r--r--src/imports/controls/universal/SwipeDelegate.qml18
-rw-r--r--src/quicktemplates2/qquickswipe_p.h8
-rw-r--r--src/quicktemplates2/qquickswipedelegate.cpp109
-rw-r--r--tests/auto/controls/data/tst_swipedelegate.qml31
6 files changed, 126 insertions, 76 deletions
diff --git a/src/imports/controls/SwipeDelegate.qml b/src/imports/controls/SwipeDelegate.qml
index 099ee117..1c900b52 100644
--- a/src/imports/controls/SwipeDelegate.qml
+++ b/src/imports/controls/SwipeDelegate.qml
@@ -52,6 +52,8 @@ T.SwipeDelegate {
padding: 12
spacing: 12
+ swipe.rebound: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
contentItem: Text {
leftPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
rightPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
@@ -63,27 +65,11 @@ T.SwipeDelegate {
visible: control.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
background: Rectangle {
color: control.visualFocus
? (control.down ? Default.focusPressedColor : Default.delegateFocusColor)
: (control.down ? Default.delegatePressedColor : Default.backgroundColor)
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
}
diff --git a/src/imports/controls/material/SwipeDelegate.qml b/src/imports/controls/material/SwipeDelegate.qml
index c6240910..4247ddf1 100644
--- a/src/imports/controls/material/SwipeDelegate.qml
+++ b/src/imports/controls/material/SwipeDelegate.qml
@@ -54,6 +54,8 @@ T.SwipeDelegate {
bottomPadding: 8
spacing: 16
+ swipe.rebound: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
contentItem: Text {
leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width + control.spacing : 0) : 0
rightPadding: control.mirrored ? (control.indicator ? control.indicator.width + control.spacing : 0) : 0
@@ -65,14 +67,6 @@ T.SwipeDelegate {
visible: control.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
background: Rectangle {
@@ -98,13 +92,5 @@ T.SwipeDelegate {
color: control.Material.rippleColor
enabled: control.swipe.position === 0
}
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
}
diff --git a/src/imports/controls/universal/SwipeDelegate.qml b/src/imports/controls/universal/SwipeDelegate.qml
index 0b888e70..193d1ab1 100644
--- a/src/imports/controls/universal/SwipeDelegate.qml
+++ b/src/imports/controls/universal/SwipeDelegate.qml
@@ -54,6 +54,8 @@ T.SwipeDelegate {
topPadding: padding - 1
bottomPadding: padding + 1
+ swipe.rebound: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
contentItem: Text {
leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
rightPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
@@ -68,14 +70,6 @@ T.SwipeDelegate {
opacity: enabled ? 1.0 : 0.2
color: control.Universal.foreground
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
background: Rectangle {
@@ -94,13 +88,5 @@ T.SwipeDelegate {
opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
}
}
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
}
diff --git a/src/quicktemplates2/qquickswipe_p.h b/src/quicktemplates2/qquickswipe_p.h
index bedf5b1f..2201bb06 100644
--- a/src/quicktemplates2/qquickswipe_p.h
+++ b/src/quicktemplates2/qquickswipe_p.h
@@ -56,12 +56,13 @@ QT_BEGIN_NAMESPACE
class QQmlComponent;
class QQuickItem;
+class QQuickTransition;
class QQuickSwipePrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipe : public QObject
{
Q_OBJECT
- Q_PROPERTY(qreal position READ position NOTIFY positionChanged FINAL)
+ Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
Q_PROPERTY(bool complete READ isComplete NOTIFY completeChanged FINAL)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) // REVISION 2
Q_PROPERTY(QQmlComponent *left READ left WRITE setLeft NOTIFY leftChanged FINAL)
@@ -70,6 +71,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipe : public QObject
Q_PROPERTY(QQuickItem *leftItem READ leftItem NOTIFY leftItemChanged FINAL)
Q_PROPERTY(QQuickItem *behindItem READ behindItem NOTIFY behindItemChanged FINAL)
Q_PROPERTY(QQuickItem *rightItem READ rightItem NOTIFY rightItemChanged FINAL)
+ Q_PROPERTY(QQuickTransition *rebound READ rebound WRITE setRebound NOTIFY reboundChanged FINAL) // REVISION 2
public:
explicit QQuickSwipe(QQuickSwipeDelegate *control);
@@ -101,6 +103,9 @@ public:
QQuickItem *rightItem() const;
void setRightItem(QQuickItem *item);
+ QQuickTransition *rebound() const;
+ void setRebound(QQuickTransition *rebound);
+
Q_REVISION(2) Q_INVOKABLE void open(QQuickSwipeDelegate::Side side);
Q_REVISION(1) Q_INVOKABLE void close();
@@ -115,6 +120,7 @@ Q_SIGNALS:
void leftItemChanged();
void behindItemChanged();
void rightItemChanged();
+ /*Q_REVISION(2)*/ void reboundChanged();
private:
Q_DISABLE_COPY(QQuickSwipe)
diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp
index 2f7e7382..5504dfc8 100644
--- a/src/quicktemplates2/qquickswipedelegate.cpp
+++ b/src/quicktemplates2/qquickswipedelegate.cpp
@@ -44,6 +44,9 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qqmlinfo.h>
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
QT_BEGIN_NAMESPACE
@@ -113,6 +116,48 @@ namespace {
};
}
+class QQuickSwipeTransitionManager : public QQuickTransitionManager
+{
+public:
+ QQuickSwipeTransitionManager(QQuickSwipe *swipe);
+
+ void transition(QQuickTransition *rebound, qreal position);
+
+protected:
+ void finished() override;
+
+private:
+ QQuickSwipe *m_swipe;
+};
+
+QQuickSwipeTransitionManager::QQuickSwipeTransitionManager(QQuickSwipe *swipe)
+ : m_swipe(swipe)
+{
+}
+
+void QQuickSwipeTransitionManager::transition(QQuickTransition *rebound, qreal position)
+{
+ qmlExecuteDeferred(rebound);
+
+ QQmlProperty defaultTarget(m_swipe, QLatin1String("position"));
+ QQmlListProperty<QQuickAbstractAnimation> animations = rebound->animations();
+ const int count = animations.count(&animations);
+ for (int i = 0; i < count; ++i) {
+ QQuickAbstractAnimation *anim = animations.at(&animations, i);
+ anim->setDefaultTarget(defaultTarget);
+ }
+
+ QList<QQuickStateAction> actions;
+ actions << QQuickStateAction(m_swipe, QLatin1String("position"), position);
+ QQuickTransitionManager::transition(actions, rebound, m_swipe);
+}
+
+void QQuickSwipeTransitionManager::finished()
+{
+ const qreal pos = m_swipe->position();
+ m_swipe->setComplete(qFuzzyCompare(qAbs(pos), 1.0));
+}
+
class QQuickSwipePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickSwipe)
@@ -130,7 +175,9 @@ public:
right(nullptr),
leftItem(nullptr),
behindItem(nullptr),
- rightItem(nullptr)
+ rightItem(nullptr),
+ rebound(nullptr),
+ transitionManager(nullptr)
{
}
@@ -152,6 +199,9 @@ public:
bool hasDelegates() const;
+ bool isTransitioning() const;
+ void transition(qreal position);
+
QQuickSwipeDelegate *control;
// Same range as position, but is set before press events so that we can
// keep track of which direction the user must swipe when using left and right delegates.
@@ -169,6 +219,8 @@ public:
QQuickItem *leftItem;
QQuickItem *behindItem;
QQuickItem *rightItem;
+ QQuickTransition *rebound;
+ QScopedPointer<QQuickSwipeTransitionManager> transitionManager;
};
QQuickSwipePrivate *QQuickSwipePrivate::get(QQuickSwipe *swipe)
@@ -358,6 +410,26 @@ bool QQuickSwipePrivate::hasDelegates() const
return left || right || behind;
}
+bool QQuickSwipePrivate::isTransitioning() const
+{
+ return transitionManager && transitionManager->isRunning();
+}
+
+void QQuickSwipePrivate::transition(qreal position)
+{
+ Q_Q(QQuickSwipe);
+ if (!rebound) {
+ q->setPosition(position);
+ q->setComplete(qFuzzyCompare(qAbs(position), 1.0));
+ return;
+ }
+
+ if (!transitionManager)
+ transitionManager.reset(new QQuickSwipeTransitionManager(q));
+
+ transitionManager->transition(rebound, position);
+}
+
QQuickSwipe::QQuickSwipe(QQuickSwipeDelegate *control) :
QObject(*(new QQuickSwipePrivate(control)))
{
@@ -592,6 +664,22 @@ void QQuickSwipe::setEnabled(bool enabled)
emit enabledChanged();
}
+QQuickTransition *QQuickSwipe::rebound() const
+{
+ Q_D(const QQuickSwipe);
+ return d->rebound;
+}
+
+void QQuickSwipe::setRebound(QQuickTransition *rebound)
+{
+ Q_D(QQuickSwipe);
+ if (rebound == d->rebound)
+ return;
+
+ d->rebound = rebound;
+ emit reboundChanged();
+}
+
void QQuickSwipe::open(QQuickSwipeDelegate::Side side)
{
Q_D(QQuickSwipe);
@@ -600,8 +688,7 @@ void QQuickSwipe::open(QQuickSwipeDelegate::Side side)
|| (!d->right && !d->behind && side == QQuickSwipeDelegate::Right))
return;
- setPosition(side);
- setComplete(true);
+ d->transition(side);
d->wasComplete = true;
d->velocityCalculator.reset();
d->positionBeforePress = d->position;
@@ -610,8 +697,7 @@ void QQuickSwipe::open(QQuickSwipeDelegate::Side side)
void QQuickSwipe::close()
{
Q_D(QQuickSwipe);
- setPosition(0);
- setComplete(false);
+ d->transition(0.0);
d->wasComplete = false;
d->positionBeforePress = 0.0;
d->velocityCalculator.reset();
@@ -748,6 +834,8 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv
position = distance > 0 ? normalizedDistance - 1.0 : normalizedDistance + 1.0;
}
+ if (swipePrivate->isTransitioning())
+ swipePrivate->transitionManager->cancel();
swipe.setPosition(position);
}
} else {
@@ -794,17 +882,14 @@ bool QQuickSwipeDelegatePrivate::handleMouseReleaseEvent(QQuickItem *item, QMous
const qreal swipeVelocity = swipePrivate->velocityCalculator.velocity().x();
if (swipePrivate->position > 0.5 ||
(swipePrivate->position > 0.0 && swipeVelocity > exposeVelocityThreshold)) {
- swipe.setPosition(1.0);
- swipe.setComplete(true);
+ swipePrivate->transition(1.0);
swipePrivate->wasComplete = true;
} else if (swipePrivate->position < -0.5 ||
(swipePrivate->position < 0.0 && swipeVelocity < -exposeVelocityThreshold)) {
- swipe.setPosition(-1.0);
- swipe.setComplete(true);
+ swipePrivate->transition(-1.0);
swipePrivate->wasComplete = true;
- } else {
- swipe.setPosition(0.0);
- swipe.setComplete(false);
+ } else if (!swipePrivate->isTransitioning()) {
+ swipePrivate->transition(0.0);
swipePrivate->wasComplete = false;
}
diff --git a/tests/auto/controls/data/tst_swipedelegate.qml b/tests/auto/controls/data/tst_swipedelegate.qml
index a6e11246..27a1028b 100644
--- a/tests/auto/controls/data/tst_swipedelegate.qml
+++ b/tests/auto/controls/data/tst_swipedelegate.qml
@@ -40,7 +40,7 @@
import QtQuick 2.6
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
@@ -380,8 +380,8 @@ TestCase {
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "canceled"];
mouseRelease(control, control.width / 2, control.height / 2);
verify(!control.pressed);
- compare(control.swipe.position, 1.0);
- verify(control.swipe.complete);
+ tryCompare(control.swipe, "position", 1.0);
+ tryCompare(control.swipe, "complete", true);
compare(completedSpy.count, 1);
verify(mouseSignalSequenceSpy.success);
verify(control.swipe.leftItem);
@@ -411,8 +411,8 @@ TestCase {
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "canceled"];
mouseRelease(control, control.width * 0.4, control.height / 2);
verify(!control.pressed);
- compare(control.swipe.position, 1.0);
- verify(control.swipe.complete);
+ tryCompare(control.swipe, "position", 1.0);
+ tryCompare(control.swipe, "complete", true);
compare(completedSpy.count, 2);
verify(mouseSignalSequenceSpy.success);
tryCompare(control.contentItem, "x", control.width + control.leftPadding);
@@ -435,7 +435,7 @@ TestCase {
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "canceled"];
mouseRelease(control, control.width * -0.1, control.height / 2);
verify(!control.pressed);
- compare(control.swipe.position, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
verify(!control.swipe.complete);
compare(completedSpy.count, 2);
verify(mouseSignalSequenceSpy.success);
@@ -572,7 +572,7 @@ TestCase {
// Returning back to a position of 0 and pressing on the control should
// result in the control being pressed.
mouseDrag(control, control.width / 2, control.height / 2, control.width * 0.6, 0);
- compare(control.swipe.position, 0);
+ tryCompare(control.swipe, "position", 0);
mousePress(control, control.width / 2, control.height / 2);
verify(control.pressed);
verify(!button.pressed);
@@ -730,8 +730,8 @@ TestCase {
mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
verify(!firstItem.pressed);
- compare(firstItem.swipe.position, 1.0);
- verify(firstItem.swipe.complete);
+ tryCompare(firstItem.swipe, "position", 1.0);
+ tryCompare(firstItem.swipe, "complete", true);
compare(listView.count, 3);
// Wait for it to settle down.
@@ -1032,7 +1032,7 @@ TestCase {
mouseMove(control, control.width / 2 + control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
compare(control.swipe.position, -0.2);
mouseRelease(control, control.width / 2 + control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
- compare(control.swipe.position, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
// Try wrapping the other way.
swipe(control, 0.0, -1.0);
@@ -1043,7 +1043,7 @@ TestCase {
mouseMove(control, control.width / 2 - control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
compare(control.swipe.position, 0.2);
mouseRelease(control, control.width / 2 - control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
- compare(control.swipe.position, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
control.destroy();
}
@@ -1475,8 +1475,8 @@ TestCase {
verify(control);
control.swipe.open(data.side);
- compare(control.swipe.position, data.position);
- compare(control.swipe.complete, data.complete);
+ tryCompare(control.swipe, "position", data.position);
+ tryCompare(control.swipe, "complete", data.complete);
control.destroy();
}
@@ -1502,12 +1502,12 @@ TestCase {
verify(control);
mouseClick(control);
- compare(control.swipe.position, SwipeDelegate.Right);
+ tryCompare(control.swipe, "position", SwipeDelegate.Right);
tryCompare(control.background, "x", -control.background.width);
// Swiping after opening should work as normal.
swipe(control, SwipeDelegate.Right, 0.0);
- compare(control.swipe.position, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
tryCompare(control.background, "x", 0);
control.destroy();
@@ -1522,6 +1522,7 @@ TestCase {
width: 150
swipe.left: greenLeftComponent
swipe.right: redRightComponent
+ swipe.rebound: null
property alias behavior: xBehavior
property alias animation: numberAnimation