Unity 8
 All Classes Functions Properties
Bottombar.qml
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  */
16 
17 import QtQuick 2.0
18 import "../Components"
19 import Utils 0.1
20 import Unity.Application 0.1
21 import Ubuntu.Gestures 0.1
22 import Ubuntu.Components 0.1
23 
24 Item {
25  id: bottombar
26 
27  // Whether there's an application on foreground (as opposed to have shell's Dash on foreground)
28  property bool applicationIsOnForeground
29 
30  property variant theHud
31  property bool enabled: false
32  property bool preventHiding: dragArea.dragging
33  readonly property real bottomEdgeButtonCenterDistance: units.gu(34)
34 
35  state: "hidden"
36 
37  function hide() {
38  dismissTimer.stop()
39  bottombar.state = "hidden"
40  }
41 
42  onApplicationIsOnForegroundChanged: {
43  if (!applicationIsOnForeground) {
44  hide()
45  }
46  }
47 
48  onStateChanged: {
49  if (state == "hidden") {
50  dismissTimer.stop()
51  bottomBarVisibilityCommunicatorShell.forceHidden = false
52  } else {
53  dismissTimer.restart()
54  }
55  }
56 
57  onPreventHidingChanged: {
58  if (!preventHiding) {
59  if (state == "hint" || state == "reveal")
60  hide()
61  }
62 
63  if (dismissTimer.running) {
64  dismissTimer.restart();
65  }
66  }
67 
68  Timer {
69  id: dismissTimer
70  interval: 1000
71  onTriggered: {
72  if (!bottombar.preventHiding) {
73  bottombar.state = "hidden"
74  } else {
75  dismissTimer.restart()
76  }
77  }
78  }
79 
80  HudButton {
81  id: hudButton
82 
83  readonly property bool centeredHud: parent.width < units.gu(68) // Nexus 7 has 67 gu width
84 
85  x: centeredHud ? parent.width / 2 - width / 2 : MathUtils.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
86  y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
87  z: 1
88  visible: opacity != 0
89 
90  mouseOver: {
91  if (dragArea.status === DirectionalDragArea.Recognized) {
92  var touchLocal = mapFromItem(dragArea, dragArea.touchX, dragArea.touchY)
93  return touchLocal.x > 0 && touchLocal.x < width
94  && touchLocal.y > 0 && touchLocal.y < height
95  } else {
96  return false
97  }
98  }
99 
100  onClicked: theHud.show()
101 
102  Behavior on bottomMargin {
103  NumberAnimation{duration: hudButton.opacity < 0.01 ? 200 : 70; easing.type: Easing.OutQuart}
104  }
105 
106  Behavior on opacity {
107  NumberAnimation{duration: 200; easing.type: Easing.OutCubic}
108  }
109  }
110 
111  Connections {
112  target: theHud
113  onShownChanged: {
114  bottomBarVisibilityCommunicatorShell.forceHidden = theHud.shown
115  if (theHud.shown) {
116  bottombar.state = "hidden"
117  }
118  }
119  }
120 
121  EdgeDragArea {
122  id: dragArea
123  objectName: "hudDragArea"
124  width: parent.width
125  height: shell.edgeSize
126  anchors.bottom: parent.bottom
127 
128  distanceThreshold: units.gu(8)
129  enabled: !theHud.shown && bottombar.enabled && applicationIsOnForeground
130  direction: Direction.Upwards
131  maxSilenceTime: 2000
132 
133  property int previousStatus: -1
134  property real touchStartX: -1
135 
136  readonly property real distanceFromThreshold: (-distance) - distanceThreshold // distance is negative
137  readonly property real revealDistance: units.gu(2)
138  readonly property real commitDistance: units.gu(6)
139  readonly property real commitProgress: MathUtils.clamp(distanceFromThreshold / commitDistance, 0, 1)
140 
141  onStatusChanged: {
142  if (status === DirectionalDragArea.WaitingForTouch) {
143  if (previousStatus == DirectionalDragArea.Recognized) {
144  if (hudButton.mouseOver) {
145  hudButton.clicked()
146  }
147  }
148  } else if (status === DirectionalDragArea.Undecided) {
149  if (!hudButton.centeredHud) {
150  touchStartX = touchX
151  }
152  } else if (status === DirectionalDragArea.Recognized) {
153  bottombar.state = "hint"
154  }
155  previousStatus = status
156  }
157 
158  onDistanceChanged: {
159  if (status === DirectionalDragArea.Recognized) {
160  if (distanceFromThreshold > commitDistance)
161  bottombar.state = "shown"
162  else if (distanceFromThreshold > revealDistance)
163  bottombar.state = "reveal"
164  }
165  }
166  }
167 
168  Item {
169  id: dismissArea
170  anchors {
171  top: parent.top
172  left: parent.left
173  right: parent.right
174  }
175  height: parent.height - bottomBarVisibilityCommunicatorShell.position
176 
177  MouseArea {
178  anchors.fill: parent
179  enabled: bottombar.state == "shown"
180  onPressed: {
181  bottomBarVisibilityCommunicatorShell.forceHidden = true
182  bottombar.state = "hidden"
183  }
184  }
185 
186  InputFilterArea {
187  anchors.fill: parent
188  blockInput: (hudButton.opacity == 1)
189  }
190  }
191 
192  MouseArea {
193  anchors {
194  top: dismissArea.bottom
195  left: parent.left
196  right: parent.right
197  bottom: parent.bottom
198  }
199  enabled: bottombar.state == "shown" && bottomBarVisibilityCommunicatorShell.position > 0
200  onPressed: {
201  bottombar.state = "hidden"
202  }
203  }
204 
205  states: [
206  State {
207  name: "hidden"
208  PropertyChanges { target: hudButton; opacity: 0 }
209  PropertyChanges { target: hudButton; bottomMargin: units.gu(-2) }
210  },
211  State {
212  name: "hint"
213  extend: "hidden"
214  PropertyChanges { target: hudButton; opacity: 0.5 }
215  },
216  State {
217  name: "reveal"
218  extend: "hint"
219  PropertyChanges { target: hudButton; bottomMargin: units.gu(-2) + units.gu(2) * dragArea.commitProgress }
220  },
221  State {
222  name: "shown"
223  PropertyChanges { target: hudButton; opacity: 1 }
224  PropertyChanges { target: hudButton; bottomMargin: units.gu(0) }
225  }
226  ]
227 }