Files
dots-hyprland/.config/quickshell/modules/bar/Workspaces.qml
T
2025-04-11 00:05:34 +02:00

196 lines
6.5 KiB
QML

import "../common"
import "../common/widgets"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
Rectangle {
required property var bar
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen)
readonly property list<bool> workspaceOccupied: []
readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / ConfigOptions.bar.workspacesShown)
property int widgetPadding: 4
property int workspaceButtonWidth: 26
property int activeWorkspaceMargin: 1
property double animatedActiveWorkspaceIndex: (monitor.activeWorkspace?.id - 1) % ConfigOptions.bar.workspacesShown
Behavior on animatedActiveWorkspaceIndex {
NumberAnimation {
duration: Appearance.animation.menuDecel.duration
easing.type: Appearance.animation.menuDecel.type
}
}
// Function to update workspaceOccupied
function updateWorkspaceOccupied() {
workspaceOccupied = Array.from({ length: ConfigOptions.bar.workspacesShown }, (_, i) => {
return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * ConfigOptions.bar.workspacesShown + i + 1);
});
}
// Initialize workspaceOccupied when the component is created
Component.onCompleted: updateWorkspaceOccupied()
// Listen for changes in Hyprland.workspaces.values
Connections {
target: Hyprland.workspaces
function onValuesChanged() {
updateWorkspaceOccupied();
}
}
Layout.fillHeight: true
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
implicitHeight: 40
color: "transparent"
// Background
Rectangle {
z: 0
anchors.centerIn: parent
implicitHeight: 32
implicitWidth: rowLayout.implicitWidth + widgetPadding * 2
radius: Appearance.rounding.small
color: Appearance.colors.colLayer1
}
// Scroll to switch workspaces
WheelHandler {
onWheel: (event) => {
if (event.angleDelta.y < 0)
Hyprland.dispatch(`workspace r+1`);
else if (event.angleDelta.y > 0)
Hyprland.dispatch(`workspace r-1`);
}
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
}
// Workspaces - background
RowLayout {
id: rowLayout
z: 1
spacing: 0
anchors.fill: parent
implicitHeight: 40
Repeater {
model: ConfigOptions.bar.workspacesShown
Rectangle {
z: 1
implicitWidth: workspaceButtonWidth
implicitHeight: workspaceButtonWidth
radius: Appearance.rounding.full
property var radiusLeft: workspaceOccupied[index-1] ? 0 : Appearance.rounding.full
property var radiusRight: workspaceOccupied[index+1] ? 0 : Appearance.rounding.full
topLeftRadius: radiusLeft
bottomLeftRadius: radiusLeft
topRightRadius: radiusRight
bottomRightRadius: radiusRight
color: Appearance.colors.colLayer2
opacity: workspaceOccupied[index] ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
Behavior on radiusLeft {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
Behavior on radiusRight {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
}
}
}
// Active workspace
Rectangle {
z: 2
implicitWidth: workspaceButtonWidth - activeWorkspaceMargin * 2
implicitHeight: workspaceButtonWidth - activeWorkspaceMargin * 2
radius: Appearance.rounding.full
color: Appearance.m3colors.m3primary
anchors.verticalCenter: parent.verticalCenter
x: animatedActiveWorkspaceIndex * workspaceButtonWidth + activeWorkspaceMargin
}
// Workspaces - numbers
RowLayout {
id: rowLayoutNumbers
z: 3
spacing: 0
anchors.fill: parent
implicitHeight: 40
Repeater {
model: ConfigOptions.bar.workspacesShown
Button {
id: button
Layout.fillHeight: true
onPressed: Hyprland.dispatch(`workspace ${index+1}`)
width: workspaceButtonWidth
contentItem: StyledText {
z: 3
property int workspaceValue: workspaceGroup * ConfigOptions.bar.workspacesShown + index + 1
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pointSize: Appearance.font.pointSize.small
text: `${workspaceValue}`
elide: Text.ElideRight
color: (monitor.activeWorkspace?.id == workspaceValue) ? Appearance.m3colors.m3onPrimary : (workspaceOccupied[index] ? Appearance.colors.colOnLayer1 : Appearance.colors.colOnLayer1Inactive)
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
}
background: Rectangle {
color: "transparent" // Transparent background
implicitWidth: workspaceButtonWidth
implicitHeight: workspaceButtonWidth
}
}
}
}
}