198 lines
4.5 KiB
QML
198 lines
4.5 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Effects
|
|
import Quickshell
|
|
import Quickshell.Hyprland
|
|
import qs.Config
|
|
import qs.Components
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property real activeWorkspaceMargin: Math.ceil(Appearance.padding.small / 2)
|
|
required property PanelWindow bar
|
|
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
|
|
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.bar.screen)
|
|
property int workspaceButtonWidth: bgRect.implicitHeight - root.activeWorkspaceMargin * 2
|
|
property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown
|
|
readonly property list<var> workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor)
|
|
readonly property int workspacesShown: workspaces.length
|
|
|
|
anchors.bottom: parent.bottom
|
|
anchors.top: parent.top
|
|
implicitWidth: (root.workspaceButtonWidth * root.workspacesShown) + root.activeWorkspaceMargin * 2
|
|
|
|
Behavior on implicitWidth {
|
|
Anim {
|
|
}
|
|
}
|
|
|
|
CustomRect {
|
|
id: bgRect
|
|
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: DynamicColors.tPalette.m3surfaceContainer
|
|
implicitHeight: root.parent.height - ((Appearance.padding.small - 1) * 2)
|
|
radius: height / 2
|
|
|
|
CustomRect {
|
|
id: indicator
|
|
|
|
property real indicatorLength: (Math.abs(idxPair.idx1 - idxPair.idx2) + 1) * root.workspaceButtonWidth
|
|
property real indicatorPosition: Math.min(idxPair.idx1, idxPair.idx2) * root.workspaceButtonWidth + root.activeWorkspaceMargin
|
|
property real indicatorThickness: root.workspaceButtonWidth
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: DynamicColors.palette.m3primary
|
|
implicitHeight: indicatorThickness
|
|
implicitWidth: indicatorLength
|
|
radius: Appearance.rounding.full
|
|
x: indicatorPosition
|
|
z: 2
|
|
|
|
AnimatedTabIndexPair {
|
|
id: idxPair
|
|
|
|
index: root.workspaces.findIndex(w => w.active)
|
|
}
|
|
}
|
|
|
|
Grid {
|
|
anchors.fill: parent
|
|
anchors.margins: root.activeWorkspaceMargin
|
|
columnSpacing: 0
|
|
columns: root.workspacesShown
|
|
rowSpacing: 0
|
|
rows: 1
|
|
z: 3
|
|
|
|
Repeater {
|
|
model: root.workspaces
|
|
|
|
Button {
|
|
id: button
|
|
|
|
required property int index
|
|
required property HyprlandWorkspace modelData
|
|
|
|
implicitHeight: indicator.indicatorThickness
|
|
implicitWidth: indicator.indicatorThickness
|
|
width: root.workspaceButtonWidth
|
|
|
|
background: Item {
|
|
id: workspaceButtonBackground
|
|
|
|
implicitHeight: root.workspaceButtonWidth
|
|
implicitWidth: root.workspaceButtonWidth
|
|
|
|
CustomText {
|
|
anchors.centerIn: parent
|
|
color: DynamicColors.palette.m3onSecondaryContainer
|
|
elide: Text.ElideRight
|
|
horizontalAlignment: Text.AlignHCenter
|
|
text: button.modelData.name
|
|
verticalAlignment: Text.AlignVCenter
|
|
z: 3
|
|
}
|
|
}
|
|
|
|
onPressed: {
|
|
Hyprland.dispatch(`workspace ${button.modelData.name}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: activeTextSource
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: root.activeWorkspaceMargin
|
|
layer.enabled: true
|
|
visible: false
|
|
z: 4
|
|
|
|
Grid {
|
|
anchors.fill: parent
|
|
columnSpacing: 0
|
|
columns: root.workspacesShown
|
|
rowSpacing: 0
|
|
rows: 1
|
|
|
|
Repeater {
|
|
model: root.workspaces
|
|
|
|
Item {
|
|
id: activeWorkspace
|
|
|
|
required property int index
|
|
required property HyprlandWorkspace modelData
|
|
|
|
implicitHeight: indicator.indicatorThickness
|
|
implicitWidth: indicator.indicatorThickness
|
|
width: root.workspaceButtonWidth
|
|
|
|
CustomText {
|
|
anchors.centerIn: parent
|
|
color: DynamicColors.palette.m3onPrimary
|
|
elide: Text.ElideRight
|
|
horizontalAlignment: Text.AlignHCenter
|
|
text: activeWorkspace.modelData.name
|
|
verticalAlignment: Text.AlignVCenter
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ShaderEffectSource {
|
|
id: activeTextTex
|
|
|
|
anchors.fill: bgRect
|
|
anchors.margins: root.activeWorkspaceMargin
|
|
hideSource: true
|
|
live: true
|
|
recursive: true
|
|
sourceItem: activeTextSource
|
|
}
|
|
|
|
Item {
|
|
id: indicatorMask
|
|
|
|
anchors.fill: bgRect
|
|
visible: false
|
|
|
|
CustomRect {
|
|
color: "white"
|
|
height: indicator.height
|
|
radius: indicator.radius
|
|
width: indicator.width
|
|
x: indicator.x
|
|
y: indicator.y
|
|
}
|
|
}
|
|
|
|
ShaderEffectSource {
|
|
id: indicatorMaskEffect
|
|
|
|
anchors.fill: activeTextSource
|
|
live: true
|
|
sourceItem: indicatorMask
|
|
visible: false
|
|
}
|
|
|
|
MultiEffect {
|
|
anchors.fill: activeTextSource
|
|
maskEnabled: true
|
|
maskInverted: false
|
|
maskSource: indicatorMaskEffect
|
|
source: activeTextTex
|
|
z: 5
|
|
}
|
|
}
|
|
}
|