Skip to content

Commit 4004041

Browse files
committed
feat: add FashionAlignment mode for dock panel
1. Implement new FashionAlignment enum value (2) for dock item alignment 2. Create FashionDockController QML component to manage fashion dock layout and appearance 3. Add "Fashion Mode" menu item in dock context menu for easy mode switching 4. Integrate fashion dock logic into main dock window: adjust width, anchors, margins, window radius, and blur effects 5. Update showdesktop and taskmanager to be hidden or behave differently in fashion mode 6. Ensure width animation when entering/exiting fashion mode 7. Add appropriate DTK blur and styling for fashion dock appearance 8. Update string conversion functions to support the new "fashion" alignment 9. Hide left part and adjust spacing in fashion mode for a compact, floating design Log: Added new dock fashion alignment mode with floating UI and compact layout Influence: 1. Test switching between Center, Left, and Fashion alignment modes via context menu 2. Verify fashion mode only enables on Bottom/Top positions and not in column layout 3. Check that showdesktop widget is hidden in fashion mode 4. Verify dock width and margin adjustments in fashion mode (floating margin, vertical padding) 5. Test taskmanager behavior in fashion mode (no remaining space calculation, no text calculator) 6. Verify blur and color blending correctness in fashion mode for both light and dark themes 7. Test width animation when enabling/disabling fashion mode 8. Verify dock exclusion zone includes floating margin in fashion mode 9. Test on different screen sizes and DPI settings 10. Validate that left part and its items are hidden in fashion mode feat: 新增时尚模式对齐方式 1. 实现新的时尚模式对齐枚举值 (2),用于 dock 面板的项目对齐 2. 创建 FashionDockController QML 组件,管理时尚模式布局和外观 3. 在 dock 右键菜单中添加 "时尚模式" 菜单项,便于模式切换 4. 将时尚模式逻辑集成到主 dock 窗口中:调整宽度、锚点、边距、窗口圆角和 模糊效果 5. 更新显示桌面和任务管理器,使其在时尚模式下隐藏或改变行为 6. 在进入/退出时尚模式时启用宽度动画 7. 为时尚模式外观添加合适的 DTK 模糊和样式 8. 更新字符串转换函数以支持新的 "fashion" 对齐方式 9. 在时尚模式下隐藏左侧部分并调整间距,实现紧凑浮动设计 Log: 新增时尚模式对齐方式,浮动UI和紧凑布局 Influence: 1. 通过右键菜单测试中心、左对齐和时尚模式之间的切换 2. 验证时尚模式仅在底部/顶部位置且非列布局时启用 3. 检查显示桌面小部件在时尚模式下是否隐藏 4. 验证时尚模式下的 dock 宽度和边距调整(浮动边距、垂直内边距) 5. 测试任务管理器在时尚模式下的行为(无剩余空间计算、无文本计算器) 6. 验证时尚模式下浅色和深色主题的模糊和颜色混合正确性 7. 测试启用/禁用时尚模式时的宽度动画 8. 验证时尚模式下 dock 排除区域包含浮动边距 9. 在不同屏幕尺寸和 DPI 设置下进行测试 10. 验证左侧部分及其项目在时尚模式下是否隐藏
1 parent 76ef0ba commit 4004041

6 files changed

Lines changed: 150 additions & 20 deletions

File tree

