Skip to content

Commit

Permalink
feat: [sidebar] add animation spliter
Browse files Browse the repository at this point in the history
Add AnimationHSpliter provides sidebar show/hide
animation and drag.

Log: Add animation spliter
  • Loading branch information
rb-union committed Jun 27, 2024
1 parent 38b03a8 commit 6c09768
Show file tree
Hide file tree
Showing 10 changed files with 413 additions and 26 deletions.
127 changes: 127 additions & 0 deletions src/dfm-declarative/AnimationHSpliter.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick
import QtQuick.Layouts

/*!
* 用于边栏的横向分裂器,提供拖拽控件,动画交互功能
*/
Item {
id: spliter

// 是否响应动画触发事件
property alias enableAnimation: trans.enabled
// 是否响应 Hover 和拖拽效果
property alias enableMouse: mouseLoader.active
property alias handle: handleLoader.sourceComponent
property int handleWidth: 6
// 分裂器附加 anchor 位置,允许在父控件左侧或右侧的边缘,计算方向相反
property bool leftSide: false
property real maximumWidth: 600
property real minimumWidth: 150
// 缓存手动拖拽的宽度,用于动画恢复
property real showWidth: 200
// 动画控制切换,switchShow 更新为 true 时触发弹出动画,为 false 时触发隐藏动画
property bool switchShow: true
property Item target: parent

function adjustParentWidth(xOffset) {
var adjWidth;
if (null === spliter.target) {
return;
}
adjWidth = spliter.target.width + (leftSide ? -xOffset : xOffset);
adjWidth = Math.min(Math.max(minimumWidth, adjWidth), maximumWidth);
// 缓存用于动画的宽度
showWidth = adjWidth;
// 外部组件可能被布局管理
if (null !== target.Layout) {
target.Layout.preferredWidth = adjWidth;
} else {
target.width = adjWidth;
}
}

implicitHeight: target ? target.height : 0
implicitWidth: handleWidth

// 拖拽也会触发属性变更,因此未使用 Behaviour
states: [
State {
name: "show"
when: spliter.switchShow

PropertyChanges {
Layout.preferredWidth: showWidth
explicit: true
target: spliter.target
}
},
State {
name: "hide"
when: !spliter.switchShow

PropertyChanges {
Layout.preferredWidth: 0
explicit: true
target: spliter.target
}
}
]
transitions: Transition {
id: trans

onRunningChanged: {
if (running && spliter.switchShow) {
spliter.target.visible = true;
} else if (!running && !spliter.switchShow) {
spliter.target.visible = false;
}
}

NumberAnimation {
duration: 200
easing.type: Easing.InOutQuad
property: "Layout.preferredWidth"
}
}

anchors {
left: leftSide ? target.left : undefined
right: leftSide ? undefined : target.right
}

Loader {
id: handleLoader

sourceComponent: Item {
height: spliter.height
width: handleWidth
}
}

Loader {
id: mouseLoader

anchors.fill: parent

sourceComponent: MouseArea {
property real baseX

anchors.fill: parent
cursorShape: (containsMouse || pressed) ? Qt.SplitHCursor : Qt.ArrowCursor
hoverEnabled: true

onPositionChanged: {
if (pressed) {
spliter.adjustParentWidth(mouseX - baseX);
}
}
onPressed: {
baseX = mouseX;
}
}
}
}
2 changes: 1 addition & 1 deletion src/dfm-declarative/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ qt_add_qml_module(${BIN_NAME}
SHARED
RESOURCE_PREFIX /
OUTPUT_DIRECTORY ${DFM_BUILD_PLUGIN_DIR}/qml/org/dfm/${BASE_NAME}
QML_FILES ActionMenu.qml
QML_FILES ActionMenu.qml AnimationHSpliter.qml
)

