diff --git a/Modules/AudioWidget.qml b/Modules/AudioWidget.qml index 80efd85..d9031cb 100644 --- a/Modules/AudioWidget.qml +++ b/Modules/AudioWidget.qml @@ -29,7 +29,7 @@ Item { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter color: DynamicColors.tPalette.m3surfaceContainer - height: 22 + implicitHeight: root.parent.height - ((Appearance.padding.small - 1) * 2) radius: height / 2 } diff --git a/Modules/MediaWidget.qml b/Modules/MediaWidget.qml index 8b47a07..cbb67d2 100644 --- a/Modules/MediaWidget.qml +++ b/Modules/MediaWidget.qml @@ -25,7 +25,7 @@ Item { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: 22 + implicitHeight: root.parent.height - ((Appearance.padding.small - 1) * 2) radius: Appearance.rounding.full } diff --git a/Modules/Resource-old.qml b/Modules/Resource-old.qml new file mode 100644 index 0000000..3be26f9 --- /dev/null +++ b/Modules/Resource-old.qml @@ -0,0 +1,116 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Shapes +import qs.Components +import qs.Config + +Item { + id: root + + property color borderColor: warning ? DynamicColors.palette.m3onError : mainColor + required property color mainColor + required property double percentage + property bool shown: true + property color usageColor: warning ? DynamicColors.palette.m3error : mainColor + property bool warning: percentage * 100 >= warningThreshold + property int warningThreshold: 100 + + clip: true + implicitHeight: 22 + implicitWidth: resourceRowLayout.x < 0 ? 0 : resourceRowLayout.implicitWidth + visible: width > 0 && height > 0 + + Behavior on percentage { + NumberAnimation { + duration: 300 + easing.type: Easing.InOutQuad + } + } + + RowLayout { + id: resourceRowLayout + + spacing: 2 + x: shown ? 0 : -resourceRowLayout.width + + anchors { + verticalCenter: parent.verticalCenter + } + + Item { + Layout.alignment: Qt.AlignVCenter + implicitHeight: root.implicitHeight + implicitWidth: 14 + + Rectangle { + id: backgroundCircle + + anchors.centerIn: parent + border.color: "#404040" + border.width: 1 + color: "#40000000" + height: 14 + radius: height / 2 + width: 14 + } + + Shape { + anchors.fill: backgroundCircle + preferredRendererType: Shape.CurveRenderer + smooth: true + + ShapePath { + fillColor: root.usageColor + startX: backgroundCircle.width / 2 + startY: backgroundCircle.height / 2 + strokeWidth: 0 + + Behavior on fillColor { + CAnim { + } + } + + PathLine { + x: backgroundCircle.width / 2 + y: 0 + (1 / 2) + } + + PathAngleArc { + centerX: backgroundCircle.width / 2 + centerY: backgroundCircle.height / 2 + radiusX: backgroundCircle.width / 2 - (1 / 2) + radiusY: backgroundCircle.height / 2 - (1 / 2) + startAngle: -90 + sweepAngle: 360 * root.percentage + } + + PathLine { + x: backgroundCircle.width / 2 + y: backgroundCircle.height / 2 + } + } + + ShapePath { + capStyle: ShapePath.FlatCap + fillColor: "transparent" + strokeColor: root.borderColor + strokeWidth: 1 + + Behavior on strokeColor { + CAnim { + } + } + + PathAngleArc { + centerX: backgroundCircle.width / 2 + centerY: backgroundCircle.height / 2 + radiusX: backgroundCircle.width / 2 - (1 / 2) + radiusY: backgroundCircle.height / 2 - (1 / 2) + startAngle: -90 + sweepAngle: 360 * root.percentage + } + } + } + } + } +} diff --git a/Modules/Resource.qml b/Modules/Resource.qml index 3be26f9..20ae4de 100644 --- a/Modules/Resource.qml +++ b/Modules/Resource.qml @@ -7,110 +7,72 @@ import qs.Config Item { id: root + property color accentColor: DynamicColors.palette.m3primary + property real animatedPercentage: 0 + readonly property real arcStartAngle: 0.75 * Math.PI + readonly property real arcSweep: 1.5 * Math.PI property color borderColor: warning ? DynamicColors.palette.m3onError : mainColor + property string icon required property color mainColor required property double percentage property bool shown: true + property string subtitle + property string title property color usageColor: warning ? DynamicColors.palette.m3error : mainColor property bool warning: percentage * 100 >= warningThreshold property int warningThreshold: 100 clip: true - implicitHeight: 22 - implicitWidth: resourceRowLayout.x < 0 ? 0 : resourceRowLayout.implicitWidth + implicitHeight: root.parent.height + implicitWidth: root.parent.width + percentage: 0 visible: width > 0 && height > 0 - Behavior on percentage { - NumberAnimation { - duration: 300 - easing.type: Easing.InOutQuad - } - } + Canvas { + id: gaugeCanvas - RowLayout { - id: resourceRowLayout + anchors.centerIn: parent + height: width + width: Math.min(parent.width, parent.height) - spacing: 2 - x: shown ? 0 : -resourceRowLayout.width - - anchors { - verticalCenter: parent.verticalCenter + Component.onCompleted: requestPaint() + onPaint: { + const ctx = getContext("2d"); + ctx.reset(); + const cx = width / 2; + const cy = height / 2; + const radius = (Math.min(width, height) - 12) / 2; + const lineWidth = 3; + ctx.beginPath(); + ctx.arc(cx, cy, radius, root.arcStartAngle, root.arcStartAngle + root.arcSweep); + ctx.lineWidth = lineWidth; + ctx.lineCap = "round"; + ctx.strokeStyle = DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHigh, 2); + ctx.stroke(); + if (root.animatedPercentage > 0) { + ctx.beginPath(); + ctx.arc(cx, cy, radius, root.arcStartAngle, root.arcStartAngle + root.arcSweep * root.animatedPercentage); + ctx.lineWidth = lineWidth; + ctx.lineCap = "round"; + ctx.strokeStyle = root.accentColor; + ctx.stroke(); + } } - Item { - Layout.alignment: Qt.AlignVCenter - implicitHeight: root.implicitHeight - implicitWidth: 14 - - Rectangle { - id: backgroundCircle - - anchors.centerIn: parent - border.color: "#404040" - border.width: 1 - color: "#40000000" - height: 14 - radius: height / 2 - width: 14 + Connections { + function onAnimatedPercentageChanged() { + gaugeCanvas.requestPaint(); } - Shape { - anchors.fill: backgroundCircle - preferredRendererType: Shape.CurveRenderer - smooth: true + target: root + } - ShapePath { - fillColor: root.usageColor - startX: backgroundCircle.width / 2 - startY: backgroundCircle.height / 2 - strokeWidth: 0 - - Behavior on fillColor { - CAnim { - } - } - - PathLine { - x: backgroundCircle.width / 2 - y: 0 + (1 / 2) - } - - PathAngleArc { - centerX: backgroundCircle.width / 2 - centerY: backgroundCircle.height / 2 - radiusX: backgroundCircle.width / 2 - (1 / 2) - radiusY: backgroundCircle.height / 2 - (1 / 2) - startAngle: -90 - sweepAngle: 360 * root.percentage - } - - PathLine { - x: backgroundCircle.width / 2 - y: backgroundCircle.height / 2 - } - } - - ShapePath { - capStyle: ShapePath.FlatCap - fillColor: "transparent" - strokeColor: root.borderColor - strokeWidth: 1 - - Behavior on strokeColor { - CAnim { - } - } - - PathAngleArc { - centerX: backgroundCircle.width / 2 - centerY: backgroundCircle.height / 2 - radiusX: backgroundCircle.width / 2 - (1 / 2) - radiusY: backgroundCircle.height / 2 - (1 / 2) - startAngle: -90 - sweepAngle: 360 * root.percentage - } - } + Connections { + function onPaletteChanged() { + gaugeCanvas.requestPaint(); } + + target: DynamicColors } } } diff --git a/Modules/Resources.qml b/Modules/Resources.qml index 8707508..46d7ec2 100644 --- a/Modules/Resources.qml +++ b/Modules/Resources.qml @@ -14,15 +14,16 @@ Item { required property PersistentProperties visibilities + anchors.bottom: parent.bottom + anchors.top: parent.top clip: true - implicitHeight: 34 implicitWidth: rowLayout.implicitWidth + Appearance.padding.small * 2 CustomRect { id: backgroundRect color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: 22 + implicitHeight: root.parent.height - ((Appearance.padding.small - 1) * 2) radius: height / 2 anchors { diff --git a/Modules/UpdatesWidget.qml b/Modules/UpdatesWidget.qml index c0141a8..13bdc54 100644 --- a/Modules/UpdatesWidget.qml +++ b/Modules/UpdatesWidget.qml @@ -19,7 +19,7 @@ Item { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: 22 + implicitHeight: root.parent.height - ((Appearance.padding.small - 1) * 2) radius: height / 2 } diff --git a/Modules/Workspaces-old.qml b/Modules/Workspaces-old.qml deleted file mode 100644 index 36a4de3..0000000 --- a/Modules/Workspaces-old.qml +++ /dev/null @@ -1,128 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Effects -import Quickshell -import Quickshell.Hyprland -import qs.Config -import qs.Components - -Item { - id: itemRoot - - required property PanelWindow bar - - anchors.bottom: parent.bottom - anchors.top: parent.top - implicitWidth: workspacesRow.implicitWidth + 10 - - Behavior on implicitWidth { - NumberAnimation { - duration: MaterialEasing.expressiveEffectsTime - easing.bezierCurve: MaterialEasing.expressiveEffects - } - } - - Rectangle { - id: root - - property HyprlandMonitor monitor: Hyprland.monitorFor(itemRoot.bar?.screen) - - function shouldShow(monitor) { - Hyprland.refreshWorkspaces(); - Hyprland.refreshMonitors(); - if (monitor === root.monitor) { - return true; - } else { - return false; - } - } - - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - color: DynamicColors.tPalette.m3surfaceContainer - implicitHeight: 22 - radius: height / 2 - - Behavior on color { - CAnim { - } - } - - RowLayout { - id: workspacesRow - - anchors.left: parent.left - anchors.leftMargin: 6 - anchors.verticalCenter: parent.verticalCenter - spacing: 8 - - Repeater { - model: Hyprland.workspaces - - RowLayout { - id: workspaceIndicator - - required property var modelData - - visible: root.shouldShow(workspaceIndicator.modelData.monitor) - - CustomText { - color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant - font.pointSize: 12 - text: workspaceIndicator.modelData.name - visible: true - } - - Rectangle { - border.color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant - border.width: 1 - color: "transparent" - implicitHeight: 14 - implicitWidth: 14 - opacity: 1.0 - radius: height / 2 - scale: 1.0 - - Behavior on border.color { - ColorAnimation { - duration: 150 - easing.type: Easing.InOutQuad - } - } - NumberAnimation on opacity { - duration: 200 - from: 0.0 - to: 1.0 - } - NumberAnimation on scale { - duration: 300 - easing.type: Easing.OutBack - from: 0.0 - to: 1.0 - } - - CustomRect { - anchors.centerIn: parent - color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : "transparent" - implicitHeight: 8 - implicitWidth: 8 - radius: implicitHeight / 2 - } - - MouseArea { - anchors.fill: parent - - onClicked: { - workspaceIndicator.modelData.activate(); - } - } - } - } - } - } - } -} diff --git a/Modules/Workspaces.qml b/Modules/Workspaces.qml index ccf7db7..e444508 100644 --- a/Modules/Workspaces.qml +++ b/Modules/Workspaces.qml @@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls +import QtQuick.Effects import Quickshell import Quickshell.Hyprland import qs.Config @@ -14,7 +15,7 @@ Item { required property PanelWindow bar readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1 readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.bar.screen) - property int workspaceButtonWidth: rect.implicitHeight - root.activeWorkspaceMargin * 2 + property int workspaceButtonWidth: bgRect.implicitHeight - root.activeWorkspaceMargin * 2 property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown readonly property list workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor) readonly property int workspacesShown: workspaces.length @@ -29,7 +30,7 @@ Item { } CustomRect { - id: rect + id: bgRect anchors.left: parent.left anchors.right: parent.right @@ -80,17 +81,17 @@ Item { implicitHeight: indicator.indicatorThickness implicitWidth: indicator.indicatorThickness - width: workspaceButtonWidth + width: root.workspaceButtonWidth background: Item { id: workspaceButtonBackground - implicitHeight: workspaceButtonWidth - implicitWidth: workspaceButtonWidth + implicitHeight: root.workspaceButtonWidth + implicitWidth: root.workspaceButtonWidth CustomText { anchors.centerIn: parent - color: (root.effectiveActiveWorkspaceId === button.modelData.id) ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer + color: DynamicColors.palette.m3onSecondaryContainer elide: Text.ElideRight horizontalAlignment: Text.AlignHCenter text: button.modelData.name @@ -105,5 +106,92 @@ Item { } } } + + 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 + } } }