2 step top panel slide

a top panel can be just "half" opened showing only the top row of icons. don't duplicate the icons but dynamically fade in/out those making also possible to open the drawer completely by a single, longer swipe
This commit is contained in:
Marco Martin 2021-03-09 12:52:17 +00:00
parent 33400a872f
commit 113fe48caf
5 changed files with 145 additions and 52 deletions

View file

@ -18,7 +18,7 @@ DrawerBackground {
visible: shouldBeVisible
property bool shouldBeVisible: applet && (applet.status != PlasmaCore.Types.HiddenStatus && applet.status != PlasmaCore.Types.PassiveStatus)
height: parent.height
width: visible ? quickSettingsParent.width : 0
width: visible ? quickSettings.width : 0
Layout.minimumHeight: applet && applet.switchHeight
onShouldBeVisibleChanged: fullContainer.visible = fullContainer.shouldBeVisible

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.0
import QtQuick 2.14
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
@ -23,14 +23,15 @@ NanoShell.FullScreenOverlay {
property alias fixedArea: mainScope
property alias flickable: mainFlickable
color: "transparent"//Qt.rgba(0, 0, 0, 0.6 * Math.min(1, offset/contentArea.height))
color: "transparent"
property alias contentItem: contentArea.contentItem
property int headerHeight
property real topEmptyAreaHeight
signal closed
//width: Screen.width
//height: Screen.height
width: Screen.width
height: Screen.height
enum MovementDirection {
None = 0,
@ -115,7 +116,7 @@ NanoShell.FullScreenOverlay {
easing.type: Easing.InOutQuad
properties: "offset"
from: window.offset
to: contentArea.height
to: contentArea.height - topEmptyAreaHeight
}
Rectangle {
@ -188,9 +189,9 @@ NanoShell.FullScreenOverlay {
oldContentY = contentY;
}
property real oldContentY
boundsBehavior: Flickable.StopAtBounds
boundsMovement: Flickable.StopAtBounds
contentWidth: window.width
contentHeight: window.height*2
contentHeight: window.height*2 - headerHeight*2
bottomMargin: window.height
onMovementStarted: {
window.cancelAnimations();

View file

@ -269,6 +269,10 @@ Item {
slidingPanel.userInteracting = false;
slidingPanel.updateState();
}
onCanceled: {
slidingPanel.userInteracting = false;
slidingPanel.updateState();
}
}
SlidingPanel {
@ -277,35 +281,36 @@ Item {
height: plasmoid.availableScreenRect.height
openThreshold: units.gridUnit * 2
headerHeight: root.height
topEmptyAreaHeight: quickSettings.topEmptyAreaHeight
offset: quickSettingsParent.height
offset: quickSettings.height
onClosed: quickSettings.closed()
contentItem: Item {
implicitWidth: panelContents.implicitWidth
implicitHeight: Math.min(slidingPanel.height, quickSettingsParent.implicitHeight)
implicitHeight: Math.min(slidingPanel.height, quickSettings.implicitHeight)
GridLayout {
id: panelContents
anchors.fill: parent
implicitWidth: quickSettingsParent.implicitWidth
implicitHeight: Math.min(slidingPanel.height, quickSettingsParent.implicitHeight)
implicitWidth: quickSettings.implicitWidth
implicitHeight: Math.min(slidingPanel.height, quickSettings.implicitHeight)
columns: slidingPanel.wideScreen ? 2 : 1
rows: slidingPanel.wideScreen ? 1 : 2
DrawerBackground {
id: quickSettingsParent
//anchors.fill: parent
QuickSettings {
id: quickSettings
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: slidingPanel.wideScreen ? Math.min(slidingPanel.width/2, units.gridUnit * 25) : panelContents.width
z: 4
contentItem: QuickSettings {
id: quickSettings
onCloseRequested: {
slidingPanel.hide()
}
parentSlidingPanel: slidingPanel
onCloseRequested: {
slidingPanel.hide()
}
background: DrawerBackground {}
}
ListView {
@ -313,12 +318,14 @@ Item {
z: 1
interactive: width < contentWidth
//parent: slidingPanel.wideScreen ? slidingPanel.flickable.contentItem : panelContents
Layout.preferredWidth: slidingPanel.wideScreen ? Math.min(slidingPanel.width - quickSettingsParent.width, quickSettingsParent.width*fullRepresentationModel.count) : panelContents.width
Layout.preferredWidth: slidingPanel.wideScreen ? Math.min(slidingPanel.width/2, quickSettings.width*fullRepresentationModel.count) : panelContents.width
//Layout.fillWidth: true
clip: slidingPanel.wideScreen
y: slidingPanel.wideScreen ? 0 : quickSettingsParent.height - height * (1-opacity)
opacity: slidingPanel.wideScreen ? 1 : fullRepresentationModel.count > 0 && slidingPanel.offset/panelContents.height
height: Math.min(plasmoid.screenGeometry.height - slidingPanel.headerHeight - quickSettingsParent.height - bottomBar.height, implicitHeight)
y: slidingPanel.wideScreen ? 0 : quickSettings.height - (quickSettings.height + height) * (1-opacity)
opacity: slidingPanel.wideScreen ? 1 : fullRepresentationModel.count > 0 && (slidingPanel.offset + slidingPanel.headerHeight)/(quickSettings.height -slidingPanel.topEmptyAreaHeight)
Layout.preferredHeight: Math.min(plasmoid.screenGeometry.height - slidingPanel.headerHeight - quickSettings.height - bottomBar.height + slidingPanel.topEmptyAreaHeight, implicitHeight)
//leftMargin: slidingPanel.drawerX
preferredHighlightBegin: slidingPanel.drawerX

View file

@ -23,6 +23,7 @@ ColumnLayout {
required property bool enabled
required property string settingsCommand
required property var toggleFunction
property alias labelOpacity: label.opacity
Rectangle {
Layout.preferredWidth: units.iconSizes.large + units.smallSpacing

View file

@ -4,13 +4,17 @@
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.1
import QtQuick 2.14
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.networkmanagement 0.2 as PlasmaNM
import org.kde.bluezqt 1.0 as BluezQt
import org.kde.colorcorrect 0.1 as CC
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
import org.kde.plasma.components 3.0 as PC3
Item {
id: root
@ -21,8 +25,37 @@ Item {
signal closeRequested
signal closed
property bool expandedMode: parentSlidingPanel.wideScreen
readonly property real expandedRatio: expandedMode ? 1 : Math.max(0, Math.min(1, (parentSlidingPanel.offset - firstRowHeight - parentSlidingPanel.headerHeight) / otherRowsHeight))
readonly property real topEmptyAreaHeight: parentSlidingPanel.userInteracting
? (root.height - collapsedHeight) * (1 - expandedRatio)
: (expandedMode ? 0 : root.height - collapsedHeight)
readonly property real collapsedHeight: firstRowHeight + PlasmaCore.Units.largeSpacing * 2
readonly property real firstRowHeight: flow.children[0].height
readonly property real otherRowsHeight: flow.height - firstRowHeight
Connections {
target: root.parentSlidingPanel
function onUserInteractingChanged() {
if (!parentSlidingPanel.userInteracting) {
if (root.expandedRatio > 0.7) {
root.expandedMode = true;
}
}
}
}
property bool screenshotRequested: false
property NanoShell.FullScreenOverlay parentSlidingPanel
property Item background
onBackgroundChanged: {
background.parent = backgroundParent
background.anchors.fill = backgroundParent
}
PlasmaNM.Handler {
id: nmHandler
}
@ -31,6 +64,14 @@ Item {
id: enabledConnections
}
Connections {
target: root.Window.window
function onVisibilityChanged() {
root.expandedMode = parentSlidingPanel.wideScreen;
}
}
Connections {
target: BluezQt.Manager
@ -249,44 +290,87 @@ Item {
id: settingsModel
}
Flow {
id: flow
Item {
id: backgroundParent
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: firstRowHeight + units.largeSpacing*2 + otherRowsHeight * root.expandedRatio
}
Item {
anchors {
fill: parent
margins: units.smallSpacing
}
readonly property real cellSizeHint: units.iconSizes.large + units.smallSpacing * 6
readonly property real columnWidth: Math.floor(width / Math.floor(width / cellSizeHint))
spacing: 0
Repeater {
model: settingsModel
delegate: Delegate {
id: delegateItem
//FIXME: why this is needed?
width: flow.columnWidth
Flow {
id: flow
anchors {
fill: parent
margins: units.largeSpacing
}
Connections {
target: delegateItem
onCloseRequested: root.closeRequested();
}
Connections {
target: root
onClosed: delegateItem.panelClosed();
readonly property real cellSizeHint: units.iconSizes.large + units.smallSpacing * 6
readonly property real columnWidth: Math.floor(width / Math.floor(width / cellSizeHint))
spacing: 0
Repeater {
model: settingsModel
delegate: Delegate {
id: delegateItem
//FIXME: why this is needed?
width: flow.columnWidth - (y > 0 ? 0 : (flow.columnWidth/Math.floor(flow.width / flow.columnWidth)) * (1 - root.expandedRatio))
height: item ? item.implicitHeight : 0
labelOpacity: y > 0 ? 1 : root.expandedRatio
opacity: y <= 0 ? 1 : root.expandedRatio
transform: Translate {
y: otherRowsHeight * (1 - root.expandedRatio)
}
Connections {
target: delegateItem
onCloseRequested: root.closeRequested();
}
Connections {
target: root
onClosed: delegateItem.panelClosed();
}
}
}
}
BrightnessItem {
id: brightnessSlider
width: flow.width
icon: "video-display-brightness"
label: i18n("Display Brightness")
value: root.screenBrightness
maximumValue: root.maximumScreenBrightness
Connections {
target: root
onScreenBrightnessChanged: brightnessSlider.value = root.screenBrightness
move: Transition {
NumberAnimation {
duration: units.shortDuration
//Here a linear easing actually looks better
//easing.type: Easing.InOutQuad
properties: "x,y"
}
}
BrightnessItem {
id: brightnessSlider
width: flow.width
icon: "video-display-brightness"
label: i18n("Display Brightness")
value: root.screenBrightness
maximumValue: root.maximumScreenBrightness
opacity: root.expandedRatio
transform: Translate{
y: otherRowsHeight * (1 - root.expandedRatio)
}
Connections {
target: root
onScreenBrightnessChanged: brightnessSlider.value = root.screenBrightness
}
}
}
}