on xenial help sign in
Fix DragHandle so it works in all directions
be06a7aDaniel d'Andrada
qml/Components/DragHandle.qml+28−8
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -70,15 +70,16 @@ SwipeArea {
70 property: "targetValue"
70 property: "targetValue"
71 duration: 150
71 duration: 150
72 velocity: -1
72 velocity: -1
73+
73− to: Direction.isPositive(direction) ? d.startValue + hintDisplacement
74+ to: d.incrementTargetProp ? d.startValue + hintDisplacement
74− : d.startValue - hintDisplacement
75+ : d.startValue - hintDisplacement
75 property real targetValue
76 property real targetValue
76 onTargetValueChanged: {
77 onTargetValueChanged: {
77 if (!running) {
78 if (!running) {
78 return;
79 return;
79 }
80 }
80
81
81− if (Direction.isPositive(direction)) {
82+ if (d.incrementTargetProp) {
82 if (parent[d.targetProp] < targetValue) {
83 if (parent[d.targetProp] < targetValue) {
83 parent[d.targetProp] = targetValue;
84 parent[d.targetProp] = targetValue;
84 }
85 }
@@ -93,19 +94,24 @@ SwipeArea {
93 // Private stuff
94 // Private stuff
94 QtObject {
95 QtObject {
95 id: d
96 id: d
97+
98+ // Whether movement along the designated direction will increment the value of the target property
99+ readonly property bool incrementTargetProp: (Direction.isPositive(direction) && !dragArea.stretch)
100+ || (dragArea.stretch && !d.dragParent.shown)
101+
96 property real startValue
102 property real startValue
97 property real minValue: {
103 property real minValue: {
98 if (direction == Direction.Horizontal) {
104 if (direction == Direction.Horizontal) {
99 return startValue - maxTotalDragDistance;
105 return startValue - maxTotalDragDistance;
100− } else if (Direction.isPositive(direction)) {
106+ } else if (incrementTargetProp) {
101 return startValue;
107 return startValue;
102 } else {
108 } else {
103 return startValue - maxTotalDragDistance;
109 return startValue - maxTotalDragDistance;
104 }
110 }
105 }
111 }
106
112
107− property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
113+ property real maxValue: incrementTargetProp ? startValue + maxTotalDragDistance
108− : startValue
114+ : startValue;
109
115
110 property var dragParent: dragArea.parent
116 property var dragParent: dragArea.parent
111
117
@@ -127,7 +133,7 @@ SwipeArea {
127 }
133 }
128
134
129 // we should not go behind hintingAnimation's current value
135 // we should not go behind hintingAnimation's current value
130− if (Direction.isPositive(direction)) {
136+ if (d.incrementTargetProp) {
131 if (d.startValue + diff < hintingAnimation.targetValue) {
137 if (d.startValue + diff < hintingAnimation.targetValue) {
132 diff = hintingAnimation.targetValue - d.startValue;
138 diff = hintingAnimation.targetValue - d.startValue;
133 }
139 }
@@ -180,6 +186,20 @@ SwipeArea {
180 if (dragging) {
186 if (dragging) {
181 if (!Direction.isPositive(direction))
187 if (!Direction.isPositive(direction))
182 distance = -distance;
188 distance = -distance;
189+
190+ if (dragArea.stretch &&
191+ ((!Direction.isPositive(direction) && !d.dragParent.shown)
192+ ||
193+ (Direction.isPositive(direction) && d.dragParent.shown))
194+ )
195+ {
196+ // This happens when you have a stretching showable being shown from the right or
197+ // top edge (and consequently being hidden when dragged towards the right/top edge)
198+ // In those situations, dimension expansion/retraction happens in the opposite
199+ // sign of the axis direction
200+ distance = -distance;
201+ }
202+
183 var toAdd = d.limitMovement(distance);
203 var toAdd = d.limitMovement(distance);
184 parent[d.targetProp] = d.startValue + toAdd;
204 parent[d.targetProp] = d.startValue + toAdd;
185 }
205 }
qml/Stages/SideStage.qml+1−2
@@ -98,8 +98,7 @@ Showable {
98 id: hideSideStageDragArea
98 id: hideSideStageDragArea
99 objectName: "hideSideStageDragArea"
99 objectName: "hideSideStageDragArea"
100
100
101− direction: Direction.Leftwards
101+ direction: Direction.Rightwards
102− rotation: 180
103 enabled: root.shown
102 enabled: root.shown
104 anchors.right: root.left
103 anchors.right: root.left
105 width: sideStageDragHandle.width
104 width: sideStageDragHandle.width
tests/qmltests/Components/tst_DragHandle.cpp+7−7
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013-2014 Canonical, Ltd.
2+ * Copyright (C) 2013-2014,2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -290,7 +290,7 @@ void tst_DragHandle::dragThreshold_vertical()
290 QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
290 QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
291 baseItem->setRotation(rotation);
291 baseItem->setRotation(rotation);
292
292
293− QQuickItem *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
293+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
294
294
295 qreal dragThreshold = fetchDragThreshold(dragHandle);
295 qreal dragThreshold = fetchDragThreshold(dragHandle);
296
296
@@ -309,7 +309,7 @@ void tst_DragHandle::dragThreshold_vertical()
309 tryCompare([&](){ return parentItem->y(); }, 0);
309 tryCompare([&](){ return parentItem->y(); }, 0);
310 QCOMPARE(parentItem->property("shown").toBool(), true);
310 QCOMPARE(parentItem->property("shown").toBool(), true);
311
311
312− dragHandle = fetchAndSetupDragHandle("upwardsDragHandle");
312+ dragHandle = fetchAndSetupDragHandle("topEdgeHideDragHandle");
313
313
314 dragThreshold = fetchDragThreshold(dragHandle);
314 dragThreshold = fetchDragThreshold(dragHandle);
315
315
@@ -372,7 +372,7 @@ void tst_DragHandle::stretch_horizontal()
372
372
373void tst_DragHandle::stretch_vertical()
373void tst_DragHandle::stretch_vertical()
374{
374{
375− QQuickItem *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
375+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
376 qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
376 qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
377 QQuickItem *parentItem = dragHandle->parentItem();
377 QQuickItem *parentItem = dragHandle->parentItem();
378
378
@@ -389,7 +389,7 @@ void tst_DragHandle::stretch_vertical()
389 tryCompare([&](){ return parentItem->height(); }, totalDragDistance);
389 tryCompare([&](){ return parentItem->height(); }, totalDragDistance);
390 QCOMPARE(parentItem->property("shown").toBool(), true);
390 QCOMPARE(parentItem->property("shown").toBool(), true);
391
391
392− dragHandle = fetchAndSetupDragHandle("upwardsDragHandle");
392+ dragHandle = fetchAndSetupDragHandle("topEdgeHideDragHandle");
393
393
394 // flick all the way
394 // flick all the way
395 flickAndHold(dragHandle, totalDragDistance);
395 flickAndHold(dragHandle, totalDragDistance);
@@ -408,7 +408,7 @@ void tst_DragHandle::stretch_vertical()
408 */
408 */
409void tst_DragHandle::hintingAnimation()
409void tst_DragHandle::hintingAnimation()
410{
410{
411− QQuickItem *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
411+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
412 QQuickItem *parentItem = dragHandle->parentItem();
412 QQuickItem *parentItem = dragHandle->parentItem();
413 qreal hintDisplacement = 100.0;
413 qreal hintDisplacement = 100.0;
414
414
@@ -449,7 +449,7 @@ void tst_DragHandle::hintingAnimation()
449 */
449 */
450void tst_DragHandle::hintingAnimation_dontRestartAfterFinishedAndStillPressed()
450void tst_DragHandle::hintingAnimation_dontRestartAfterFinishedAndStillPressed()
451{
451{
452− QQuickItem *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
452+ QQuickItem *dragHandle = fetchAndSetupDragHandle("topEdgeShowDragHandle");
453 QQuickItem *parentItem = dragHandle->parentItem();
453 QQuickItem *parentItem = dragHandle->parentItem();
454 qreal hintDisplacement = 100.0;
454 qreal hintDisplacement = 100.0;
455
455
tests/qmltests/Components/tst_DragHandle.qml+22−4
@@ -64,15 +64,33 @@ Rectangle {
64 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
64 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
65 }
65 }
66
66
67− VerticalShowable {
67+ TopEdgeShowable {
68+ id: topEdgeShowable
68− visible: !root.bidirectional
69+ visible: !root.bidirectional && !bottomEdgeShowable.shown
69 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
70 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
70 stretch: root.stretch
71 stretch: root.stretch
71 hintDisplacement: root.hintDisplacement
72 hintDisplacement: root.hintDisplacement
72 }
73 }
73
74
74− HorizontalShowable {
75+ BottomEdgeShowable {
76+ id: bottomEdgeShowable
77+ visible: !root.bidirectional && !topEdgeShowable.shown
78+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
79+ stretch: root.stretch
80+ hintDisplacement: root.hintDisplacement
81+ }
82+
83+ LeftEdgeShowable {
84+ id: leftEdgeShowable
75− visible: !root.bidirectional
85+ visible: !root.bidirectional && !rightEdgeShowable.shown
86+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
87+ stretch: root.stretch
88+ hintDisplacement: root.hintDisplacement
89+ }
90+
91+ RightEdgeShowable {
92+ id: rightEdgeShowable
93+ visible: !root.bidirectional && !leftEdgeShowable.shown
76 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
94 onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
77 stretch: root.stretch
95 stretch: root.stretch
78 hintDisplacement: root.hintDisplacement
96 hintDisplacement: root.hintDisplacement
tests/qmltests/Components/tst_DragHandle/BottomEdgeShowable.qmlnew file+108
@@ -0,0 +1,108 @@
1+/*
2+ * Copyright (C) 2016 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.4
18+import "../../../../qml/Components"
19+import Ubuntu.Components 1.3
20+import Ubuntu.Gestures 0.1
21+
22+Showable {
23+ id: root
24+ y: height
25+ width: parent.width
26+ height: parent.height
27+
28+ property bool stretch
29+ property real hintDisplacement
30+
31+ Binding {
32+ when: stretch
33+ target: root
34+ property: "y"
35+ value: root.parent.height - root.height
36+ }
37+
38+ onStretchChanged: {
39+ // reset
40+ shown = false;
41+ if (stretch) {
42+ height = 0;
43+ } else {
44+ y = parent.height;
45+ height = parent.height;
46+ }
47+ }
48+
49+ shown: false
50+
51+ signal dragHandleRecognizedGesture(var dragHandle)
52+
53+ property string animatedProp: stretch ? "height" : "y"
54+ property real propValueWhenShown: stretch ? parent.height : 0
55+ property real propValueWhenHidden: stretch ? 0 : height
56+
57+ showAnimation: StandardAnimation { property: animatedProp; to: propValueWhenShown }
58+ hideAnimation: StandardAnimation { property: animatedProp; to: propValueWhenHidden }
59+
60+ Image { source: "../../UnityLogo.png"; anchors.fill: parent }
61+
62+ DragHandle {
63+ objectName: "topEdgeHideDragHandle"
64+ id: hideDragHandle
65+ anchors.left: parent.left
66+ anchors.right: parent.right
67+ anchors.top: parent.top
68+
69+ height: units.gu(2)
70+
71+ direction: Direction.Downwards
72+ stretch: root.stretch
73+ maxTotalDragDistance: root.parent.height
74+ hintDisplacement: root.hintDisplacement
75+
76+ onDraggingChanged: {
77+ if (dragging) {
78+ dragHandleRecognizedGesture(hideDragHandle);
79+ }
80+ }
81+
82+ Rectangle { color: "red"; anchors.fill: parent }
83+ }
84+
85+ DragHandle {
86+ objectName: "topEdgeShowDragHandle"
87+ id: showDragHandle
88+ anchors.left: parent.left
89+ anchors.right: parent.right
90+ anchors.bottom: parent.top
91+
92+ height: units.gu(2)
93+
94+ direction: Direction.Upwards
95+ stretch: root.stretch
96+ maxTotalDragDistance: root.parent.height
97+ hintDisplacement: root.hintDisplacement
98+
99+ onDraggingChanged: {
100+ if (dragging) {
101+ dragHandleRecognizedGesture(showDragHandle);
102+ }
103+ }
104+
105+ Rectangle { color: "green"; anchors.fill: parent }
106+ }
107+
108+}
tests/qmltests/Components/tst_DragHandle/HorizontalShowable.qml → tests/qmltests/Components/tst_DragHandle/LeftEdgeShowable.qmlrenamed

The content is the same.

tests/qmltests/Components/tst_DragHandle/RightEdgeShowable.qmlnew file+108
@@ -0,0 +1,108 @@
1+/*
2+ * Copyright (C) 2016 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.4
18+import "../../../../qml/Components"
19+import Ubuntu.Components 1.3
20+import Ubuntu.Gestures 0.1
21+
22+Showable {
23+ id: root
24+ x: parent.width
25+ width: parent.width
26+ height: parent.height
27+
28+ property bool stretch
29+ property real hintDisplacement
30+
31+ Binding {
32+ when: stretch
33+ target: root
34+ property: "x"
35+ value: root.parent.width - root.width
36+ }
37+
38+ onStretchChanged: {
39+ // reset
40+ shown = false;
41+ if (stretch) {
42+ width = 0;
43+ } else {
44+ x = parent.width;
45+ width = parent.width;
46+ }
47+ }
48+
49+ shown: false
50+
51+ signal dragHandleRecognizedGesture(var dragHandle)
52+
53+ property string animatedProp: stretch ? "width" : "x"
54+ property real propValueWhenShown: stretch ? parent.width : 0
55+ property real propValueWhenHidden: stretch ? 0 : parent.width
56+
57+ showAnimation: StandardAnimation { property: animatedProp; to: propValueWhenShown }
58+ hideAnimation: StandardAnimation { property: animatedProp; to: propValueWhenHidden }
59+
60+ Image { source: "../../UnityLogo.png"; anchors.fill: parent }
61+
62+ DragHandle {
63+ objectName: "rightEdgeHideDragHandle"
64+ id: hideDragHandle
65+ anchors.top: parent.top
66+ anchors.bottom: parent.bottom
67+ anchors.left: parent.left
68+
69+ width: units.gu(2)
70+
71+ direction: Direction.Rightwards
72+ stretch: root.stretch
73+ maxTotalDragDistance: root.parent.width
74+ hintDisplacement: root.hintDisplacement
75+
76+ onDraggingChanged: {
77+ if (dragging) {
78+ dragHandleRecognizedGesture(hideDragHandle);
79+ }
80+ }
81+
82+ Rectangle { color: "red"; anchors.fill: parent }
83+ }
84+
85+ DragHandle {
86+ objectName: "rightEdgeShowDragHandle"
87+ id: showDragHandle
88+ anchors.top: parent.top
89+ anchors.bottom: parent.bottom
90+ anchors.right: parent.left
91+
92+ width: units.gu(2)
93+
94+ direction: Direction.Leftwards
95+ stretch: root.stretch
96+ maxTotalDragDistance: root.parent.width
97+ hintDisplacement: root.hintDisplacement
98+
99+ onDraggingChanged: {
100+ if (dragging) {
101+ dragHandleRecognizedGesture(showDragHandle);
102+ }
103+ }
104+
105+ Rectangle { color: "green"; anchors.fill: parent }
106+ }
107+
108+}
tests/qmltests/Components/tst_DragHandle/VerticalShowable.qml → tests/qmltests/Components/tst_DragHandle/TopEdgeShowable.qmlrenamed+7−7
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013,2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -52,8 +52,8 @@ Showable {
52 Image { source: "../../UnityLogo.png"; anchors.fill: parent }
52 Image { source: "../../UnityLogo.png"; anchors.fill: parent }
53
53
54 DragHandle {
54 DragHandle {
55− objectName: "upwardsDragHandle"
55+ objectName: "topEdgeHideDragHandle"
56− id: upwardsDragHandle
56+ id: hideDragHandle
57 anchors.left: parent.left
57 anchors.left: parent.left
58 anchors.right: parent.right
58 anchors.right: parent.right
59 anchors.bottom: parent.bottom
59 anchors.bottom: parent.bottom
@@ -67,7 +67,7 @@ Showable {
67
67
68 onDraggingChanged: {
68 onDraggingChanged: {
69 if (dragging) {
69 if (dragging) {
70− dragHandleRecognizedGesture(upwardsDragHandle);
70+ dragHandleRecognizedGesture(hideDragHandle);
71 }
71 }
72 }
72 }
73
73
@@ -75,8 +75,8 @@ Showable {
75 }
75 }
76
76
77 DragHandle {
77 DragHandle {
78− objectName: "downwardsDragHandle"
78+ objectName: "topEdgeShowDragHandle"
79− id: downwardsDragHandle
79+ id: showDragHandle
80 anchors.left: parent.left
80 anchors.left: parent.left
81 anchors.right: parent.right
81 anchors.right: parent.right
82 anchors.top: parent.bottom
82 anchors.top: parent.bottom
@@ -90,7 +90,7 @@ Showable {
90
90
91 onDraggingChanged: {
91 onDraggingChanged: {
92 if (dragging) {
92 if (dragging) {
93− dragHandleRecognizedGesture(downwardsDragHandle);
93+ dragHandleRecognizedGesture(showDragHandle);
94 }
94 }
95 }
95 }
96
96