Unity 8
SwipeToAct.qml
1 /*
2  * Copyright (C) 20014-2015 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.3
18 import Ubuntu.Components 1.1
19 
20 Item {
21  id: swipeToAct
22 
23  height: childrenRect.height
24 
25  signal leftTriggered()
26  signal rightTriggered()
27 
28  property string leftIconName
29  property string rightIconName
30 
31  QtObject {
32  id: priv
33 
34  property double opacityDelta
35  readonly property double sliderHeight: units.gu(8)
36  readonly property double gap: units.gu(1)
37  readonly property color sliderMainColor: "#b2b2b2"
38  readonly property color sliderBGColor: "#f4f4f4"
39  readonly property double halfWay: mouseArea.drag.maximumX / 2
40 
41  UbuntuNumberAnimation on opacityDelta {
42  from: 0
43  to: .5
44  loops: Animation.Infinite
45  duration: UbuntuAnimation.SleepyDuration
46  easing.type: Easing.Linear
47  }
48 
49  // linearly interpolate between start- and end-color
50  // with a normalized weight-factor
51  // 0.0 meaning just the start-color being taken into
52  // account and 1.0 only taking the end-color into
53  // account
54  function interpolate(start, end, factor) {
55  var rdiff = start.r > end.r ? end.r - start.r : end.r - start.r
56  var gdiff = start.g > end.g ? end.g - start.g : end.g - start.g
57  var bdiff = start.b > end.b ? end.b - start.b : end.b - start.b
58  var adiff = start.a > end.a ? end.a - start.a : end.a - start.a
59  var r = start.r + factor * rdiff
60  var g = start.g + factor * gdiff
61  var b = start.b + factor * bdiff
62  var a = start.a + factor * adiff
63  return Qt.rgba(r,g,b,a)
64  }
65  }
66 
67  UbuntuShape {
68  id: row
69  width: parent.width
70  height: priv.sliderHeight
71  color: priv.sliderBGColor
72  borderSource: "none"
73 
74  UbuntuShape {
75  id: leftShape
76  anchors.top: parent.top
77  anchors.left: parent.left
78  anchors.margins: priv.gap
79  color: UbuntuColors.red
80  borderSource: "none"
81 
82  state: "normal"
83  height: units.gu(6)
84  width: units.gu(6)
85  radius: "medium"
86  opacity: slider.x <= priv.halfWay ? 1.0 : 1.0 - ((slider.x - priv.halfWay) / priv.halfWay)
87 
88  Icon {
89  anchors.centerIn: parent
90  width: units.gu(3.5)
91  height: units.gu(3.5)
92  name: leftIconName
93  color: "white"
94  }
95  }
96 
97  Row {
98  anchors.verticalCenter: parent.verticalCenter
99  anchors.right: slider.left
100  anchors.rightMargin: units.gu(1.5)
101  spacing: -units.gu(1)
102  visible: slider.x === priv.halfWay
103  Icon {
104  name: "back"
105  height: units.gu(2.5)
106  color: priv.sliderMainColor
107  opacity: .5 + priv.opacityDelta
108  }
109  Icon {
110  name: "back"
111  height: units.gu(2.5)
112  color: priv.sliderMainColor
113  opacity: 1 - priv.opacityDelta
114  }
115  }
116 
117  UbuntuShape {
118  id: slider
119  objectName: "slider"
120  anchors.top: parent.top
121  anchors.margins: priv.gap
122  x: priv.halfWay
123 
124  Component.onCompleted: {
125  xBehavior.enabled = true
126  }
127 
128  Behavior on x {
129  id: xBehavior
130  enabled: false
131  UbuntuNumberAnimation {
132  duration: UbuntuAnimation.FastDuration
133  easing.type: Easing.OutBounce
134  }
135  }
136 
137  Behavior on opacity {
138  UbuntuNumberAnimation {
139  duration: UbuntuAnimation.FastDuration
140  }
141  }
142 
143  onXChanged: {
144  var factor
145  if (slider.x <= priv.gap + leftShape.width)
146  {
147  factor = (slider.x - priv.gap) / leftShape.width
148  slider.color = priv.interpolate(leftShape.color, priv.sliderMainColor, factor)
149  } else if (slider.x >= rightShape.x - slider.width) {
150  factor = (slider.x - rightShape.x + rightShape.width) / rightShape.width
151  slider.color = priv.interpolate(priv.sliderMainColor, rightShape.color, factor)
152  } else {
153  slider.color = priv.sliderMainColor
154  }
155  }
156 
157  z: 1
158  color: priv.sliderMainColor
159  height: units.gu(6)
160  width: units.gu(6)
161  borderSource: "none"
162  radius: "medium"
163  Icon {
164  anchors.fill: parent
165  anchors.margins: units.gu(1.5)
166  source: "grip-large.svg"
167  color: "white"
168  }
169  }
170  Row {
171  anchors.verticalCenter: parent.verticalCenter
172  anchors.left: slider.right
173  anchors.leftMargin: units.gu(1.5)
174  spacing: -units.gu(1)
175  visible: slider.x === priv.halfWay
176  Icon {
177  name: "next"
178  height: units.gu(2.5)
179  color: priv.sliderMainColor
180  opacity: 1 - priv.opacityDelta
181  }
182  Icon {
183  name: "next"
184  height: units.gu(2.5)
185  color: priv.sliderMainColor
186  opacity: 0.5 + priv.opacityDelta
187  }
188  }
189 
190  UbuntuShape {
191  id: rightShape
192  anchors.top: parent.top
193  anchors.right: parent.right
194  anchors.margins: priv.gap
195  color: UbuntuColors.green
196  borderSource: "none"
197 
198  state: "normal"
199  height: units.gu(6)
200  width: units.gu(6)
201  radius: "medium"
202  opacity: slider.x >= priv.halfWay ? 1.0 : slider.x / priv.halfWay
203 
204  Icon {
205  anchors.centerIn: parent
206  width: units.gu(3.5)
207  height: units.gu(3.5)
208  name: rightIconName
209  color: "white"
210  }
211  }
212  }
213 
214  MouseArea {
215  id: mouseArea
216  objectName: "swipeMouseArea"
217 
218  anchors.fill: row
219  drag.target: slider
220  drag.axis: Drag.XAxis
221  drag.minimumX: priv.gap
222  drag.maximumX: row.width - slider.width - priv.gap
223 
224  onReleased: {
225  if (slider.x !== drag.minimumX || slider.x !== drag.maximumX) {
226  slider.x = priv.halfWay
227  }
228  if (slider.x === drag.minimumX) {
229  slider.x = drag.minimumX
230  enabled = false
231  leftTriggered()
232  }
233  if (slider.x === drag.maximumX) {
234  slider.x = drag.maximumX
235  enabled = false
236  rightTriggered()
237  }
238  }
239  }
240 }