panels/dock/constants.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
22
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
3-
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
3+
// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd.
44
//
55
// SPDX-License-Identifier: GPL-3.0-or-later
66
// SPDX-License-Identifier: LGPL-3.0-or-later
@@ -36,6 +36,7 @@ enum IndicatorStyle {
3636
enum ItemAlignment {
3737
CenterAlignment = 0,
3838
LeftAlignment = 1,
39+
FashionAlignment = 2,
3940
};
4041

4142
enum ColorTheme {

panels/dock/docksettings.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ static QString itemAlignment2String(const ItemAlignment& alignment)
8585
return "left";
8686
case ItemAlignment::CenterAlignment:
8787
return "center";
88+
case ItemAlignment::FashionAlignment:
89+
return "fashion";
8890
}
8991

9092
return "center";
@@ -111,6 +113,8 @@ static ItemAlignment string2ItenAlignment(const QString& alignmentStr)
111113
return ItemAlignment::LeftAlignment;
112114
else if (alignmentStr == "center")
113115
return ItemAlignment::CenterAlignment;
116+
else if (alignmentStr == "fashion")
117+
return ItemAlignment::FashionAlignment;
114118

115119
return ItemAlignment::CenterAlignment;
116120
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
2+
//
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
import QtQuick 2.15
6+
7+
import org.deepin.ds 1.0
8+
import org.deepin.ds.dock 1.0
9+
import org.deepin.dtk.style 1.0 as DStyle
10+
11+
QtObject {
12+
id: root
13+
14+
property bool useColumnLayout: false
15+
property int itemAlignment: Dock.CenterAlignment
16+
property int position: Dock.Bottom
17+
property int hideState: Dock.Show
18+
property real dockSize: 0
19+
property real dockItemIconSize: 0
20+
property real devicePixelRatio: 1
21+
property int screenWidth: 0
22+
property int colorTheme: Dock.Light
23+
property bool dragging: false
24+
property var gridLayout: null
25+
property var rightPart: null
26+
27+
readonly property bool enabled: !useColumnLayout
28+
&& itemAlignment === Dock.FashionAlignment
29+
&& (position === Dock.Bottom || position === Dock.Top)
30+
readonly property bool topMode: enabled && position === Dock.Top
31+
readonly property bool bottomMode: enabled && position === Dock.Bottom
32+
readonly property int floatingMargin: 8
33+
readonly property int verticalPadding: Math.max(6, Math.round(dockSize * 0.16))
34+
readonly property int surfaceThickness: useColumnLayout ? dockSize : dockSize + verticalPadding * 2
35+
readonly property int backgroundRadius: Math.round(surfaceThickness / 4)
36+
readonly property real gridDisplayedWidth: enabled && gridLayout
37+
? gridLayout.implicitWidth
38+
: 0
39+
readonly property real gridDisplayedHeight: enabled && gridLayout
40+
? gridLayout.implicitHeight
41+
: 0
42+
readonly property real contentWidth: {
43+
if (!enabled) {
44+
return 0
45+
}
46+
47+
let width = gridDisplayedWidth
48+
if (rightPart && rightPart.visible) {
49+
if (width > 0) {
50+
width += gridLayout.columnSpacing
51+
}
52+
width += rightPart.implicitWidth
53+
}
54+
return width
55+
}
56+
readonly property bool widthAnimationEnabled: enabled && !dragging
57+
58+
function effectiveShellWidth() {
59+
if (!enabled) {
60+
return 0
61+
}
62+
63+
return Math.min(contentWidth, screenWidth)
64+
}
65+
}

panels/dock/package/main.qml

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,42 @@ import Qt.labs.platform as LP
1313
import org.deepin.ds 1.0
1414
import org.deepin.ds.dock 1.0
1515
import org.deepin.dtk 1.0 as D
16-
import org.deepin.dtk.style 1.0 as DStyle
1716

1817
Window {
1918
id: dock
2019
property int positionForAnimation: Panel.position
2120
property bool useColumnLayout: positionForAnimation % 2
21+
22+
FashionDockController {
23+
id: fashionDockController
24+
useColumnLayout: dock.useColumnLayout
25+
itemAlignment: Panel.itemAlignment
26+
position: dock.positionForAnimation
27+
hideState: Panel.hideState
28+
dockSize: dock.dockSize
29+
dockItemIconSize: dock.dockItemIconSize
30+
devicePixelRatio: Panel.devicePixelRatio > 0 ? Panel.devicePixelRatio : Screen.devicePixelRatio
31+
screenWidth: Screen.width
32+
colorTheme: Panel.colorTheme
33+
dragging: dock.isDragging
34+
gridLayout: gridLayout
35+
rightPart: dockRightPart
36+
}
37+
38+
property alias fashionDock: fashionDockController
2239
property int dockCenterPartCount: dockCenterPartModel.count
2340

2441
readonly property int dockRawCenterSpace: {
2542
if (useColumnLayout) {
2643
return Screen.height - dockLeftPart.implicitHeight - dockRightPart.implicitHeight;
2744
} else {
28-
return Screen.width - dockLeftPart.implicitWidth - dockRightPart.implicitWidth;
45+
let space = Screen.width - dockLeftPart.implicitWidth - dockRightPart.implicitWidth;
46+
if (fashionDock.enabled && gridLayout) {
47+
// 时尚模式下,dockRightPart 在 gridLayout 右侧,之间需要扣除 dockSpacing
48+
// 这是为了确保 gridLayout 的宽度 + dockSpacing + rightPart 宽度 <= screenWidth
49+
space -= Math.ceil(gridLayout.columnSpacing);
50+
}
51+
return Math.max(0, space);
2952
}
3053
}
3154

@@ -45,7 +68,13 @@ Window {
4568
property real dockItemIconSize: dockItemMaxSize * 9 / 14
4669

4770
// NOTE: -1 means not set its size, follow the platform size
48-
width: positionForAnimation === Dock.Top || positionForAnimation === Dock.Bottom ? -1 : dockSize
71+
width: {
72+
if (fashionDock.enabled) {
73+
return Math.max(1, fashionDock.effectiveShellWidth())
74+
}
75+
76+
return positionForAnimation === Dock.Top || positionForAnimation === Dock.Bottom ? -1 : dockSize
77+
}
4978
height: positionForAnimation === Dock.Left || positionForAnimation === Dock.Right ? -1 : dockSize
5079
color: "transparent"
5180
flags: Qt.WindowDoesNotAcceptFocus
@@ -65,14 +94,21 @@ Window {
6594
MenuHelper.openMenu(dockMenuLoader.item)
6695
}
6796

68-
DLayerShellWindow.anchors: position2Anchors(positionForAnimation)
97+
DLayerShellWindow.anchors: fashionDock.enabled
98+
? (fashionDock.topMode ? DLayerShellWindow.AnchorTop : DLayerShellWindow.AnchorBottom)
99+
: position2Anchors(positionForAnimation)
100+
DLayerShellWindow.topMargin: fashionDock.topMode ? fashionDock.floatingMargin : 0
101+
102+
DLayerShellWindow.bottomMargin: fashionDock.bottomMode ? fashionDock.floatingMargin : 0
69103
DLayerShellWindow.layer: DLayerShellWindow.LayerTop
70-
DLayerShellWindow.exclusionZone: Panel.hideMode === Dock.KeepShowing ? Applet.dockSize : 0
104+
DLayerShellWindow.exclusionZone: Panel.hideMode === Dock.KeepShowing
105+
? Applet.dockSize + (fashionDock.enabled ? fashionDock.floatingMargin : 0)
106+
: 0
71107
DLayerShellWindow.scope: "dde-shell/dock"
72108
DLayerShellWindow.keyboardInteractivity: DLayerShellWindow.KeyboardInteractivityOnDemand
73109

74110
D.DWindow.enabled: true
75-
D.DWindow.windowRadius: 0
111+
D.DWindow.windowRadius: fashionDock.enabled ? fashionDock.backgroundRadius : 0
76112
//TODO:由于windoweffect处理有BUG,导致动画结束后一致保持无阴影,无borderwidth状态。 无法恢复到最初的阴影和边框
77113
//D.DWindow.windowEffect: hideShowAnimation.running ? D.PlatformHandle.EffectNoShadow | D.PlatformHandle.EffectNoBorder : 0
78114

@@ -89,12 +125,21 @@ Window {
89125
D.ColorSelector.family: D.Palette.CrystalColor
90126

91127
onDockSizeChanged: {
92-
if (dock.dockSize === Dock.MIN_DOCK_SIZE) {
128+
if (fashionDock.enabled) {
129+
Panel.indicatorStyle = Dock.Fashion
130+
} else if (dock.dockSize === Dock.MIN_DOCK_SIZE) {
93131
Panel.indicatorStyle = Dock.Efficient
94132
} else {
95133
Panel.indicatorStyle = Dock.Fashion
96134
}
97135
}
136+
Behavior on width {
137+
enabled: fashionDock.widthAnimationEnabled
138+
NumberAnimation {
139+
duration: 200
140+
easing.type: Easing.OutQuad
141+
}
142+
}
98143

99144
Binding on itemIconSizeBase {
100145
when: !isDragging
@@ -326,6 +371,11 @@ Window {
326371
prop: "itemAlignment"
327372
value: Dock.CenterAlignment
328373
}
374+
EnumPropertyMenuItem {
375+
name: qsTr("Fashion Mode")
376+
prop: "itemAlignment"
377+
value: Dock.FashionAlignment
378+
}
329379
}
330380
MutuallyExclusiveMenu {
331381
title: qsTr("Position")
@@ -401,7 +451,7 @@ Window {
401451
D.StyledBehindWindowBlur {
402452
control: parent
403453
anchors.fill: parent
404-
cornerRadius: 0
454+
cornerRadius: fashionDock.enabled ? fashionDock.backgroundRadius : 0
405455
blendColor: {
406456
if (valid) {
407457
return DStyle.Style.control.selectColor(undefined,
@@ -476,7 +526,7 @@ Window {
476526
//此处为边距区域的点击实践特殊处理。
477527
MouseArea {
478528
id: leftMarginArea
479-
width: useColumnLayout ? parent.width : gridLayout.columnSpacing
529+
width: useColumnLayout ? parent.width : (fashionDock.enabled ? 0 : gridLayout.columnSpacing)
480530
height: useColumnLayout ? gridLayout.rowSpacing : parent.height
481531
anchors.left: parent.left
482532
anchors.top: parent.top
@@ -505,13 +555,14 @@ Window {
505555

506556
Item {
507557
id: leftMargin
558+
visible: !fashionDock.enabled
508559
implicitWidth: 0
509560
implicitHeight: 0
510561
}
511562

512563
Item {
513564
id: dockLeftPart
514-
visible: dockLeftPartModel.count > 0
565+
visible: !fashionDock.enabled && dockLeftPartModel.count > 0
515566
implicitWidth: leftLoader.implicitWidth
516567
implicitHeight: leftLoader.implicitHeight
517568
OverflowContainer {
@@ -534,7 +585,7 @@ Window {
534585
Layout.maximumHeight: useColumnLayout ? dockRawCenterSpace : -1
535586
onXChanged: dockCenterPartPosChanged()
536587
onYChanged: dockCenterPartPosChanged()
537-
Layout.leftMargin: !useColumnLayout && Panel.itemAlignment === Dock.CenterAlignment ?
588+
Layout.leftMargin: !useColumnLayout && !fashionDock.enabled && Panel.itemAlignment === Dock.CenterAlignment ?
538589
Math.max(0, (dock.width - dockCenterPart.implicitWidth) / 2 - (dockLeftPart.implicitWidth + 20) + Math.min((dock.width - dockCenterPart.implicitWidth) / 2 - (dockRightPart.implicitWidth + 20), 0)) : 0
539590
Layout.topMargin: useColumnLayout && Panel.itemAlignment === Dock.CenterAlignment ?
540591
Math.max(0, (dock.height - dockCenterPart.implicitHeight) / 2 - (dockLeftPart.implicitHeight + 20) + Math.min((dock.height - dockCenterPart.implicitHeight) / 2 - (dockRightPart.implicitHeight + 20), 0)) : 0
@@ -569,8 +620,9 @@ Window {
569620
}
570621

571622
Item {
572-
Layout.fillWidth: true
573-
Layout.fillHeight: true
623+
Layout.fillWidth: !fashionDock.enabled
624+
Layout.fillHeight: !fashionDock.enabled
625+
visible: !fashionDock.enabled
574626
}
575627
}
576628

panels/dock/showdesktop/package/showdesktop.qml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -13,11 +13,13 @@ AppletItem {
1313
id: showdesktop
1414
readonly property int showDesktopWidth: 10
1515
property bool useColumnLayout: Panel.position % 2
16+
readonly property bool fashionMode: Panel.rootObject && Panel.rootObject.fashionDock && Panel.rootObject.fashionDock.enabled
1617
property int dockSize: Panel.rootObject.dockItemMaxSize
1718
property int dockOrder: 30
18-
property bool shouldVisible: Applet.visible
19-
implicitWidth: useColumnLayout ? Panel.rootObject.dockSize : showDesktopWidth
20-
implicitHeight: useColumnLayout ? showDesktopWidth : Panel.rootObject.dockSize
19+
property bool shouldVisible: Applet.visible && !fashionMode
20+
visible: shouldVisible
21+
implicitWidth: shouldVisible ? (useColumnLayout ? Panel.rootObject.dockSize : showDesktopWidth) : 0
22+
implicitHeight: shouldVisible ? (useColumnLayout ? showDesktopWidth : Panel.rootObject.dockSize) : 0
2123

2224
PanelToolTip {
2325
id: toolTip

panels/dock/taskmanager/package/TaskManager.qml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ ContainmentItem {
1414
id: taskmanager
1515
property bool useColumnLayout: Panel.rootObject.useColumnLayout
1616
property int dockOrder: 16
17+
readonly property bool fashionMode: Panel.rootObject && Panel.rootObject.fashionDock && Panel.rootObject.fashionDock.enabled
18+
readonly property bool horizontalFashionMode: fashionMode && !useColumnLayout
1719

1820
function calcRemainingSpace(baseSize) {
1921
const otherCount = Panel.rootObject.dockCenterPartCount - 1;
2022
const otherOccupied = otherCount > 0 ? otherCount * baseSize * multitaskViewIconRatio : 0;
2123
return Panel.rootObject.dockRawCenterSpace - otherOccupied;
2224
}
2325

24-
readonly property real remainingSpacesForTaskManager: calcRemainingSpace(Panel.rootObject.dockItemMaxSize)
26+
property real remainingSpacesForTaskManager: fashionMode
27+
? 0
28+
: calcRemainingSpace(Panel.rootObject.dockItemMaxSize)
2529
readonly property int appTitleSpacing: Math.max(10, Math.round(Panel.rootObject.dockItemMaxSize * 9 / 14) / 3)
2630
// Start padding for the app container so that the visual gap
2731
// (multitask icon right edge → first app icon left edge) = appTitleSpacing.
@@ -37,12 +41,14 @@ ContainmentItem {
3741
readonly property real startPadding: Math.max(0, appTitleSpacing - (Panel.rootObject.dockItemMaxSize * (multitaskViewIconRatio - iconWidthToMaxSizeRatio) / 2))
3842

3943
implicitWidth: {
44+
if (horizontalFashionMode) return appContainer.implicitWidth + (useColumnLayout ? 0 : startPadding)
4045
let extra = useColumnLayout ? 0 : startPadding
4146
let w = appContainer.implicitWidth + extra
4247
let maxW = Panel.itemAlignment === Dock.LeftAlignment ? Math.max(remainingSpacesForTaskManager, w) : Math.min(remainingSpacesForTaskManager, w)
4348
return useColumnLayout ? Panel.rootObject.dockSize : maxW
4449
}
4550
implicitHeight: {
51+
if (fashionMode && useColumnLayout) return appContainer.implicitHeight + (useColumnLayout ? startPadding : 0)
4652
let extra = useColumnLayout ? startPadding : 0
4753
let h = appContainer.implicitHeight + extra
4854
let maxH = Panel.itemAlignment === Dock.LeftAlignment ? Math.max(remainingSpacesForTaskManager, h) : Math.min(remainingSpacesForTaskManager, h)
@@ -81,7 +87,7 @@ ContainmentItem {
8187

8288
TextCalculator {
8389
id: textCalculator
84-
enabled: taskmanager.Applet.windowSplit && (Panel.position == Dock.Bottom || Panel.position == Dock.Top)
90+
enabled: !fashionMode && taskmanager.Applet.windowSplit && (Panel.position == Dock.Bottom || Panel.position == Dock.Top)
8591
dataModel: taskmanager.Applet.dataModel
8692
iconSize: Panel.rootObject.dockSize * 9 / 14
8793
spacing: Math.max(10, Math.round(textCalculator.iconSize) / 3)

0 commit comments

Comments
 (0)