2 * Copyright (C) 2013 Canonical, Ltd.
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.
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.
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/>.
18 import Ubuntu.Components 0.1
19 import Ubuntu.Gestures 0.1
22 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
23 Main use case is to drag fullscreen Showables into the screen or off the screen.
25 This example shows a DragHandle placed on the right corner of a Showable, used
26 to slide it away, off the screen.
31 width: ... // screen width
32 height: ... // screen height
36 anchors.right: parent.right
37 anchors.top: parent.top
38 anchors.bottom: parent.bottom
41 direction: DirectionalDragArea::Leftwards
48 objectName: "dragHandle"
50 // Disable gesture recognition by default when hinting is used as
51 // it conflicts with the hinting idea.
52 distanceThreshold: hintDisplacement > 0 ? 0 : defaultDistanceThreshold
53 maxSilenceTime: hintDisplacement > 0 ? 60*60*1000 : defaultMaxSilenceTime
54 maxDeviation: hintDisplacement > 0 ? 999999 : defaultMaxDeviation
55 compositionTime: hintDisplacement > 0 ? 0 : defaultCompositionTime
57 property bool stretch: false
59 property alias autoCompleteDragThreshold: dragEvaluator.dragThreshold
61 // How far you can drag
62 property real maxTotalDragDistance: {
64 0; // not enough context information to set a sensible default
66 Direction.isHorizontal(direction) ? parent.width : parent.height;
70 property real hintDisplacement: 0
73 target: hintingAnimation
74 property: "targetValue"
77 to: Direction.isPositive(direction) ? d.startValue + hintDisplacement
78 : d.startValue - hintDisplacement
79 property real targetValue
80 onTargetValueChanged: {
85 if (Direction.isPositive(direction)) {
86 if (parent[d.targetProp] < targetValue) {
87 parent[d.targetProp] = targetValue;
90 if (parent[d.targetProp] > targetValue) {
91 parent[d.targetProp] = targetValue;
100 property var previousStatus: DirectionalDragArea.WaitingForTouch
101 property real startValue
102 property real minValue: Direction.isPositive(direction) ? startValue
103 : startValue - maxTotalDragDistance
104 property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
107 property var dragParent: dragArea.parent
109 // The property of DragHandle's parent that will be modified
110 property string targetProp: {
112 Direction.isHorizontal(direction) ? "width" : "height";
114 Direction.isHorizontal(direction) ? "x" : "y";
118 function limitMovement(inputStep) {
119 var targetValue = MathUtils.clamp(dragParent[targetProp] + inputStep, minValue, maxValue);
120 var step = targetValue - dragParent[targetProp];
122 if (hintDisplacement == 0) {
126 // we should not go behind hintingAnimation's current value
127 if (Direction.isPositive(direction)) {
128 if (dragParent[targetProp] + step < hintingAnimation.targetValue) {
129 step = hintingAnimation.targetValue - dragParent[targetProp];
132 if (dragParent[targetProp] + step > hintingAnimation.targetValue) {
133 step = hintingAnimation.targetValue - dragParent[targetProp];
140 function onFinishedRecognizedGesture() {
141 if (dragEvaluator.shouldAutoComplete()) {
148 function completeDrag() {
149 if (dragParent.shown) {
156 function rollbackDrag() {
157 if (dragParent.shown) {
165 property alias edgeDragEvaluator: dragEvaluator
168 objectName: "edgeDragEvaluator"
170 // Effectively convert distance into the drag position projected onto the gesture direction axis
171 trackedPosition: Direction.isPositive(dragArea.direction) ? sceneDistance : -sceneDistance
172 maxDragDistance: maxTotalDragDistance
173 direction: dragArea.direction
177 if (status === DirectionalDragArea.Recognized) {
178 // don't go the whole distance in order to smooth out the movement
179 var step = distance * 0.3;
181 step = d.limitMovement(step);
183 parent[d.targetProp] += step;
188 if (status === DirectionalDragArea.WaitingForTouch) {
189 hintingAnimation.stop();
190 if (d.previousStatus === DirectionalDragArea.Recognized) {
191 d.onFinishedRecognizedGesture();
192 } else /* d.previousStatus === DirectionalDragArea.Undecided */ {
193 // Gesture was rejected.
196 } else /* Undecided || Recognized */ {
197 if (d.previousStatus === DirectionalDragArea.WaitingForTouch) {
198 dragEvaluator.reset();
199 d.startValue = parent[d.targetProp];
201 if (hintDisplacement > 0) {
202 hintingAnimation.targetValue = d.startValue;
203 hintingAnimation.start();
208 d.previousStatus = status;