target_include_directories(${BIN_NAME} PRIVATE ${PROJECT_SOURCE_DIR})
Expand Down
71 changes: 61 additions & 10 deletions src/plugins/filemanager/core/dfmplugin-core/FileWindow.qml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import org.deepin.dtk
ApplicationWindow {
id: root

DWindow.enabled: false
DWindow.enabled: true
flags: Qt.Window | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
height: 600
minimumHeight: 380
minimumWidth: 600
width: 800

// TODO: 待评估方案
Expand All @@ -24,10 +26,9 @@ ApplicationWindow {
return;
}
if (undefined !== appletItem.widgetType) {
var control;
switch (appletItem.widgetType) {
case QuickUtils.Sidebar:
sidebar.contentItem = appletItem;
sidebar.target = appletItem;
break;
case QuickUtils.Titlebar:
titlebar.target = appletItem;
Expand All @@ -50,24 +51,73 @@ ApplicationWindow {
// For local module test
ActionMenu {
}
SplitView {

Connections {
function onWidthChanged(width) {
}

enabled: Window.window !== null
target: Window.window
}

RowLayout {
anchors.fill: parent

Control {
id: sidebar
Item {
id: sidebarProxy

Layout.preferredHeight: parent.height

contentItem: Rectangle {
width: 200
ColumnLayout {
id: sidebarLayoutContent

anchors.fill: parent

// 用于同步标题栏高度占位的区块
Rectangle {
id: titlebarCorner

Layout.preferredHeight: titlebar.target ? titlebar.target.topHeaderHeight : titlebar.height
Layout.preferredWidth: parent.width
color: "lightyellow"
}

LayoutItemProxy {
id: sidebar

Layout.fillHeight: true
}
}

AnimationHSpliter {
id: spliter

enableAnimation: sidebar.target !== null
height: parent.height
target: sidebarProxy

// TODO 移动到 Sidebar, 通过事件处理,而不是 QML 隐式传输
Connections {
function onSidebarVisibleNotify(bVisible) {
spliter.switchShow = bVisible;
}

enabled: titlebar.target !== null
target: titlebar.target
}
}
}

ColumnLayout {
SplitView.fillHeight: true
SplitView.fillWidth: true
Layout.fillHeight: true
Layout.fillWidth: true

LayoutItemProxy {
id: titlebar

onTargetChanged: target => {}
}

RowLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Expand All @@ -76,6 +126,7 @@ ApplicationWindow {
id: workspace

}

LayoutItemProxy {
id: detailspace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ ViewMode TitleBarEventCaller::sendGetDefualtViewMode(const QString &scheme)
return static_cast<ViewMode>(defaultViewMode);
}

void TitleBarEventCaller::sendDetailViewState(dfmgui::Applet *applet, bool checked)
{
quint64 id = TitleBarHelper::windowId(applet);
Q_ASSERT(id > 0);
dpfSlotChannel->push("dfmplugin_detailspace", "slot_DetailView_Show", id, checked);
}

void TitleBarEventCaller::sendCd(dfmgui::Applet *applet, const QUrl &url)
{
DFMBASE_USE_NAMESPACE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class TitleBarEventCaller
static bool sendCheckTabAddable(quint64 windowId);
static DFMGLOBAL_NAMESPACE::ViewMode sendGetDefualtViewMode(const QString &scheme);

static void sendDetailViewState(dfmgui::Applet *applet, bool checked);
static void sendCd(dfmgui::Applet *applet, const QUrl &url);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ import QtQuick
import QtQuick.Controls

TextEdit {
property bool visibleState: true

width: 200

Behavior on width {
NumberAnimation {
duration: 200
easing.type: Easing.InOutQuad
}
}

TextField {
anchors.fill: parent
horizontalAlignment: TextInput.AlignCenter
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.deepin.dtk
import org.dfm.base

RowLayout {
property int iconSize: 28

ButtonGroup {
buttons: viewMode.children
exclusive: true
}

Row {
id: viewMode

ToolButton {
id: iconView

checkable: true

icon {
height: iconSize
name: "unchecked"
width: iconSize
}
}

ToolButton {
id: listView

checkable: true

icon {
height: iconSize
name: "unchecked"
width: iconSize
}
}

ToolButton {
id: treeView

checkable: true

icon {
height: iconSize
name: "unchecked"
width: iconSize
}
}
}

ToolButton {
id: detail

checkable: true

Component.onCompleted: {
checked = Containment.showDetail;
}

icon {
height: iconSize
name: "splitscreen_right"
width: iconSize
}
}
}
Loading

0 comments on commit 6c09768

Please sign in to comment.