on xenial help sign in
Final rotation fixes for DragHandle and DirectionalDragArea
61b6ac4Daniel d'Andrada
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+16−9
@@ -246,13 +246,15 @@ qreal DirectionalDragArea::distance() const
246 }
246 }
247}
247}
248
248
249+void DirectionalDragArea::updateSceneDistance()
250+{
251+ QPointF totalMovement = m_previousScenePos - m_startScenePos;
252+ m_sceneDistance = projectOntoDirectionVector(totalMovement);
253+}
254+
249qreal DirectionalDragArea::sceneDistance() const
255qreal DirectionalDragArea::sceneDistance() const
250{
256{
251− if (Direction::isHorizontal(m_direction)) {
257+ return m_sceneDistance;
252− return m_previousScenePos.x() - m_startScenePos.x();
253− } else {
254− return m_previousScenePos.y() - m_startScenePos.y();
255− }
256}
258}
257
259
258qreal DirectionalDragArea::touchX() const
260qreal DirectionalDragArea::touchX() const
@@ -587,18 +589,23 @@ void DirectionalDragArea::setPreviousScenePos(const QPointF &point)
587 bool xChanged = m_previousScenePos.x() != point.x();
589 bool xChanged = m_previousScenePos.x() != point.x();
588 bool yChanged = m_previousScenePos.y() != point.y();
590 bool yChanged = m_previousScenePos.y() != point.y();
589
591
592+ if (!xChanged && !yChanged)
593+ return;
594+
595+ qreal oldSceneDistance = sceneDistance();
590 m_previousScenePos = point;
596 m_previousScenePos = point;
597+ updateSceneDistance();
598+
599+ if (oldSceneDistance != sceneDistance()) {
600+ Q_EMIT sceneDistanceChanged(sceneDistance());
601+ }
591
602
592 if (xChanged) {
603 if (xChanged) {
593 Q_EMIT touchSceneXChanged(point.x());
604 Q_EMIT touchSceneXChanged(point.x());
594− if (Direction::isHorizontal(m_direction))
595− Q_EMIT sceneDistanceChanged(sceneDistance());
596 }
605 }
597
606
598 if (yChanged) {
607 if (yChanged) {
599 Q_EMIT touchSceneYChanged(point.y());
608 Q_EMIT touchSceneYChanged(point.y());
600− if (Direction::isVertical(m_direction))
601− Q_EMIT sceneDistanceChanged(sceneDistance());
602 }
609 }
603}
610}
604
611
plugins/Ubuntu/Gestures/DirectionalDragArea.h+2
@@ -160,6 +160,7 @@ public:
160
160
161 qreal distance() const;
161 qreal distance() const;
162 qreal sceneDistance() const;
162 qreal sceneDistance() const;
163+ void updateSceneDistance();
163
164
164 qreal touchX() const;
165 qreal touchX() const;
165 qreal touchY() const;
166 qreal touchY() const;
@@ -242,6 +243,7 @@ private:
242 QPointF m_startScenePos;
243 QPointF m_startScenePos;
243 QPointF m_previousPos;
244 QPointF m_previousPos;
244 QPointF m_previousScenePos;
245 QPointF m_previousScenePos;
246+ qreal m_sceneDistance;
245 int m_touchId;
247 int m_touchId;
246
248
247 // A movement damper is used in some of the gesture recognition calculations
249 // A movement damper is used in some of the gesture recognition calculations
qml/Components/DragHandle.qml+2−1
@@ -167,7 +167,8 @@ EdgeDragArea {
167 EdgeDragEvaluator {
167 EdgeDragEvaluator {
168 objectName: "edgeDragEvaluator"
168 objectName: "edgeDragEvaluator"
169 id: dragEvaluator
169 id: dragEvaluator
170+ // Effectively convert distance into the drag position projected onto the gesture direction axis
170− trackedPosition: sceneDistance
171+ trackedPosition: Direction.isPositive(dragArea.direction) ? sceneDistance : -sceneDistance
171 maxDragDistance: maxTotalDragDistance
172 maxDragDistance: maxTotalDragDistance
172 direction: dragArea.direction
173 direction: dragArea.direction
173 }
174 }
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+55
@@ -84,6 +84,8 @@ private Q_SLOTS:
84 void movingDDA();
84 void movingDDA();
85 void ignoreOldFinger();
85 void ignoreOldFinger();
86 void rotated();
86 void rotated();
87+ void sceneDistance();
88+ void sceneDistance_data();
87
89
88private:
90private:
89 void passTime(qint64 timeSpan);
91 void passTime(qint64 timeSpan);
@@ -740,6 +742,59 @@ void tst_DirectionalDragArea::rotated()
740 QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
742 QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
741}
743}
742
744
745+void tst_DirectionalDragArea::sceneDistance()
746+{
747+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
748+ QFETCH(qreal, rotation);
749+ QFETCH(QPointF, dragDirectionVector);
750+ baseItem->setRotation(rotation);
751+
752+ QQuickItem *rightwardsLauncher = m_view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
753+ Q_ASSERT(rightwardsLauncher != 0);
754+
755+ DirectionalDragArea *edgeDragArea =
756+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
757+ Q_ASSERT(edgeDragArea != 0);
758+ edgeDragArea->setRecognitionTimer(fakeTimer);
759+ edgeDragArea->setTimeSource(fakeTimeSource);
760+
761+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea);
762+ QPointF touchPoint = initialTouchPos;
763+
764+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
765+
766+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
767+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
768+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
769+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
770+
771+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
772+
773+ for (int i = 0; i < totalMovementSteps; ++i) {
774+ touchPoint += touchMovement;
775+ passTime(movementTimeStepMs);
776+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
777+ }
778+
779+ qreal actualDragDistance = ((qreal)totalMovementSteps) * movementStepDistance;
780+
781+ // DirectionalDragArea::sceneDistance() must match the actual drag distance as the
782+ // drag was aligned with the gesture direction
783+ // NB: qFuzzyCompare(), used internally by QCOMPARE(), is broken.
784+ QVERIFY(qAbs(edgeDragArea->sceneDistance() - actualDragDistance) < 0.001);
785+
786+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
787+}
788+
789+void tst_DirectionalDragArea::sceneDistance_data()
790+{
791+ QTest::addColumn<qreal>("rotation");
792+ QTest::addColumn<QPointF>("dragDirectionVector");
793+
794+ QTest::newRow("not rotated") << 0. << QPointF(1., 0.);
795+ QTest::newRow("rotated by 90 degrees") << 90. << QPointF(0., 1.);
796+}
797+
743QTEST_MAIN(tst_DirectionalDragArea)
798QTEST_MAIN(tst_DirectionalDragArea)
744
799
745#include "tst_DirectionalDragArea.moc"
800#include "tst_DirectionalDragArea.moc"
tests/qmltests/Components/tst_DragHandle.qml+71−56
@@ -29,62 +29,67 @@ import Ubuntu.Gestures 0.1
29 */
29 */
30Item {
30Item {
31 id: root
31 id: root
32− width: 700
32+ width: units.gu(70)
33− height: 500
33+ height: units.gu(70)
34
34
35 property var dragHandle
35 property var dragHandle
36
36
37 property bool stretch: false
37 property bool stretch: false
38 property real hintDisplacement: 0
38 property real hintDisplacement: 0
39
39
40− VerticalShowable {
40+ Item {
41− onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
41+ id: baseItem
42− stretch: root.stretch
42+ anchors.fill: parent
43− hintDisplacement: root.hintDisplacement
44− }
45−
46− HorizontalShowable {
47− onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
48− stretch: root.stretch
49− hintDisplacement: root.hintDisplacement
50− }
51
43
52− // Visually mark drag threshold
44+ VerticalShowable {
53− Rectangle {
45+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
54− color: "black"
46+ stretch: root.stretch
55− width: 2
47+ hintDisplacement: root.hintDisplacement
56− height: parent.height
48+ }
57
49
58− visible: dragHandle !== undefined && Direction.isHorizontal(dragHandle.direction)
50+ HorizontalShowable {
51+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
52+ stretch: root.stretch
53+ hintDisplacement: root.hintDisplacement
54+ }
59
55
56+ // Visually mark drag threshold
57+ Rectangle {
58+ color: "black"
59+ width: 2
60+ height: parent.height
61+
62+ visible: dragHandle !== undefined && Direction.isHorizontal(dragHandle.direction)
63+
60− x: {
64+ x: {
61− if (dragHandle) {
65+ if (dragHandle) {
62− if (dragHandle.direction === Direction.Rightwards) {
66+ if (dragHandle.direction === Direction.Rightwards) {
67+ dragHandle.edgeDragEvaluator.dragThreshold;
68+ } else {
63− dragHandle.edgeDragEvaluator.dragThreshold;
69+ parent.width - dragHandle.edgeDragEvaluator.dragThreshold;
70+ }
64 } else {
71 } else {
65− parent.width - dragHandle.edgeDragEvaluator.dragThreshold;
72+ 0
66 }
73 }
67− } else {
68− 0
69 }
74 }
70 }
75 }
71− }
72− Rectangle {
76+ Rectangle {
73− color: "black";
77+ color: "black";
74− height: 2
78+ height: 2
75− width: parent.width
79+ width: parent.width
76−
80+
77− visible: dragHandle !== undefined && Direction.isVertical(dragHandle.direction)
81+ visible: dragHandle !== undefined && Direction.isVertical(dragHandle.direction)
78−
82+
79− y: {
83+ y: {
80− if (dragHandle) {
84+ if (dragHandle) {
81− if (dragHandle.direction === Direction.Downwards) {
85+ if (dragHandle.direction === Direction.Downwards) {
86+ dragHandle.edgeDragEvaluator.dragThreshold;
87+ } else {
82− dragHandle.edgeDragEvaluator.dragThreshold;
88+ parent.height - dragHandle.edgeDragEvaluator.dragThreshold;
89+ }
83 } else {
90 } else {
84− parent.height - dragHandle.edgeDragEvaluator.dragThreshold;
91+ 0
85 }
92 }
86− } else {
87− 0
88 }
93 }
89 }
94 }
90 }
95 }
@@ -119,27 +124,37 @@ Item {
119 }
124 }
120 }
125 }
121
126
122− TestButton {
127+ Row {
123− id: stretchButton
124 anchors.bottom: parent.bottom
128 anchors.bottom: parent.bottom
125 anchors.left: parent.left
129 anchors.left: parent.left
126 anchors.margins: units.gu(1)
130 anchors.margins: units.gu(1)
131+ spacing: units.gu(1)
127
132
133+ Button {
134+ id: stretchButton
128− text: root.stretch ? "stretch" : "move"
135+ text: root.stretch ? "stretch" : "move"
129− onClicked: { root.stretch = !root.stretch; }
136+ onClicked: { root.stretch = !root.stretch; }
130− }
137+ }
131
138
132− TestButton {
139+ Button {
133− anchors.bottom: parent.bottom
140+ text: root.hintDisplacement > 0 ? "hint" : "no hint"
134− anchors.left: stretchButton.right
141+ onClicked: {
135− anchors.margins: units.gu(1)
142+ if (root.hintDisplacement > 0) {
143+ root.hintDisplacement = 0;
144+ } else {
145+ root.hintDisplacement = units.gu(6);
146+ }
147+ }
148+ }
136
149
137− text: root.hintDisplacement > 0 ? "hint" : "no hint"
150+ Button {
151+ text: "rotation: " + baseItem.rotation
138− onClicked: {
152+ onClicked: {
139− if (root.hintDisplacement > 0) {
153+ if (baseItem.rotation === 0.0) {
140− root.hintDisplacement = 0;
154+ baseItem.rotation = 90.0
141− } else {
155+ } else {
142− root.hintDisplacement = units.gu(6);
156+ baseItem.rotation = 0.0
157+ }
143 }
158 }
144 }
159 }
145 }
160 }
tests/qmltests/Components/tst_DragHandle/TestButton.qmldeleted−41
@@ -1,41 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−
20−Rectangle {
21− id: rect
22− width: childrenRect.width
23− height: childrenRect.height
24−
25− property alias text: textComponent.text
26−
27− signal clicked
28−
29− color: "yellow"
30− Text {
31− id: textComponent
32− font.pixelSize: units.gu(2)
33− text: root.stretch ? "stretch" : "move"
34− MouseArea {
35− anchors.fill: parent
36− onClicked: {
37− rect.clicked()
38− }
39− }
40− }
41−}