159 lines
3.6 KiB
QML
159 lines
3.6 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import Quickshell
|
|
import Quickshell.Widgets
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Effects
|
|
import qs.Components
|
|
import qs.Modules
|
|
import qs.Config
|
|
|
|
Column {
|
|
id: menu
|
|
|
|
property int biggestWidth: 0
|
|
required property QsMenuHandle handle
|
|
required property int level
|
|
required property PopoutState popouts
|
|
required property ShellScreen screen
|
|
property bool shown: true
|
|
|
|
height: childrenRect.height
|
|
opacity: shown ? 1 : 0
|
|
padding: 0
|
|
scale: shown ? 1 : 0.8
|
|
spacing: 4
|
|
width: biggestWidth
|
|
|
|
Behavior on opacity {
|
|
Anim {
|
|
}
|
|
}
|
|
Behavior on scale {
|
|
Anim {
|
|
}
|
|
}
|
|
|
|
QsMenuOpener {
|
|
id: menuOpener
|
|
|
|
menu: menu.handle
|
|
}
|
|
|
|
Repeater {
|
|
model: menuOpener.children
|
|
|
|
CustomRect {
|
|
id: item
|
|
|
|
required property int index
|
|
required property QsMenuEntry modelData
|
|
|
|
color: modelData.isSeparator ? DynamicColors.palette.m3outlineVariant : "transparent"
|
|
implicitHeight: modelData.isSeparator ? 1 : children.implicitHeight
|
|
implicitWidth: menu.biggestWidth
|
|
radius: Appearance.rounding.full
|
|
visible: index !== (menuOpener.children.values.length - 1) ? true : (modelData.isSeparator ? false : true)
|
|
|
|
Loader {
|
|
id: children
|
|
|
|
active: !item.modelData.isSeparator
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
implicitHeight: 30
|
|
|
|
StateLayer {
|
|
function onClicked(): void {
|
|
const entry = item.modelData;
|
|
if (entry.hasChildren) {
|
|
menu.popouts.pushSubmenu(menu.level, entry, item, menu.biggestWidth);
|
|
} else {
|
|
entry.triggered();
|
|
menu.popouts.hasCurrent = false;
|
|
}
|
|
}
|
|
|
|
disabled: !item.modelData.enabled
|
|
radius: item.radius
|
|
}
|
|
|
|
Loader {
|
|
id: icon
|
|
|
|
active: item.modelData.icon !== ""
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 10
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
asynchronous: true
|
|
|
|
sourceComponent: Item {
|
|
implicitHeight: label.implicitHeight
|
|
implicitWidth: label.implicitHeight
|
|
|
|
IconImage {
|
|
id: iconImage
|
|
|
|
implicitSize: parent.implicitHeight
|
|
source: item.modelData.icon
|
|
visible: false
|
|
}
|
|
|
|
MultiEffect {
|
|
anchors.fill: iconImage
|
|
colorization: 1.0
|
|
colorizationColor: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
|
source: iconImage
|
|
}
|
|
}
|
|
}
|
|
|
|
CustomText {
|
|
id: label
|
|
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 10
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
|
text: labelMetrics.elidedText
|
|
}
|
|
|
|
TextMetrics {
|
|
id: labelMetrics
|
|
|
|
font.family: label.font.family
|
|
font.pointSize: label.font.pointSize
|
|
text: item.modelData.text
|
|
|
|
Component.onCompleted: {
|
|
var biggestWidth = menu.biggestWidth;
|
|
var currentWidth = labelMetrics.width + (item.modelData.icon ?? "" ? 30 : 0) + (item.modelData.hasChildren ? 30 : 0) + 20;
|
|
if (currentWidth > biggestWidth) {
|
|
menu.biggestWidth = currentWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: expand
|
|
|
|
active: item.modelData.hasChildren
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
asynchronous: true
|
|
|
|
sourceComponent: MaterialIcon {
|
|
color: item.modelData.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3outline
|
|
text: "chevron_right"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|