diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml index ebd79a96a..a388cdb62 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarContent.qml @@ -28,12 +28,9 @@ Item { Side { id: centerLeftSide anchors.right: !root.vertical ? centerSide.left : parent.right - anchors.bottom: root.vertical ? parent.bottom : undefined + anchors.bottom: !root.vertical ? parent.bottom : centerSide.top HBarUserFallbackComponentRepeater { - componentNames: [ - ...root.centerLeftWidgets, - ...(root.centerLeftWidgets.length > 0 ? [invisibleItem] : []), - ] + componentNames: [...root.centerLeftWidgets, ...(root.centerLeftWidgets.length > 0 ? [invisibleItem] : []),] } } @@ -42,23 +39,16 @@ Item { anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined HBarUserFallbackComponentRepeater { - componentNames: [ - ...(root.centerLeftWidgets.length > 0 ? [invisibleItem] : []), - ...root.centerWidgets, - ...(root.centerRightWidgets.length > 0 ? [invisibleItem] : []), - ] + componentNames: [...(root.centerLeftWidgets.length > 0 ? [invisibleItem] : []), ...root.centerWidgets, ...(root.centerRightWidgets.length > 0 ? [invisibleItem] : []),] } } Side { id: centerRightSide anchors.left: !root.vertical ? centerSide.right : parent.left - anchors.top: root.vertical ? parent.top : undefined + anchors.top: root.vertical ? parent.top : centerSide.bottom HBarUserFallbackComponentRepeater { - componentNames: [ - ...(root.centerLeftWidgets.length > 0 ? [invisibleItem] : []), - ...root.centerRightWidgets, - ] + componentNames: [...(root.centerLeftWidgets.length > 0 ? [invisibleItem] : []), ...root.centerRightWidgets,] } } diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarWidgetShapeBackground.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarWidgetShapeBackground.qml index 464dc683a..aca8d7da7 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarWidgetShapeBackground.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/HBarWidgetShapeBackground.qml @@ -7,10 +7,13 @@ import qs.modules.common.widgets as W import qs.modules.common.widgets.shapes as Shapes import "../../../common/widgets/shapes/material-shapes.js" as MaterialShapes -// TODO: generalize this shi for vertical +// Notes +// vertical + atBottom = right side +// start radius = top or left, end radius = bottom or right Shapes.ShapeCanvas { id: bgShape + // Stuff fed from outside required property bool vertical required property bool atBottom required property bool showPopup @@ -23,45 +26,98 @@ Shapes.ShapeCanvas { property real popupHeight: popupContentHeight + popupPadding * 2 required property real startRadius required property real endRadius - property real baseMargin: (parent.height - containerShape.height) / 2 // TODO vertical - readonly property real popupContentOffsetBase: -baseMargin + popupPadding - readonly property real popupContentOffsetY: spacing + popupContentOffsetBase + (atBottom ? -(popupHeight + backgroundHeight + spacing * 2) : 0) - readonly property real popupContentOffsetX: popupXOffset + popupContentOffsetBase + property real baseMargin: { + if (!vertical) + return (parent.height - containerShape.height) / 2; + else + return (parent.width - containerShape.width) / 2; + } property alias containerShape: containerShape property alias popupShape: popupShape + // Popup constraints // mapToGlobal is not reactive so we gotta hook manually property real xInGlobal + property real yInGlobal function updateXInGlobal() { xInGlobal = mapToGlobal(0, 0).x + xOffset; } - Component.onCompleted: updateXInGlobal() - onXChanged: updateXInGlobal() + function updateYInGlobal() { + yInGlobal = mapToGlobal(0, 0).y + yOffset; + } + function updatePosInGlobal() { + updateXInGlobal() + updateYInGlobal() + } + Component.onCompleted: updatePosInGlobal() + onXChanged: updatePosInGlobal() + onYChanged: updatePosInGlobal() readonly property real minPopupXOffset: -xInGlobal + baseMargin + readonly property real minPopupYOffset: -yInGlobal + baseMargin readonly property real maxPopupXOffset: { const maxPopupX = QsWindow.window.screen.width - popupWidth - baseMargin; const maxOffset = maxPopupX - xInGlobal; return maxOffset; } - readonly property real popupXOffset: Math.min(Math.max(-(popupWidth - containerShape.width) / 2, minPopupXOffset), maxPopupXOffset) + readonly property real maxPopupYOffset: { + const maxPopupY = QsWindow.window.screen.height - popupHeight - baseMargin; + const maxOffset = maxPopupY - yInGlobal; + return maxOffset; + } + readonly property real popupXOffset: { + if (!vertical) return Math.min(Math.max(-(popupWidth - containerShape.width) / 2, minPopupXOffset), maxPopupXOffset); + else return atBottom ? -(popupShape.width + spacing) : (containerShape.width + spacing); + } + readonly property real popupYOffset: { + if (!vertical) return atBottom ? -(popupShape.height + spacing) : (containerShape.height + spacing); + else return Math.min(Math.max(-(popupHeight - containerShape.height) / 2, minPopupYOffset), maxPopupYOffset) + } + + // Positioning + readonly property real popupContentOffsetBase: -baseMargin + popupPadding + readonly property real paddedContainerHeight: containerShape.height + baseMargin * 2 + readonly property real paddedContainerWidth: containerShape.width + baseMargin * 2 + readonly property real popupContentOffsetY: { + if (!vertical) return paddedContainerHeight + spacing + popupContentOffsetBase + (atBottom ? -(popupHeight + backgroundHeight + spacing * 2) : 0) + else return popupYOffset + popupContentOffsetBase; + } + readonly property real popupContentOffsetX: { + if (!vertical) return popupXOffset + popupContentOffsetBase; + else return paddedContainerWidth + spacing + popupContentOffsetBase + (atBottom ? -(popupWidth + backgroundWidth + spacing * 2) : 0); + } anchors { left: parent.left - leftMargin: -xOffset + leftMargin: { + if (!vertical) return -xOffset; + if (!bgShape.atBottom || !bgShape.showPopup) return baseMargin; + return baseMargin - popupShape.width - bgShape.spacing; + } top: parent.top topMargin: { - if (!bgShape.atBottom || !bgShape.showPopup) - return baseMargin; - else - return baseMargin - popupShape.height - bgShape.spacing; + if (vertical) return -yOffset; + if (!bgShape.atBottom || !bgShape.showPopup) return baseMargin; + return baseMargin - popupShape.height - bgShape.spacing; } } - width: bgShape.showPopup ? Math.max(backgroundWidth, popupWidth) : backgroundWidth - height: bgShape.showPopup ? (containerShape.height + popupShape.height + bgShape.spacing) : containerShape.height + width: { + if (!vertical) return bgShape.showPopup ? Math.max(backgroundWidth, popupWidth) : backgroundWidth; + else return bgShape.showPopup ? (containerShape.width + popupShape.width + bgShape.spacing) : containerShape.width; + } + height: { + if (!vertical) return bgShape.showPopup ? (containerShape.height + popupShape.height + bgShape.spacing) : containerShape.height; + else return bgShape.showPopup ? Math.max(backgroundHeight, popupHeight) : backgroundHeight; + } color: bgShape.showPopup || progress < 1 ? C.Appearance.colors.colLayer3Base : C.Appearance.colors.colLayer1 - xOffset: showPopup ? -popupXOffset : 0 - yOffset: bgShape.atBottom ? (height - containerShape.height) : 0 + xOffset: { + if (!vertical) return showPopup ? -popupXOffset : 0; + else return bgShape.atBottom ? (width - containerShape.width) : 0; + } + yOffset: { + if (!vertical) return bgShape.atBottom ? (height - containerShape.height) : 0; + else return showPopup ? -popupYOffset : 0; + } animation: Anim {} Behavior on width { @@ -71,10 +127,16 @@ Shapes.ShapeCanvas { Anim {} } Behavior on anchors.topMargin { - Anim {} + animation: !bgShape.vertical ? animComp.createObject(this) : undefined + } + Behavior on anchors.leftMargin { + animation: bgShape.vertical ? animComp.createObject(this) : undefined } Behavior on xOffset { - Anim {} + animation: !bgShape.vertical ? animComp.createObject(this) : undefined + } + Behavior on yOffset { + animation: bgShape.vertical ? animComp.createObject(this) : undefined } polygonIsNormalized: false @@ -85,6 +147,7 @@ Shapes.ShapeCanvas { height: bgShape.backgroundHeight startRadius: bgShape.startRadius endRadius: bgShape.endRadius + vertical: bgShape.vertical } W.RectangularContainerShape { id: popupShape @@ -92,18 +155,73 @@ Shapes.ShapeCanvas { height: bgShape.popupHeight radius: C.Appearance.rounding.large xOffset: bgShape.popupXOffset - yOffset: bgShape.atBottom ? -(popupShape.height + bgShape.spacing) : (containerShape.height + bgShape.spacing) + yOffset: bgShape.popupYOffset } roundedPolygon: { - if (!bgShape.showPopup) - return containerShape.getFullShape(); - // return popupShape.getFullShape(); // debug - const points = [...(bgShape.atBottom ? containerShape.getFirstBottomPoints() : [...popupShape.getFirstBottomPoints(), popupShape.getBottomLeftPoint(), ...popupShape.leftPoints, popupShape.getTopLeftPoint(),]), containerShape.getBottomLeftPoint(0, bgShape.spacing * (!bgShape.atBottom ? 1 : 0), containerShape.radiusLimit), - // ...containerShape.leftPoints, - containerShape.getTopLeftPoint(0, bgShape.spacing * (bgShape.atBottom ? -1 : 0), containerShape.radiusLimit), ...(!bgShape.atBottom ? containerShape.topPoints : [popupShape.getBottomLeftPoint(), ...popupShape.leftPoints, popupShape.getTopLeftPoint(), ...popupShape.topPoints, popupShape.getTopRightPoint(), ...popupShape.rightPoints, popupShape.getBottomRightPoint(),]), containerShape.getTopRightPoint(0, bgShape.spacing * (bgShape.atBottom ? -1 : 0), containerShape.radiusLimit), - // ...containerShape.rightPoints, - containerShape.getBottomRightPoint(0, bgShape.spacing * (!bgShape.atBottom ? 1 : 0), containerShape.radiusLimit), ...(bgShape.atBottom ? containerShape.getLastBottomPoints() : [popupShape.getTopRightPoint(), ...popupShape.rightPoints, popupShape.getBottomRightPoint(), ...popupShape.getLastBottomPoints(),]),]; + var points = []; + if (!bgShape.showPopup) return containerShape.getFullShape(); + if (!bgShape.vertical) { + // Inline comment spam to mitigate qmlls' sabotaging of the (code) layout + points = [ + ...(bgShape.atBottom ? containerShape.getFirstBottomPoints() : [ // + ...popupShape.getFirstBottomPoints(), popupShape.getBottomLeftPoint(), // + ...popupShape.leftPoints, // + popupShape.getTopLeftPoint(), // + ]), // + containerShape.getBottomLeftPoint(0, bgShape.spacing * (!bgShape.atBottom ? 1 : 0), containerShape.radiusLimit), // + containerShape.getTopLeftPoint(0, bgShape.spacing * (bgShape.atBottom ? -1 : 0), containerShape.radiusLimit), // + ...(!bgShape.atBottom ? containerShape.topPoints : [ // + popupShape.getBottomLeftPoint(), // + ...popupShape.leftPoints, // + popupShape.getTopLeftPoint(), // + ...popupShape.topPoints, // + popupShape.getTopRightPoint(), // + ...popupShape.rightPoints, // + popupShape.getBottomRightPoint(), // + ]), // + containerShape.getTopRightPoint(0, bgShape.spacing * (bgShape.atBottom ? -1 : 0), containerShape.radiusLimit), // + containerShape.getBottomRightPoint(0, bgShape.spacing * (!bgShape.atBottom ? 1 : 0), containerShape.radiusLimit), // + ...(bgShape.atBottom ? containerShape.getLastBottomPoints() : [ // + popupShape.getTopRightPoint(), // + ...popupShape.rightPoints, // + popupShape.getBottomRightPoint(), // + ...popupShape.getLastBottomPoints(), // + ]), + ]; + } else { + points = [ // + ...containerShape.getFirstBottomPoints(), // + containerShape.getBottomLeftPoint(), // + ...(!bgShape.atBottom ? containerShape.leftPoints : [ // + containerShape.getBottomLeftPoint(-bgShape.spacing, 0, containerShape.radiusLimit), // + popupShape.getBottomRightPoint(), // + ...popupShape.bottomPoints, // + popupShape.getBottomLeftPoint(), // + ...popupShape.leftPoints, // + popupShape.getTopLeftPoint(), // + ...popupShape.topPoints, // + popupShape.getTopRightPoint(), // + containerShape.getTopLeftPoint(-bgShape.spacing, 0, containerShape.radiusLimit), // + ]), // + containerShape.getTopLeftPoint(), // + ...containerShape.topPoints, // + containerShape.getTopRightPoint(), // + ...(bgShape.atBottom ? containerShape.rightPoints : [ // + containerShape.getTopRightPoint(bgShape.spacing, 0, containerShape.radiusLimit), // + popupShape.getTopLeftPoint(), // + ...popupShape.topPoints, // + popupShape.getTopRightPoint(), // + ...popupShape.rightPoints, // + popupShape.getBottomRightPoint(), // + ...popupShape.bottomPoints, // + popupShape.getBottomLeftPoint(), // + containerShape.getBottomRightPoint(bgShape.spacing, 0, containerShape.radiusLimit), // + ]), // + containerShape.getBottomRightPoint(), // + ...containerShape.getLastBottomPoints(), // + ]; + } return MaterialShapes.customPolygon(points); } @@ -111,4 +229,9 @@ Shapes.ShapeCanvas { spring: 3.5 damping: 0.3 } + + Component { + id: animComp + Anim {} + } } diff --git a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/HTime.qml b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/HTime.qml index a76832140..6e917652a 100644 --- a/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/HTime.qml +++ b/dots/.config/quickshell/ii/modules/hefty/topLayer/bar/widgets/HTime.qml @@ -15,6 +15,11 @@ HBarWidgetContainer { readonly property bool vertical: C.Config.options.bar.vertical readonly property bool atBottom: C.Config.options.bar.bottom + readonly property string timeFormatString: C.Config.options.time.format + readonly property bool is12h: timeFormatString.startsWith("h:") + readonly property bool hasAmPm: timeFormatString.toLowerCase().includes("ap") || timeFormatString.toLowerCase().endsWith("a") + readonly property bool capitalizedAmPm: timeFormatString.includes("AP") || timeFormatString.endsWith("A") + // Interactions property var morphedPanelParent: F.ObjectUtils.findParentWithProperty(root, "maskItems") onShowPopupChanged: { @@ -83,14 +88,14 @@ HBarWidgetContainer { text: S.DateTime.time } - W.StyledText { + W.VisuallyCenteredStyledText { Layout.alignment: Qt.AlignVCenter font.pixelSize: C.Appearance.font.pixelSize.small color: C.Appearance.colors.colOnLayer1 text: "•" } - W.StyledText { + W.VisuallyCenteredStyledText { Layout.alignment: Qt.AlignVCenter font.pixelSize: C.Appearance.font.pixelSize.small color: C.Appearance.colors.colOnLayer1 @@ -104,15 +109,52 @@ HBarWidgetContainer { W.FadeLoader { id: verticalContent anchors.fill: parent + shown: contentRoot.vertical + + sourceComponent: Item { + anchors.fill: parent + implicitWidth: contentLayoutVertical.implicitWidth + implicitHeight: contentLayoutVertical.implicitHeight + + ColumnLayout { + id: contentLayoutVertical + anchors.fill: parent + spacing: -6 + + W.StyledText { + Layout.alignment: Qt.AlignHCenter + font.pixelSize: C.Appearance.font.pixelSize.large + color: C.Appearance.colors.colOnLayer1 + text: { + var hrs = S.DateTime.clock.hours; + if (root.is12h) hrs %= 12; + return hrs.toString().padStart(2, '0') + } + } + W.StyledText { + Layout.alignment: Qt.AlignHCenter + font.pixelSize: C.Appearance.font.pixelSize.large + color: C.Appearance.colors.colOnLayer1 + text: S.DateTime.clock.minutes.toString().padStart(2, '0') + } + W.StyledText { + visible: root.hasAmPm + Layout.alignment: Qt.AlignHCenter + font.pixelSize: C.Appearance.font.pixelSize.smaller + color: C.Appearance.colors.colOnLayer1 + text: Qt.locale().toString(S.DateTime.clock.date, root.capitalizedAmPm ? "AP" : "ap") + } + } + } } // Popup content W.ChoreographerGrid { id: popupContent anchors { - top: horizontalContent.bottom + top: root.vertical ? verticalContent.top : horizontalContent.top topMargin: bgShape.popupContentOffsetY - left: horizontalContent.left + left: root.vertical ? verticalContent.left : horizontalContent.left leftMargin: bgShape.popupContentOffsetX }