diff --git a/Components/MarqueeText.qml b/Components/MarqueeText.qml index b17c1c6..7d3d12d 100644 --- a/Components/MarqueeText.qml +++ b/Components/MarqueeText.qml @@ -18,13 +18,14 @@ Item { property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle property int leftFadeWidth: 28 property bool marqueeEnabled: true - readonly property bool overflowing: metrics.width > root.width + readonly property bool overflowing: metrics.width > content.width property int pauseMs: 1200 property real pixelsPerSecond: 40 property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle property int rightFadeWidth: 28 property bool sliding: false property alias text: elideText.text + property bool vertical: false function durationForDistance(px): int { return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000)); @@ -42,7 +43,8 @@ Item { } clip: false - implicitHeight: elideText.implicitHeight + implicitHeight: vertical ? elideText.implicitWidth : elideText.implicitHeight + implicitWidth: vertical ? elideText.implicitHeight : elideText.implicitWidth Behavior on leftFadeStrength { Anim { @@ -53,171 +55,187 @@ Item { } } + onHeightChanged: resetMarquee() onTextChanged: resetMarquee() + onVerticalChanged: resetMarquee() onVisibleChanged: if (!visible) resetMarquee() onWidthChanged: resetMarquee() - TextMetrics { - id: metrics - - font: elideText.font - text: elideText.text - } - - CustomText { - id: elideText - - anchors.verticalCenter: parent.verticalCenter - animate: root.animate - animateProp: "scale,opacity" - color: root.color - elide: Text.ElideNone - visible: !root.overflowing - width: root.width - } - Item { - id: marqueeViewport + id: content - anchors.fill: parent - clip: false - layer.enabled: true - visible: root.overflowing + anchors.centerIn: parent + height: root.vertical ? root.width : root.height + width: root.vertical ? root.height : root.width - layer.effect: OpacityMask { - maskSource: rightFadeMask + transform: Rotation { + angle: root.vertical ? -90 : 0 + origin.x: content.width / 2 + origin.y: content.height / 2 + } + + TextMetrics { + id: metrics + + font: elideText.font + text: elideText.text + } + + CustomText { + id: elideText + + anchors.verticalCenter: parent.verticalCenter + animate: root.animate + animateProp: "scale,opacity" + color: root.color + elide: Text.ElideNone + visible: !root.overflowing + width: content.width } Item { - id: strip + id: marqueeViewport - anchors.verticalCenter: parent.verticalCenter - height: t1.implicitHeight - width: t1.width + root.gap + t2.width - x: 0 + anchors.fill: parent + clip: false + layer.enabled: true + visible: root.overflowing - CustomText { - id: t1 - - animate: root.animate - animateProp: "opacity" - color: root.color - font.pointSize: elideText.font.pointSize - text: elideText.text + layer.effect: OpacityMask { + maskSource: rightFadeMask } - CustomText { - id: t2 + Item { + id: strip - animate: root.animate - animateProp: "opacity" - color: root.color - font.pointSize: elideText.font.pointSize - text: t1.text - x: t1.width + root.gap - } - } + anchors.verticalCenter: parent.verticalCenter + height: t1.implicitHeight + width: t1.width + root.gap + t2.width + x: 0 - SequentialAnimation { - id: marqueeAnim + CustomText { + id: t1 - running: false + animate: root.animate + animateProp: "opacity" + color: root.color + font.pointSize: elideText.font.pointSize + text: elideText.text + } - onFinished: pauseTimer.restart() + CustomText { + id: t2 - ScriptAction { - script: { - root.sliding = true; - root.leftFadeEnabled = true; + animate: root.animate + animateProp: "opacity" + color: root.color + font.pointSize: elideText.font.pointSize + text: t1.text + x: t1.width + root.gap } } - Anim { - duration: root.durationForDistance(t1.width) - easing.bezierCurve: Easing.Linear - easing.type: Easing.Linear - from: 0 - property: "x" - target: strip - to: -t1.width - } + SequentialAnimation { + id: marqueeAnim - ScriptAction { - script: { - root.leftFadeEnabled = false; + running: false + + onFinished: pauseTimer.restart() + + ScriptAction { + script: { + root.sliding = true; + root.leftFadeEnabled = true; + } + } + + Anim { + duration: root.durationForDistance(t1.width) + easing.bezierCurve: Easing.Linear + easing.type: Easing.Linear + from: 0 + property: "x" + target: strip + to: -t1.width + } + + ScriptAction { + script: { + root.leftFadeEnabled = false; + } + } + + Anim { + duration: root.durationForDistance(root.gap) + easing.bezierCurve: Easing.Linear + easing.type: Easing.Linear + from: -t1.width + property: "x" + target: strip + to: -(t1.width + root.gap) + } + + ScriptAction { + script: { + root.sliding = false; + strip.x = 0; + } } } - Anim { - duration: root.durationForDistance(root.gap) - easing.bezierCurve: Easing.Linear - easing.type: Easing.Linear - from: -t1.width - property: "x" - target: strip - to: -(t1.width + root.gap) - } + Timer { + id: pauseTimer - ScriptAction { - script: { - root.sliding = false; - strip.x = 0; + interval: root.pauseMs + repeat: false + running: true + + onTriggered: { + if (root.marqueeEnabled) + marqueeAnim.start(); } } } - Timer { - id: pauseTimer + Rectangle { + id: rightFadeMask - interval: root.pauseMs - repeat: false - running: true - - onTriggered: { - if (root.marqueeEnabled) - marqueeAnim.start(); + readonly property real fadeStartPos: { + const w = Math.max(1, width); + return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w)); } - } - } - - Rectangle { - id: rightFadeMask - - readonly property real fadeStartPos: { - const w = Math.max(1, width); - return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w)); - } - readonly property real leftFadeEndPos: { - const w = Math.max(1, width); - return Math.max(0, Math.min(1, root.leftFadeWidth / w)); - } - - anchors.fill: marqueeViewport - layer.enabled: true - visible: false - - gradient: Gradient { - orientation: Gradient.Horizontal - - GradientStop { - color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength) - position: 0.0 + readonly property real leftFadeEndPos: { + const w = Math.max(1, width); + return Math.max(0, Math.min(1, root.leftFadeWidth / w)); } - GradientStop { - color: Qt.rgba(1, 1, 1, 1.0) - position: rightFadeMask.leftFadeEndPos - } + anchors.fill: marqueeViewport + layer.enabled: true + visible: false - GradientStop { - color: Qt.rgba(1, 1, 1, 1.0) - position: rightFadeMask.fadeStartPos - } + gradient: Gradient { + orientation: Gradient.Horizontal - GradientStop { - color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength) - position: 1.0 + GradientStop { + color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength) + position: 0.0 + } + + GradientStop { + color: Qt.rgba(1, 1, 1, 1.0) + position: rightFadeMask.leftFadeEndPos + } + + GradientStop { + color: Qt.rgba(1, 1, 1, 1.0) + position: rightFadeMask.fadeStartPos + } + + GradientStop { + color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength) + position: 1.0 + } } } } diff --git a/Drawers/Panels.qml b/Drawers/Panels.qml index 630582e..66827ad 100644 --- a/Drawers/Panels.qml +++ b/Drawers/Panels.qml @@ -53,8 +53,9 @@ Item { Item { id: resourcesWrapper + anchors.bottom: root.geometry.position === "bottom" ? parent.bottom : undefined anchors.left: parent.left - anchors.top: parent.top + anchors.top: root.geometry.position !== "bottom" ? parent.top : undefined clip: true implicitHeight: root.geometry.horizontal ? resources.implicitHeight * (1 - resources.offsetScale) : resources.implicitHeight implicitWidth: root.geometry.horizontal ? resources.implicitWidth : resources.implicitWidth * (1 - resources.offsetScale) @@ -62,9 +63,7 @@ Item { Resources.Wrapper { id: resources - anchors.left: parent.left - anchors.top: parent.top - horizontal: root.geometry.horizontal + position: root.geometry.position visibilities: root.visibilities } } @@ -169,8 +168,8 @@ Item { Dashboard.Wrapper { id: dashboard - horizontal: root.geometry.horizontal offsetScale: dashboardWrapper.offsetScale + position: root.geometry.position visibilities: root.visibilities } } diff --git a/Drawers/Windows.qml b/Drawers/Windows.qml index 4eab93f..dc118cc 100644 --- a/Drawers/Windows.qml +++ b/Drawers/Windows.qml @@ -221,7 +221,7 @@ CustomWindow { panel: panels.dashboardWrapper radius: Tokens.rounding.normal x: panels.dashboardWrapper.x + panels.dashboard.x + geometry.insetLeft(root.borderThickness) - (geometry.horizontal ? 0 : panels.dashboard.width * extraExtent) - y: panels.dashboardWrapper.y + panels.dashboard.y + geometry.insetTop(root.borderThickness) - (geometry.horizontal ? panels.dashboard.height * extraExtent : 0) + y: panels.dashboardWrapper.y + panels.dashboard.y + geometry.insetTop(root.borderThickness) - (geometry.horizontal && geometry.position !== "bottom" ? panels.dashboard.height * extraExtent : 0) } PanelBg { diff --git a/Modules/Bar/BarLoader.qml b/Modules/Bar/BarLoader.qml index 6429b13..2243ad7 100644 --- a/Modules/Bar/BarLoader.qml +++ b/Modules/Bar/BarLoader.qml @@ -10,7 +10,7 @@ Item { id: root readonly property int clampedExtent: Math.max(Config.bar.border, extent) - readonly property int contentThickness: Math.max(Config.bar.height, Tokens.bar.innerSize) + padding * 2 + readonly property int contentThickness: Math.floor(Math.max(Config.bar.height, Tokens.bar.innerSize * (horizontal ? 1 : 1.5))) + padding * 2 readonly property int exclusiveZone: Config.bar.autoHide ? Config.bar.border : contentThickness property real extent: fullscreen ? 0 : Config.bar.border required property bool fullscreen diff --git a/Modules/Bar/Components/Clock.qml b/Modules/Bar/Components/Clock.qml index 3c86067..0125670 100644 --- a/Modules/Bar/Components/Clock.qml +++ b/Modules/Bar/Components/Clock.qml @@ -1,58 +1,154 @@ +pragma ComponentBehavior: Bound + import Quickshell import QtQuick import QtQuick.Layouts import ZShell.Config import qs.Modules.Bar.Popouts +import qs.Modules.Bar.Components.Common import qs.Helpers import qs.Components import qs.Services -CustomRect { +WidgetBase { id: root - required property bool horizontal + readonly property color contentColor: visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface + readonly property string effectiveFormat: { + let fmt = Config.general.dateFormat; + if (!root.horizontal) + fmt = fmt.replace("dddd", "ddd"); + return fmt; + } + readonly property var formatParts: { + const segments = root.effectiveFormat.split(" - "); + let datePart = ""; + let timePart = ""; + + if (segments.length > 1) { + datePart = segments[0]; + timePart = segments[1]; + } else if (/[hms]/.test(segments[0])) { + timePart = segments[0]; + } else { + datePart = segments[0]; + } + + const dateTokens = datePart.trim().length ? datePart.trim().split(/\s+/) : []; + const timeTokens = timePart.trim().length ? timePart.trim().split(":") : []; + + return { + dateTokens: dateTokens, + timeTokens: timeTokens + }; + } required property GridLayout loader required property Wrapper popouts - readonly property real shortSize: Math.max(Config.bar.height, Tokens.bar.innerSize) - readonly property real size: timeText.contentWidth + (horizontal ? Tokens.padding.normal : Tokens.padding.larger) * 2 + readonly property real size: horizontal ? timeText.contentWidth + Tokens.padding.normal * 2 : verticalColumn.implicitHeight + Tokens.padding.larger * 2 required property PersistentProperties visibilities color: visibilities.dashboard ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? shortSize : size - implicitWidth: horizontal ? size : shortSize + implicitHeight: horizontal ? baseSize : size + implicitWidth: horizontal ? size : baseSize radius: Tokens.rounding.full CustomText { id: timeText anchors.centerIn: parent - // anchors.horizontalCenter: root.horizontal ? undefined : parent.horizontalCenter - // anchors.verticalCenter: root.horizontal ? parent.verticalCenter : undefined - color: root.visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface + color: root.contentColor font: Config.appearance.font.family.mono // qmllint disable incompatible-type - height: root.horizontal ? implicitHeight : implicitWidth + height: implicitHeight text: Time.dateStr - width: root.horizontal ? implicitWidth : implicitHeight + visible: root.horizontal Behavior on color { CAnim { } } - transform: [ - Translate { - x: !root.horizontal ? -timeText.implicitWidth + timeText.implicitHeight : 0 - }, - Rotation { - angle: root.horizontal ? 0 : 270 - origin.x: timeText.implicitHeight / 2 - origin.y: timeText.implicitHeight / 2 + } + + ColumnLayout { + id: verticalColumn + + anchors.centerIn: parent + spacing: Tokens.padding.small ?? 2 + visible: !root.horizontal + width: root.baseSize + + Repeater { + model: root.formatParts.dateTokens + + CustomText { + required property string modelData + + Layout.alignment: Qt.AlignHCenter + color: root.contentColor + font: Config.appearance.font.family.mono // qmllint disable incompatible-type + text: Qt.formatDateTime(Time.date, modelData) + + Behavior on color { + CAnim { + } + } } - ] + } + + Rectangle { + Layout.alignment: Qt.AlignHCenter + Layout.bottomMargin: Tokens.padding.small ?? 2 + Layout.topMargin: Tokens.padding.small ?? 2 + color: root.contentColor + height: 1 + implicitWidth: root.baseSize * 0.5 + opacity: 0.4 + radius: 1 + visible: root.formatParts.dateTokens.length > 0 && root.formatParts.timeTokens.length > 0 + } + + Repeater { + model: root.formatParts.timeTokens + + CustomText { + required property string modelData + + Layout.alignment: Qt.AlignHCenter + color: root.contentColor + font: Config.appearance.font.family.mono // qmllint disable incompatible-type + text: { + if (modelData.includes("h")) + return Time.hourStr; + if (modelData.includes("m")) + return Time.minuteStr; + if (modelData.includes("s")) + return Time.secondStr; + return ""; + } + + Behavior on color { + CAnim { + } + } + } + } + + CustomText { + Layout.alignment: Qt.AlignHCenter + color: root.contentColor + font: Config.appearance.font.family.mono // qmllint disable incompatible-type + text: Qt.formatDateTime(Time.date, "AP") + visible: Config.services.useTwelveHourClock && root.formatParts.timeTokens.length > 0 + + Behavior on color { + CAnim { + } + } + } } StateLayer { acceptedButtons: Qt.LeftButton - color: root.visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface + color: root.contentColor onClicked: { root.visibilities.dashboard = !root.visibilities.dashboard; diff --git a/Modules/Bar/Components/Common/WidgetBase.qml b/Modules/Bar/Components/Common/WidgetBase.qml new file mode 100644 index 0000000..2a0fb95 --- /dev/null +++ b/Modules/Bar/Components/Common/WidgetBase.qml @@ -0,0 +1,16 @@ +import QtQuick +import ZShell.Config +import qs.Components +import qs.Services + +CustomRect { + id: root + + readonly property int baseSize: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : Math.max(Config.bar.height, Math.floor(Tokens.bar.innerSize * 1.5)) + required property bool horizontal + + color: Colors.tPalette.m3surfaceContainer + implicitHeight: horizontal ? baseSize : width + implicitWidth: horizontal ? height : baseSize + radius: Tokens.rounding.full +} diff --git a/Modules/Bar/Components/HyprsunsetWidget.qml b/Modules/Bar/Components/HyprsunsetWidget.qml index 34d1426..8afd545 100644 --- a/Modules/Bar/Components/HyprsunsetWidget.qml +++ b/Modules/Bar/Components/HyprsunsetWidget.qml @@ -1,18 +1,16 @@ import QtQuick import ZShell.Config import qs.Components +import qs.Modules.Bar.Components.Common import qs.Helpers import qs.Services -CustomRect { +WidgetBase { id: root - required property bool horizontal property bool tempEnabled: Hyprsunset.enabled color: root.tempEnabled ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : width - implicitWidth: horizontal ? height : Math.max(Config.bar.height, Tokens.bar.innerSize) radius: Tokens.rounding.full StateLayer { diff --git a/Modules/Bar/Components/MediaWidget.qml b/Modules/Bar/Components/MediaWidget.qml index 15e9679..99e4e1e 100644 --- a/Modules/Bar/Components/MediaWidget.qml +++ b/Modules/Bar/Components/MediaWidget.qml @@ -1,21 +1,19 @@ import QtQuick import QtQuick.Layouts -import qs.Components -import qs.Daemons import ZShell.Config +import qs.Components +import qs.Modules.Bar.Components.Common import qs.Helpers import qs.Services -CustomRect { +WidgetBase { id: root readonly property string currentMedia: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title") - required property bool horizontal readonly property int textWidth: Math.min(metrics.width, 200) - color: Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : layout.implicitHeight + Tokens.padding.normal * 2 - implicitWidth: horizontal ? layout.implicitWidth + Tokens.padding.normal * 2 : Math.max(Config.bar.height, Tokens.bar.innerSize) + implicitHeight: horizontal ? baseSize : layout.implicitHeight + Tokens.padding.normal * 2 + implicitWidth: horizontal ? layout.implicitWidth + Tokens.padding.normal * 2 : baseSize radius: Tokens.rounding.full Behavior on implicitHeight { @@ -69,34 +67,26 @@ CustomRect { color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface font.pointSize: Tokens.font.size.normal horizontalAlignment: Text.AlignHCenter - implicitWidth: root.textWidth + implicitHeight: root.horizontal ? root.implicitHeight : root.textWidth + implicitWidth: root.horizontal ? root.textWidth : root.implicitWidth marqueeEnabled: false pauseMs: 4000 text: root.currentMedia + vertical: !root.horizontal + } + } - transform: [ - Translate { - x: !root.horizontal ? -root.textWidth + mediatext.implicitHeight : 0 - }, - Rotation { - angle: root.horizontal ? 0 : 270 - origin.x: mediatext.implicitHeight / 2 - origin.y: mediatext.implicitHeight / 2 - } - ] + CustomMouseArea { + anchors.fill: parent + hoverEnabled: true - CustomMouseArea { - anchors.fill: parent - hoverEnabled: true - - onContainsMouseChanged: { - if (!containsMouse) { - mediatext.marqueeEnabled = false; - } else { - mediatext.marqueeEnabled = true; - mediatext.anim.start(); - } - } + onContainsMouseChanged: { + console.log(root.textWidth, mediatext.implicitWidth, mediatext.implicitHeight); + if (!containsMouse) { + mediatext.marqueeEnabled = false; + } else { + mediatext.marqueeEnabled = true; + mediatext.anim.start(); } } } diff --git a/Modules/Bar/Components/NotifBell.qml b/Modules/Bar/Components/NotifBell.qml index c1db86f..c255deb 100644 --- a/Modules/Bar/Components/NotifBell.qml +++ b/Modules/Bar/Components/NotifBell.qml @@ -1,21 +1,19 @@ import Quickshell import QtQuick import ZShell.Config +import qs.Modules.Bar.Components.Common import qs.Modules.Bar.Popouts import qs.Daemons import qs.Components import qs.Services -CustomRect { +WidgetBase { id: root - required property bool horizontal required property Wrapper popouts required property PersistentProperties visibilities color: visibilities.sidebar ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : width - implicitWidth: horizontal ? height : Math.max(Config.bar.height, Tokens.bar.innerSize) radius: Tokens.rounding.full MaterialIcon { diff --git a/Modules/Bar/Components/Resources.qml b/Modules/Bar/Components/Resources.qml index 123636e..5759d54 100644 --- a/Modules/Bar/Components/Resources.qml +++ b/Modules/Bar/Components/Resources.qml @@ -6,19 +6,18 @@ import QtQuick.Layouts import ZShell.Config import ZShell.Services import qs.Services -import qs.Modules +import qs.Modules.Bar.Components.Common import qs.Components -CustomRect { +WidgetBase { id: root - required property bool horizontal required property PersistentProperties visibilities clip: true color: visibilities.resources ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : gridLayout.implicitHeight + Tokens.padding.normal * 2 - implicitWidth: horizontal ? gridLayout.implicitWidth + Tokens.padding.larger * 2 : Math.max(Config.bar.height, Tokens.bar.innerSize) + implicitHeight: horizontal ? baseSize : gridLayout.implicitHeight + Tokens.padding.normal * 2 + implicitWidth: horizontal ? gridLayout.implicitWidth + Tokens.padding.larger * 2 : baseSize radius: Tokens.rounding.full StateLayer { diff --git a/Modules/Bar/Components/StatusIcons.qml b/Modules/Bar/Components/StatusIcons.qml index e0d6655..66f6158 100644 --- a/Modules/Bar/Components/StatusIcons.qml +++ b/Modules/Bar/Components/StatusIcons.qml @@ -6,10 +6,11 @@ import QtQuick.Layouts import ZShell.Config import qs.Helpers import qs.Modules.Bar.Components.StatusIcons +import qs.Modules.Bar.Components.Common import qs.Components import qs.Services -CustomClippingRect { +WidgetBase { id: root readonly property int firstPresent: { @@ -19,7 +20,6 @@ CustomClippingRect { return i; return -1; } - required property bool horizontal // Index of the first/last entry that isn't collapsed, for edge margin gating readonly property alias items: grid @@ -30,7 +30,6 @@ CustomClippingRect { return i; return -1; } - readonly property real shortSize: Math.max(Config.bar.height, Tokens.bar.innerSize) readonly property real size: horizontal ? grid.implicitWidth + Tokens.padding.small * 2 : grid.implicitHeight + Tokens.padding.small * 2 readonly property int spacing: Tokens.spacing.normal / 2 @@ -43,8 +42,8 @@ CustomClippingRect { bottomLeftRadius: horizontal ? Tokens.rounding.smallest / 2 : Tokens.rounding.full color: Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? shortSize : size - implicitWidth: horizontal ? size : shortSize + implicitHeight: horizontal ? baseSize : size + implicitWidth: horizontal ? size : baseSize radius: Tokens.rounding.full topLeftRadius: Tokens.rounding.smallest / 2 topRightRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.smallest / 2 diff --git a/Modules/Bar/Components/TrayIcons.qml b/Modules/Bar/Components/TrayIcons.qml index a7175b4..568ee28 100644 --- a/Modules/Bar/Components/TrayIcons.qml +++ b/Modules/Bar/Components/TrayIcons.qml @@ -3,29 +3,28 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import Quickshell.Services.SystemTray -import qs.Components import ZShell.Config +import qs.Components +import qs.Modules.Bar.Components.Common import qs.Modules.Bar.Components.Tray import qs.Modules.Bar.Popouts import qs.Services -CustomClippingRect { +WidgetBase { id: root - required property bool horizontal readonly property alias items: repeater readonly property alias layout: sysGrid required property GridLayout loader readonly property int padding: Tokens.padding.small required property Wrapper popouts - readonly property real shortSize: Math.max(Config.bar.height, Tokens.bar.innerSize) readonly property real size: horizontal ? sysGrid.implicitWidth + Tokens.padding.small : sysGrid.implicitHeight + Tokens.padding.small bottomLeftRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.smallest / 2 bottomRightRadius: Tokens.rounding.smallest / 2 color: Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? shortSize : size - implicitWidth: horizontal ? size : shortSize + implicitHeight: horizontal ? baseSize : size + implicitWidth: horizontal ? size : baseSize radius: Tokens.rounding.full topRightRadius: horizontal ? Tokens.rounding.smallest / 2 : Tokens.rounding.full diff --git a/Modules/Bar/Components/UpdatesWidget.qml b/Modules/Bar/Components/UpdatesWidget.qml index 3babcae..a525040 100644 --- a/Modules/Bar/Components/UpdatesWidget.qml +++ b/Modules/Bar/Components/UpdatesWidget.qml @@ -1,21 +1,20 @@ import QtQuick import QtQuick.Layouts -import qs.Components -import qs.Modules -import qs.Helpers import ZShell.Config +import qs.Components +import qs.Modules.Bar.Components.Common +import qs.Helpers import qs.Services -CustomRect { +WidgetBase { id: root property int countUpdates: Updates.availableUpdates - required property bool horizontal property color textColor: Colors.palette.m3onSurface color: Colors.tPalette.m3surfaceContainer - implicitHeight: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : content.implicitHeight + Tokens.spacing.small - implicitWidth: horizontal ? content.implicitWidth + Tokens.spacing.small * 2 : Math.max(Config.bar.height, Tokens.bar.innerSize) + implicitHeight: horizontal ? baseSize : content.implicitHeight + Tokens.spacing.small + implicitWidth: horizontal ? content.implicitWidth + Tokens.spacing.small * 2 : baseSize radius: Tokens.rounding.full GridLayout { diff --git a/Modules/Bar/Components/WindowTitle.qml b/Modules/Bar/Components/WindowTitle.qml index a9c7a4e..c213072 100644 --- a/Modules/Bar/Components/WindowTitle.qml +++ b/Modules/Bar/Components/WindowTitle.qml @@ -1,8 +1,8 @@ pragma ComponentBehavior: Bound import QtQuick -import qs.Components import ZShell.Config +import qs.Components import qs.Helpers import qs.Services @@ -17,11 +17,10 @@ Item { readonly property int maxSize: { const otherModules = bar.children.filter(c => c.enabled && c.entryId && c.item !== this && c.entryId !== "spacer"); const otherSize = otherModules.reduce((acc, curr) => acc + (horizontal ? (curr.item?.nonAnimWidth ?? curr.width ?? 0) : (curr.item.nonAnimHeight ?? curr.height ?? 0)), 0); - return horizontal ? bar.width - otherSize - bar.spacing * (bar.children.length - 1) - bar.vPadding * 2 : bar.height - otherSize - bar.vPadding * (bar.children.length - 1) - bar.vPadding * 4; + return horizontal ? (bar.width - otherSize - bar.columnSpacing * (bar.children.length - 1) - bar.vPadding * 2) : (bar.height - otherSize - bar.rowSpacing * (bar.children.length - 1) - bar.vPadding * 4); } - anchors.centerIn: parent - clip: false + clip: true implicitHeight: horizontal ? current.implicitHeight : current.implicitWidth + current.anchors.topMargin implicitWidth: horizontal ? current.implicitWidth + current.anchors.leftMargin : current.implicitHeight + current.anchors.topMargin @@ -36,6 +35,7 @@ Item { enabled: root.horizontal Anim { + type: Anim.DefaultEffects } } diff --git a/Modules/Dashboard/Wrapper.qml b/Modules/Dashboard/Wrapper.qml index de1856b..c78a97f 100644 --- a/Modules/Dashboard/Wrapper.qml +++ b/Modules/Dashboard/Wrapper.qml @@ -14,16 +14,18 @@ Item { reloadableId: "dashboardState" } - required property bool horizontal readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0 required property real offsetScale + required property string position readonly property bool shouldBeActive: root.visibilities.dashboard && Config.dashboard.enabled required property PersistentProperties visibilities - anchors.left: horizontal ? undefined : parent.left - anchors.leftMargin: horizontal ? 0 : (-implicitWidth - 5) * offsetScale - anchors.top: horizontal ? parent.top : undefined - anchors.topMargin: horizontal ? (-implicitHeight - 5) * offsetScale : 0 + anchors.bottom: position === "bottom" ? parent.bottom : undefined + anchors.bottomMargin: position === "bottom" ? (-implicitHeight - 5) * offsetScale : 0 + anchors.left: position === "left" ? parent.left : undefined + anchors.leftMargin: position === "left" ? (-implicitWidth - 5) * offsetScale : 0 + anchors.top: position === "top" ? parent.top : undefined + anchors.topMargin: position === "top" ? (-implicitHeight - 5) * offsetScale : 0 implicitHeight: content.implicitHeight implicitWidth: content.implicitWidth || 854 opacity: 1 - offsetScale @@ -33,10 +35,11 @@ Item { id: content active: root.shouldBeActive || root.visible - anchors.bottom: root.horizontal ? parent.bottom : undefined - anchors.horizontalCenter: root.horizontal ? parent.horizontalCenter : undefined - anchors.right: root.horizontal ? undefined : parent.right - anchors.verticalCenter: root.horizontal ? undefined : parent.verticalCenter + anchors.bottom: root.position === "top" ? parent.bottom : undefined + anchors.horizontalCenter: root.position !== "left" ? parent.horizontalCenter : undefined + anchors.right: root.position !== "left" ? undefined : parent.right + anchors.top: root.position === "bottom" ? parent.top : undefined + anchors.verticalCenter: root.position === "left" ? undefined : parent.verticalCenter sourceComponent: Content { dashState: root.dashState diff --git a/Modules/Resources/Wrapper.qml b/Modules/Resources/Wrapper.qml index 25629a8..52f4c1b 100644 --- a/Modules/Resources/Wrapper.qml +++ b/Modules/Resources/Wrapper.qml @@ -8,14 +8,18 @@ import ZShell.Config Item { id: root - required property bool horizontal readonly property real nonAnimHeight: content.item?.nonAnimHeight ?? 0 property real offsetScale: shouldBeActive ? 0 : 1 + required property string position readonly property bool shouldBeActive: root.visibilities.resources required property PersistentProperties visibilities - anchors.leftMargin: horizontal ? 0 : (-implicitWidth - 5) * offsetScale - anchors.topMargin: horizontal ? (-implicitHeight - 5) * offsetScale : 0 + anchors.bottom: position === "bottom" ? parent.bottom : undefined + anchors.bottomMargin: position === "bottom" ? (-implicitHeight - 5) * offsetScale : 0 + anchors.left: parent.left + anchors.leftMargin: position === "left" ? (-implicitWidth - 5) * offsetScale : 0 + anchors.top: position !== "bottom" ? parent.top : undefined + anchors.topMargin: position === "top" ? (-implicitHeight - 5) * offsetScale : 0 clip: true implicitHeight: content.implicitHeight implicitWidth: content.implicitWidth || 854 // Hard coded fallback for first open @@ -33,7 +37,11 @@ Item { id: content active: root.shouldBeActive || root.visible - anchors.centerIn: parent + anchors.bottom: root.position === "top" ? parent.bottom : undefined + anchors.horizontalCenter: root.position !== "left" ? parent.horizontalCenter : undefined + anchors.right: root.position !== "left" ? undefined : parent.right + anchors.top: root.position === "bottom" ? parent.top : undefined + anchors.verticalCenter: root.position === "left" ? undefined : parent.verticalCenter sourceComponent: Content { wrapper: root