2 * Copyright (C) 2012, 2013 Canonical, Ltd.
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.
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.
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/>.
18 import Ubuntu.Components 0.1
21 import "../Components"
22 import "../Components/Flickables" as Flickables
27 readonly property real elementsPadding: units.gu(1)
28 readonly property real elementsYSliding: units.gu(2)
30 property alias revealerTarget: hudShowable
31 property alias showAnimation: hudShowable.showAnimation
32 property alias hideAnimation: hudShowable.hideAnimation
33 property alias available: hudShowable.available
34 property alias shown: hudShowable.shown
35 property alias handleHeight: handle.height
37 readonly property variant outEasing: Easing.OutQuad
38 readonly property variant inEasing: Easing.InQuad
39 readonly property int animationDuration: 200
40 readonly property int showableAnimationDuration: 100
41 property bool showingOpenIndicator: false
43 // FIXME At the moment since we have no appstack
44 // it's not possible to get results of the sidestage app
45 // design has to come up with a solution
52 function resetToInitialState() {
56 parametrizedActionsPage.shown = false
62 PropertyChanges { target: searchBar; placeholderText: i18n.tr("Type or say a command") }
63 PropertyChanges { target: searchBar; searchEnabled: true }
64 PropertyChanges { target: toolBarAnimator; visible: true}
65 AnchorChanges { target: searchBarAnimator; anchors.top: undefined; anchors.bottom: parent.bottom; }
66 AnchorChanges { target: resultsCardAnimator; anchors.top: undefined; anchors.bottom: toolBarAnimator.top; }
69 name: "input" //only inherited by other states.
70 AnchorChanges { target: searchBarAnimator; anchors.top: parent.top; anchors.bottom: undefined; }
71 AnchorChanges { target: resultsCardAnimator; anchors.top: searchBarAnimator.bottom; anchors.bottom: undefined; }
72 PropertyChanges { target: toolBarAnimator; visible: false }
75 name: "voice_input" //only inherited by other states.
77 PropertyChanges { target: soundAmplitudeVisualAnimator; visible: true }
78 PropertyChanges { target: resultsCardAnimator; visible: false }
79 PropertyChanges { target: soundAmplitudeVisualAnimator; progress: 1 }
80 PropertyChanges { target: searchBar; searchEnabled: false }
83 name: "voice_recognition_loading"
85 PropertyChanges { target: searchBar; placeholderText: i18n.tr("Loading. Please Wait...") }
88 name: "voice_recognition_listening"
90 PropertyChanges { target: searchBar; placeholderText: i18n.tr("Speak Now...") }
93 name: "voice_recognition_processing"
95 PropertyChanges { target: searchBar; placeholderText: i18n.tr("Speaking...") }
98 name: "showing_results"
100 PropertyChanges { target: searchBar; placeholderText: i18n.tr("Type or say a command") }
101 PropertyChanges { target: searchBar; searchEnabled: true }
108 to: "voice_recognition_loading"
109 SequentialAnimation {
110 NumberAnimation { // hide these components
111 targets: [toolBarAnimator, searchBarAnimator, resultsCardAnimator]
112 property: "progress"; duration: animationDuration; to: 0
115 PropertyAction { targets: [toolBarAnimator, resultsCardAnimator]; property: "visible"; value: false}
116 PropertyAction { target: soundAmplitudeVisualAnimator; property: "visible"; value: true}
118 AnchorAnimation { duration: 0 } // so anchor change happens at this point
120 NumberAnimation { // show these components
121 targets: [searchBarAnimator, soundAmplitudeVisualAnimator]
122 property: "progress"; duration: animationDuration; from: 0; to: 1
127 from: "showing_results"
128 to: "voice_recognition_loading"
129 SequentialAnimation {
130 PropertyAction { target: soundAmplitudeVisualAnimator; property: "progress"; value: 0}
132 PropertyAction { // hide these components
133 target: resultsCardAnimator; property: "progress"; value: 0
136 NumberAnimation { // show these components
137 target: soundAmplitudeVisualAnimator; property: "progress"; duration: animationDuration; from: 0; to: 1
142 from: "voice_recognition_processing"
143 to: "showing_results"
144 SequentialAnimation {
145 NumberAnimation { // hide these components
146 target: soundAmplitudeVisualAnimator; property: "progress"; duration: animationDuration; to: 0
148 PropertyAction { target: resultsCardAnimator; property: "visible"; value: true}
150 NumberAnimation { // show these components
151 target: resultsCardAnimator; property: "progress"; duration: animationDuration; from: 0; to: 1
157 to: "showing_results"
158 SequentialAnimation {
160 targets: [toolBarAnimator, searchBarAnimator, resultsCardAnimator]
161 property: "progress"; duration: animationDuration; to: 0
164 PropertyAction { target: toolBarAnimator; property: "visible"; value: false}
166 AnchorAnimation { duration: 0 } // so anchor change happens at this point
169 targets: [searchBarAnimator, resultsCardAnimator]
170 property: "progress"; duration: animationDuration; from: 0; to: 1
185 onShowParametrizedAction: {
186 parametrizedActionsPage.header = action
187 parametrizedActionsPage.setItems(items)
188 parametrizedActionsPage.shown = true
191 onVoiceQueryLoading: {
192 hud.state = "voice_recognition_loading"
193 searchBar.ignoreNextTextChange = true
196 soundAmplitudeVisual.startIdle()
198 onVoiceQueryListening: {
199 if (hud.state == "voice_recognition_loading" || hud.state == "showing_results") {
200 searchBar.ignoreNextTextChange = true
203 hud.state = "voice_recognition_listening"
206 onVoiceQueryHeardSomething: {
207 if (hud.state == "voice_recognition_listening") {
208 hud.state = "voice_recognition_processing"
209 soundAmplitudeVisual.setDetectorEnabled(true)
212 onVoiceQueryFinished: {
213 hud.state = "showing_results"
214 searchBar.text = query
215 soundAmplitudeVisual.setDetectorEnabled(false)
217 onVoiceQueryFailed: {
218 hud.state = "showing_results"
220 soundAmplitudeVisual.setDetectorEnabled(false)
226 objectName: "hudShowable"
227 height: parent.height
232 showAnimation.duration = 0
233 hideAnimation.duration = 0
234 } else if (!showAnimation.running && !hideAnimation.running) {
235 if (parent.height > 0) {
236 showAnimation.duration = Math.min(showableAnimationDuration * (1 - (parent.height - y) / parent.height), showableAnimationDuration)
237 hideAnimation.duration = showableAnimationDuration - showAnimation.duration
243 // Eat everything that doesn't go to other places
250 source: "graphics/hud_bg.png"
254 target: hideAnimation
256 if (!hideAnimation.running) {
257 showAnimation.duration = showableAnimationDuration
258 hud.resetToInitialState()
264 target: showAnimation
266 if (!showAnimation.running) {
267 hideAnimation.duration = showableAnimationDuration
282 height: handleImage.height
290 source: "graphics/hud_handlebar.png"
296 anchors.horizontalCenter: parent.horizontalCenter
297 source: "graphics/hud_handlearrow.png"
303 id: hudContentClipper
308 bottom: parent.bottom
311 clip: visible && hudContent.height !== height
312 visible: hudContent.height >= 0
319 bottom: parent.bottom
325 x: parametrizedActionsPage.x - width
331 objectName: "toolBarAnimator"
335 bottom: searchBarAnimator.top
336 margins: 2*elementsPadding //ensures positioning correct
338 progress: MathUtils.clamp((y - hudShowable.y - anchors.margins)/elementsYSliding, 0, 1)
342 objectName: "toolBar"
343 model: hudClient.toolBarModel
344 anchors.horizontalCenter: parent.horizontalCenter
346 hudClient.executeToolBarAction(action)
352 id: searchBarAnimator
353 objectName: "searchBarAnimator"
357 bottom: parent.bottom
358 margins: elementsPadding
359 topMargin: handle.height + units.dp(1) + elementsPadding
361 progress: MathUtils.clamp((y - hudShowable.y - anchors.margins)/elementsYSliding, 0, 1)
365 objectName: "searchBar"
367 property bool ignoreNextTextChange: false
369 anchors.left: parent.left
370 anchors.right: parent.right
373 placeholderText: i18n.tr("Type or say a command")
374 activityIndicatorVisible: hud.state == "voice_recognition_processing"
376 onMicrophoneClicked: hudClient.startVoiceQuery()
379 if (ignoreNextTextChange) {
380 ignoreNextTextChange = false
382 hudClient.setQuery(searchBar.text)
387 hud.state = "showing_results"
393 id: resultsCardAnimator
394 objectName: "resultsCardAnimator"
399 top: searchBarAnimator.bottom
400 margins: elementsPadding
402 progress: MathUtils.clamp((y - hudShowable.y + height - units.gu(8))/elementsYSliding, 0, 1)
404 Flickables.Flickable {
405 anchors.left: parent.left
406 anchors.right: parent.right
407 contentHeight: resultList.height
409 clip: height < contentHeight
410 interactive: height < contentHeight
413 if (hud.state == "showing_results") {
414 return shell.applicationManager.keyboardVisible ? Math.min(hud.height - searchBarAnimator.y - searchBarAnimator.height - units.gu(2) - shell.applicationManager.keyboardHeight, contentHeight) : contentHeight
424 anchors.left: parent.left
425 anchors.right: parent.right
426 height: childrenRect.height
429 hudClient.executeCommand(index)
432 model: hudClient.results
438 id: soundAmplitudeVisualAnimator
441 horizontalCenter: parent.horizontalCenter
442 verticalCenter: parent.verticalCenter
443 verticalCenterOffset: (searchBar.height + 2*elementsPadding)/2
447 progress: MathUtils.clamp((y - hudShowable.y - anchors.verticalCenterOffset)/elementsYSliding, 0, 1)
449 SoundAmplitudeVisual {
450 id: soundAmplitudeVisual
457 HudParametrizedActionsPage {
458 id: parametrizedActionsPage
459 objectName: "parametrizedActionsPage"
460 property bool shown: false
462 anchors.bottom: parent.bottom
463 height: hud.height - handle.height - units.dp(1)
467 hudClient.executeParametrizedAction(values())
470 hudClient.updateParametrizedAction(values())
477 hudClient.cancelParametrizedAction()
482 easing.type: outEasing
483 duration: animationDuration
491 anchors.left: hudContentClipper.right
492 anchors.top: hudContentClipper.top
493 anchors.bottom: hudContentClipper.bottom
495 source: "../graphics/dropshadow_right.png"