Unity 8
SwipeToAct.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.3
18 import Ubuntu.Components 1.1
19 import QtGraphicalEffects 1.0
20 
21 Item {
22  id: swipeToAct
23 
24  width: parent.width
25  height: childrenRect.height
26 
27  signal leftTriggered()
28  signal rightTriggered()
29 
30  property string leftIconName
31  property string rightIconName
32  readonly property double sliderHeight: units.gu(6)
33  readonly property double gap: units.gu(1)
34  readonly property double halfWay: mouseArea.drag.maximumX / 2
35 
36  Rectangle {
37  id: gradient
38  width: parent.width * 5
39  height: sliderHeight
40  visible: false
41  LinearGradient {
42  anchors.fill: parent
43  start: Qt.point(parent.x, parent.y)
44  end: Qt.point(parent.width, parent.y)
45  gradient: Gradient {
46  GradientStop { position: 0.0; color: UbuntuColors.red }
47  GradientStop { position: 0.2; color: UbuntuColors.red }
48  GradientStop { position: 0.4; color: "#dddddd" }
49  GradientStop { position: 0.6; color: "#dddddd" }
50  GradientStop { position: 0.8; color: UbuntuColors.green }
51  GradientStop { position: 1.0; color: UbuntuColors.green }
52  }
53  }
54  }
55 
56  ShaderEffectSource {
57  id: effectSourceGradient
58  sourceItem: gradient
59  width: gradient.width
60  height: gradient.height
61  sourceRect: Qt.rect(0.4 * gradient.width * (slider.x / halfWay), 0, mask.width, mask.height)
62  visible: false
63  hideSource: true
64  }
65 
66  UbuntuShape {
67  id: mask
68  color: "black"
69  width: parent.width
70  height: sliderHeight
71  borderSource: "none"
72  visible: false
73  }
74 
75  ShaderEffectSource {
76  id: effectSourceMask
77  sourceItem: mask
78  width: mask.width
79  height: mask.height
80  visible: false
81  hideSource: true
82  }
83 
84  ShaderEffect {
85  width: parent.width
86  height: sliderHeight
87  property variant mask: effectSourceMask
88  property variant gradient: effectSourceGradient
89  vertexShader: "
90  uniform highp mat4 qt_Matrix;
91  attribute highp vec4 qt_Vertex;
92  attribute highp vec2 qt_MultiTexCoord0;
93  varying highp vec2 coord;
94  void main() {
95  coord = qt_MultiTexCoord0;
96  gl_Position = qt_Matrix * qt_Vertex;
97  }"
98  fragmentShader: "
99  varying highp vec2 coord;
100  uniform sampler2D mask;
101  uniform sampler2D gradient;
102  void main() {
103  lowp vec4 texMask = texture2D(mask, coord);
104  lowp vec4 texGradient = texture2D(gradient, coord);
105  gl_FragColor = texGradient.rgba * texMask.a ;
106  }"
107 
108  Row {
109  id: row
110  anchors.fill: parent
111  spacing: gap
112  anchors.margins: gap
113 
114  UbuntuShape {
115  id: leftShape
116  states: [
117  State {
118  name: "normal"
119  PropertyChanges {
120  target: leftShape
121  color: UbuntuColors.red
122  }
123  PropertyChanges {
124  target: innerLeftShape
125  color: UbuntuColors.red
126  visible: false
127  }
128  },
129  State {
130  name: "selected"
131  PropertyChanges {
132  target: leftShape
133  color: "white"
134  }
135  PropertyChanges {
136  target: innerLeftShape
137  color: UbuntuColors.red
138  visible: true
139  }
140  }
141  ]
142  state: "normal"
143  height: units.gu(4)
144  width: units.gu(7)
145  borderSource: "none"
146  opacity: slider.x <= halfWay ? 1.0 : 1.0 - ((slider.x - halfWay) / halfWay)
147  UbuntuShape {
148  id: innerLeftShape
149  anchors.centerIn: parent
150  borderSource: "none"
151  width: parent.width - units.gu(.5)
152  height: parent.height - units.gu(.5)
153  }
154  Icon {
155  anchors.centerIn: parent
156  width: units.gu(2)
157  height: units.gu(2)
158  name: leftIconName
159  color: "white"
160  }
161  }
162 
163  Rectangle {
164  id: leftSpacer
165  width: (row.width - (leftShape.width + slider.width + rightShape.width + 4 * row.spacing)) / 2
166  height: units.gu(4)
167  opacity: 0
168  }
169 
170  UbuntuShape {
171  id: slider
172  objectName: "slider"
173 
174  Behavior on x {
175  UbuntuNumberAnimation {
176  duration: UbuntuAnimation.FastDuration
177  easing.type: Easing.OutBounce
178  }
179  }
180 
181  Behavior on opacity {
182  UbuntuNumberAnimation {
183  duration: UbuntuAnimation.FastDuration
184  }
185  }
186 
187  onOpacityChanged: {
188  if (opacity === 0) {
189  if (rightShape.state === "selected") {
190  rightTriggered()
191  }
192  if (leftShape.state === "selected") {
193  leftTriggered()
194  }
195  }
196  }
197 
198  z: 1
199  color: "white"
200  height: units.gu(4)
201  width: units.gu(7)
202  borderSource: "none"
203  Row {
204  anchors.fill: parent
205  spacing: 2 * gap
206  anchors.leftMargin: units.gu(.5)
207  anchors.rightMargin: units.gu(.5)
208  Icon {
209  anchors.verticalCenter: parent.verticalCenter
210  name: "back"
211  width: units.gu(2)
212  height: units.gu(2)
213  }
214  Icon {
215  anchors.verticalCenter: parent.verticalCenter
216  name: "next"
217  width: units.gu(2)
218  height: units.gu(2)
219  }
220  }
221  }
222 
223  Rectangle {
224  id: rightSpacer
225  width: leftSpacer.width
226  height: units.gu(4)
227  opacity: 0
228  }
229 
230  UbuntuShape {
231  id: rightShape
232  states: [
233  State {
234  name: "normal"
235  PropertyChanges {
236  target: rightShape
237  color: UbuntuColors.green
238  }
239  PropertyChanges {
240  target: innerRightShape
241  color: UbuntuColors.green
242  visible: false
243  }
244  },
245  State {
246  name: "selected"
247  PropertyChanges {
248  target: rightShape
249  color: "white"
250  }
251  PropertyChanges {
252  target: innerRightShape
253  color: UbuntuColors.green
254  visible: true
255  }
256  }
257  ]
258  state: "normal"
259  height: units.gu(4)
260  width: units.gu(7)
261  borderSource: "none"
262  opacity: slider.x >= halfWay ? 1.0 : slider.x / halfWay
263  UbuntuShape {
264  id: innerRightShape
265  anchors.centerIn: parent
266  borderSource: "none"
267  width: parent.width - units.gu(.5)
268  height: parent.height - units.gu(.5)
269  }
270  Icon {
271  anchors.centerIn: parent
272  width: units.gu(2)
273  height: units.gu(2)
274  name: rightIconName
275  color: "white"
276  }
277  }
278  }
279 
280  MouseArea {
281  id: mouseArea
282  objectName: "swipeMouseArea"
283 
284  anchors.fill: row
285  drag.target: slider
286  drag.axis: Drag.XAxis
287  drag.minimumX: 0
288  drag.maximumX: row.width - slider.width
289 
290  onReleased: {
291  if (slider.x !== drag.minimumX || slider.x !== drag.maximumX) {
292  slider.x = halfWay
293  }
294  if (slider.x === drag.minimumX) {
295  slider.x = drag.minimumX
296  slider.opacity = 0
297  enabled = false
298  leftShape.state = "selected"
299  }
300  if (slider.x === drag.maximumX) {
301  slider.x = drag.maximumX
302  slider.opacity = 0
303  enabled = false
304  rightShape.state = "selected"
305  }
306  }
307  }
308  }
309 }