on bf461a2 help sign in
unity8/Components/Revealer.qml
242 lines 7.7 kB history raw
1/*
2 * Copyright (C) 2013 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 */
17import QtQuick 2.0
18import Ubuntu.Components 0.1
19import "Math.js" as MathLocal
21Item {
22 id: revealer
24 property Showable target
25 property var hintingAnimation: hintingAnimation
26 property string boundProperty: orientation == Qt.Vertical ? "y" : "x"
27 property int orientation: Qt.Vertical
28 property int direction: Qt.LeftToRight
29 property real openedValue: orientation == Qt.Vertical ? y : x
30 property real closedValue: orientation == Qt.Vertical ? y + (direction == Qt.LeftToRight ? -height : height) : x + (direction == Qt.LeftToRight ? -width : width)
31 property real hintDisplacement: 0
32 property real handleSize: units.gu(2)
33 property real dragVelocity: draggingArea.dragVelocity != 0 ? Math.abs(draggingArea.dragVelocity) : -1
34 property real dragVelocityThreshold: units.gu(5)
35 property bool dragging: false
36 property bool pressed: draggingArea.pressed
37 property int lateralPosition: draggingArea.lateralPosition
38 property real dragPosition
39 property bool openOnPress: true
41 signal openPressed(int mouseX, int mouseY)
42 signal openReleased(int mouseX, int mouseY)
43 signal closePressed
44 signal openClicked
45 signal closeClicked
47 dragPosition: {
48 var value
49 if (orientation == Qt.Vertical) {
50 value = draggingArea.dragValue + draggingArea.y
51 if (direction == Qt.RightToLeft) {
52 value += draggingArea.height - height
53 }
54 } else {
55 value = draggingArea.dragValue + draggingArea.x
56 if (direction == Qt.RightToLeft) {
57 value += draggingArea.width - width
58 }
59 }
60 if (__opened) {
61 if (direction == Qt.LeftToRight) {
62 value += handleSize
63 } else {
64 value -= handleSize
65 }
66 } else if (dragging) {
67 if (direction == Qt.LeftToRight) {
68 value += hintDisplacement
69 } else {
70 value -= hintDisplacement
71 }
72 }
74 return value
75 }
76 property var draggingArea: leftDraggingArea.enabled ? leftDraggingArea : rightDraggingArea
78 property real __hintValue: closedValue + (direction == Qt.LeftToRight ? hintDisplacement : -hintDisplacement)
80 function dragToValue(dragPosition) {
81 return dragPosition + closedValue
82 }
84 property bool __opened: target.shown
85 enabled: target.available
87 // Can be replaced with a fake implementation during tests
88 // property var __getCurrentTimeMs: function () { return new Date().getTime() }
89 property var __dateTime: new function() {
90 this.getCurrentTimeMs = function() {return new Date().getTime()}
91 }
93 Component.onCompleted: target[boundProperty] = __opened ? openedValue : closedValue
94 onOpenedValueChanged: if (__opened && !dragging) target[boundProperty] = openedValue
95 onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
97 function __computeValue(dragPosition) {
98 return MathLocal.clamp(dragToValue(dragPosition), __hintValue, openedValue)
99 }
101 function __open() {
102 hintingAnimation.stop()
103 target.show()
104 }
106 function __close() {
107 hintingAnimation.stop()
108 target.hide()
109 }
111 function __hint() {
112 target.showAnimation.stop()
113 target.hideAnimation.stop()
114 hintingAnimation.restart()
115 }
117 function __settle() {
118 hintingAnimation.stop()
119 if (__opened) target.show()
120 else target.hide()
121 }
123 function __startDragging() {
124 hintingAnimation.stop()
125 dragging = true
126 }
128 function __endDragging(dragVelocity) {
129 dragging = false
130 if (revealer.direction == Qt.RightToLeft) {
131 dragVelocity = -dragVelocity
132 }
133 if (Math.abs(dragVelocity) >= dragVelocityThreshold) {
134 if (dragVelocity > 0) __open()
135 else __close()
136 } else {
137 __settle()
138 }
139 }
141 Binding {
142 id: dragBinding
144 target: revealer.target
145 property: revealer.boundProperty
146 value: __computeValue(dragPosition)
147 when: dragging
148 }
150 SmoothedAnimation {
151 id: hintingAnimation
153 target: revealer.target
154 property: revealer.boundProperty
155 duration: 150
156 to: revealer.__hintValue
157 }
159 DraggingArea {
160 id: leftDraggingArea
162 property bool isOpeningArea: revealer.direction == Qt.LeftToRight
164 height: orientation == Qt.Vertical ? handleSize : parent.height
165 width: orientation == Qt.Horizontal ? handleSize : parent.width
166 orientation: revealer.orientation
167 enabled: isOpeningArea ? !revealer.__opened : revealer.__opened
169 __dateTime: revealer.__dateTime
171 onPressed: {
172 if (isOpeningArea) {
173 if (revealer.openOnPress) {
174 revealer.openPressed(mouseX, mouseY)
175 __hint()
176 }
177 } else {
178 revealer.closePressed()
179 }
180 }
181 onReleased: {
182 if (isOpeningArea && revealer.openOnPress) {
183 revealer.openReleased(mouseX, mouseY)
184 __settle()
185 }
186 }
187 onDragStart: __startDragging()
188 onDragEnd: __endDragging(dragVelocity)
189 onClicked: {
190 if (clickValidated) {
191 if (isOpeningArea) {
192 if (revealer.openOnPress) revealer.openClicked()
193 } else {
194 revealer.closeClicked()
195 }
196 }
197 }
198 }
200 DraggingArea {
201 id: rightDraggingArea
203 property bool isOpeningArea: revealer.direction == Qt.RightToLeft
205 x: orientation == Qt.Vertical ? 0 : parent.width - width
206 y: orientation == Qt.Vertical ? parent.height - height : 0
207 height: orientation == Qt.Vertical ? handleSize : parent.height
208 width: orientation == Qt.Horizontal ? handleSize : parent.width
209 orientation: revealer.orientation
210 enabled: isOpeningArea ? !revealer.__opened : revealer.__opened
212 __dateTime: revealer.__dateTime
214 onPressed: {
215 if (isOpeningArea) {
216 if (revealer.openOnPress) {
217 revealer.openPressed(mouseX, mouseY)
218 __hint()
219 }
220 } else {
221 revealer.closePressed()
222 }
223 }
224 onReleased: {
225 if (isOpeningArea && revealer.openOnPress) {
226 revealer.openReleased(mouseX, mouseY)
227 __settle()
228 }
229 }
230 onDragStart: __startDragging()
231 onDragEnd: __endDragging(dragVelocity)
232 onClicked: {
233 if (clickValidated) {
234 if (isOpeningArea) {
235 if (revealer.openOnPress) revealer.openClicked()
236 } else {
237 revealer.closeClicked()
238 }
239 }
240 }
241 }