diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml index 7b4d8d04cf1..6e72a258cbb 100644 --- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml +++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml @@ -191,17 +191,12 @@ ColumnLayout { HelperWidgets.ScrollView { id: scrollView + readonly property int dragScrollMargin: 50 + anchors.fill: parent clip: true 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 { id: nodesCol width: scrollView.width @@ -221,7 +216,10 @@ ColumnLayout { width: parent.width modelIndex: index + property bool wasExpanded: false + Behavior on y { + id: dragAnimation PropertyAnimation { duration: 300 easing.type: Easing.InOutQuad @@ -231,54 +229,29 @@ ColumnLayout { onStartDrag: (section) => { root.draggedSec = section root.moveFromIdx = index - + // We only need to animate non-dragged sections + dragAnimation.enabled = false + wasExpanded = expanded + expanded = false highlightBorder = true - root.secsY = [] - for (let i = 0; i < repeater.count; ++i) - root.secsY[i] = repeater.itemAt(i).y } onStopDrag: { - if (root.moveFromIdx === root.moveToIdx) - root.draggedSec.y = root.secsY[root.moveFromIdx] - else - root.backendModel.moveNode(root.moveFromIdx, root.moveToIdx) + if (root.secsY.length !== 0) { + if (root.moveFromIdx === root.moveToIdx) + root.draggedSec.y = root.secsY[root.moveFromIdx] + else + root.backendModel.moveNode(root.moveFromIdx, root.moveToIdx) + } highlightBorder = false root.draggedSec = null + expanded = wasExpanded + dragAnimation.enabled = true } } } // 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 } // ScrollView @@ -295,4 +268,77 @@ ColumnLayout { } // Item } // Column } // 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 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index f078f3dd48d..dbbb200f738 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -318,5 +318,10 @@ Item { duration: 120 easing.type: Easing.OutCubic } + + onRunningChanged: { + if (!running) + enabled = false + } } }