on 8fa9520 help sign in
unity8/qml/Panel/Panel.qml
455 lines 16 kB history raw
1/*
2 * Copyright (C) 2013-2016 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 */
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19import Ubuntu.Layouts 1.0
20import Unity.Application 0.1
21import Unity.Indicators 0.1
22import Utils 0.1
23import Unity.ApplicationMenu 0.1
25import QtQuick.Window 2.2
26// for indicator-keyboard
27import AccountsService 0.1
28import Unity.InputInfo 0.1
30import "../ApplicationMenus"
31import "../Components"
32import "../Components/PanelState"
33import ".."
34import "Indicators"
36Item {
37 id: root
38 readonly property real panelHeight: panelArea.y + minimizedPanelHeight
40 property real minimizedPanelHeight: units.gu(3)
41 property real expandedPanelHeight: units.gu(7)
42 property real indicatorMenuWidth: width
43 property real applicationMenuWidth: width
45 property alias applicationMenus: __applicationMenus
46 property alias indicators: __indicators
47 property bool fullscreenMode: false
48 property real panelAreaShowProgress: 1.0
49 property bool greeterShown: false
51 property string mode: "staged"
53 MouseArea {
54 id: backMouseEater
55 anchors.fill: parent
56 anchors.topMargin: panelHeight
57 visible: !indicators.fullyClosed || !applicationMenus.fullyClosed
58 enabled: visible
59 hoverEnabled: true // should also eat hover events, otherwise they will pass through
61 onClicked: {
62 __applicationMenus.hide();
63 __indicators.hide();
64 }
65 }
67 Binding {
68 target: PanelState
69 property: "panelHeight"
70 value: minimizedPanelHeight
71 }
73 RegisteredApplicationMenuModel {
74 id: registeredMenuModel
75 persistentSurfaceId: PanelState.focusedPersistentSurfaceId
76 }
78 QtObject {
79 id: d
81 property bool revealControls: !greeterShown &&
82 !applicationMenus.shown &&
83 !indicators.shown &&
84 (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)
86 property bool showWindowDecorationControls: (revealControls && PanelState.decorationsVisible) ||
87 PanelState.decorationsAlwaysVisible
89 property bool showPointerMenu: revealControls &&
90 (PanelState.decorationsVisible || mode == "staged")
92 property bool enablePointerMenu: revealControls &&
93 applicationMenus.available &&
94 applicationMenus.model
96 property bool showTouchMenu: !greeterShown &&
97 !showPointerMenu
99 property bool enableTouchMenus: showTouchMenu &&
100 applicationMenus.available &&
101 applicationMenus.model
102 }
104 Item {
105 id: panelArea
106 objectName: "panelArea"
108 anchors.fill: parent
110 transform: Translate {
111 y: indicators.state === "initial"
112 ? (1.0 - panelAreaShowProgress) * - minimizedPanelHeight
113 : 0
114 }
116 BorderImage {
117 id: indicatorsDropShadow
118 anchors {
119 fill: __indicators
120 margins: -units.gu(1)
121 }
122 visible: !__indicators.fullyClosed
123 source: "graphics/rectangular_dropshadow.sci"
124 }
126 BorderImage {
127 id: appmenuDropShadow
128 anchors {
129 fill: __applicationMenus
130 margins: -units.gu(1)
131 }
132 visible: !__applicationMenus.fullyClosed
133 source: "graphics/rectangular_dropshadow.sci"
134 }
136 BorderImage {
137 id: panelDropShadow
138 anchors {
139 fill: panelAreaBackground
140 bottomMargin: -units.gu(1)
141 }
142 visible: PanelState.dropShadow
143 source: "graphics/rectangular_dropshadow.sci"
144 }
146 Rectangle {
147 id: panelAreaBackground
148 color: callHint.visible ? theme.palette.normal.positive : theme.palette.normal.background
149 anchors {
150 top: parent.top
151 left: parent.left
152 right: parent.right
153 }
154 height: minimizedPanelHeight
156 Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
157 }
159 MouseArea {
160 id: decorationMouseArea
161 objectName: "windowControlArea"
162 anchors {
163 left: parent.left
164 right: parent.right
165 }
166 height: minimizedPanelHeight
167 hoverEnabled: !__indicators.shown
168 onClicked: {
169 if (callHint.visible) {
170 callHint.showLiveCall();
171 }
172 }
174 onPressed: {
175 if (!callHint.visible) {
176 // let it fall through to the window decoration of the maximized window behind, if any
177 mouse.accepted = false;
178 }
179 }
181 Row {
182 anchors.fill: parent
183 spacing: units.gu(2)
185 // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
186 // cf. https://bugreports.qt.io/browse/QTBUG-32909
187 WindowControlButtons {
188 id: windowControlButtons
189 objectName: "panelWindowControlButtons"
190 height: indicators.minimizedPanelHeight
191 opacity: d.showWindowDecorationControls ? 1 : 0
192 visible: opacity != 0
193 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
195 active: PanelState.decorationsVisible || PanelState.decorationsAlwaysVisible
196 windowIsMaximized: true
197 onCloseClicked: PanelState.closeClicked()
198 onMinimizeClicked: PanelState.minimizeClicked()
199 onMaximizeClicked: PanelState.restoreClicked()
200 closeButtonShown: PanelState.closeButtonShown
201 }
203 Loader {
204 id: menuBarLoader
205 objectName: "menuBarLoader"
206 height: parent.height
207 enabled: d.enablePointerMenu
208 opacity: d.showPointerMenu ? 1 : 0
209 visible: opacity != 0
210 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
211 active: __applicationMenus.model && !callHint.visible
213 width: parent.width - windowControlButtons.width - units.gu(2) - __indicators.barWidth
215 property bool menusRequested: menuBarLoader.item ? menuBarLoader.item.showRequested : false
217 sourceComponent: MenuBar {
218 id: bar
219 objectName: "menuBar"
220 anchors.left: parent.left
221 anchors.margins: units.gu(1)
222 height: menuBarLoader.height
223 enableKeyFilter: valid && PanelState.decorationsVisible
224 unityMenuModel: __applicationMenus.model
226 Connections {
227 target: __applicationMenus
228 onShownChanged: bar.dismiss();
229 }
231 Connections {
232 target: __indicators
233 onShownChanged: bar.dismiss();
234 }
236 onDoubleClicked: PanelState.restoreClicked()
237 onPressed: decorationMouseArea.onPressed(mouse)
238 }
239 }
240 }
242 ActiveCallHint {
243 id: callHint
244 objectName: "callHint"
246 anchors.centerIn: parent
247 height: minimizedPanelHeight
249 visible: active && indicators.state == "initial" && __applicationMenus.state == "initial"
250 greeterShown: root.greeterShown
251 }
252 }
254 PanelMenu {
255 id: __applicationMenus
257 model: registeredMenuModel.model
258 width: root.applicationMenuWidth
259 minimizedPanelHeight: root.minimizedPanelHeight
260 expandedPanelHeight: root.expandedPanelHeight
261 openedHeight: root.height
262 alignment: Qt.AlignLeft
263 enableHint: !callHint.active && !fullscreenMode
264 showOnClick: false
265 panelColor: panelAreaBackground.color
267 onShowTapped: {
268 if (callHint.active) {
269 callHint.showLiveCall();
270 }
271 }
273 showRowTitle: !expanded
274 rowTitle: PanelState.title
275 rowItemDelegate: ActionItem {
276 id: actionItem
277 property int ownIndex: index
278 objectName: "appMenuItem"+index
280 width: _title.width + units.gu(2)
281 height: parent.height
283 action: Action {
284 text: model.label.replace("_", "&")
285 }
287 Label {
288 id: _title
289 anchors.centerIn: parent
290 text: actionItem.text
291 horizontalAlignment: Text.AlignLeft
292 color: enabled ? theme.palette.normal.backgroundText : theme.palette.disabled.backgroundText
293 }
294 }
296 pageDelegate: PanelMenuPage {
297 menuModel: __applicationMenus.model
298 submenuIndex: modelIndex
300 factory: ApplicationMenuItemFactory {
301 rootModel: __applicationMenus.model
302 }
303 }
305 enabled: d.enableTouchMenus
306 opacity: d.showTouchMenu ? 1 : 0
307 visible: opacity != 0
308 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
310 onEnabledChanged: {
311 if (!enabled) hide();
312 }
313 }
315 PanelMenu {
316 id: __indicators
317 objectName: "indicators"
319 anchors {
320 top: parent.top
321 right: parent.right
322 }
323 width: root.indicatorMenuWidth
324 minimizedPanelHeight: root.minimizedPanelHeight
325 expandedPanelHeight: root.expandedPanelHeight
326 openedHeight: root.height
328 overFlowWidth: root.width
329 enableHint: !callHint.active && !fullscreenMode
330 showOnClick: !callHint.visible
331 panelColor: panelAreaBackground.color
333 onShowTapped: {
334 if (callHint.active) {
335 callHint.showLiveCall();
336 }
337 }
339 rowItemDelegate: IndicatorItem {
340 id: indicatorItem
341 objectName: identifier+"-panelItem"
343 property int ownIndex: index
344 property bool overflow: parent.width - x > __indicators.overFlowWidth
345 property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator || hideKeyboardIndicator)
346 // HACK for indicator-session
347 readonly property bool hideSessionIndicator: identifier == "indicator-session" && Math.min(Screen.width, Screen.height) <= units.gu(60)
348 // HACK for indicator-keyboard
349 readonly property bool hideKeyboardIndicator: identifier == "indicator-keyboard" && (AccountsService.keymaps.length < 2 || keyboardsModel.count == 0)
351 height: parent.height
352 expanded: indicators.expanded
353 selected: ListView.isCurrentItem
355 identifier: model.identifier
356 busName: indicatorProperties.busName
357 actionsObjectPath: indicatorProperties.actionsObjectPath
358 menuObjectPath: indicatorProperties.menuObjectPath
360 opacity: hidden ? 0.0 : 1.0
361 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
363 width: ((expanded || indicatorVisible) && !hideSessionIndicator && !hideKeyboardIndicator) ? implicitWidth : 0
365 Behavior on width { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
366 }
368 pageDelegate: PanelMenuPage {
369 objectName: modelData.identifier + "-page"
370 submenuIndex: 0
372 menuModel: delegate.menuModel
374 factory: IndicatorMenuItemFactory {
375 indicator: {
376 var context = modelData.identifier;
377 if (context && context.indexOf("fake-") === 0) {
378 context = context.substring("fake-".length)
379 }
380 return context;
381 }
382 rootModel: delegate.menuModel
383 }
385 IndicatorDelegate {
386 id: delegate
387 busName: modelData.indicatorProperties.busName
388 actionsObjectPath: modelData.indicatorProperties.actionsObjectPath
389 menuObjectPath: modelData.indicatorProperties.menuObjectPath
390 }
391 }
393 enabled: !applicationMenus.expanded
394 opacity: !callHint.visible && !applicationMenus.expanded ? 1 : 0
395 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
397 onEnabledChanged: {
398 if (!enabled) hide();
399 }
400 }
401 }
403 InputDeviceModel {
404 id: keyboardsModel
405 deviceFilter: InputInfo.Keyboard
406 }
408 IndicatorsLight {
409 id: indicatorLights
410 }
412 states: [
413 State {
414 name: "onscreen" //fully opaque and visible at top edge of screen
415 when: !fullscreenMode
416 PropertyChanges {
417 target: panelArea;
418 anchors.topMargin: 0
419 opacity: 1;
420 }
421 },
422 State {
423 name: "offscreen" //pushed off screen
424 when: fullscreenMode
425 PropertyChanges {
426 target: panelArea;
427 anchors.topMargin: {
428 if (indicators.state !== "initial") return 0;
429 if (applicationMenus.state !== "initial") return 0;
430 return -minimizedPanelHeight;
431 }
432 opacity: indicators.fullyClosed && applicationMenus.fullyClosed ? 0.0 : 1.0
433 }
434 PropertyChanges {
435 target: indicators.showDragHandle;
436 anchors.bottomMargin: -units.gu(1)
437 }
438 PropertyChanges {
439 target: applicationMenus.showDragHandle;
440 anchors.bottomMargin: -units.gu(1)
441 }
442 }
443 ]
445 transitions: [
446 Transition {
447 to: "onscreen"
448 UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
449 },
450 Transition {
451 to: "offscreen"
452 UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
453 }
454 ]