256 lines
9.1 KiB
QML
256 lines
9.1 KiB
QML
// =========================================
|
||
// =============== 水平标签栏 ===============
|
||
// =========================================
|
||
|
||
import QtQuick 2.15
|
||
import QtQuick.Controls 2.15
|
||
import QtQuick.Layouts 1.15
|
||
|
||
import "../Widgets"
|
||
|
||
RowLayout {
|
||
id: hTabBarLayout
|
||
anchors.fill: parent
|
||
spacing: 0
|
||
|
||
// 标签栏控制(左,置顶按钮)
|
||
Item {
|
||
width: size_.hTabBarHeight
|
||
Layout.fillHeight: true
|
||
// 图钉按钮
|
||
Button {
|
||
checkable: true
|
||
checked: mainWindowRoot.isMainWindowTop
|
||
onCheckedChanged: { // 双向绑定锁定标记
|
||
mainWindowRoot.isMainWindowTop = checked
|
||
qmlapp.globalConfigs.setValue("window.isMainWindowTop", checked, true)
|
||
}
|
||
anchors.fill: parent
|
||
anchors.margins: 4
|
||
|
||
contentItem: Icon_ {
|
||
icon: "pin"
|
||
anchors.fill: parent
|
||
color: parent.checked ? theme.bgColor : theme.textColor
|
||
}
|
||
|
||
background: Rectangle {
|
||
anchors.fill: parent
|
||
radius: size_.btnRadius
|
||
color: parent.checked ? theme.coverColor4 : (
|
||
parent.hovered ? theme.coverColor2 : "#00000000"
|
||
)
|
||
}
|
||
|
||
ToolTip_ {
|
||
visible: parent.hovered
|
||
text: qsTr("窗口置顶")
|
||
}
|
||
}
|
||
}
|
||
|
||
// 标签栏本体(中)
|
||
Rectangle {
|
||
id: hTabBarMain
|
||
Layout.fillWidth: true
|
||
Layout.fillHeight: true
|
||
color: "#00000000"
|
||
|
||
property int tabWidth: 200 // 标签当前宽度
|
||
|
||
// 方法:重设标签按钮宽度
|
||
function resetTabBtnWidth() {
|
||
let w = hTabBarMain.width
|
||
if(!qmlapp.tab.barIsLock) w -= tabBarControl.width // 无锁定时,减去+按钮宽度
|
||
w = w / barManager.model.count
|
||
tabWidth = Math.min(w, size_.line * 8)
|
||
}
|
||
onWidthChanged: resetTabBtnWidth() // 监听标签栏总宽度变化
|
||
// 监听改变锁定,重设宽度
|
||
property bool isLock: qmlapp.tab.barIsLock
|
||
onIsLockChanged: {
|
||
hTabBarMain.resetTabBtnWidth()
|
||
}
|
||
|
||
MouseArea { // 点击标签栏空余位置,都是添加新标签
|
||
anchors.fill: parent
|
||
onClicked: {
|
||
if(!qmlapp.tab.barIsLock)
|
||
qmlapp.tab.addNavi() // 添加导航页
|
||
}
|
||
}
|
||
|
||
// Rectangle { // 标签按钮下方的阴影
|
||
// anchors.bottom: parent.bottom
|
||
// width: parent.width
|
||
// height: size_.hTabBarHeight * 0.5
|
||
// gradient: Gradient {
|
||
// GradientStop { position: 0.0; color: "#00000000" }
|
||
// GradientStop { position: 1.0; color: theme.coverColor2 }
|
||
// }
|
||
// }
|
||
|
||
Rectangle { // 拖拽时的位置指示器
|
||
id: dragIndicator
|
||
visible: false
|
||
width: parent.tabWidth
|
||
height: size_.hTabBarHeight
|
||
gradient: Gradient { // 水平渐变
|
||
orientation: Gradient.Horizontal
|
||
GradientStop { position: 1.0; color: "#00000000" }
|
||
GradientStop { position: 0.0; color: theme.coverColor3 }
|
||
}
|
||
}
|
||
|
||
// 水平标签栏行布局
|
||
Row {
|
||
id: hTabBarMainRow
|
||
spacing: -1 // 给负的间隔,是为了让选中标签能覆盖左右两边标签的竖线
|
||
|
||
// ===== 标签按钮组 =====
|
||
BarManager {
|
||
id: barManager
|
||
// 标签元素模板
|
||
delegate: TabButton_ {
|
||
title: title_ // 标题
|
||
checked: checked_ // 初始时是否选中
|
||
index: index_ // 初始位置
|
||
width: hTabBarMain.tabWidth
|
||
}
|
||
|
||
// 事件:创建新标签时(与父类的槽同时生效)
|
||
onItemAdded: {
|
||
// 链接表现相关的槽函数
|
||
item.dragStart.connect(dragStart)
|
||
item.dragFinish.connect(dragFinish)
|
||
item.dragMoving.connect(dragMoving)
|
||
}
|
||
|
||
// 事件:按钮数量变化
|
||
onCountChanged: hTabBarMain.resetTabBtnWidth()
|
||
|
||
// ========================= 【拖拽相关】 =========================
|
||
|
||
property var intervalList: [] // 记录按钮位置区间的列表
|
||
property var originalPosList: [] // 记录按钮初始位置的列表
|
||
property int originalX // 记录本轮拖拽前,被拖拽按钮原本的位置
|
||
function dragStart(index){ // 方法:开始拖拽
|
||
// 重新记录当前所有按钮的位置
|
||
originalX = itemAt(index).x
|
||
intervalList = [-Infinity] // 下限:负无穷
|
||
originalPosList = [itemAt(0).x]
|
||
for(let i=1, c=model.count; i < c; i++){ // 按钮位置区间
|
||
const it = itemAt(i)
|
||
intervalList.push(it.x)
|
||
originalPosList.push(it.x)
|
||
}
|
||
intervalList.push(Infinity) // 上限:负无穷
|
||
dragIndicator.visible = true
|
||
|
||
}
|
||
function btnDragIndex(index){ // 函数:返回当前index应该所处的序号
|
||
const dragItem = itemAt(index)
|
||
const x = dragItem.x + Math.round(dragItem.width/2) // 被拖动按钮的中心位置
|
||
let go = 0 // 应该拖放到的位置
|
||
for(const c=intervalList.length-1; go < c; go++){
|
||
if(x >= intervalList[go] && x <= intervalList[go+1]){
|
||
break;
|
||
}
|
||
}
|
||
return go;
|
||
}
|
||
function dragMoving(index, x){ // 方法:拖拽移动
|
||
let go = btnDragIndex(index) // 应该拖放到的序号
|
||
dragIndicator.x = originalPosList[go]
|
||
}
|
||
function dragFinish(index){ // 方法:结束拖拽
|
||
dragIndicator.visible = false
|
||
let go = btnDragIndex(index) // 应该拖放到的序号
|
||
if(index !== go){ // 需要移动
|
||
// model.move(index, go, 1)
|
||
qmlapp.tab.moveTabPage(index, go)
|
||
} else { // 无需移动,则回到原位
|
||
itemAt(index).x = originalX
|
||
}
|
||
resetIndex()
|
||
}
|
||
}
|
||
|
||
// 元素:控制按钮
|
||
Rectangle{
|
||
id: tabBarControl
|
||
color: "#00000000"
|
||
width: size_.hTabBarHeight
|
||
height: size_.hTabBarHeight
|
||
visible: !qmlapp.tab.barIsLock
|
||
|
||
// 添加“+”按钮
|
||
IconButton {
|
||
anchors.fill: parent
|
||
anchors.margins: 4
|
||
icon_: "add"
|
||
color: theme.textColor
|
||
onClicked: {
|
||
qmlapp.tab.addNavi() // 添加导航页
|
||
}
|
||
}
|
||
}
|
||
|
||
// 动画
|
||
add: Transition { // 添加子项
|
||
enabled: qmlapp.enabledEffect
|
||
NumberAnimation {
|
||
properties: "opacity, scale" // 透明度和大小从小到大
|
||
from: 0; to: 1.0
|
||
easing.type: Easing.OutBack // 缓动:超出反弹
|
||
duration: 300
|
||
}
|
||
}
|
||
move: Transition { // 移动子项
|
||
enabled: qmlapp.enabledEffect
|
||
NumberAnimation {
|
||
properties: "x,y"
|
||
easing.type: Easing.OutBack
|
||
duration: 300
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 标签栏控制(右,锁定按钮)
|
||
Item{
|
||
width: size_.hTabBarHeight
|
||
Layout.fillHeight: true
|
||
|
||
// 锁定“🔒︎”按钮
|
||
Button {
|
||
checkable: true
|
||
checked: qmlapp.tab.barIsLock
|
||
onCheckedChanged: { // 双向绑定锁定标记
|
||
qmlapp.tab.barIsLock = checked
|
||
qmlapp.globalConfigs.setValue("window.barIsLock", checked, true)
|
||
}
|
||
anchors.fill: parent
|
||
anchors.margins: 4
|
||
|
||
contentItem: Icon_ {
|
||
icon: "lock"
|
||
anchors.fill: parent
|
||
color: parent.checked ? theme.bgColor : theme.textColor
|
||
}
|
||
|
||
background: Rectangle {
|
||
anchors.fill: parent
|
||
radius: size_.btnRadius
|
||
color: parent.checked ? theme.coverColor4 : (
|
||
parent.hovered ? theme.coverColor2 : "#00000000"
|
||
)
|
||
}
|
||
|
||
ToolTip_ {
|
||
visible: parent.hovered
|
||
text: qsTr("锁定标签栏")
|
||
}
|
||
}
|
||
}
|
||
} |