237 lines
7.5 KiB
QML
237 lines
7.5 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import "root:/widgets"
|
|
import "root:/services"
|
|
import "root:/config"
|
|
import Quickshell
|
|
import Quickshell.Widgets
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
|
|
StackView {
|
|
id: root
|
|
|
|
required property Item popouts
|
|
required property QsMenuHandle trayItem
|
|
|
|
implicitWidth: currentItem.implicitWidth
|
|
implicitHeight: currentItem.implicitHeight
|
|
|
|
initialItem: SubMenu {
|
|
handle: root.trayItem
|
|
}
|
|
|
|
pushEnter: Anim {}
|
|
pushExit: Anim {}
|
|
popEnter: Anim {}
|
|
popExit: Anim {}
|
|
|
|
component Anim: Transition {
|
|
NumberAnimation {
|
|
duration: 0
|
|
}
|
|
}
|
|
|
|
component SubMenu: Column {
|
|
id: menu
|
|
|
|
required property QsMenuHandle handle
|
|
property bool isSubMenu
|
|
property bool shown
|
|
|
|
padding: Appearance.padding.smaller
|
|
spacing: Appearance.spacing.small
|
|
|
|
opacity: shown ? 1 : 0
|
|
scale: shown ? 1 : 0.8
|
|
|
|
Component.onCompleted: shown = true
|
|
StackView.onActivating: shown = true
|
|
StackView.onDeactivating: shown = false
|
|
StackView.onRemoved: destroy()
|
|
|
|
Behavior on opacity {
|
|
NumberAnimation {
|
|
duration: Appearance.anim.durations.normal
|
|
easing.type: Easing.BezierSpline
|
|
easing.bezierCurve: Appearance.anim.curves.standard
|
|
}
|
|
}
|
|
|
|
Behavior on scale {
|
|
NumberAnimation {
|
|
duration: Appearance.anim.durations.normal
|
|
easing.type: Easing.BezierSpline
|
|
easing.bezierCurve: Appearance.anim.curves.standard
|
|
}
|
|
}
|
|
|
|
QsMenuOpener {
|
|
id: menuOpener
|
|
|
|
menu: menu.handle
|
|
}
|
|
|
|
Repeater {
|
|
model: menuOpener.children
|
|
|
|
StyledRect {
|
|
id: item
|
|
|
|
required property QsMenuEntry modelData
|
|
|
|
implicitWidth: BarConfig.sizes.trayMenuWidth
|
|
implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight
|
|
|
|
radius: Appearance.rounding.full
|
|
color: modelData.isSeparator ? Colours.palette.m3outlineVariant : "transparent"
|
|
|
|
Loader {
|
|
id: children
|
|
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
|
|
active: !item.modelData.isSeparator
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
implicitHeight: label.implicitHeight
|
|
|
|
StateLayer {
|
|
anchors.margins: -Appearance.padding.small / 2
|
|
anchors.leftMargin: -Appearance.padding.smaller
|
|
anchors.rightMargin: -Appearance.padding.smaller
|
|
|
|
radius: item.radius
|
|
disabled: !item.modelData.enabled
|
|
|
|
function onClicked(): void {
|
|
const entry = item.modelData;
|
|
if (entry.hasChildren)
|
|
root.push(subMenuComp.createObject(null, {
|
|
handle: entry,
|
|
isSubMenu: true
|
|
}));
|
|
else {
|
|
item.modelData.triggered();
|
|
root.popouts.hasCurrent = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: icon
|
|
|
|
anchors.left: parent.left
|
|
|
|
active: item.modelData.icon !== ""
|
|
asynchronous: true
|
|
|
|
sourceComponent: IconImage {
|
|
implicitSize: label.implicitHeight
|
|
|
|
source: item.modelData.icon
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
id: label
|
|
|
|
anchors.left: icon.right
|
|
anchors.leftMargin: icon.active ? Appearance.spacing.smaller : 0
|
|
|
|
text: labelMetrics.elidedText
|
|
color: item.modelData.enabled ? Colours.palette.m3onSurface : Colours.palette.m3outline
|
|
}
|
|
|
|
TextMetrics {
|
|
id: labelMetrics
|
|
|
|
text: item.modelData.text
|
|
font.pointSize: label.font.pointSize
|
|
font.family: label.font.family
|
|
|
|
elide: Text.ElideRight
|
|
elideWidth: BarConfig.sizes.trayMenuWidth - (icon.active ? icon.implicitWidth + label.anchors.leftMargin : 0) - (expand.active ? expand.implicitWidth + Appearance.spacing.normal : 0)
|
|
}
|
|
|
|
Loader {
|
|
id: expand
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.right: parent.right
|
|
|
|
active: item.modelData.hasChildren
|
|
asynchronous: true
|
|
|
|
sourceComponent: MaterialIcon {
|
|
text: "chevron_right"
|
|
color: item.modelData.enabled ? Colours.palette.m3onSurface : Colours.palette.m3outline
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
active: menu.isSubMenu
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
implicitWidth: back.implicitWidth
|
|
implicitHeight: back.implicitHeight + Appearance.spacing.small / 2
|
|
|
|
Item {
|
|
anchors.bottom: parent.bottom
|
|
implicitWidth: back.implicitWidth
|
|
implicitHeight: back.implicitHeight
|
|
|
|
StyledRect {
|
|
anchors.fill: parent
|
|
anchors.margins: -Appearance.padding.small / 2
|
|
anchors.leftMargin: -Appearance.padding.smaller
|
|
anchors.rightMargin: -Appearance.padding.smaller * 2
|
|
|
|
radius: Appearance.rounding.full
|
|
color: Colours.palette.m3secondaryContainer
|
|
|
|
StateLayer {
|
|
radius: parent.radius
|
|
color: Colours.palette.m3onSecondaryContainer
|
|
|
|
function onClicked(): void {
|
|
root.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
Row {
|
|
id: back
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
MaterialIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: "chevron_left"
|
|
color: Colours.palette.m3onSecondaryContainer
|
|
}
|
|
|
|
StyledText {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: qsTr("Back")
|
|
color: Colours.palette.m3onSecondaryContainer
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: subMenuComp
|
|
|
|
SubMenu {}
|
|
}
|
|
}
|