Lomiri
ScrollCalculator.qml
1 /*
2  * Copyright (C) 2014 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 Lomiri.Components 1.3
19 
20 Item {
21  id: scrollArea
22 
23  readonly property bool areaActive: lateralPosition >= 0
24  property real stopScrollThreshold: units.gu(2)
25  property real progressThreshold: units.dp(4)
26  property int direction: Qt.LeftToRight
27  property real baseScrollAmount: units.dp(3)
28  property real maximumScrollAmount: units.dp(8)
29  property real lateralPosition: -1
30  property real forceScrollingPercentage: 0.4
31 
32  signal scroll(real scrollAmount)
33 
34  width: units.gu(5)
35  rotation: direction === Qt.LeftToRight ? 0 : 180
36 
37  onAreaActiveChanged: areaActive ? handleEnter() : handleExit()
38 
39  function handleEnter() {
40  d.thresholdAreaX = -scrollArea.stopScrollThreshold;
41  scrollTimer.restart();
42  d.init = true;
43  d.passedProgressThreshold = false;
44 
45  d.progression = 0;
46  d.startingProgression = 0;
47  }
48 
49  function handleExit() {
50  d.thresholdAreaX = -scrollArea.stopScrollThreshold;
51  scrollTimer.stop();
52  }
53 
54  onLateralPositionChanged: {
55  if (scrollArea.areaActive) {
56  if (lateralPosition > width * (1 - forceScrollingPercentage)) {
57  d.thresholdAreaX = width * (1 - forceScrollingPercentage);
58  if (!scrollTimer.running) scrollTimer.restart();
59  } else if (lateralPosition > d.thresholdAreaX + scrollArea.stopScrollThreshold) {
60  d.thresholdAreaX = lateralPosition - scrollArea.stopScrollThreshold;
61  if (!scrollTimer.running) scrollTimer.restart();
62  } else if (lateralPosition < d.thresholdAreaX) {
63  d.thresholdAreaX = lateralPosition;
64  scrollTimer.stop();
65  }
66 
67  d.progression = lateralPosition / width;
68  if (d.init) {
69  d.startingProgression = d.progression;
70  d.init = false;
71  }
72  }
73  }
74 
75  Timer {
76  id: scrollTimer
77  interval: 16
78  repeat: true
79 
80  onTriggered: {
81  if (d.passedProgressThreshold ||
82  Math.abs(d.progression - d.startingProgression) * scrollArea.width > scrollArea.progressThreshold) {
83  d.passedProgressThreshold = true;
84 
85  var scrollAmount = scrollArea.baseScrollAmount + scrollArea.maximumScrollAmount * d.progression;
86  scrollArea.scroll(scrollAmount);
87  }
88  }
89  }
90 
91  QtObject {
92  id: d
93  property real startingProgression: 0
94  property bool init: true
95 
96  property real progression: 0
97  property real thresholdAreaX: -scrollArea.stopScrollThreshold
98  property bool passedProgressThreshold: false
99  }
100 }