diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-04-28 00:21:53 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-04-28 00:21:53 +1000 |
| commit | cba440bcfced79eda2764e441c68239b6c594457 (patch) | |
| tree | 15e72a41a47015a1440a7c6b54c51d8f182ebe24 | |
| parent | hyprland: use qs hyprland service (diff) | |
| download | caelestia-shell-cba440bcfced79eda2764e441c68239b6c594457.tar.gz caelestia-shell-cba440bcfced79eda2764e441c68239b6c594457.tar.bz2 caelestia-shell-cba440bcfced79eda2764e441c68239b6c594457.zip | |
feat: anims + box padding
box provide padding and animate size and colour
provide box and boxlayout for with/without layout
provide clippingbox
provide label for anim + rendertype
configure QtQuick controls
| -rw-r--r-- | config/Appearance.qml | 18 | ||||
| -rw-r--r-- | config/BarConfig.qml | 13 | ||||
| -rw-r--r-- | modules/bar/ActiveWindow.qml | 10 | ||||
| -rw-r--r-- | modules/bar/Bar.qml | 41 | ||||
| -rw-r--r-- | modules/bar/Clock.qml | 6 | ||||
| -rw-r--r-- | modules/bar/OsIcon.qml | 14 | ||||
| -rw-r--r-- | modules/bar/Workspaces.qml | 66 | ||||
| -rw-r--r-- | shell.qml | 7 | ||||
| -rw-r--r-- | widgets/Box.qml | 90 | ||||
| -rw-r--r-- | widgets/BoxLayout.qml | 97 | ||||
| -rw-r--r-- | widgets/ClippingBox.qml | 87 | ||||
| -rw-r--r-- | widgets/ClippingBoxLayout.qml | 98 | ||||
| -rw-r--r-- | widgets/Label.qml | 16 | ||||
| -rw-r--r-- | widgets/MaterialIcon.qml | 2 |
14 files changed, 526 insertions, 39 deletions
diff --git a/config/Appearance.qml b/config/Appearance.qml index 8c441b1..263b653 100644 --- a/config/Appearance.qml +++ b/config/Appearance.qml @@ -54,6 +54,24 @@ Singleton { } } + readonly property QtObject anim: QtObject { + readonly property QtObject curves: QtObject { + readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1] + readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1] + readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1] + readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1] + readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1] + readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1] + } + + readonly property QtObject durations: QtObject { + readonly property int small: 200 + readonly property int normal: 400 + readonly property int large: 600 + readonly property int extraLarge: 1000 + } + } + readonly property QtObject colours: QtObject { property color primary: "#85D2E7" property color secondary: "#B2CBD3" diff --git a/config/BarConfig.qml b/config/BarConfig.qml new file mode 100644 index 0000000..a61e7cd --- /dev/null +++ b/config/BarConfig.qml @@ -0,0 +1,13 @@ +pragma Singleton + +import Quickshell +import QtQuick + +Singleton { + property bool vertical: false + + readonly property QtObject workspaces: QtObject { + property int shown: 10 + property string style: "" + } +} diff --git a/modules/bar/ActiveWindow.qml b/modules/bar/ActiveWindow.qml index f65a83f..f351534 100644 --- a/modules/bar/ActiveWindow.qml +++ b/modules/bar/ActiveWindow.qml @@ -5,17 +5,19 @@ import "root:/config" import QtQuick import QtQuick.Layouts -Box { +ClippingBoxLayout { id: root - property color colour: Appearance.colours.pink + readonly property color colour: Appearance.colours.pink + + animated: true MaterialIcon { Layout.alignment: Qt.AlignCenter - text: Icons.getAppCategoryIcon(Hyprland.activeClient?.wmClass) ?? "desktop_windows" + text: Icons.getAppCategoryIcon(Hyprland.activeClient?.class) ?? "desktop_windows" color: root.colour } - Text { + Label { Layout.alignment: Qt.AlignCenter text: Hyprland.activeClient?.title ?? "Desktop" diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index 5aa18f7..6e18f50 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -2,6 +2,7 @@ import "root:/widgets" import "root:/config" import Quickshell import Quickshell.Wayland +import QtQuick Variants { model: Quickshell.screens @@ -9,12 +10,13 @@ Variants { WlrLayershell { id: win - property var modelData - property bool vertical: false + required property ShellScreen modelData + readonly property bool vertical: BarConfig.vertical screen: modelData namespace: "caelestia-bar" - color: Appearance.alpha(Appearance.colours.base, false) + // color: Appearance.alpha(Appearance.colours.base, false) + color: "transparent" anchors { top: true @@ -23,25 +25,34 @@ Variants { bottom: vertical } - width: contents.implicitWidth + (vertical ? Appearance.padding.normal * 2 : 0) - height: contents.implicitHeight + (vertical ? 0 : Appearance.padding.smaller * 2) + width: contents.implicitWidth + height: contents.implicitHeight Box { id: contents - vertical: win.vertical - spacing: Appearance.spacing.larger - x: Appearance.padding.normal - y: vertical ? Appearance.padding.normal : Appearance.padding.smaller + padding: [Appearance.padding.normal, Appearance.padding.large, 0, Appearance.padding.large] - OsIcon {} - - Clock { + BoxLayout { vertical: win.vertical - } + spacing: Appearance.spacing.larger + padding: [Appearance.padding.smaller, Appearance.padding.large] + color: Appearance.alpha(Appearance.colours.base, false) + radius: Appearance.rounding.small - ActiveWindow { - vertical: win.vertical + OsIcon {} + + Clock { + vertical: win.vertical + } + + ActiveWindow { + vertical: win.vertical + } + + // Workspaces { + // vertical: win.vertical + // } } } } diff --git a/modules/bar/Clock.qml b/modules/bar/Clock.qml index 4c743a6..2332f29 100644 --- a/modules/bar/Clock.qml +++ b/modules/bar/Clock.qml @@ -4,9 +4,9 @@ import "root:/config" import QtQuick import QtQuick.Layouts -Box { +BoxLayout { id: root - property color colour: Appearance.colours.peach + readonly property color colour: Appearance.colours.peach MaterialIcon { Layout.alignment: Qt.AlignCenter @@ -14,7 +14,7 @@ Box { color: root.colour } - Text { + Label { Layout.alignment: Qt.AlignCenter horizontalAlignment: Text.AlignJustify diff --git a/modules/bar/OsIcon.qml b/modules/bar/OsIcon.qml index 1737814..62ff5e6 100644 --- a/modules/bar/OsIcon.qml +++ b/modules/bar/OsIcon.qml @@ -5,11 +5,13 @@ import "root:/config" import QtQuick import QtQuick.Layouts -Text { - Layout.alignment: Qt.AlignCenter +Box { + Label { + Layout.alignment: Qt.AlignCenter - text: Icons.osIcon - font.pointSize: Appearance.font.size.smaller - font.family: Appearance.font.family.mono - color: Appearance.colours.yellow + text: Icons.osIcon + font.pointSize: Appearance.font.size.smaller + font.family: Appearance.font.family.mono + color: Appearance.colours.yellow + } } diff --git a/modules/bar/Workspaces.qml b/modules/bar/Workspaces.qml new file mode 100644 index 0000000..73995c8 --- /dev/null +++ b/modules/bar/Workspaces.qml @@ -0,0 +1,66 @@ +pragma ComponentBehavior: Bound + +import "root:/widgets" +import "root:/services" +import "root:/config" +import Quickshell +import QtQuick +import QtQuick.Layouts + +Item { + property alias vertical: root.vertical + + implicitWidth: root.implicitWidth + implicitHeight: root.implicitHeight + + Box { + id: root + + readonly property color colour: Appearance.colours.mauve + + // homogenous: true + + Repeater { + model: BarConfig.workspaces.shown + + Label { + required property int index + + text: (index + 1).toString() + color: root.colour + } + } + + // Text { + // Layout.alignment: Qt.AlignCenter + // horizontalAlignment: Text.AlignJustify + + // text: root.vertical ? Time.format("hh\nmm") : Time.format("dd/MM/yy hh:mm") + // font.pointSize: Appearance.font.size.smaller + // font.family: Appearance.font.family.mono + // color: root.colour + // } + } + + Rectangle { + x: (root.childrenRect.width / BarConfig.workspaces.shown) * ((Hyprland.activeWorkspace?.id ?? 1) - 1) + y: 0 + width: root.childrenRect.width / BarConfig.workspaces.shown + height: root.childrenRect.height + color: "red" + radius: 1000 + + // layer.enabled: true + // layer.effect: ShaderEffect { + // readonly property Item source: root + // fragmentShader: ` + // varying highp vec2 qt_TexCoord0; + // uniform highp vec4 color; + // uniform sampler2D source; + // void main() { + // gl_FragColor = color * (1.0 - texture2D(source, qt_TexCoord0).w); + // } + // ` + // } + } +} @@ -1,6 +1,13 @@ import "modules/bar" +import "config" import Quickshell +import QtQuick.Controls.Material ShellRoot { + Material.accent: Appearance.colours.primary + Material.primary: Appearance.colours.secondary + Material.foreground: Appearance.colours.text + Material.background: Appearance.colours.base + Bar {} } diff --git a/widgets/Box.qml b/widgets/Box.qml index c0d7f06..536469e 100644 --- a/widgets/Box.qml +++ b/widgets/Box.qml @@ -1,16 +1,86 @@ import "root:/config" -import QtQuick.Layouts +import QtQuick + +Rectangle { + id: root -GridLayout { property bool vertical: false - property real spacing: Appearance.spacing.small property bool homogenous: false + property bool animated: false + property int spacing: Appearance.spacing.small + property var padding: 0 + + readonly property int paddingTop: getRealPadding().top + readonly property int paddingRight: getRealPadding().right + readonly property int paddingBottom: getRealPadding().bottom + readonly property int paddingLeft: getRealPadding().left + readonly property int paddingX: getRealPadding().x + readonly property int paddingY: getRealPadding().y + + color: "transparent" + + implicitWidth: childrenRect.width + paddingX + implicitHeight: childrenRect.height + paddingY + + function getRealPadding() { + const pad = {}; + + if (Array.isArray(padding)) { + if (padding.length === 2) { + pad.top = pad.bottom = padding[0]; + pad.left = pad.right = padding[1]; + } else if (padding.length === 3) { + pad.top = padding[0]; + pad.left = pad.right = padding[1]; + pad.bottom = padding[2]; + } else if (padding.length === 4) { + pad.top = padding[0]; + pad.right = padding[1]; + pad.bottom = padding[2]; + pad.left = padding[3]; + } + } else { + pad.top = pad.bottom = pad.left = pad.right = padding; + } + + pad.x = pad.left + pad.right; + pad.y = pad.top + pad.bottom; + + return pad; + } + + onChildrenChanged: { + for (const child of children) { + child.x = Qt.binding(() => paddingLeft); + child.y = Qt.binding(() => paddingTop); + } + } + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + + Behavior on implicitWidth { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + + Behavior on implicitHeight { + enabled: root.animated - flow: vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - uniformCellWidths: homogenous && vertical - uniformCellHeights: homogenous && !vertical - rows: vertical ? -1 : 1 - columns: vertical ? 1 : -1 - rowSpacing: spacing - columnSpacing: spacing + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } } diff --git a/widgets/BoxLayout.qml b/widgets/BoxLayout.qml new file mode 100644 index 0000000..12aa4f7 --- /dev/null +++ b/widgets/BoxLayout.qml @@ -0,0 +1,97 @@ +import "root:/config" +import QtQuick +import QtQuick.Layouts + +Rectangle { + id: root + + property bool vertical: false + property bool homogenous: false + property bool animated: false + property int spacing: Appearance.spacing.small + property var padding: 0 + + readonly property int paddingTop: getRealPadding().top + readonly property int paddingRight: getRealPadding().right + readonly property int paddingBottom: getRealPadding().bottom + readonly property int paddingLeft: getRealPadding().left + readonly property int paddingX: getRealPadding().x + readonly property int paddingY: getRealPadding().y + + color: "transparent" + + implicitWidth: layout.implicitWidth + paddingX + implicitHeight: layout.implicitHeight + paddingY + + function getRealPadding() { + const pad = {}; + + if (Array.isArray(padding)) { + if (padding.length === 2) { + pad.top = pad.bottom = padding[0]; + pad.left = pad.right = padding[1]; + } else if (padding.length === 3) { + pad.top = padding[0]; + pad.left = pad.right = padding[1]; + pad.bottom = padding[2]; + } else if (padding.length === 4) { + pad.top = padding[0]; + pad.right = padding[1]; + pad.bottom = padding[2]; + pad.left = padding[3]; + } + } else { + pad.top = pad.bottom = pad.left = pad.right = padding; + } + + pad.x = pad.left + pad.right; + pad.y = pad.top + pad.bottom; + + return pad; + } + + default property alias children: layout.children + + GridLayout { + id: layout + + x: root.paddingLeft + y: root.paddingTop + + flow: root.vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight + uniformCellWidths: root.homogenous || root.vertical + uniformCellHeights: root.homogenous || !root.vertical + rows: root.vertical ? -1 : 1 + columns: root.vertical ? 1 : -1 + rowSpacing: root.spacing + columnSpacing: root.spacing + } + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + + Behavior on implicitWidth { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + + Behavior on implicitHeight { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } +} diff --git a/widgets/ClippingBox.qml b/widgets/ClippingBox.qml new file mode 100644 index 0000000..1ced873 --- /dev/null +++ b/widgets/ClippingBox.qml @@ -0,0 +1,87 @@ +import "root:/config" +import Quickshell.Widgets +import QtQuick + +ClippingRectangle { + id: root + + property bool vertical: false + property bool homogenous: false + property bool animated: false + property int spacing: Appearance.spacing.small + property var padding: 0 + + readonly property int paddingTop: getRealPadding().top + readonly property int paddingRight: getRealPadding().right + readonly property int paddingBottom: getRealPadding().bottom + readonly property int paddingLeft: getRealPadding().left + readonly property int paddingX: getRealPadding().x + readonly property int paddingY: getRealPadding().y + + color: "transparent" + + implicitWidth: childrenRect.width + paddingX + implicitHeight: childrenRect.height + paddingY + + function getRealPadding() { + const pad = {}; + + if (Array.isArray(padding)) { + if (padding.length === 2) { + pad.top = pad.bottom = padding[0]; + pad.left = pad.right = padding[1]; + } else if (padding.length === 3) { + pad.top = padding[0]; + pad.left = pad.right = padding[1]; + pad.bottom = padding[2]; + } else if (padding.length === 4) { + pad.top = padding[0]; + pad.right = padding[1]; + pad.bottom = padding[2]; + pad.left = padding[3]; + } + } else { + pad.top = pad.bottom = pad.left = pad.right = padding; + } + + pad.x = pad.left + pad.right; + pad.y = pad.top + pad.bottom; + + return pad; + } + + onChildrenChanged: { + for (const child of children) { + child.x = Qt.binding(() => paddingLeft); + child.y = Qt.binding(() => paddingTop); + } + } + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + + Behavior on implicitWidth { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + + Behavior on implicitHeight { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } +} diff --git a/widgets/ClippingBoxLayout.qml b/widgets/ClippingBoxLayout.qml new file mode 100644 index 0000000..2b22c8c --- /dev/null +++ b/widgets/ClippingBoxLayout.qml @@ -0,0 +1,98 @@ +import "root:/config" +import Quickshell.Widgets +import QtQuick +import QtQuick.Layouts + +ClippingRectangle { + id: root + + property bool vertical: false + property bool homogenous: false + property bool animated: false + property int spacing: Appearance.spacing.small + property var padding: 0 + + readonly property int paddingTop: getRealPadding().top + readonly property int paddingRight: getRealPadding().right + readonly property int paddingBottom: getRealPadding().bottom + readonly property int paddingLeft: getRealPadding().left + readonly property int paddingX: getRealPadding().x + readonly property int paddingY: getRealPadding().y + + color: "transparent" + + implicitWidth: layout.implicitWidth + paddingX + implicitHeight: layout.implicitHeight + paddingY + + function getRealPadding() { + const pad = {}; + + if (Array.isArray(padding)) { + if (padding.length === 2) { + pad.top = pad.bottom = padding[0]; + pad.left = pad.right = padding[1]; + } else if (padding.length === 3) { + pad.top = padding[0]; + pad.left = pad.right = padding[1]; + pad.bottom = padding[2]; + } else if (padding.length === 4) { + pad.top = padding[0]; + pad.right = padding[1]; + pad.bottom = padding[2]; + pad.left = padding[3]; + } + } else { + pad.top = pad.bottom = pad.left = pad.right = padding; + } + + pad.x = pad.left + pad.right; + pad.y = pad.top + pad.bottom; + + return pad; + } + + default property alias children: layout.children + + GridLayout { + id: layout + + x: root.paddingLeft + y: root.paddingTop + + flow: root.vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight + uniformCellWidths: root.homogenous || root.vertical + uniformCellHeights: root.homogenous || !root.vertical + rows: root.vertical ? -1 : 1 + columns: root.vertical ? 1 : -1 + rowSpacing: root.spacing + columnSpacing: root.spacing + } + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + + Behavior on implicitWidth { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + + Behavior on implicitHeight { + enabled: root.animated + + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } +} diff --git a/widgets/Label.qml b/widgets/Label.qml new file mode 100644 index 0000000..e1e22ba --- /dev/null +++ b/widgets/Label.qml @@ -0,0 +1,16 @@ +import "root:/config" +import QtQuick + +Text { + id: root + + renderType: Text.NativeRendering + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } +} diff --git a/widgets/MaterialIcon.qml b/widgets/MaterialIcon.qml index 0115abf..55e6b99 100644 --- a/widgets/MaterialIcon.qml +++ b/widgets/MaterialIcon.qml @@ -1,7 +1,7 @@ import "root:/config" import QtQuick -Text { +Label { font.family: Appearance.font.family.material font.pointSize: Appearance.font.size.larger } |