~mterry/unity8/power-button-on-lock

« back to all changes in this revision

Viewing changes to qml/Panel/IndicatorsMenu.qml

  • Committer: Michael Terry
  • Date: 2014-11-24 15:25:42 UTC
  • mfrom: (1368.1.82 unity8)
  • Revision ID: michael.terry@canonical.com-20141124152542-5cysva8ds3qfula6
MergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.2
 
18
import Ubuntu.Components 1.1
 
19
import Ubuntu.Gestures 0.1
 
20
import "../Components"
 
21
 
 
22
Showable {
 
23
    id: root
 
24
    property alias indicatorsModel: bar.indicatorsModel
 
25
    property alias showDragHandle: __showDragHandle
 
26
    property alias hideDragHandle: __hideDragHandle
 
27
    property alias overFlowWidth: bar.overFlowWidth
 
28
    property alias verticalVelocityThreshold: yVelocityCalculator.velocityThreshold
 
29
    property int minimizedPanelHeight: units.gu(3)
 
30
    property int expandedPanelHeight: units.gu(7)
 
31
    property real openedHeight: units.gu(71)
 
32
    readonly property real unitProgress: Math.max(0, (height - minimizedPanelHeight) / (openedHeight - minimizedPanelHeight))
 
33
    readonly property bool fullyOpened: unitProgress >= 1
 
34
    readonly property bool partiallyOpened: unitProgress > 0 && unitProgress < 1.0
 
35
    readonly property bool fullyClosed: unitProgress == 0
 
36
    property bool enableHint: true
 
37
    property bool contentEnabled: true
 
38
    property color panelColor: "black"
 
39
 
 
40
    signal showTapped(point position)
 
41
 
 
42
    // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
 
43
    // use its own values. Need to ask design about this.
 
44
    showAnimation: StandardAnimation {
 
45
        property: "height"
 
46
        to: openedHeight
 
47
        duration: UbuntuAnimation.BriskDuration
 
48
        easing.type: Easing.OutCubic
 
49
    }
 
50
 
 
51
    hideAnimation: StandardAnimation {
 
52
        property: "height"
 
53
        to: minimizedPanelHeight
 
54
        duration: UbuntuAnimation.BriskDuration
 
55
        easing.type: Easing.OutCubic
 
56
    }
 
57
 
 
58
    height: minimizedPanelHeight
 
59
 
 
60
    onUnitProgressChanged: d.updateState()
 
61
    clip: root.partiallyOpened
 
62
 
 
63
    // eater
 
64
    MouseArea {
 
65
        anchors.fill: parent
 
66
    }
 
67
 
 
68
    MenuContent {
 
69
        id: content
 
70
        objectName: "menuContent"
 
71
 
 
72
        anchors {
 
73
            left: parent.left
 
74
            right: parent.right
 
75
            top: bar.bottom
 
76
        }
 
77
        height: openedHeight - bar.height - handle.height
 
78
        indicatorsModel: root.indicatorsModel
 
79
        visible: root.unitProgress > 0
 
80
        enabled: contentEnabled
 
81
        currentMenuIndex: bar.currentItemIndex
 
82
    }
 
83
 
 
84
    Handle {
 
85
        id: handle
 
86
        anchors {
 
87
            left: parent.left
 
88
            right: parent.right
 
89
            bottom: parent.bottom
 
90
        }
 
91
        height: units.gu(2)
 
92
        active: d.activeDragHandle ? true : false
 
93
 
 
94
        //small shadow gradient at bottom of menu
 
95
        Rectangle {
 
96
            anchors {
 
97
                left: parent.left
 
98
                right: parent.right
 
99
                bottom: parent.top
 
100
            }
 
101
            height: units.gu(0.5)
 
102
            gradient: Gradient {
 
103
                GradientStop { position: 0.0; color: "transparent" }
 
104
                GradientStop { position: 1.0; color: "black" }
 
105
            }
 
106
            opacity: 0.3
 
107
        }
 
108
    }
 
109
 
 
110
    Rectangle {
 
111
        anchors.fill: bar
 
112
        color: panelColor
 
113
    }
 
114
 
 
115
    IndicatorsBar {
 
116
        id: bar
 
117
        objectName: "indicatorsBar"
 
118
 
 
119
        anchors {
 
120
            left: parent.left
 
121
            right: parent.right
 
122
        }
 
123
        expanded: false
 
124
        enableLateralChanges: false
 
125
        lateralPosition: -1
 
126
        unitProgress: root.unitProgress
 
127
 
 
128
        height: expanded ? expandedPanelHeight : minimizedPanelHeight
 
129
        Behavior on height { NumberAnimation { duration: UbuntuAnimation.SnapDuration; easing: UbuntuAnimation.StandardEasing } }
 
130
    }
 
131
 
 
132
    ScrollCalculator {
 
133
        id: leftScroller
 
134
        width: units.gu(5)
 
135
        anchors.left: bar.left
 
136
        height: bar.height
 
137
 
 
138
        forceScrollingPercentage: 0.33
 
139
        stopScrollThreshold: units.gu(0.75)
 
140
        direction: Qt.RightToLeft
 
141
        lateralPosition: -1
 
142
 
 
143
        onScroll: bar.addScrollOffset(-scrollAmount);
 
144
    }
 
145
 
 
146
    ScrollCalculator {
 
147
        id: rightScroller
 
148
        width: units.gu(5)
 
149
        anchors.right: bar.right
 
150
        height: bar.height
 
151
 
 
152
        forceScrollingPercentage: 0.33
 
153
        stopScrollThreshold: units.gu(0.75)
 
154
        direction: Qt.LeftToRight
 
155
        lateralPosition: -1
 
156
 
 
157
        onScroll: bar.addScrollOffset(scrollAmount);
 
158
    }
 
159
 
 
160
    DragHandle {
 
161
        id: __showDragHandle
 
162
        anchors.bottom: parent.bottom
 
163
        anchors.left: parent.left
 
164
        anchors.right: parent.right
 
165
        height: minimizedPanelHeight
 
166
        direction: Direction.Downwards
 
167
        enabled: !root.shown && root.available
 
168
        autoCompleteDragThreshold: maxTotalDragDistance / 2
 
169
        stretch: true
 
170
        distanceThreshold: enableHint ? 0 : minimizedPanelHeight
 
171
 
 
172
        onTapped: showTapped(Qt.point(touchSceneX, touchSceneY));
 
173
 
 
174
        // using hint regulates minimum to hint displacement, but in fullscreen mode, we need to do it manually.
 
175
        overrideStartValue: enableHint ? minimizedPanelHeight : expandedPanelHeight + handle.height
 
176
        maxTotalDragDistance: openedHeight - (enableHint ? minimizedPanelHeight : expandedPanelHeight + handle.height)
 
177
        hintDisplacement: enableHint ? expandedPanelHeight - minimizedPanelHeight + handle.height : 0
 
178
    }
 
179
 
 
180
    DragHandle {
 
181
        id: __hideDragHandle
 
182
        anchors.fill: handle
 
183
        direction: Direction.Upwards
 
184
        enabled: root.shown && root.available
 
185
        hintDisplacement: units.gu(3)
 
186
        autoCompleteDragThreshold: maxTotalDragDistance / 6
 
187
        stretch: true
 
188
        maxTotalDragDistance: openedHeight - expandedPanelHeight - handle.height
 
189
 
 
190
        onTouchSceneXChanged: {
 
191
            if (root.state === "locked") {
 
192
                d.xDisplacementSinceLock += (touchSceneX - d.lastHideTouchSceneX)
 
193
                d.lastHideTouchSceneX = touchSceneX;
 
194
            }
 
195
        }
 
196
    }
 
197
 
 
198
    PanelVelocityCalculator {
 
199
        id: yVelocityCalculator
 
200
        velocityThreshold: d.hasCommitted ? 0.1 : 0.3
 
201
        trackedValue: d.activeDragHandle ? d.activeDragHandle.touchSceneY : 0
 
202
 
 
203
        onVelocityAboveThresholdChanged: d.updateState()
 
204
    }
 
205
 
 
206
    Connections {
 
207
        target: showAnimation
 
208
        onRunningChanged: {
 
209
            if (showAnimation.running) {
 
210
                root.state = "commit";
 
211
            }
 
212
        }
 
213
    }
 
214
 
 
215
    Connections {
 
216
        target: hideAnimation
 
217
        onRunningChanged: {
 
218
            if (hideAnimation.running) {
 
219
                root.state = "initial";
 
220
            }
 
221
        }
 
222
    }
 
223
 
 
224
    QtObject {
 
225
        id: d
 
226
        property var activeDragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle.dragging ? hideDragHandle : null
 
227
        property bool hasCommitted: false
 
228
        property real lastHideTouchSceneX: 0
 
229
        property real xDisplacementSinceLock: 0
 
230
        onXDisplacementSinceLockChanged: d.updateState()
 
231
 
 
232
        property real rowMappedLateralPosition: {
 
233
            if (!d.activeDragHandle) return -1;
 
234
            return d.activeDragHandle.mapToItem(bar, d.activeDragHandle.touchX, 0).x;
 
235
        }
 
236
 
 
237
        function updateState() {
 
238
            if (!showAnimation.running && !hideAnimation.running) {
 
239
                if (unitProgress <= 0) {
 
240
                    root.state = "initial";
 
241
                // lock indicator if we've been committed and aren't moving too much laterally or too fast up.
 
242
                } else if (d.hasCommitted && (Math.abs(d.xDisplacementSinceLock) < units.gu(2) || yVelocityCalculator.velocityAboveThreshold)) {
 
243
                    root.state = "locked";
 
244
                } else {
 
245
                    root.state = "reveal";
 
246
                }
 
247
            }
 
248
        }
 
249
    }
 
250
 
 
251
    states: [
 
252
        State {
 
253
            name: "initial"
 
254
            PropertyChanges { target: d; hasCommitted: false; restoreEntryValues: false }
 
255
        },
 
256
        State {
 
257
            name: "reveal"
 
258
            StateChangeScript {
 
259
                script: {
 
260
                    yVelocityCalculator.reset();
 
261
                    // initial item selection
 
262
                    if (!d.hasCommitted) bar.selectItemAt(d.activeDragHandle ? d.activeDragHandle.touchX : -1);
 
263
                    d.hasCommitted = false;
 
264
                }
 
265
            }
 
266
            PropertyChanges {
 
267
                target: bar
 
268
                expanded: true
 
269
                // changes to lateral touch position effect which indicator is selected
 
270
                lateralPosition: d.rowMappedLateralPosition
 
271
                // vertical velocity determines if changes in lateral position has an effect
 
272
                enableLateralChanges: d.activeDragHandle &&
 
273
                                      !yVelocityCalculator.velocityAboveThreshold
 
274
            }
 
275
            // left scroll bar handling
 
276
            PropertyChanges {
 
277
                target: leftScroller
 
278
                lateralPosition: {
 
279
                    if (!d.activeDragHandle) return -1;
 
280
                    var mapped = d.activeDragHandle.mapToItem(leftScroller, d.activeDragHandle.touchX, 0);
 
281
                    return mapped.x;
 
282
                }
 
283
            }
 
284
            // right scroll bar handling
 
285
            PropertyChanges {
 
286
                target: rightScroller
 
287
                lateralPosition: {
 
288
                    if (!d.activeDragHandle) return -1;
 
289
                    var mapped = d.activeDragHandle.mapToItem(rightScroller, d.activeDragHandle.touchX, 0);
 
290
                    return mapped.x;
 
291
                }
 
292
            }
 
293
        },
 
294
        State {
 
295
            name: "locked"
 
296
            StateChangeScript {
 
297
                script: {
 
298
                    d.xDisplacementSinceLock = 0;
 
299
                    d.lastHideTouchSceneX = hideDragHandle.touchSceneX;
 
300
                }
 
301
            }
 
302
            PropertyChanges { target: bar; expanded: true }
 
303
        },
 
304
        State {
 
305
            name: "commit"
 
306
            extend: "locked"
 
307
            PropertyChanges { target: bar; interactive: true }
 
308
            PropertyChanges {
 
309
                target: d;
 
310
                hasCommitted: true
 
311
                lastHideTouchSceneX: 0
 
312
                xDisplacementSinceLock: 0
 
313
                restoreEntryValues: false
 
314
            }
 
315
        }
 
316
    ]
 
317
    state: "initial"
 
318
}