Files
work-secretfile-selfcheck/UmiOCR-data/qt_res/qml/Widgets/DoubleRowLayout.qml

271 lines
11 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ===========================================
// =============== 左右双栏布局 ===============
// ===========================================
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Item {
// ========================= 【可调参数】 =========================
property QtObject leftItem // 左元素
property QtObject rightItem // 右元素
property real hideWidth: 80 // 一个栏小于该值时隐藏
property real initSplitterX: 0.5 // 分割线初始位置。>1时为像素0~1为比例。
property string saveKey: "" // 如果非空,则缓存 hideLR 参数。
property real margins: size_.spacing // 边缘空白
property bool isShowSplitView: false // 是否展示分栏按钮
signal switchView() // 更改分栏布局信号
// 只读信息
property int hideLR: 0 // 0为不隐藏1为隐藏左边2为隐藏右边
// ===============================================================
id: doubleCC
// 左右元素变化时,挂到容器下
onLeftItemChanged: leftItem.parent = leftContainer
onRightItemChanged: rightItem.parent = rightContainer
Item {
id: doubleColumn
anchors.fill: parent
anchors.margins: parent.margins
property alias hideWidth: doubleCC.hideWidth
property alias splitterX: splitter.x // 分割线当前位置
property bool isInitialized: false // 当前是否初始化完毕
Component.onCompleted: { // 初始化分割线位置
if(parent.initSplitterX <= 0)
parent.initSplitterX = 0.5 // 默认值0.5
Qt.callLater(() => { // 延迟一个事件循环,再进行位置初始化
isInitialized = true // 标记初始化完成
let hideFlag = 0
if(doubleCC.saveKey) { // 取hide缓存
const layoutDict = qmlapp.globalConfigs.getValue("window.doubleLayout")
const f = layoutDict[doubleCC.saveKey]
if(Number.isInteger(f)) hideFlag = f // 合法检查
}
toLR(hideFlag)
})
}
property int rightMax: width - splitter.width // 右边缘位置
function setHideLR(h) {
if(doubleCC.hideLR === h) return
doubleCC.hideLR = h
// 缓存状态
if(doubleCC.saveKey) {
let layoutDict = qmlapp.globalConfigs.getValue("window.doubleLayout")
layoutDict[doubleCC.saveKey] = doubleCC.hideLR
qmlapp.globalConfigs.setValue("window.doubleLayout", layoutDict)
}
}
// 检查左右隐藏
function toHide(isWidthChanged = false){
if(!isInitialized) return // 防止初始化完成之前自动触发
if(isWidthChanged && doubleCC.hideLR === 2) { // 总体宽度改变时右吸附
splitterX = width - splitter.width
return
}
if(splitterX+splitter.width > (width - hideWidth)){ // 隐藏右边
leftContainer.visible = true
rightContainer.visible = false
setHideLR(2)
splitterX = width - splitter.width
}
else if(splitterX < hideWidth){ // 隐藏左边
leftContainer.visible = false
rightContainer.visible = true
setHideLR(1)
splitterX = 0
}
else{
leftContainer.visible = true
rightContainer.visible = true
setHideLR(0)
}
}
// 去到左右。flag: 0-初始 1-左 2-右 3-切换分栏信号
function toLR(flag) {
if(flag === 3) {
switchView()
return
}
if(flag === 0)
toInitPosition()
else if(flag === 1)
splitterX = hideWidth-1
else if(flag === 2)
splitterX = width-splitter.width-hideWidth+1
toHide()
}
// 去到初始位置
function toInitPosition() {
if(parent.initSplitterX >= 0 && parent.initSplitterX <= 1)
splitterX = width * parent.initSplitterX - size_.spacing * 2
else
splitterX = parent.initSplitterX
}
// 拖拽分割线,或者调整整体宽度,都会触发检查隐藏
onSplitterXChanged: toHide()
onWidthChanged: toHide(true)
// 左容器
Item{
id: leftContainer
anchors.right: splitter.left
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
onVisibleChanged: {
leftItem.parent = visible?leftContainer:hideContainer
}
}
// 中间拖动条
Item{
id: splitter
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.topMargin: size_.spacing
anchors.bottomMargin: size_.spacing
width: size_.spacing
x: 0 // 位置可变换
z: 1
property bool isVisible: splitterMouseArea.containsMouse || btnsMouseArea.containsMouse || splitterMouseArea.drag.active || doubleCC.hideLR!==0
// 分割线 拖拽、悬停
MouseArea {
id: splitterMouseArea
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: btnsMouseArea.top
// 平常宽度为分隔栏宽度,按下拖拽时宽度增加防止鼠标出界
width: pressed ? doubleCC.width : parent.width
hoverEnabled: true // 鼠标悬停时,分割线颜色变深
cursorShape: Qt.SizeHorCursor // 鼠标指针为双箭头
// 拖拽
drag.target: splitter
drag.axis: Drag.XAxis
drag.minimumX: 0
drag.maximumX: doubleColumn.rightMax
drag.smoothed: false // 无阈值,一拖就动
}
// 分割线 视觉展示
Rectangle {
id: splitterShow
visible: splitter.isVisible
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: parent.bottom
width: size_.spacing * 0.3
radius: width
color: splitterMouseArea.pressed ? theme.coverColor4 : theme.coverColor2
}
// 控制按钮 点击
MouseArea {
id: btnsMouseArea
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
width: containsMouse ? size_.line * 2 : parent.width
height: size_.line * ((doubleCC.hideLR===0 ? 6 : 4) + (doubleCC.isShowSplitView ? 2 : 0))
property int selectIndex: -1
onExited: selectIndex = -1
onPositionChanged: {
if(doubleCC.hideLR===0) {
if(mouse.y < size_.line * 2)
selectIndex = 1
else if(mouse.y < size_.line * 4)
selectIndex = 2
else if(mouse.y < size_.line * 6)
selectIndex = 0
else
selectIndex = 3
}
else {
if(mouse.y < size_.line * 2)
selectIndex = doubleCC.hideLR===1 ? 2 : 1
else if(mouse.y < size_.line * 4)
selectIndex = 0
else
selectIndex = 3
}
}
onClicked: doubleColumn.toLR(selectIndex)
// 控制按钮 视觉
Rectangle {
color: theme.specialBgColor
visible: (splitterMouseArea.containsMouse || btnsMouseArea.containsMouse) && !splitterMouseArea.drag.active
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: parent.bottom
width: size_.line * 2
radius: size_.panelRadius
Column {
width: parent.width
Icon_ {
visible: doubleCC.hideLR!==1
width: parent.width
height: width
color: btnsMouseArea.selectIndex===1 ? theme.textColor:theme.specialTextColor
icon: "arrow_to_left"
}
Icon_ {
visible: doubleCC.hideLR!==2
width: parent.width
height: width
color: btnsMouseArea.selectIndex===2 ? theme.textColor:theme.specialTextColor
icon: "arrow_to_left"
mirror: true
}
Icon_ {
width: parent.width
height: width
color: btnsMouseArea.selectIndex===0 ? theme.textColor:theme.specialTextColor
icon: "arrow_to_center"
}
// 转为上下分栏
Icon_ {
visible: doubleCC.isShowSplitView
width: parent.width
height: width
color: btnsMouseArea.selectIndex===3 ? theme.textColor:theme.specialTextColor
icon: "split_view"
rotation: 90
}
}
}
}
}
// 右容器
Item{
id: rightContainer
anchors.left: splitter.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
onVisibleChanged: {
rightItem.parent = visible?rightContainer:hideContainer
}
}
// 隐藏容器
Item {
id: hideContainer
visible: false
width: Math.max(doubleCC.width, 400)
anchors.top: parent.top
anchors.bottom: parent.bottom
}
}
}