2 * Copyright (C) 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
20 import "../../Components"
25 property bool closeable: true
26 readonly property real minSpeedToClose: units.gu(40)
27 property bool zeroVelocityCounts: false
29 readonly property alias distance: d.distance
36 property real distance: 0
37 property bool moving: false
38 property var dragEvents: []
39 property real dragVelocity: 0
40 property int threshold: units.gu(2)
42 // Can be replaced with a fake implementation during tests
43 // property var __getCurrentTimeMs: function () { return new Date().getTime() }
44 property var __dateTime: new function() {
45 this.getCurrentTimeMs = function() {return new Date().getTime()}
48 function pushDragEvent(event) {
49 var currentTime = __dateTime.getCurrentTimeMs()
50 dragEvents.push([currentTime, event.x - event.startX, event.y - event.startY, getEventSpeed(currentTime, event)])
51 cullOldDragEvents(currentTime)
55 function cullOldDragEvents(currentTime) {
56 // cull events older than 50 ms but always keep the latest 2 events
57 for (var numberOfCulledEvents = 0; numberOfCulledEvents < dragEvents.length-2; numberOfCulledEvents++) {
58 // dragEvents[numberOfCulledEvents][0] is the dragTime
59 if (currentTime - dragEvents[numberOfCulledEvents][0] <= 50) break
62 dragEvents.splice(0, numberOfCulledEvents)
65 function updateSpeed() {
67 for (var i = 0; i < dragEvents.length; i++) {
68 totalSpeed += dragEvents[i][3]
71 if (zeroVelocityCounts || Math.abs(totalSpeed) > 0.001) {
72 dragVelocity = totalSpeed / dragEvents.length * 1000
76 function getEventSpeed(currentTime, event) {
77 if (dragEvents.length != 0) {
78 var lastDrag = dragEvents[dragEvents.length-1]
79 var duration = Math.max(1, currentTime - lastDrag[0])
80 return (event.y - event.startY - lastDrag[2]) / duration
90 onClicked: root.clicked()
91 onWheel: wheel.accepted = true
98 property int offset: 0
108 animation.animate("center");
113 if (Math.abs(tp.startY - tp.y) > d.threshold) {
116 offset = tp.y - tp.startY;
122 if (root.closeable) {
123 d.distance = tp.y - tp.startY - offset
125 var value = tp.y - tp.startY - offset;
126 d.distance = Math.sqrt(Math.abs(value)) * (value < 0 ? -1 : 1) * 3
137 if (!root.closeable) {
138 animation.animate("center")
142 var touchPoint = touchPoints[0];
144 if ((d.dragVelocity < -root.minSpeedToClose && d.distance < -units.gu(8)) || d.distance < -root.height / 2) {
145 animation.animate("up")
146 } else if ((d.dragVelocity > root.minSpeedToClose && d.distance > units.gu(8)) || d.distance > root.height / 2) {
147 animation.animate("down")
149 animation.animate("center")
154 UbuntuNumberAnimation {
156 objectName: "closeAnimation"
159 property bool requestClose: false
161 function animate(direction) {
162 animation.from = dragArea.distance;
165 animation.to = -root.height * 1.5;
169 animation.to = root.height * 1.5;