on c08b89c help sign in
unity8/qml/Panel/Panel.qml
484 lines 17 kB history raw
1/*
2 * Copyright (C) 2013-2017 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
27import "../ApplicationMenus"
28import "../Components"
29import "../Components/PanelState"
30import ".."
31import "Indicators"
33Item {
34 id: root
35 readonly property real panelHeight: panelArea.y + minimizedPanelHeight
37 property real minimizedPanelHeight: units.gu(3)
38 property real expandedPanelHeight: units.gu(7)
39 property real indicatorMenuWidth: width
40 property real applicationMenuWidth: width
41 property alias applicationMenuContentX: __applicationMenus.menuContentX
43 property alias applicationMenus: __applicationMenus
44 property alias indicators: __indicators
45 property bool fullscreenMode: false
46 property real panelAreaShowProgress: 1.0
47 property bool greeterShown: false
48 property bool hasKeyboard: false
50 property string mode: "staged"
52 MouseArea {
53 id: backMouseEater
54 anchors.fill: parent
55 anchors.topMargin: panelHeight
56 visible: !indicators.fullyClosed || !applicationMenus.fullyClosed
57 enabled: visible
58 hoverEnabled: true // should also eat hover events, otherwise they will pass through
60 onClicked: {
61 __applicationMenus.hide();
62 __indicators.hide();
63 }
64 }
66 Binding {
67 target: PanelState
68 property: "panelHeight"
69 value: minimizedPanelHeight
70 }
72 RegisteredApplicationMenuModel {
73 id: registeredMenuModel
74 persistentSurfaceId: PanelState.focusedPersistentSurfaceId
75 }
77 QtObject {
78 id: d
80 property bool revealControls: !greeterShown &&
81 !applicationMenus.shown &&
82 !indicators.shown &&
83 (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)
85 property bool showWindowDecorationControls: (revealControls && PanelState.decorationsVisible) ||
86 PanelState.decorationsAlwaysVisible
88 property bool showPointerMenu: revealControls && enablePointerMenu &&
89 (PanelState.decorationsVisible || mode == "windowed")
91 property bool enablePointerMenu: applicationMenus.available &&
92 applicationMenus.model
94 property bool showTouchMenu: !greeterShown &&
95 !showPointerMenu &&
96 !showWindowDecorationControls
98 property bool enableTouchMenus: showTouchMenu &&
99 applicationMenus.available &&
100 applicationMenus.model
101 }
103 Item {
104 id: panelArea
105 objectName: "panelArea"
107 anchors.fill: parent
109 transform: Translate {
110 y: indicators.state === "initial"
111 ? (1.0 - panelAreaShowProgress) * - minimizedPanelHeight
112 : 0
113 }
115 BorderImage {
116 id: indicatorsDropShadow
117 anchors {
118 fill: __indicators
119 margins: -units.gu(1)
120 }
121 visible: !__indicators.fullyClosed
122 source: "graphics/rectangular_dropshadow.sci"
123 }
125 BorderImage {
126 id: appmenuDropShadow
127 anchors {
128 fill: __applicationMenus
129 margins: -units.gu(1)
130 }
131 visible: !__applicationMenus.fullyClosed
132 source: "graphics/rectangular_dropshadow.sci"
133 }
135 BorderImage {
136 id: panelDropShadow
137 anchors {
138 fill: panelAreaBackground
139 bottomMargin: -units.gu(1)
140 }
141 visible: PanelState.dropShadow
142 source: "graphics/rectangular_dropshadow.sci"
143 }
145 Rectangle {
146 id: panelAreaBackground
147 color: callHint.visible ? theme.palette.normal.positive : theme.palette.normal.background
148 anchors {
149 top: parent.top
150 left: parent.left
151 right: parent.right
152 }
153 height: minimizedPanelHeight
155 Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
156 }
158 MouseArea {
159 id: decorationMouseArea
160 objectName: "windowControlArea"
161 anchors {
162 left: parent.left
163 right: parent.right
164 }
165 height: minimizedPanelHeight
166 hoverEnabled: !__indicators.shown
167 onClicked: {
168 if (callHint.visible) {
169 callHint.showLiveCall();
170 }
171 }
173 onPressed: {
174 if (!callHint.visible) {
175 // let it fall through to the window decoration of the maximized window behind, if any
176 mouse.accepted = false;
177 }
178 var menubar = menuBarLoader.item;
179 if (menubar) {
180 menubar.invokeMenu(mouse);
181 }
182 }
184 Row {
185 anchors.fill: parent
186 spacing: units.gu(2)
188 // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
189 // cf. https://bugreports.qt.io/browse/QTBUG-32909
190 WindowControlButtons {
191 id: windowControlButtons
192 objectName: "panelWindowControlButtons"
193 height: indicators.minimizedPanelHeight
194 opacity: d.showWindowDecorationControls ? 1 : 0
195 visible: opacity != 0
196 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
198 active: PanelState.decorationsVisible || PanelState.decorationsAlwaysVisible
199 windowIsMaximized: true
200 onCloseClicked: PanelState.closeClicked()
201 onMinimizeClicked: PanelState.minimizeClicked()
202 onMaximizeClicked: PanelState.restoreClicked()
203 closeButtonShown: PanelState.closeButtonShown
204 }
206 Loader {
207 id: menuBarLoader
208 objectName: "menuBarLoader"
209 height: parent.height
210 enabled: d.enablePointerMenu
211 opacity: d.showPointerMenu ? 1 : 0
212 visible: opacity != 0
213 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
214 active: d.showPointerMenu && !callHint.visible
216 width: parent.width - windowControlButtons.width - units.gu(2) - __indicators.barWidth
218 readonly property bool menusRequested: menuBarLoader.item ? menuBarLoader.item.showRequested : false
220 sourceComponent: MenuBar {
221 id: bar
222 objectName: "menuBar"
223 anchors.left: parent ? parent.left : undefined
224 anchors.margins: units.gu(1)
225 height: menuBarLoader.height
226 enableKeyFilter: valid && PanelState.decorationsVisible
227 unityMenuModel: __applicationMenus.model
229 Connections {
230 target: __applicationMenus
231 onShownChanged: bar.dismiss();
232 }
234 Connections {
235 target: __indicators
236 onShownChanged: bar.dismiss();
237 }
239 onDoubleClicked: PanelState.restoreClicked()
240 onPressed: mouse.accepted = false // let the parent mouse area handle this, so it can both unsnap window and show menu
241 }
242 }
243 }
245 ActiveCallHint {
246 id: callHint
247 objectName: "callHint"
249 anchors.centerIn: parent
250 height: minimizedPanelHeight
252 visible: active && indicators.state == "initial" && __applicationMenus.state == "initial"
253 greeterShown: root.greeterShown
254 }
255 }
257 PanelMenu {
258 id: __applicationMenus
260 x: menuContentX
261 model: registeredMenuModel.model
262 width: root.applicationMenuWidth
263 minimizedPanelHeight: root.minimizedPanelHeight
264 expandedPanelHeight: root.expandedPanelHeight
265 openedHeight: root.height
266 alignment: Qt.AlignLeft
267 enableHint: !callHint.active && !fullscreenMode
268 showOnClick: false
269 adjustDragHandleSizeToContents: false
270 panelColor: panelAreaBackground.color
272 onShowTapped: {
273 if (callHint.active) {
274 callHint.showLiveCall();
275 }
276 }
278 hideRow: !expanded
279 rowItemDelegate: ActionItem {
280 id: actionItem
281 property int ownIndex: index
282 objectName: "appMenuItem"+index
283 enabled: model.sensitive
285 width: _title.width + units.gu(2)
286 height: parent.height
288 action: Action {
289 text: model.label.replace("_", "&")
290 }
292 Label {
293 id: _title
294 anchors.centerIn: parent
295 text: actionItem.text
296 horizontalAlignment: Text.AlignLeft
297 color: enabled ? theme.palette.normal.backgroundText : theme.palette.disabled.backgroundText
298 }
299 }
301 pageDelegate: PanelMenuPage {
302 readonly property bool isCurrent: modelIndex == __applicationMenus.currentMenuIndex
303 onIsCurrentChanged: {
304 if (isCurrent && menuModel) {
305 menuModel.aboutToShow(modelIndex);
306 }
307 }
309 menuModel: __applicationMenus.model
310 submenuIndex: modelIndex
312 factory: ApplicationMenuItemFactory {
313 rootModel: __applicationMenus.model
314 }
315 }
317 enabled: d.enableTouchMenus
318 opacity: d.showTouchMenu ? 1 : 0
319 visible: opacity != 0
320 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
322 onEnabledChanged: {
323 if (!enabled) hide();
324 }
325 }
327 Label {
328 id: rowLabel
329 objectName: "panelTitle"
330 anchors {
331 left: parent.left
332 leftMargin: units.gu(1)
333 right: __indicators.left
334 rightMargin: units.gu(1)
335 }
336 height: root.minimizedPanelHeight
337 verticalAlignment: Text.AlignVCenter
338 elide: Text.ElideRight
339 maximumLineCount: 1
340 fontSize: "medium"
341 font.weight: Font.Medium
342 color: theme.palette.selected.backgroundText
343 opacity: __applicationMenus.visible && !__applicationMenus.expanded ? 1 : 0
344 visible: opacity != 0
345 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
346 text: PanelState.title
347 }
349 PanelMenu {
350 id: __indicators
351 objectName: "indicators"
353 anchors {
354 top: parent.top
355 right: parent.right
356 }
357 width: root.indicatorMenuWidth
358 minimizedPanelHeight: root.minimizedPanelHeight
359 expandedPanelHeight: root.expandedPanelHeight
360 openedHeight: root.height
362 overFlowWidth: root.width
363 enableHint: !callHint.active && !fullscreenMode
364 showOnClick: !callHint.visible
365 panelColor: panelAreaBackground.color
367 onShowTapped: {
368 if (callHint.active) {
369 callHint.showLiveCall();
370 }
371 }
373 rowItemDelegate: IndicatorItem {
374 id: indicatorItem
375 objectName: identifier+"-panelItem"
377 property int ownIndex: index
378 readonly property bool overflow: parent.width - x > __indicators.overFlowWidth
379 readonly property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator || hideKeyboardIndicator)
380 // HACK for indicator-session
381 readonly property bool hideSessionIndicator: identifier == "indicator-session" && Math.min(Screen.width, Screen.height) <= units.gu(60)
382 // HACK for indicator-keyboard
383 readonly property bool hideKeyboardIndicator: identifier == "indicator-keyboard" && !hasKeyboard
385 height: parent.height
386 expanded: indicators.expanded
387 selected: ListView.isCurrentItem
389 identifier: model.identifier
390 busName: indicatorProperties.busName
391 actionsObjectPath: indicatorProperties.actionsObjectPath
392 menuObjectPath: indicatorProperties.menuObjectPath
394 opacity: hidden ? 0.0 : 1.0
395 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
397 width: ((expanded || indicatorVisible) && !hideSessionIndicator && !hideKeyboardIndicator) ? implicitWidth : 0
399 Behavior on width { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
400 }
402 pageDelegate: PanelMenuPage {
403 objectName: modelData.identifier + "-page"
404 submenuIndex: 0
406 menuModel: delegate.menuModel
408 factory: IndicatorMenuItemFactory {
409 indicator: {
410 var context = modelData.identifier;
411 if (context && context.indexOf("fake-") === 0) {
412 context = context.substring("fake-".length)
413 }
414 return context;
415 }
416 rootModel: delegate.menuModel
417 }
419 IndicatorDelegate {
420 id: delegate
421 busName: modelData.indicatorProperties.busName
422 actionsObjectPath: modelData.indicatorProperties.actionsObjectPath
423 menuObjectPath: modelData.indicatorProperties.menuObjectPath
424 }
425 }
427 enabled: !applicationMenus.expanded
428 opacity: !callHint.visible && !applicationMenus.expanded ? 1 : 0
429 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
431 onEnabledChanged: {
432 if (!enabled) hide();
433 }
434 }
435 }
437 IndicatorsLight {
438 id: indicatorLights
439 }
441 states: [
442 State {
443 name: "onscreen" //fully opaque and visible at top edge of screen
444 when: !fullscreenMode
445 PropertyChanges {
446 target: panelArea;
447 anchors.topMargin: 0
448 opacity: 1;
449 }
450 },
451 State {
452 name: "offscreen" //pushed off screen
453 when: fullscreenMode
454 PropertyChanges {
455 target: panelArea;
456 anchors.topMargin: {
457 if (indicators.state !== "initial") return 0;
458 if (applicationMenus.state !== "initial") return 0;
459 return -minimizedPanelHeight;
460 }
461 opacity: indicators.fullyClosed && applicationMenus.fullyClosed ? 0.0 : 1.0
462 }
463 PropertyChanges {
464 target: indicators.showDragHandle;
465 anchors.bottomMargin: -units.gu(1)
466 }
467 PropertyChanges {
468 target: applicationMenus.showDragHandle;
469 anchors.bottomMargin: -units.gu(1)
470 }
471 }
472 ]
474 transitions: [
475 Transition {
476 to: "onscreen"
477 UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
478 },
479 Transition {
480 to: "offscreen"
481 UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
482 }
483 ]