171 lines
5.2 KiB
QML
171 lines
5.2 KiB
QML
|
|
// ==================================================
|
|||
|
|
// =============== 水平标签栏的标签按钮 ===============
|
|||
|
|
// ==================================================
|
|||
|
|
|
|||
|
|
import QtQuick 2.15
|
|||
|
|
import QtQuick.Controls 2.15
|
|||
|
|
import QtQuick.Layouts 1.15
|
|||
|
|
import QtGraphicalEffects 1.15 // 阴影
|
|||
|
|
|
|||
|
|
import "../Widgets"
|
|||
|
|
|
|||
|
|
Button {
|
|||
|
|
id: btn
|
|||
|
|
|
|||
|
|
// 设定值
|
|||
|
|
property string title: "Unknown TabBtn" // 显示的标题
|
|||
|
|
property int index: -1 // 在标签栏中的序号
|
|||
|
|
|
|||
|
|
// 默认值
|
|||
|
|
height: size_.hTabBarHeight
|
|||
|
|
checkable: false // 手动控制
|
|||
|
|
z: checked? 10 : 0 // 选中模式下弹到顶层
|
|||
|
|
// 信号
|
|||
|
|
signal dragStart(int index) // 开始拖拽的信号
|
|||
|
|
signal dragFinish(int index) // 结束拖拽的信号
|
|||
|
|
signal dragMoving(int index, int x) // 拖拽移动的信号
|
|||
|
|
|
|||
|
|
// 按钮前景
|
|||
|
|
contentItem: Item {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
|
|||
|
|
RowLayout {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
|
|||
|
|
// TODO: 图标
|
|||
|
|
Item {
|
|||
|
|
width: size_.line*0.2 // 先占位
|
|||
|
|
height: btn.height // 适应整个按钮的高度
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 标题
|
|||
|
|
Text_ {
|
|||
|
|
text: title // 外部传入的title
|
|||
|
|
|
|||
|
|
elide: Text.ElideRight // 隐藏超出宽度
|
|||
|
|
Layout.fillWidth: true // 填充宽度
|
|||
|
|
height: btn.height // 适应整个按钮的高度
|
|||
|
|
color: (btn.hovered || btn.checked)?theme.textColor:theme.subTextColor
|
|||
|
|
font.bold: btn.checked
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 关闭按钮
|
|||
|
|
IconButton {
|
|||
|
|
// 未锁定,且主按钮悬停或选中时才显示
|
|||
|
|
visible: !qmlapp.tab.barIsLock && (btn.hovered || btn.checked)
|
|||
|
|
Layout.alignment: Qt.AlignRight
|
|||
|
|
Layout.rightMargin: size_.hTabBarHeight * 0.2
|
|||
|
|
|
|||
|
|
property real size: size_.hTabBarHeight * 0.7
|
|||
|
|
implicitWidth: size
|
|||
|
|
implicitHeight: size
|
|||
|
|
bgColor_: "#00000000"
|
|||
|
|
|
|||
|
|
icon_: "no"
|
|||
|
|
|
|||
|
|
onClicked: {
|
|||
|
|
qmlapp.tab.closeTabPage(index)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 按钮背景
|
|||
|
|
background: Rectangle {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
|
|||
|
|
color: parent.checked ? theme.bgColor : (
|
|||
|
|
parent.hovered ? theme.coverColor1 : "#00000000"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 侧边小条
|
|||
|
|
Rectangle{
|
|||
|
|
visible: !parent.parent.checked
|
|||
|
|
height: size_.line
|
|||
|
|
width: 1
|
|||
|
|
anchors.verticalCenter: parent.verticalCenter
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
color: theme.coverColor4
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 边缘阴影
|
|||
|
|
layer.enabled: parent.checked
|
|||
|
|
layer.effect: DropShadow {
|
|||
|
|
transparentBorder: true
|
|||
|
|
color: theme.coverColor3
|
|||
|
|
samples: size_.hTabBarHeight
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 点击和拖拽处理
|
|||
|
|
MouseArea {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
|||
|
|
|
|||
|
|
// 拖拽
|
|||
|
|
drag.target: qmlapp.tab.barIsLock ? undefined : parent.parent // 动态启用、禁用拖拽
|
|||
|
|
drag.axis: Drag.XAxis // 只能沿X轴
|
|||
|
|
drag.threshold: 50 // 起始阈值
|
|||
|
|
property bool dragActive: drag.active // 动态记录拖拽状态
|
|||
|
|
property int dragX: parent.parent.x // 动态记录拖拽时整体的位置
|
|||
|
|
|
|||
|
|
onPressed: { // 左键按下,切换焦点
|
|||
|
|
if(mouse.button === Qt.LeftButton) {
|
|||
|
|
qmlapp.tab.showTabPage(index)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
onClicked: { // 中键点击,删除标签
|
|||
|
|
if(mouse.button === Qt.MiddleButton && !qmlapp.tab.barIsLock) {
|
|||
|
|
qmlapp.tab.closeTabPage(index)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
onDragActiveChanged: {
|
|||
|
|
if(drag.active) { // 拖拽开始
|
|||
|
|
parent.opacity = 0.6
|
|||
|
|
parent.parent.y += parent.parent.height / 2
|
|||
|
|
dragStart(index)
|
|||
|
|
} else { // 拖拽结束
|
|||
|
|
parent.opacity = 1
|
|||
|
|
parent.parent.y -= parent.parent.height / 2
|
|||
|
|
dragFinish(index)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
onDragXChanged: {
|
|||
|
|
if(drag.active) {
|
|||
|
|
dragMoving(index, dragX)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 选中时的放大动画
|
|||
|
|
property bool enabledAni: false // true是允许动画
|
|||
|
|
property bool runAni: false
|
|||
|
|
Timer { // 计时器,保证初始化的一段时间内不允许动画
|
|||
|
|
running: true
|
|||
|
|
interval: 300
|
|||
|
|
onTriggered: enabledAni=true
|
|||
|
|
}
|
|||
|
|
onCheckedChanged: {
|
|||
|
|
if(enabledAni) runAni = checked
|
|||
|
|
}
|
|||
|
|
SequentialAnimation{ // 串行动画
|
|||
|
|
running: qmlapp.enabledEffect && runAni
|
|||
|
|
// 动画1:放大
|
|||
|
|
NumberAnimation{
|
|||
|
|
target: btn
|
|||
|
|
property: "scale"
|
|||
|
|
to: 1.2
|
|||
|
|
duration: 80
|
|||
|
|
easing.type: Easing.OutCubic
|
|||
|
|
}
|
|||
|
|
// 动画2:缩小
|
|||
|
|
NumberAnimation{
|
|||
|
|
target: btn
|
|||
|
|
property: "scale"
|
|||
|
|
to: 1
|
|||
|
|
duration: 150
|
|||
|
|
easing.type: Easing.InCubic
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|