forked from qt-creator/qt-creator
EffectComposer: Improve reordering nodes via drag
The dragged effect is collapsed when dragging start, which helps with large nodes. Autoscrolling content was added when dragging nodes to the top/bottom of the scrollview. Fixes: QDS-10857 Change-Id: I5027324918a200746356704e36a6d99cb98aa04e Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -191,17 +191,12 @@ ColumnLayout {
|
|||||||
HelperWidgets.ScrollView {
|
HelperWidgets.ScrollView {
|
||||||
id: scrollView
|
id: scrollView
|
||||||
|
|
||||||
|
readonly property int dragScrollMargin: 50
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
clip: true
|
clip: true
|
||||||
interactive: !HelperWidgets.Controller.contextMenuOpened
|
interactive: !HelperWidgets.Controller.contextMenuOpened
|
||||||
|
|
||||||
onContentHeightChanged: {
|
|
||||||
if (scrollView.contentItem.height > scrollView.height) {
|
|
||||||
let lastItemH = repeater.itemAt(repeater.count - 1).height
|
|
||||||
scrollView.contentY = scrollView.contentItem.height - lastItemH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: nodesCol
|
id: nodesCol
|
||||||
width: scrollView.width
|
width: scrollView.width
|
||||||
@@ -221,7 +216,10 @@ ColumnLayout {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
modelIndex: index
|
modelIndex: index
|
||||||
|
|
||||||
|
property bool wasExpanded: false
|
||||||
|
|
||||||
Behavior on y {
|
Behavior on y {
|
||||||
|
id: dragAnimation
|
||||||
PropertyAnimation {
|
PropertyAnimation {
|
||||||
duration: 300
|
duration: 300
|
||||||
easing.type: Easing.InOutQuad
|
easing.type: Easing.InOutQuad
|
||||||
@@ -231,54 +229,29 @@ ColumnLayout {
|
|||||||
onStartDrag: (section) => {
|
onStartDrag: (section) => {
|
||||||
root.draggedSec = section
|
root.draggedSec = section
|
||||||
root.moveFromIdx = index
|
root.moveFromIdx = index
|
||||||
|
// We only need to animate non-dragged sections
|
||||||
|
dragAnimation.enabled = false
|
||||||
|
wasExpanded = expanded
|
||||||
|
expanded = false
|
||||||
highlightBorder = true
|
highlightBorder = true
|
||||||
|
|
||||||
root.secsY = []
|
root.secsY = []
|
||||||
for (let i = 0; i < repeater.count; ++i)
|
|
||||||
root.secsY[i] = repeater.itemAt(i).y
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onStopDrag: {
|
onStopDrag: {
|
||||||
if (root.moveFromIdx === root.moveToIdx)
|
if (root.secsY.length !== 0) {
|
||||||
root.draggedSec.y = root.secsY[root.moveFromIdx]
|
if (root.moveFromIdx === root.moveToIdx)
|
||||||
else
|
root.draggedSec.y = root.secsY[root.moveFromIdx]
|
||||||
root.backendModel.moveNode(root.moveFromIdx, root.moveToIdx)
|
else
|
||||||
|
root.backendModel.moveNode(root.moveFromIdx, root.moveToIdx)
|
||||||
|
}
|
||||||
|
|
||||||
highlightBorder = false
|
highlightBorder = false
|
||||||
root.draggedSec = null
|
root.draggedSec = null
|
||||||
|
expanded = wasExpanded
|
||||||
|
dragAnimation.enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Repeater
|
} // Repeater
|
||||||
|
|
||||||
Timer {
|
|
||||||
running: root.draggedSec
|
|
||||||
interval: 50
|
|
||||||
repeat: true
|
|
||||||
|
|
||||||
onTriggered: {
|
|
||||||
root.moveToIdx = root.moveFromIdx
|
|
||||||
for (let i = 0; i < repeater.count; ++i) {
|
|
||||||
let currItem = repeater.itemAt(i)
|
|
||||||
if (i > root.moveFromIdx) {
|
|
||||||
if (root.draggedSec.y > currItem.y + (currItem.height - root.draggedSec.height) * .5) {
|
|
||||||
currItem.y = root.secsY[i] - root.draggedSec.height - nodesCol.spacing
|
|
||||||
root.moveToIdx = i
|
|
||||||
} else {
|
|
||||||
currItem.y = root.secsY[i]
|
|
||||||
}
|
|
||||||
} else if (i < root.moveFromIdx) {
|
|
||||||
if (!repeater.model.isDependencyNode(i)
|
|
||||||
&& root.draggedSec.y < currItem.y + (currItem.height - root.draggedSec.height) * .5) {
|
|
||||||
currItem.y = root.secsY[i] + root.draggedSec.height + nodesCol.spacing
|
|
||||||
root.moveToIdx = Math.min(root.moveToIdx, i)
|
|
||||||
} else {
|
|
||||||
currItem.y = root.secsY[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // Timer
|
|
||||||
} // Column
|
} // Column
|
||||||
} // ScrollView
|
} // ScrollView
|
||||||
|
|
||||||
@@ -295,4 +268,77 @@ ColumnLayout {
|
|||||||
} // Item
|
} // Item
|
||||||
} // Column
|
} // Column
|
||||||
} // SplitView
|
} // SplitView
|
||||||
|
|
||||||
|
function handleDragMove() {
|
||||||
|
dragTimer.stop()
|
||||||
|
if (root.secsY.length === 0) {
|
||||||
|
for (let i = 0; i < repeater.count; ++i)
|
||||||
|
root.secsY[i] = repeater.itemAt(i).y
|
||||||
|
}
|
||||||
|
|
||||||
|
let oldContentY = scrollView.contentY
|
||||||
|
if (root.draggedSec.y < scrollView.dragScrollMargin + scrollView.contentY
|
||||||
|
&& scrollView.contentY > 0) {
|
||||||
|
scrollView.contentY -= scrollView.dragScrollMargin / 2
|
||||||
|
} else if (root.draggedSec.y > scrollView.contentY + scrollView.height - scrollView.dragScrollMargin
|
||||||
|
&& scrollView.contentY < scrollView.contentHeight - scrollView.height) {
|
||||||
|
scrollView.contentY += scrollView.dragScrollMargin / 2
|
||||||
|
if (scrollView.contentY > scrollView.contentHeight - scrollView.height)
|
||||||
|
scrollView.contentY = scrollView.contentHeight - scrollView.height
|
||||||
|
}
|
||||||
|
if (scrollView.contentY < 0)
|
||||||
|
scrollView.contentY = 0
|
||||||
|
|
||||||
|
if (oldContentY !== scrollView.contentY) {
|
||||||
|
// Changing dragged section position in drag handler doesn't seem to stick
|
||||||
|
// when triggered by mouse move, so do it again async
|
||||||
|
dragTimer.targetY = root.draggedSec.y - oldContentY + scrollView.contentY
|
||||||
|
dragTimer.restart()
|
||||||
|
dragConnection.enabled = false
|
||||||
|
root.draggedSec.y = dragTimer.targetY
|
||||||
|
dragConnection.enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
root.moveToIdx = root.moveFromIdx
|
||||||
|
for (let i = 0; i < repeater.count; ++i) {
|
||||||
|
let currItem = repeater.itemAt(i)
|
||||||
|
if (i > root.moveFromIdx) {
|
||||||
|
if (root.draggedSec.y > currItem.y) {
|
||||||
|
currItem.y = root.secsY[i] - root.draggedSec.height - nodesCol.spacing
|
||||||
|
root.moveToIdx = i
|
||||||
|
} else {
|
||||||
|
currItem.y = root.secsY[i]
|
||||||
|
}
|
||||||
|
} else if (i < root.moveFromIdx) {
|
||||||
|
if (!repeater.model.isDependencyNode(i) && root.draggedSec.y < currItem.y) {
|
||||||
|
currItem.y = root.secsY[i] + root.draggedSec.height + nodesCol.spacing
|
||||||
|
root.moveToIdx = Math.min(root.moveToIdx, i)
|
||||||
|
} else {
|
||||||
|
currItem.y = root.secsY[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
id: dragConnection
|
||||||
|
target: root.draggedSec
|
||||||
|
onYChanged: root.handleDragMove()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: dragTimer
|
||||||
|
running: false
|
||||||
|
interval: 16
|
||||||
|
repeat: false
|
||||||
|
|
||||||
|
property real targetY: -1
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
// Ensure we get position change triggers even if user holds mouse still to
|
||||||
|
// make scrolling smooth
|
||||||
|
root.draggedSec.y = targetY
|
||||||
|
root.handleDragMove()
|
||||||
|
}
|
||||||
|
} // Timer
|
||||||
}
|
}
|
||||||
|
@@ -318,5 +318,10 @@ Item {
|
|||||||
duration: 120
|
duration: 120
|
||||||
easing.type: Easing.OutCubic
|
easing.type: Easing.OutCubic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onRunningChanged: {
|
||||||
|
if (!running)
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user