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 dockIconSize: 40
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 int overviewRows: 2

View File

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

View File

@@ -1,14 +1,12 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Shapes
import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets
import qs.Common
import qs.Services
import qs.Widgets
pragma ComponentBehavior: Bound
Variants {
id: dockVariants
model: SettingsData.getFilteredScreens("dock")
@@ -30,376 +28,438 @@ Variants {
}
property var modelData: item
property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency
property bool groupByApp: SettingsData.dockGroupByApp
property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency
property bool groupByApp: SettingsData.dockGroupByApp
readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0
readonly property real widgetHeight: SettingsData.dockIconSize
readonly property real effectiveBarHeight: widgetHeight + SettingsData.dockSpacing * 2 + 10
readonly property real barSpacing: {
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default")
if (!defaultBar) return 0
readonly property real widgetHeight: SettingsData.dockIconSize
readonly property real effectiveBarHeight: widgetHeight + SettingsData.dockSpacing * 2 + 10 + borderThickness * 2
readonly property real barSpacing: {
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default");
if (!defaultBar)
return 0;
const barPos = defaultBar.position ?? SettingsData.Position.Top
const barIsHorizontal = (barPos === SettingsData.Position.Top || barPos === SettingsData.Position.Bottom)
const barIsVertical = (barPos === SettingsData.Position.Left || barPos === SettingsData.Position.Right)
const samePosition = (SettingsData.dockPosition === barPos)
const dockIsHorizontal = !isVertical
const dockIsVertical = isVertical
const barPos = defaultBar.position ?? SettingsData.Position.Top;
const barIsHorizontal = (barPos === SettingsData.Position.Top || barPos === SettingsData.Position.Bottom);
const barIsVertical = (barPos === SettingsData.Position.Left || barPos === SettingsData.Position.Right);
const samePosition = (SettingsData.dockPosition === barPos);
const dockIsHorizontal = !isVertical;
const dockIsVertical = isVertical;
if (!(defaultBar.visible ?? true)) return 0
const spacing = defaultBar.spacing ?? 4
const bottomGap = defaultBar.bottomGap ?? 0
if (dockIsHorizontal && barIsHorizontal && samePosition) {
return spacing + effectiveBarHeight + bottomGap
}
if (dockIsVertical && barIsVertical && samePosition) {
return spacing + effectiveBarHeight + bottomGap
}
return 0
}
readonly property real dockMargin: SettingsData.dockSpacing
readonly property real positionSpacing: barSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin
readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1
function px(v) { return Math.round(v * _dpr) / _dpr }
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
property bool revealSticky: false
Timer {
id: revealHold
interval: 250
repeat: false
onTriggered: dock.revealSticky = false
}
property bool reveal: {
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
return true
}
return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky
}
onContextMenuOpenChanged: {
if (!contextMenuOpen && autoHide && !dockMouseArea.containsMouse) {
revealSticky = true
revealHold.restart()
}
}
Connections {
target: SettingsData
function onDockTransparencyChanged() {
dock.backgroundTransparency = SettingsData.dockTransparency
}
}
screen: modelData
visible: {
if (CompositorService.isNiri && NiriService.inOverview) {
return SettingsData.dockOpenOnOverview
}
return SettingsData.showDock
}
color: "transparent"
exclusiveZone: {
if (!SettingsData.showDock || autoHide) return -1
if (barSpacing > 0) return -1
return px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin)
}
property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35)
implicitWidth: isVertical ? (px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
implicitHeight: !isVertical ? (px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
Item {
id: maskItem
parent: dock.contentItem
visible: false
x: {
const baseX = dockCore.x + dockMouseArea.x
if (isVertical && SettingsData.dockPosition === SettingsData.Position.Right) {
return baseX - animationHeadroom
if (!(defaultBar.visible ?? true))
return 0;
const spacing = defaultBar.spacing ?? 4;
const bottomGap = defaultBar.bottomGap ?? 0;
if (dockIsHorizontal && barIsHorizontal && samePosition) {
return spacing + effectiveBarHeight + bottomGap;
}
return baseX
}
y: {
const baseY = dockCore.y + dockMouseArea.y
if (!isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom) {
return baseY - animationHeadroom
if (dockIsVertical && barIsVertical && samePosition) {
return spacing + effectiveBarHeight + bottomGap;
}
return baseY
return 0;
}
width: dockMouseArea.width + (isVertical ? animationHeadroom : 0)
height: dockMouseArea.height + (!isVertical ? animationHeadroom : 0)
}
mask: Region {
item: maskItem
}
property var hoveredButton: {
if (!dockApps.children[0]) {
return null
readonly property real dockMargin: SettingsData.dockSpacing
readonly property real positionSpacing: barSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin
readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1
function px(v) {
return Math.round(v * _dpr) / _dpr;
}
const layoutItem = dockApps.children[0]
const flowLayout = layoutItem.children[0]
let repeater = null
for (var i = 0; i < flowLayout.children.length; i++) {
const child = flowLayout.children[i]
if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") {
repeater = child
break
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
property bool revealSticky: false
Timer {
id: revealHold
interval: 250
repeat: false
onTriggered: dock.revealSticky = false
}
property bool reveal: {
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
return true;
}
return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky;
}
onContextMenuOpenChanged: {
if (!contextMenuOpen && autoHide && !dockMouseArea.containsMouse) {
revealSticky = true;
revealHold.restart();
}
}
if (!repeater || !repeater.itemAt) {
return null
}
for (var i = 0; i < repeater.count; i++) {
const item = repeater.itemAt(i)
if (item && item.dockButton && item.dockButton.showTooltip) {
return item.dockButton
}
}
return null
}
DankTooltip {
id: dockTooltip
targetScreen: dock.screen
}
Timer {
id: tooltipRevealDelay
interval: 250
repeat: false
onTriggered: dock.showTooltipForHoveredButton()
}
function showTooltipForHoveredButton() {
dockTooltip.hide()
if (dock.hoveredButton && dock.reveal && !slideXAnimation.running && !slideYAnimation.running) {
const buttonGlobalPos = dock.hoveredButton.mapToGlobal(0, 0)
const tooltipText = dock.hoveredButton.tooltipText || ""
if (tooltipText) {
const screenX = dock.screen ? (dock.screen.x || 0) : 0
const screenY = dock.screen ? (dock.screen.y || 0) : 0
const screenHeight = dock.screen ? dock.screen.height : 0
if (!dock.isVertical) {
const isBottom = SettingsData.dockPosition === SettingsData.Position.Bottom
const globalX = buttonGlobalPos.x + dock.hoveredButton.width / 2
const screenRelativeY = isBottom
? (screenHeight - dock.effectiveBarHeight - SettingsData.dockSpacing - SettingsData.dockBottomGap - SettingsData.dockMargin - 35)
: (buttonGlobalPos.y - screenY + dock.hoveredButton.height + Theme.spacingS)
dockTooltip.show(tooltipText,
globalX,
screenRelativeY,
dock.screen,
false, false)
} else {
const isLeft = SettingsData.dockPosition === SettingsData.Position.Left
const tooltipOffset = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + Theme.spacingXS
const tooltipX = isLeft ? tooltipOffset : (dock.screen.width - tooltipOffset)
const screenRelativeY = buttonGlobalPos.y - screenY + dock.hoveredButton.height / 2
dockTooltip.show(tooltipText,
screenX + tooltipX,
screenRelativeY,
dock.screen,
isLeft,
!isLeft)
}
}
}
}
Connections {
target: dock
function onRevealChanged() {
if (!dock.reveal) {
tooltipRevealDelay.stop()
dockTooltip.hide()
} else {
tooltipRevealDelay.restart()
}
}
function onHoveredButtonChanged() {
dock.showTooltipForHoveredButton()
}
}
Item {
id: dockCore
anchors.fill: parent
x: isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? animationHeadroom : 0
y: !isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? animationHeadroom : 0
Connections {
target: dockMouseArea
function onContainsMouseChanged() {
if (dockMouseArea.containsMouse) {
dock.revealSticky = true
revealHold.stop()
} else {
if (dock.autoHide && !dock.contextMenuOpen) {
revealHold.restart()
target: SettingsData
function onDockTransparencyChanged() {
dock.backgroundTransparency = SettingsData.dockTransparency;
}
}
screen: modelData
visible: {
if (CompositorService.isNiri && NiriService.inOverview) {
return SettingsData.dockOpenOnOverview;
}
return SettingsData.showDock;
}
color: "transparent"
exclusiveZone: {
if (!SettingsData.showDock || autoHide)
return -1;
if (barSpacing > 0)
return -1;
return px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin);
}
property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35)
implicitWidth: isVertical ? (px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
implicitHeight: !isVertical ? (px(effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
Item {
id: maskItem
parent: dock.contentItem
visible: false
x: {
const baseX = dockCore.x + dockMouseArea.x;
if (isVertical && SettingsData.dockPosition === SettingsData.Position.Right) {
return baseX - animationHeadroom - borderThickness;
}
return baseX - borderThickness;
}
y: {
const baseY = dockCore.y + dockMouseArea.y;
if (!isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom) {
return baseY - animationHeadroom - borderThickness;
}
return baseY - borderThickness;
}
width: dockMouseArea.width + (isVertical ? animationHeadroom : 0) + borderThickness * 2
height: dockMouseArea.height + (!isVertical ? animationHeadroom : 0) + borderThickness * 2
}
mask: Region {
item: maskItem
}
property var hoveredButton: {
if (!dockApps.children[0]) {
return null;
}
const layoutItem = dockApps.children[0];
const flowLayout = layoutItem.children[0];
let repeater = null;
for (var i = 0; i < flowLayout.children.length; i++) {
const child = flowLayout.children[i];
if (child && typeof child.count !== "undefined" && typeof child.itemAt === "function") {
repeater = child;
break;
}
}
if (!repeater || !repeater.itemAt) {
return null;
}
for (var i = 0; i < repeater.count; i++) {
const item = repeater.itemAt(i);
if (item && item.dockButton && item.dockButton.showTooltip) {
return item.dockButton;
}
}
return null;
}
DankTooltip {
id: dockTooltip
targetScreen: dock.screen
}
Timer {
id: tooltipRevealDelay
interval: 250
repeat: false
onTriggered: dock.showTooltipForHoveredButton()
}
function showTooltipForHoveredButton() {
dockTooltip.hide();
if (dock.hoveredButton && dock.reveal && !slideXAnimation.running && !slideYAnimation.running) {
const buttonGlobalPos = dock.hoveredButton.mapToGlobal(0, 0);
const tooltipText = dock.hoveredButton.tooltipText || "";
if (tooltipText) {
const screenX = dock.screen ? (dock.screen.x || 0) : 0;
const screenY = dock.screen ? (dock.screen.y || 0) : 0;
const screenHeight = dock.screen ? dock.screen.height : 0;
if (!dock.isVertical) {
const isBottom = SettingsData.dockPosition === SettingsData.Position.Bottom;
const globalX = buttonGlobalPos.x + dock.hoveredButton.width / 2;
const screenRelativeY = isBottom ? (screenHeight - dock.effectiveBarHeight - SettingsData.dockSpacing - SettingsData.dockBottomGap - SettingsData.dockMargin - 35) : (buttonGlobalPos.y - screenY + dock.hoveredButton.height + Theme.spacingS);
dockTooltip.show(tooltipText, globalX, screenRelativeY, dock.screen, false, false);
} else {
const isLeft = SettingsData.dockPosition === SettingsData.Position.Left;
const tooltipOffset = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockMargin + Theme.spacingXS;
const tooltipX = isLeft ? tooltipOffset : (dock.screen.width - tooltipOffset);
const screenRelativeY = buttonGlobalPos.y - screenY + dock.hoveredButton.height / 2;
dockTooltip.show(tooltipText, screenX + tooltipX, screenRelativeY, dock.screen, isLeft, !isLeft);
}
}
}
}
MouseArea {
id: dockMouseArea
property real currentScreen: modelData ? modelData : dock.screen
property real screenWidth: currentScreen ? currentScreen.geometry.width : 1920
property real screenHeight: currentScreen ? currentScreen.geometry.height : 1080
property real maxDockWidth: screenWidth * 0.98
property real maxDockHeight: screenHeight * 0.98
height: {
if (dock.isVertical) {
const hiddenHeight = Math.min(Math.max(dockBackground.implicitHeight + 64, 200), screenHeight * 0.5)
return dock.reveal ? Math.max(Math.min(dockBackground.implicitHeight + 4, maxDockHeight), hiddenHeight) : hiddenHeight
Connections {
target: dock
function onRevealChanged() {
if (!dock.reveal) {
tooltipRevealDelay.stop();
dockTooltip.hide();
} else {
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1
}
}
width: {
if (dock.isVertical) {
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1
} else {
const hiddenWidth = Math.min(Math.max(dockBackground.implicitWidth + 64, 200), screenWidth * 0.5)
return dock.reveal ? Math.max(Math.min(dockBackground.implicitWidth + 4, maxDockWidth), hiddenWidth) : hiddenWidth
}
}
anchors {
top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? undefined : parent.top) : undefined
bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? parent.bottom : undefined) : undefined
horizontalCenter: !dock.isVertical ? parent.horizontalCenter : undefined
left: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? undefined : parent.left) : undefined
right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined
verticalCenter: dock.isVertical ? parent.verticalCenter : undefined
}
hoverEnabled: true
acceptedButtons: Qt.NoButton
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
tooltipRevealDelay.restart();
}
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
function onHoveredButtonChanged() {
dock.showTooltipForHoveredButton();
}
}
Item {
id: dockContainer
anchors.fill: parent
clip: false
Item {
id: dockCore
anchors.fill: parent
x: isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? animationHeadroom : 0
y: !isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? animationHeadroom : 0
transform: Translate {
id: dockSlide
x: {
if (!dock.isVertical) return 0
if (dock.reveal) return 0
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10
if (SettingsData.dockPosition === SettingsData.Position.Right) {
return hideDistance
} else {
return -hideDistance
}
}
y: {
if (dock.isVertical) return 0
if (dock.reveal) return 0
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10
if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
return hideDistance
} else {
return -hideDistance
Connections {
target: dockMouseArea
function onContainsMouseChanged() {
if (dockMouseArea.containsMouse) {
dock.revealSticky = true;
revealHold.stop();
} else {
if (dock.autoHide && !dock.contextMenuOpen) {
revealHold.restart();
}
}
}
}
Behavior on x {
NumberAnimation {
id: slideXAnimation
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
MouseArea {
id: dockMouseArea
property real currentScreen: modelData ? modelData : dock.screen
property real screenWidth: currentScreen ? currentScreen.geometry.width : 1920
property real screenHeight: currentScreen ? currentScreen.geometry.height : 1080
property real maxDockWidth: screenWidth * 0.98
property real maxDockHeight: screenHeight * 0.98
Behavior on y {
NumberAnimation {
id: slideYAnimation
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
height: {
if (dock.isVertical) {
const extra = 4 + dock.borderThickness;
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 {
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1;
}
}
width: {
if (dock.isVertical) {
return dock.reveal ? px(dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin) : 1;
} else {
const extra = 4 + dock.borderThickness;
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 {
top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? undefined : parent.top) : undefined
bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? parent.bottom : undefined) : undefined
horizontalCenter: !dock.isVertical ? parent.horizontalCenter : undefined
left: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? undefined : parent.left) : undefined
right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined
verticalCenter: dock.isVertical ? parent.verticalCenter : undefined
}
hoverEnabled: true
acceptedButtons: Qt.NoButton
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Item {
id: dockBackground
objectName: "dockBackground"
anchors {
top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Top ? parent.top : undefined) : undefined
bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? parent.bottom : undefined) : undefined
horizontalCenter: !dock.isVertical ? parent.horizontalCenter : undefined
left: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Left ? parent.left : undefined) : undefined
right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined
verticalCenter: dock.isVertical ? parent.verticalCenter : undefined
}
anchors.topMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Top ? barSpacing + SettingsData.dockMargin + 1 : 0
anchors.bottomMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? barSpacing + SettingsData.dockMargin + 1 : 0
anchors.leftMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Left ? barSpacing + SettingsData.dockMargin + 1 : 0
anchors.rightMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? barSpacing + SettingsData.dockMargin + 1 : 0
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)
width: implicitWidth
height: implicitHeight
layer.enabled: true
id: dockContainer
anchors.fill: parent
clip: false
DankRectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency)
overlayColor: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
transform: Translate {
id: dockSlide
x: {
if (!dock.isVertical)
return 0;
if (dock.reveal)
return 0;
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10;
if (SettingsData.dockPosition === SettingsData.Position.Right) {
return hideDistance;
} else {
return -hideDistance;
}
}
y: {
if (dock.isVertical)
return 0;
if (dock.reveal)
return 0;
const hideDistance = dock.effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin + 10;
if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
return hideDistance;
} else {
return -hideDistance;
}
}
Behavior on x {
NumberAnimation {
id: slideXAnimation
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on y {
NumberAnimation {
id: slideYAnimation
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
}
}
DockApps {
id: dockApps
Item {
id: dockBackground
objectName: "dockBackground"
anchors {
top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Top ? parent.top : undefined) : undefined
bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? parent.bottom : undefined) : undefined
horizontalCenter: !dock.isVertical ? parent.horizontalCenter : undefined
left: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Left ? parent.left : undefined) : undefined
right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined
verticalCenter: dock.isVertical ? parent.verticalCenter : undefined
}
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 + dock.borderThickness : 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 + dock.borderThickness : 0
anchors.top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Top ? dockBackground.top : undefined) : undefined
anchors.bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? dockBackground.bottom : undefined) : undefined
anchors.horizontalCenter: !dock.isVertical ? dockBackground.horizontalCenter : undefined
anchors.left: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Left ? dockBackground.left : undefined) : undefined
anchors.right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? dockBackground.right : undefined) : undefined
anchors.verticalCenter: dock.isVertical ? dockBackground.verticalCenter : undefined
anchors.topMargin: !dock.isVertical ? SettingsData.dockSpacing : 0
anchors.bottomMargin: !dock.isVertical ? SettingsData.dockSpacing : 0
anchors.leftMargin: dock.isVertical ? SettingsData.dockSpacing : 0
anchors.rightMargin: dock.isVertical ? SettingsData.dockSpacing : 0
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)
width: implicitWidth
height: implicitHeight
contextMenu: dockVariants.contextMenu
groupByApp: dock.groupByApp
isVertical: dock.isVertical
dockScreen: dock.screen
iconSize: dock.widgetHeight
layer.enabled: true
clip: false
DankRectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency)
overlayColor: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
}
}
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 {
id: dockApps
anchors.top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Top ? dockBackground.top : undefined) : undefined
anchors.bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom ? dockBackground.bottom : undefined) : undefined
anchors.horizontalCenter: !dock.isVertical ? dockBackground.horizontalCenter : undefined
anchors.left: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Left ? dockBackground.left : undefined) : undefined
anchors.right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? dockBackground.right : undefined) : undefined
anchors.verticalCenter: dock.isVertical ? dockBackground.verticalCenter : undefined
anchors.topMargin: !dock.isVertical ? SettingsData.dockSpacing : 0
anchors.bottomMargin: !dock.isVertical ? SettingsData.dockSpacing : 0
anchors.leftMargin: dock.isVertical ? SettingsData.dockSpacing : 0
anchors.rightMargin: dock.isVertical ? SettingsData.dockSpacing : 0
contextMenu: dockVariants.contextMenu
groupByApp: dock.groupByApp
isVertical: dock.isVertical
dockScreen: dock.screen
iconSize: dock.widgetHeight
}
}
}
}
}
}
}

View File

@@ -45,18 +45,18 @@ Item {
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
id: positionText
text: I18n.tr("Dock Position")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
Column {
width: Math.max(0, parent.width - Theme.iconSize - Theme.spacingM - positionButtonGroup.width - Theme.spacingM)
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - Theme.iconSize - Theme.spacingM - positionText.width - positionButtonGroup.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: I18n.tr("Dock Position")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
elide: Text.ElideRight
width: parent.width
}
}
DankButtonGroup {
@@ -361,18 +361,18 @@ Item {
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
id: indicatorStyleText
text: I18n.tr("Indicator Style")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
Column {
width: Math.max(0, parent.width - Theme.iconSize - Theme.spacingM - indicatorStyleButtonGroup.width - Theme.spacingM)
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: parent.width - Theme.iconSize - Theme.spacingM - indicatorStyleText.width - indicatorStyleButtonGroup.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: I18n.tr("Indicator Style")
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
elide: Text.ElideRight
width: parent.width
}
}
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);
}
}
}
}
}
}
}
}
}