2 * Copyright (C) 2013,2016 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 1.3
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: SwipeArea::Leftwards
49 property bool stretch: false
51 property alias autoCompleteDragThreshold: dragEvaluator.dragThreshold
53 // How far you can drag
54 property real maxTotalDragDistance: {
56 0; // not enough context information to set a sensible default
58 Direction.isHorizontal(direction) ? parent.width : parent.height;
62 property real hintDisplacement: 0
64 immediateRecognition: hintDisplacement > 0
66 property var overrideStartValue: undefined
69 target: hintingAnimation
70 property: "targetValue"
74 to: d.incrementTargetProp ? d.startValue + hintDisplacement
75 : d.startValue - hintDisplacement
76 property real targetValue
77 onTargetValueChanged: {
82 if (d.incrementTargetProp) {
83 if (parent[d.targetProp] < targetValue) {
84 parent[d.targetProp] = targetValue;
87 if (parent[d.targetProp] > targetValue) {
88 parent[d.targetProp] = targetValue;
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)
102 property real startValue
103 property real minValue: {
104 if (direction == Direction.Horizontal) {
105 return startValue - maxTotalDragDistance;
106 } else if (incrementTargetProp) {
109 return startValue - maxTotalDragDistance;
113 property real maxValue: incrementTargetProp ? startValue + maxTotalDragDistance
116 property var dragParent: dragArea.parent
118 // The property of DragHandle's parent that will be modified
119 property string targetProp: {
121 Direction.isHorizontal(direction) ? "width" : "height";
123 Direction.isHorizontal(direction) ? "x" : "y";
127 function limitMovement(distance) {
128 var targetValue = MathUtils.clamp(d.startValue + distance, minValue, maxValue);
129 var diff = targetValue - d.startValue;
131 if (hintDisplacement == 0) {
135 // we should not go behind hintingAnimation's current value
136 if (d.incrementTargetProp) {
137 if (d.startValue + diff < hintingAnimation.targetValue) {
138 diff = hintingAnimation.targetValue - d.startValue;
141 if (d.startValue + diff > hintingAnimation.targetValue) {
142 diff = hintingAnimation.targetValue - d.startValue;
149 function onFinishedRecognizedGesture() {
150 if (dragEvaluator.shouldAutoComplete()) {
157 function completeDrag() {
158 if (dragParent.shown) {
165 function rollbackDrag() {
166 if (dragParent.shown) {
174 property alias edgeDragEvaluator: dragEvaluator
177 objectName: "edgeDragEvaluator"
179 // Effectively convert distance into the drag position projected onto the gesture direction axis
180 trackedPosition: Direction.isPositive(dragArea.direction) ? distance : -distance
181 maxDragDistance: maxTotalDragDistance
182 direction: dragArea.direction
187 if (!Direction.isPositive(direction))
188 distance = -distance;
190 if (dragArea.stretch &&
191 ((!Direction.isPositive(direction) && !d.dragParent.shown)
193 (Direction.isPositive(direction) && d.dragParent.shown))
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;
203 var toAdd = d.limitMovement(distance);
204 parent[d.targetProp] = d.startValue + toAdd;
210 dragEvaluator.reset();
211 if (overrideStartValue !== undefined) {
212 d.startValue = overrideStartValue;
214 d.startValue = parent[d.targetProp];
217 if (hintDisplacement > 0) {
218 hintingAnimation.targetValue = d.startValue;
219 hintingAnimation.start();
222 hintingAnimation.stop();
223 d.onFinishedRecognizedGesture();