Commit 1669197b authored by Nate Graham's avatar Nate Graham
Browse files

[applets/systemtray] Use a grid for the hidden items view

This improves the applet in a variety of ways:
- Much more touch friendly than the current skinny list view
- Many more items can be displayed without needing to scroll
- Substantial code simplification
- UI improvement from no longer sometimes showing an awkward vertical
  strip of icons that was invisibly scrollable but some of whose items
  ate scroll events, and which pushed the header over to the left in a
  somewhat random-looking way

BUG: 402681
FIXED-IN: 5.20
parent 79033399
......@@ -24,20 +24,11 @@ import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.FrameSvgItem {
id: expandedItem
property Item visualParent
property Item target
property int location
//! when the target is the root item we use the maximum thickness of the panel
x: plasmoid.formFactor === PlasmaCore.Types.Vertical && target === root ?
0 : Math.max(0, (target ? target.x : 0) + (visualParent ? visualParent.x : 0))
y: plasmoid.formFactor === PlasmaCore.Types.Horizontal && target === root ?
0 : Math.max(0, (target ? target.y : 0) + (visualParent ? visualParent.y : 0))
z: -1 // always draw behind icons
width: plasmoid.formFactor === PlasmaCore.Types.Vertical && target === root ?
parent.width : Math.min(parent.width, target ? target.width : 0)
height: plasmoid.formFactor === PlasmaCore.Types.Horizontal && target === root ?
parent.height : Math.min(parent.height, target ? target.height : 0)
width: parent.width
height: parent.height
imagePath: "widgets/tabbar"
prefix: {
......@@ -60,7 +51,7 @@ PlasmaCore.FrameSvgItem {
}
return prefix;
}
opacity: target && dialog.visible ? 1 : 0
opacity: parent && dialog.visible ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: units.longDuration
......@@ -68,28 +59,28 @@ PlasmaCore.FrameSvgItem {
}
}
Behavior on x {
enabled: target && expandedItem.opacity == 1
enabled: parent && expandedItem.opacity == 1
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
Behavior on y {
enabled: target && expandedItem.opacity == 1
enabled: parent && expandedItem.opacity == 1
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
Behavior on width {
enabled: target && expandedItem.opacity == 1
enabled: parent && expandedItem.opacity == 1
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
Behavior on height {
enabled: target && expandedItem.opacity == 1
enabled: parent && expandedItem.opacity == 1
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
......
/*
* Copyright 2016 Marco Martin <mart@kde.org>
* Copyright 2020 Nate Graham <nate@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
......@@ -25,19 +26,25 @@ import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
//set width/height to avoid an useless Dialog resize
width: Layout.minimumWidth
height: Layout.minimumHeight
Layout.minimumWidth: units.gridUnit * 24
Layout.minimumHeight: units.gridUnit * 21
Layout.preferredWidth: Layout.minimumWidth
Layout.preferredHeight: Layout.minimumHeight
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
id: popup
//set width/height to avoid useless Dialog resize
readonly property int defaultWidth: units.gridUnit * 24
readonly property int defaultHeight: units.gridUnit * 21
width: defaultWidth
Layout.minimumWidth: defaultWidth
Layout.preferredWidth: defaultWidth
Layout.maximumWidth: defaultWidth
height: defaultHeight
Layout.minimumHeight: defaultHeight
Layout.preferredHeight: defaultHeight
Layout.maximumHeight: defaultHeight
property alias activeApplet: container.activeApplet
property alias hiddenLayout: hiddenItemsView.layout
// Header
PlasmaExtras.PlasmoidHeading {
id: plasmoidHeading
anchors {
......@@ -48,78 +55,35 @@ Item {
height: trayHeading.height + bottomPadding + container.headingHeight
}
PlasmaExtras.PlasmoidHeading {
id: plasmoidFooter
location: PlasmaExtras.PlasmoidHeading.Location.Footer
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
visible: container.appletHasFooter
height: container.footerHeight
}
// Main content layout
ColumnLayout {
id: expandedRepresentation
anchors.fill: parent
// TODO: remove this so the scrollview fully touches the header;
// add top padding internally
spacing: plasmoidHeading.bottomPadding
// Header content layout
RowLayout {
id: trayHeading
PlasmaExtras.Heading {
id: heading
Layout.fillWidth: true
level: 1
Layout.leftMargin: {
//Menu mode
if (!activeApplet && hiddenItemsView.visible && !LayoutMirroring.enabled) {
return units.smallSpacing;
//applet open, sidebar
} else if (activeApplet && hiddenItemsView.visible && !LayoutMirroring.enabled) {
return hiddenItemsView.width + units.smallSpacing + dialog.margins.left;
//applet open, no sidebar
} else {
return units.smallSpacing;
}
}
Layout.rightMargin: {
//Menu mode
if (!activeApplet && hiddenItemsView.visible && LayoutMirroring.enabled) {
return units.smallSpacing;
//applet open, sidebar
} else if (activeApplet && hiddenItemsView.visible && LayoutMirroring.enabled) {
return hiddenItemsView.width + units.largeSpacing;
//applet open, no sidebar
} else {
return 0;
}
}
PlasmaComponents.ToolButton {
id: backButton
visible: activeApplet
text: activeApplet ? activeApplet.title : ""
MouseArea {
anchors.fill: parent
onClicked: {
if (activeApplet) {
activeApplet.expanded = false;
dialog.visible = true;
}
icon.name: "go-previous"
onClicked: {
if (activeApplet) {
activeApplet.expanded = false;
dialog.visible = true;
}
}
}
PlasmaExtras.Heading {
id: noAppletHeading
visible: !activeApplet
Layout.fillWidth: true
level: 1
text: i18n("Status and Notifications")
text: activeApplet ? activeApplet.title : i18n("Status and Notifications")
}
PlasmaComponents.ToolButton {
......@@ -134,40 +98,43 @@ Item {
}
}
RowLayout {
spacing: 0 // must be 0 so that the separator is as close to the indicator as possible
HiddenItemsView {
id: hiddenItemsView
Layout.fillWidth: !activeApplet
Layout.fillHeight: true
Layout.topMargin: container.headingHeight
}
// Grid view of all available items
HiddenItemsView {
id: hiddenItemsView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: units.smallSpacing
visible: !activeApplet
}
PlasmaCore.SvgItem {
visible: hiddenItemsView.visible && activeApplet
Layout.fillHeight: true
Layout.preferredWidth: lineSvg.elementSize("vertical-line").width
Layout.topMargin: container.headingHeight
elementId: "vertical-line"
svg: PlasmaCore.Svg {
id: lineSvg;
imagePath: "widgets/line"
}
}
// Container for currently visible item
PlasmoidPopupsContainer {
id: container
Layout.fillWidth: true
Layout.fillHeight: true
visible: activeApplet
// We need to add our own margins on the top and left (when the
// hidden items view is visible, at least) so it matches the
// dialog's own margins and content is centered correctly
Layout.topMargin: mergeHeadings ? 0 : dialog.margins.top
Layout.leftMargin: hiddenItemsView.visible && activeApplet && !LayoutMirroring.enabled ? dialog.margins.left : 0
Layout.rightMargin: hiddenItemsView.visible && activeApplet && LayoutMirroring.enabled ? dialog.margins.right : 0
}
}
PlasmoidPopupsContainer {
id: container
Layout.fillWidth: true
Layout.fillHeight: true
visible: activeApplet
// We need to add our own margins on the top and left (when the
// hidden items view is visible, at least) so it matches the
// dialog's own margins and content is centered correctly
Layout.topMargin: mergeHeadings ? 0 : dialog.margins.top
Layout.leftMargin: hiddenItemsView.visible && activeApplet && !LayoutMirroring.enabled ? dialog.margins.left : 0
Layout.rightMargin: hiddenItemsView.visible && activeApplet && LayoutMirroring.enabled ? dialog.margins.right : 0
}
// Footer
PlasmaExtras.PlasmoidHeading {
id: plasmoidFooter
location: PlasmaExtras.PlasmoidHeading.Location.Footer
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
visible: container.appletHasFooter
height: container.footerHeight
// So that it doesn't appear over the content view, which results in
// the footer controls being inaccessible
z: -9999
}
}
/*
* Copyright 2016 Marco Martin <mart@kde.org>
* Copyright 2020 Konrad Materka <materka@gmail.com>
* Copyright 2020 Nate Graham <nate@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
......@@ -31,12 +32,12 @@ MouseArea {
visible: !root.activeApplet || (root.activeApplet.parent && root.activeApplet.parent.inHiddenLayout)
implicitWidth: root.activeApplet ? iconColumnWidth : parent.width
property alias layout: hiddenTasksColumn
property alias layout: hiddenTasks
//Useful to align stuff to the column of icons, both in expanded and shrink modes
property int iconColumnWidth: root.hiddenItemSize + highlight.marginHints.left + highlight.marginHints.right
hoverEnabled: true
onExited: hiddenTasksColumn.currentIndex = -1
onExited: hiddenTasks.currentIndex = -1
PlasmaExtras.ScrollArea {
width: parent.width
......@@ -46,15 +47,18 @@ MouseArea {
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: root.activeApplet ? Qt.ScrollBarAlwaysOff : Qt.ScrollBarAsNeeded
ListView {
id: hiddenTasksColumn
GridView {
id: hiddenTasks
spacing: units.smallSpacing
readonly property int rows: 4
readonly property int columns: 4
cellWidth: hiddenTasks.width / hiddenTasks.columns
cellHeight: hiddenTasks.height / hiddenTasks.rows
currentIndex: -1
highlight: PlasmaComponents.Highlight {}
highlightMoveDuration: 0
highlightResizeDuration: 0
readonly property int iconItemHeight: root.hiddenItemSize + highlight.marginHints.top + highlight.marginHints.bottom
property int itemCount: model.rowCount()
......@@ -71,24 +75,17 @@ MouseArea {
}
Connections {
target: hiddenTasksColumn.model
// hiddenTasksColumn.count is not updated when ListView is hidden and is not rendered
target: hiddenTasks.model
// hiddenTasks.count is not updated when ListView is hidden and is not rendered
// manually update itemCount so that expander arrow hides/shows itself correctly
onModelReset: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount()
onRowsInserted: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount()
onRowsRemoved: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount()
onLayoutChanged: hiddenTasksColumn.itemCount = hiddenTasksColumn.model.rowCount()
onModelReset: hiddenTasks.itemCount = hiddenTasks.model.rowCount()
onRowsInserted: hiddenTasks.itemCount = hiddenTasks.model.rowCount()
onRowsRemoved: hiddenTasks.itemCount = hiddenTasks.model.rowCount()
onLayoutChanged: hiddenTasks.itemCount = hiddenTasks.model.rowCount()
}
PlasmaComponents.Highlight {
id: highlight
visible: false
}
CurrentItemHighLight {
readonly property bool hiddenAppletActivated: root.activeApplet && root.activeApplet.parent && root.activeApplet.parent.inHiddenLayout
parent: hiddenAppletActivated ? root.activeApplet.parent : hiddenTasksColumn.contentItem
target: hiddenAppletActivated ? root.activeApplet.parent : null
location: LayoutMirroring.enabled ? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge
}
}
/*
* Copyright 2016 Marco Martin <mart@kde.org>
* Copyright 2020 Konrad Materka <materka@gmail.com>
* Copyright 2020 Nate Graham <nate@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
......@@ -19,14 +20,15 @@
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
PlasmaCore.ToolTipArea {
id: abstractItem
height: inVisibleLayout ? visibleLayout.cellHeight : hiddenLayout.iconItemHeight
width: inVisibleLayout ? visibleLayout.cellWidth : hiddenLayout.width
height: inVisibleLayout ? visibleLayout.cellHeight : hiddenTasks.cellHeight
width: inVisibleLayout ? visibleLayout.cellWidth : hiddenTasks.cellWidth
property var model: itemModel
......@@ -123,21 +125,36 @@ PlasmaCore.ToolTipArea {
}
}
Row {
spacing: units.smallSpacing
anchors.horizontalCenter: inVisibleLayout ? parent.horizontalCenter : undefined
ColumnLayout {
anchors.fill: abstractItem
spacing: 0
Item {
id: iconContainer
anchors.verticalCenter: parent.verticalCenter
width: inVisibleLayout ? root.itemSize : hiddenLayout.iconItemHeight
height: width
property alias inHiddenLayout: abstractItem.inHiddenLayout
property alias inVisibleLayout: abstractItem.inVisibleLayout
readonly property int size: abstractItem.inVisibleLayout ? root.itemSize : units.iconSizes.medium
Layout.alignment: Qt.AlignHCenter
implicitWidth: size
implicitHeight: size
Layout.topMargin: abstractItem.inHiddenLayout ? units.smallSpacing : 0
}
PlasmaComponents.Label {
id: label
anchors.verticalCenter: parent.verticalCenter
Layout.fillWidth: true
Layout.fillHeight: true
Layout.bottomMargin: abstractItem.inHiddenLayout ? units.smallSpacing : 0
visible: abstractItem.inHiddenLayout && !root.activeApplet
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 3
opacity: visible ? 1 : 0
Behavior on opacity {
NumberAnimation {
......
......@@ -96,7 +96,6 @@ MouseArea {
CurrentItemHighLight {
readonly property bool visibleAppletActivated: root.activeApplet && root.activeApplet.parent && root.activeApplet.parent.inVisibleLayout
parent: visibleAppletActivated ? root.activeApplet.parent : root
target: visibleAppletActivated ? root.activeApplet.parent : root
location: plasmoid.location
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment