1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

dock: add border option

fixes #829
This commit is contained in:
bbedward
2025-12-01 10:53:15 -05:00
parent c6e9abda9f
commit cfc07f4411
4 changed files with 647 additions and 354 deletions

View File

@@ -275,6 +275,10 @@ Singleton {
property real dockMargin: 0 property real dockMargin: 0
property real dockIconSize: 40 property real dockIconSize: 40
property string dockIndicatorStyle: "circle" property string dockIndicatorStyle: "circle"
property bool dockBorderEnabled: false
property string dockBorderColor: "surfaceText"
property real dockBorderOpacity: 1.0
property int dockBorderThickness: 1
property bool notificationOverlayEnabled: false property bool notificationOverlayEnabled: false
property int overviewRows: 2 property int overviewRows: 2

View File

@@ -175,6 +175,10 @@ var SPEC = {
dockMargin: { def: 0 }, dockMargin: { def: 0 },
dockIconSize: { def: 40 }, dockIconSize: { def: 40 },
dockIndicatorStyle: { def: "circle" }, dockIndicatorStyle: { def: "circle" },
dockBorderEnabled: { def: false },
dockBorderColor: { def: "surfaceText" },
dockBorderOpacity: { def: 1.0, coerce: percentToUnit },
dockBorderThickness: { def: 1 },
notificationOverlayEnabled: { def: false }, notificationOverlayEnabled: { def: false },
overviewRows: { def: 2, persist: false }, overviewRows: { def: 2, persist: false },

View File

@@ -1,14 +1,12 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Shapes
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
pragma ComponentBehavior: Bound
Variants { Variants {
id: dockVariants id: dockVariants
model: SettingsData.getFilteredScreens("dock") model: SettingsData.getFilteredScreens("dock")
@@ -33,37 +31,41 @@ Variants {
property bool autoHide: SettingsData.dockAutoHide property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency property real backgroundTransparency: SettingsData.dockTransparency
property bool groupByApp: SettingsData.dockGroupByApp property bool groupByApp: SettingsData.dockGroupByApp
readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0
readonly property real widgetHeight: SettingsData.dockIconSize readonly property real widgetHeight: SettingsData.dockIconSize
readonly property real effectiveBarHeight: widgetHeight + SettingsData.dockSpacing * 2 + 10 readonly property real effectiveBarHeight: widgetHeight + SettingsData.dockSpacing * 2 + 10 + borderThickness * 2
readonly property real barSpacing: { readonly property real barSpacing: {
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default") const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default");
if (!defaultBar) return 0 if (!defaultBar)
return 0;
const barPos = defaultBar.position ?? SettingsData.Position.Top const barPos = defaultBar.position ?? SettingsData.Position.Top;
const barIsHorizontal = (barPos === SettingsData.Position.Top || barPos === SettingsData.Position.Bottom) const barIsHorizontal = (barPos === SettingsData.Position.Top || barPos === SettingsData.Position.Bottom);
const barIsVertical = (barPos === SettingsData.Position.Left || barPos === SettingsData.Position.Right) const barIsVertical = (barPos === SettingsData.Position.Left || barPos === SettingsData.Position.Right);
const samePosition = (SettingsData.dockPosition === barPos) const samePosition = (SettingsData.dockPosition === barPos);
const dockIsHorizontal = !isVertical const dockIsHorizontal = !isVertical;
const dockIsVertical = isVertical const dockIsVertical = isVertical;
if (!(defaultBar.visible ?? true)) return 0 if (!(defaultBar.visible ?? true))
const spacing = defaultBar.spacing ?? 4 return 0;
const bottomGap = defaultBar.bottomGap ?? 0 const spacing = defaultBar.spacing ?? 4;
const bottomGap = defaultBar.bottomGap ?? 0;
if (dockIsHorizontal && barIsHorizontal && samePosition) { if (dockIsHorizontal && barIsHorizontal && samePosition) {
return spacing + effectiveBarHeight + bottomGap return spacing + effectiveBarHeight + bottomGap;
} }
if (dockIsVertical && barIsVertical && samePosition) { if (dockIsVertical && barIsVertical && samePosition) {
return spacing + effectiveBarHeight + bottomGap return spacing + effectiveBarHeight + bottomGap;
} }
return 0 return 0;
} }
readonly property real dockMargin: SettingsData.dockSpacing readonly property real dockMargin: SettingsData.dockSpacing
readonly property real positionSpacing: barSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin readonly property real positionSpacing: barSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin
readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1 readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1
function px(v) { return Math.round(v * _dpr) / _dpr } function px(v) {
return Math.round(v * _dpr) / _dpr;
}
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData) property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
property bool revealSticky: false property bool revealSticky: false
@@ -77,39 +79,40 @@ Variants {
property bool reveal: { property bool reveal: {
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) { if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
return true return true;
} }
return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky;
} }
onContextMenuOpenChanged: { onContextMenuOpenChanged: {
if (!contextMenuOpen && autoHide && !dockMouseArea.containsMouse) { if (!contextMenuOpen && autoHide && !dockMouseArea.containsMouse) {
revealSticky = true revealSticky = true;
revealHold.restart() revealHold.restart();
} }
} }
Connections { Connections {
target: SettingsData target: SettingsData
function onDockTransparencyChanged() { function onDockTransparencyChanged() {
dock.backgroundTransparency = SettingsData.dockTransparency dock.backgroundTransparency = SettingsData.dockTransparency;
} }
} }
screen: modelData screen: modelData
visible: { visible: {
if (CompositorService.isNiri && NiriService.inOverview) { if (CompositorService.isNiri && NiriService.inOverview) {
return SettingsData.dockOpenOnOverview return SettingsData.dockOpenOnOverview;
} }
return SettingsData.showDock return SettingsData.showDock;
} }
color: "transparent" color: "transparent"
exclusiveZone: { exclusiveZone: {
if (!SettingsData.showDock || autoHide) return -1 if (!SettingsData.showDock || autoHide)
if (barSpacing > 0) return -1 return -1;
return px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) if (barSpacing > 0)
return -1;
return px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin);
} }
property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35) property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35)
@@ -122,21 +125,21 @@ Variants {
parent: dock.contentItem parent: dock.contentItem
visible: false visible: false
x: { x: {
const baseX = dockCore.x + dockMouseArea.x const baseX = dockCore.x + dockMouseArea.x;
if (isVertical && SettingsData.dockPosition === SettingsData.Position.Right) { if (isVertical && SettingsData.dockPosition === SettingsData.Position.Right) {
return baseX - animationHeadroom return baseX - animationHeadroom - borderThickness;
} }
return baseX return baseX - borderThickness;
} }
y: { y: {
const baseY = dockCore.y + dockMouseArea.y const baseY = dockCore.y + dockMouseArea.y;
if (!isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom) { if (!isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom) {
return baseY - animationHeadroom return baseY - animationHeadroom - borderThickness;
} }
return baseY return baseY - borderThickness;
} }
width: dockMouseArea.width + (isVertical ? animationHeadroom : 0) width: dockMouseArea.width + (isVertical ? animationHeadroom : 0) + borderThickness * 2
height: dockMouseArea.height + (!isVertical ? animationHeadroom : 0) height: dockMouseArea.height + (!isVertical ? animationHeadroom : 0) + borderThickness * 2
} }
mask: Region { mask: Region {
@@ -145,28 +148,28 @@ Variants {
property var hoveredButton: { property var hoveredButton: {
if (!dockApps.children[0]) { if (!dockApps.children[0]) {
return null return null;
} }
const layoutItem = dockApps.children[0] const layoutItem = dockApps.children[0];
const flowLayout = layoutItem.children[0] const flowLayout = layoutItem.children[0];
let repeater = null let repeater = null;
for (var i = 0; i < flowLayout.children.length; i++) { for (var i = 0; i < flowLayout.children.length; i++) {
const child = flowLayout.children[i] const child = flowLayout.children[i];
if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") { if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") {
repeater = child repeater = child;
break break;
} }
} }
if (!repeater || !repeater.itemAt) { if (!repeater || !repeater.itemAt) {
return null return null;
} }
for (var i = 0; i < repeater.count; i++) { for (var i = 0; i < repeater.count; i++) {
const item = repeater.itemAt(i) const item = repeater.itemAt(i);
if (item && item.dockButton && item.dockButton.showTooltip) { if (item && item.dockButton && item.dockButton.showTooltip) {
return item.dockButton return item.dockButton;
} }
} }
return null return null;
} }
DankTooltip { DankTooltip {
@@ -182,36 +185,25 @@ Variants {
} }
function showTooltipForHoveredButton() { function showTooltipForHoveredButton() {
dockTooltip.hide() dockTooltip.hide();
if (dock.hoveredButton && dock.reveal && !slideXAnimation.running && !slideYAnimation.running) { if (dock.hoveredButton && dock.reveal && !slideXAnimation.running && !slideYAnimation.running) {
const buttonGlobalPos = dock.hoveredButton.mapToGlobal(0, 0) const buttonGlobalPos = dock.hoveredButton.mapToGlobal(0, 0);
const tooltipText = dock.hoveredButton.tooltipText || "" const tooltipText = dock.hoveredButton.tooltipText || "";
if (tooltipText) { if (tooltipText) {
const screenX = dock.screen ? (dock.screen.x || 0) : 0 const screenX = dock.screen ? (dock.screen.x || 0) : 0;
const screenY = dock.screen ? (dock.screen.y || 0) : 0 const screenY = dock.screen ? (dock.screen.y || 0) : 0;
const screenHeight = dock.screen ? dock.screen.height : 0 const screenHeight = dock.screen ? dock.screen.height : 0;
if (!dock.isVertical) { if (!dock.isVertical) {
const isBottom = SettingsData.dockPosition === SettingsData.Position.Bottom const isBottom = SettingsData.dockPosition === SettingsData.Position.Bottom;
const globalX = buttonGlobalPos.x + dock.hoveredButton.width / 2 const globalX = buttonGlobalPos.x + dock.hoveredButton.width / 2;
const screenRelativeY = isBottom const screenRelativeY = isBottom ? (screenHeight - dock.effectiveBarHeight - SettingsData.dockSpacing - SettingsData.dockBottomGap - SettingsData.dockMargin - 35) : (buttonGlobalPos.y - screenY + dock.hoveredButton.height + Theme.spacingS);
? (screenHeight - dock.effectiveBarHeight - SettingsData.dockSpacing - SettingsData.dockBottomGap - SettingsData.dockMargin - 35) dockTooltip.show(tooltipText, globalX, screenRelativeY, dock.screen, false, false);
: (buttonGlobalPos.y - screenY + dock.hoveredButton.height + Theme.spacingS)
dockTooltip.show(tooltipText,
globalX,
screenRelativeY,
dock.screen,
false, false)
} else { } else {
const isLeft = SettingsData.dockPosition === SettingsData.Position.Left const isLeft = SettingsData.dockPosition === SettingsData.Position.Left;
const tooltipOffset = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + Theme.spacingXS const tooltipOffset = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + Theme.spacingXS;
const tooltipX = isLeft ? tooltipOffset : (dock.screen.width - tooltipOffset) const tooltipX = isLeft ? tooltipOffset : (dock.screen.width - tooltipOffset);
const screenRelativeY = buttonGlobalPos.y - screenY + dock.hoveredButton.height / 2 const screenRelativeY = buttonGlobalPos.y - screenY + dock.hoveredButton.height / 2;
dockTooltip.show(tooltipText, dockTooltip.show(tooltipText, screenX + tooltipX, screenRelativeY, dock.screen, isLeft, !isLeft);
screenX + tooltipX,
screenRelativeY,
dock.screen,
isLeft,
!isLeft)
} }
} }
} }
@@ -221,15 +213,15 @@ Variants {
target: dock target: dock
function onRevealChanged() { function onRevealChanged() {
if (!dock.reveal) { if (!dock.reveal) {
tooltipRevealDelay.stop() tooltipRevealDelay.stop();
dockTooltip.hide() dockTooltip.hide();
} else { } else {
tooltipRevealDelay.restart() tooltipRevealDelay.restart();
} }
} }
function onHoveredButtonChanged() { function onHoveredButtonChanged() {
dock.showTooltipForHoveredButton() dock.showTooltipForHoveredButton();
} }
} }
@@ -243,11 +235,11 @@ Variants {
target: dockMouseArea target: dockMouseArea
function onContainsMouseChanged() { function onContainsMouseChanged() {
if (dockMouseArea.containsMouse) { if (dockMouseArea.containsMouse) {
dock.revealSticky = true dock.revealSticky = true;
revealHold.stop() revealHold.stop();
} else { } else {
if (dock.autoHide && !dock.contextMenuOpen) { if (dock.autoHide && !dock.contextMenuOpen) {
revealHold.restart() revealHold.restart();
} }
} }
} }
@@ -263,18 +255,20 @@ Variants {
height: { height: {
if (dock.isVertical) { if (dock.isVertical) {
const hiddenHeight = Math.min(Math.max(dockBackground.implicitHeight + 64, 200), screenHeight * 0.5) const extra = 4 + dock.borderThickness;
return dock.reveal ? Math.max(Math.min(dockBackground.implicitHeight + 4, maxDockHeight), hiddenHeight) : hiddenHeight const hiddenHeight = Math.min(Math.max(dockBackground.implicitHeight + 64, 200), screenHeight * 0.5);
return dock.reveal ? Math.max(Math.min(dockBackground.implicitHeight + extra, maxDockHeight), hiddenHeight) : hiddenHeight;
} else { } else {
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1 return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1;
} }
} }
width: { width: {
if (dock.isVertical) { if (dock.isVertical) {
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1 return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1;
} else { } else {
const hiddenWidth = Math.min(Math.max(dockBackground.implicitWidth + 64, 200), screenWidth * 0.5) const extra = 4 + dock.borderThickness;
return dock.reveal ? Math.max(Math.min(dockBackground.implicitWidth + 4, maxDockWidth), hiddenWidth) : hiddenWidth const hiddenWidth = Math.min(Math.max(dockBackground.implicitWidth + 64, 200), screenWidth * 0.5);
return dock.reveal ? Math.max(Math.min(dockBackground.implicitWidth + extra, maxDockWidth), hiddenWidth) : hiddenWidth;
} }
} }
anchors { anchors {
@@ -310,23 +304,27 @@ Variants {
transform: Translate { transform: Translate {
id: dockSlide id: dockSlide
x: { x: {
if (!dock.isVertical) return 0 if (!dock.isVertical)
if (dock.reveal) return 0 return 0;
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10 if (dock.reveal)
return 0;
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10;
if (SettingsData.dockPosition === SettingsData.Position.Right) { if (SettingsData.dockPosition === SettingsData.Position.Right) {
return hideDistance return hideDistance;
} else { } else {
return -hideDistance return -hideDistance;
} }
} }
y: { y: {
if (dock.isVertical) return 0 if (dock.isVertical)
if (dock.reveal) return 0 return 0;
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10 if (dock.reveal)
return 0;
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10;
if (SettingsData.dockPosition === SettingsData.Position.Bottom) { if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
return hideDistance return hideDistance;
} else { } else {
return -hideDistance return -hideDistance;
} }
} }
@@ -358,10 +356,10 @@ Variants {
right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined
verticalCenter: dock.isVertical ? parent.verticalCenter : undefined verticalCenter: dock.isVertical ? parent.verticalCenter : undefined
} }
anchors.topMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Top ? barSpacing + SettingsData.dockMargin + 1 : 0 anchors.topMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Top ? barSpacing + SettingsData.dockMargin + 1 + dock.borderThickness : 0
anchors.bottomMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? barSpacing + SettingsData.dockMargin + 1 : 0 anchors.bottomMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? barSpacing + SettingsData.dockMargin + 1 + dock.borderThickness : 0
anchors.leftMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Left ? barSpacing + SettingsData.dockMargin + 1 : 0 anchors.leftMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Left ? barSpacing + SettingsData.dockMargin + 1 + dock.borderThickness : 0
anchors.rightMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? barSpacing + SettingsData.dockMargin + 1 : 0 anchors.rightMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? barSpacing + SettingsData.dockMargin + 1 + dock.borderThickness : 0
implicitWidth: dock.isVertical ? (dockApps.implicitHeight + SettingsData.dockSpacing * 2) : (dockApps.implicitWidth + SettingsData.dockSpacing * 2) implicitWidth: dock.isVertical ? (dockApps.implicitHeight + SettingsData.dockSpacing * 2) : (dockApps.implicitWidth + SettingsData.dockSpacing * 2)
implicitHeight: dock.isVertical ? (dockApps.implicitWidth + SettingsData.dockSpacing * 2) : (dockApps.implicitHeight + SettingsData.dockSpacing * 2) implicitHeight: dock.isVertical ? (dockApps.implicitWidth + SettingsData.dockSpacing * 2) : (dockApps.implicitHeight + SettingsData.dockSpacing * 2)
@@ -378,6 +376,68 @@ Variants {
} }
} }
Shape {
id: dockBorderShape
x: dockBackground.x - borderThickness
y: dockBackground.y - borderThickness
width: dockBackground.width + borderThickness * 2
height: dockBackground.height + borderThickness * 2
visible: SettingsData.dockBorderEnabled
preferredRendererType: Shape.CurveRenderer
readonly property real borderThickness: Math.max(1, dock.borderThickness)
readonly property real i: borderThickness / 2
readonly property real cr: Theme.cornerRadius
readonly property real w: dockBackground.width
readonly property real h: dockBackground.height
readonly property color borderColor: {
const opacity = SettingsData.dockBorderOpacity;
switch (SettingsData.dockBorderColor) {
case "secondary":
return Theme.withAlpha(Theme.secondary, opacity);
case "primary":
return Theme.withAlpha(Theme.primary, opacity);
default:
return Theme.withAlpha(Theme.surfaceText, opacity);
}
}
ShapePath {
fillColor: "transparent"
strokeColor: dockBorderShape.borderColor
strokeWidth: dockBorderShape.borderThickness
joinStyle: ShapePath.RoundJoin
capStyle: ShapePath.FlatCap
PathSvg {
path: {
const bt = dockBorderShape.borderThickness;
const i = dockBorderShape.i;
const cr = dockBorderShape.cr + bt - i;
const w = dockBorderShape.w;
const h = dockBorderShape.h;
let d = `M ${i + cr} ${i}`;
d += ` L ${i + w + 2 * (bt - i) - cr} ${i}`;
if (cr > 0)
d += ` A ${cr} ${cr} 0 0 1 ${i + w + 2 * (bt - i)} ${i + cr}`;
d += ` L ${i + w + 2 * (bt - i)} ${i + h + 2 * (bt - i) - cr}`;
if (cr > 0)
d += ` A ${cr} ${cr} 0 0 1 ${i + w + 2 * (bt - i) - cr} ${i + h + 2 * (bt - i)}`;
d += ` L ${i + cr} ${i + h + 2 * (bt - i)}`;
if (cr > 0)
d += ` A ${cr} ${cr} 0 0 1 ${i} ${i + h + 2 * (bt - i) - cr}`;
d += ` L ${i} ${i + cr}`;
if (cr > 0)
d += ` A ${cr} ${cr} 0 0 1 ${i + cr} ${i}`;
d += " Z";
return d;
}
}
}
}
DockApps { DockApps {
id: dockApps id: dockApps

View File

@@ -45,18 +45,18 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
Column {
width: Math.max(0, parent.width - Theme.iconSize - Theme.spacingM - positionButtonGroup.width - Theme.spacingM)
anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
id: positionText
text: I18n.tr("Dock Position") text: I18n.tr("Dock Position")
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter elide: Text.ElideRight
width: parent.width
} }
Item {
width: parent.width - Theme.iconSize - Theme.spacingM - positionText.width - positionButtonGroup.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
} }
DankButtonGroup { DankButtonGroup {
@@ -361,18 +361,18 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
Column {
width: Math.max(0, parent.width - Theme.iconSize - Theme.spacingM - indicatorStyleButtonGroup.width - Theme.spacingM)
anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
id: indicatorStyleText
text: I18n.tr("Indicator Style") text: I18n.tr("Indicator Style")
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter elide: Text.ElideRight
width: parent.width
} }
Item {
width: parent.width - Theme.iconSize - Theme.spacingM - indicatorStyleText.width - indicatorStyleButtonGroup.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
} }
DankButtonGroup { DankButtonGroup {
@@ -760,6 +760,231 @@ Item {
} }
} }
} }
StyledRect {
width: parent.width
height: borderSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.width: 0
Column {
id: borderSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
DankToggle {
width: parent.width
text: I18n.tr("Border")
description: I18n.tr("Add a border around the dock")
checked: SettingsData.dockBorderEnabled
onToggled: checked => {
SettingsData.set("dockBorderEnabled", checked);
}
}
Column {
width: parent.width
leftPadding: Theme.spacingM
spacing: Theme.spacingM
visible: SettingsData.dockBorderEnabled
Rectangle {
width: parent.width - parent.leftPadding
height: 1
color: Theme.outline
opacity: 0.2
}
Row {
width: parent.width - parent.leftPadding
spacing: Theme.spacingM
Column {
width: parent.width - dockBorderColorGroup.width - Theme.spacingM
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Border Color")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
StyledText {
text: I18n.tr("Choose the border accent color")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
width: parent.width
}
}
DankButtonGroup {
id: dockBorderColorGroup
anchors.verticalCenter: parent.verticalCenter
model: ["Surface", "Secondary", "Primary"]
currentIndex: {
switch (SettingsData.dockBorderColor) {
case "surfaceText":
return 0;
case "secondary":
return 1;
case "primary":
return 2;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
switch (index) {
case 0:
SettingsData.set("dockBorderColor", "surfaceText");
break;
case 1:
SettingsData.set("dockBorderColor", "secondary");
break;
case 2:
SettingsData.set("dockBorderColor", "primary");
break;
}
}
}
}
Column {
width: parent.width - parent.leftPadding
spacing: Theme.spacingS
Row {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: I18n.tr("Border Opacity")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - dockBorderOpacityText.implicitWidth - resetDockBorderOpacityBtn.width - Theme.spacingS - Theme.spacingM
height: 1
StyledText {
id: dockBorderOpacityText
visible: false
text: I18n.tr("Border Opacity")
font.pixelSize: Theme.fontSizeSmall
}
}
DankActionButton {
id: resetDockBorderOpacityBtn
buttonSize: 20
iconName: "refresh"
iconSize: 12
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
iconColor: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
onClicked: {
SettingsData.set("dockBorderOpacity", 1.0);
}
}
Item {
width: Theme.spacingS
height: 1
}
}
DankSlider {
id: dockBorderOpacitySlider
width: parent.width
height: 24
value: SettingsData.dockBorderOpacity * 100
minimum: 0
maximum: 100
unit: "%"
showValue: true
wheelEnabled: false
thumbOutlineColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
onSliderValueChanged: newValue => {
SettingsData.set("dockBorderOpacity", newValue / 100);
}
}
}
Column {
width: parent.width - parent.leftPadding
spacing: Theme.spacingS
Row {
width: parent.width
spacing: Theme.spacingS
StyledText {
text: I18n.tr("Border Thickness")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - dockBorderThicknessText.implicitWidth - resetDockBorderThicknessBtn.width - Theme.spacingS - Theme.spacingM
height: 1
StyledText {
id: dockBorderThicknessText
visible: false
text: I18n.tr("Border Thickness")
font.pixelSize: Theme.fontSizeSmall
}
}
DankActionButton {
id: resetDockBorderThicknessBtn
buttonSize: 20
iconName: "refresh"
iconSize: 12
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
iconColor: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
onClicked: {
SettingsData.set("dockBorderThickness", 1);
}
}
Item {
width: Theme.spacingS
height: 1
}
}
DankSlider {
id: dockBorderThicknessSlider
width: parent.width
height: 24
value: SettingsData.dockBorderThickness
minimum: 1
maximum: 10
unit: "px"
showValue: true
wheelEnabled: false
thumbOutlineColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
onSliderValueChanged: newValue => {
SettingsData.set("dockBorderThickness", newValue);
}
}
}
}
}
}
} }
} }
} }