forked from Shinonome/dots-hyprland
the perfect workspace indicator
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
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
|
||||
// color: workspaceOccupied[index] ? Appearance.colors.colLayer2 : "transparent"
|
||||
|
||||
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
|
||||
topInset: 7
|
||||
bottomInset: 7
|
||||
onPressed: Hyprland.dispath(`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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user