@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
20+import "Math.js" as MathLocal
2021
2122/*
2223 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
@@ -45,19 +46,122 @@ import Ubuntu.Gestures 0.1
4546 */
4647EdgeDragArea {
4748 id: dragArea
49+ objectName: "dragHandle"
50+
51+ property bool stretch: false
52+
53+ property alias autoCompleteDragThreshold: dragEvaluator.dragThreshold
4854
4955 // How far you can drag
50− property real maxTotalDragDistance: Direction.isHorizontal(direction) ? parent.width : parent.height
56+ property real maxTotalDragDistance: {
57+ if (stretch) {
58+ 0; // not enough context information to set a sensible default
59+ } else {
60+ Direction.isHorizontal(direction) ? parent.width : parent.height;
61+ }
62+ }
63+
64+ property real hintDisplacement: 0
65+ SmoothedAnimation {
66+ id: hintingAnimation
67+ target: hintingAnimation
68+ property: "targetValue"
69+ duration: 150
70+ velocity: -1
71+ to: Direction.isPositive(direction) ? d.startValue + hintDisplacement
72+ : d.startValue - hintDisplacement
73+ property real targetValue
74+ onTargetValueChanged: {
75+ if (!running) {
76+ return;
77+ }
78+
79+ if (Direction.isPositive(direction)) {
80+ if (parent[d.targetProp] < targetValue) {
81+ parent[d.targetProp] = targetValue;
82+ }
83+ } else {
84+ if (parent[d.targetProp] > targetValue) {
85+ parent[d.targetProp] = targetValue;
86+ }
87+ }
88+ }
89+ }
90+
91+ // Private stuff
92+ QtObject {
93+ id: d
94+ property var previousStatus: undefined
95+ property real startValue
96+ property real minValue: Direction.isPositive(direction) ? startValue
97+ : startValue - maxTotalDragDistance
98+ property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
99+ : startValue
100+
101+ property var dragParent: dragArea.parent
102+
103+ // The property of DragHandle's parent that will be modified
104+ property string targetProp: {
105+ if (stretch) {
106+ Direction.isHorizontal(direction) ? "width" : "height";
107+ } else {
108+ Direction.isHorizontal(direction) ? "x" : "y";
109+ }
110+ }
111+
112+ function limitMovement(step) {
113+ var targetValue = MathLocal.clamp(dragParent[targetProp] + step, minValue, maxValue);
114+ var step = targetValue - dragParent[targetProp];
115+
116+ if (hintDisplacement == 0) {
117+ return step;
118+ }
119+
120+ // we should not go behind hintingAnimation's current value
121+ if (Direction.isPositive(direction)) {
122+ if (dragParent[targetProp] + step < hintingAnimation.targetValue) {
123+ step = hintingAnimation.targetValue - dragParent[targetProp];
124+ }
125+ } else {
126+ if (dragParent[targetProp] + step > hintingAnimation.targetValue) {
127+ step = hintingAnimation.targetValue - dragParent[targetProp];
128+ }
129+ }
130+
131+ return step;
132+ }
133+
134+ function onFinishedRecognizedGesture() {
135+ if (dragEvaluator.shouldAutoComplete()) {
136+ completeDrag();
137+ } else {
138+ rollbackDrag();
139+ }
140+ }
51141
52− property var __previousStatus
53− property real __totalDragDistance: 0
142+ function completeDrag() {
143+ if (dragParent.shown) {
144+ dragParent.hide();
145+ } else {
146+ dragParent.show();
147+ }
148+ }
149+
150+ function rollbackDrag() {
151+ if (dragParent.shown) {
152+ dragParent.show();
153+ } else {
154+ dragParent.hide();
155+ }
156+ }
157+ }
54158
55159 property alias edgeDragEvaluator: dragEvaluator
56160
57161 EdgeDragEvaluator {
58162 objectName: "edgeDragEvaluator"
59163 id: dragEvaluator
60− trackedPosition: Direction.isHorizontal(direction) ? parent.x + touchX : parent.y + touchY
164+ trackedPosition: sceneDistance
61165 maxDragDistance: maxTotalDragDistance
62166 direction: dragArea.direction
63167 }
@@ -67,75 +171,38 @@ EdgeDragArea {
67171 // don't go the whole distance in order to smooth out the movement
68172 var step = distance * 0.3;
69173
70− step = __limitMovement(step);
174+ step = d.limitMovement(step);
71175
72− __totalDragDistance += step;
73−
74− if (Direction.isHorizontal(direction)) {
75− parent.x += step;
76− } else {
77− parent.y += step;
78− }
176+ parent[d.targetProp] += step;
79177 }
80178 }
81179
82−
83− function __limitMovement(step) {
84− if (Direction.isPositive(direction)) {
85− if (__totalDragDistance + step > maxTotalDragDistance) {
86− step = maxTotalDragDistance - __totalDragDistance;
87− } else if (__totalDragDistance + step < 0) {
88− step = 0 - __totalDragDistance;
180+ onDraggingChanged: {
181+ if (dragging) {
182+ if (hintDisplacement > 0) {
183+ hintingAnimation.targetValue = d.startValue;
184+ hintingAnimation.start();
89185 }
90186 } else {
91− if (__totalDragDistance + step < -maxTotalDragDistance) {
92− step = -maxTotalDragDistance - __totalDragDistance;
93− } else if (__totalDragDistance + step > 0) {
94− step = 0 - __totalDragDistance;
95− }
187+ hintingAnimation.stop();
96188 }
97−
98− return step;
99189 }
100190
101191 onStatusChanged: {
102192 if (status === DirectionalDragArea.WaitingForTouch) {
103− if (__previousStatus === DirectionalDragArea.Recognized) {
104− __onFinishedRecognizedGesture();
193+ if (d.previousStatus === DirectionalDragArea.Recognized) {
194+ d.onFinishedRecognizedGesture();
105195 }
106− __totalDragDistance = 0;
196+ d.startValue = parent[d.targetProp];
107197 }
108− else if (status === DirectionalDragArea.Undecided) {
198+
199+ if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
200+ d.previousStatus === undefined) {
109201 dragEvaluator.reset();
202+ d.startValue = parent[d.targetProp];
110203 }
111− else if (status === DirectionalDragArea.Recognized) {
112− if (__previousStatus === DirectionalDragArea.WaitingForTouch)
113− dragEvaluator.reset();
114− }
115− __previousStatus = status;
116− }
117204
118− function __onFinishedRecognizedGesture() {
119− if (dragEvaluator.shouldAutoComplete()) {
120− __completeDrag();
121− } else {
122− __rollbackDrag();
123− }
205+ d.previousStatus = status;
124206 }
125207
126− function __completeDrag() {
127− if (parent.shown) {
128− parent.hide();
129− } else {
130− parent.show();
131− }
132− }
133−
134− function __rollbackDrag() {
135− if (parent.shown) {
136− parent.show();
137− } else {
138− parent.hide();
139− }
140− }
141208}