forked from qt-creator/qt-creator
QmlDesigner: Implement effect maker node drag to reorder
Also small relevant tweaks Fixes: QDS-10411 Change-Id: I332482d4726c79786edbc0a5fa1e8f6489d77f11 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Amr Elsayed <amr.elsayed@qt.io> Reviewed-by: Henning Gründl <henning.gruendl@qt.io> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
@@ -15,8 +15,11 @@ HelperWidgets.Section {
|
||||
caption: nodeName
|
||||
category: "EffectMaker"
|
||||
|
||||
draggable: true
|
||||
fillBackground: true
|
||||
showCloseButton: true
|
||||
closeButtonToolTip: qsTr("Remove")
|
||||
|
||||
onCloseButtonClicked: {
|
||||
EffectMakerBackend.effectMakerModel.removeNode(index)
|
||||
}
|
||||
|
@@ -10,6 +10,11 @@ import EffectMakerBackend
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var draggedSec: null
|
||||
property var secsY: []
|
||||
property int moveFromIdx: 0
|
||||
property int moveToIdx: 0
|
||||
|
||||
Column {
|
||||
id: col
|
||||
anchors.fill: parent
|
||||
@@ -47,7 +52,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HelperWidgets.ScrollView {
|
||||
id: scrollView
|
||||
|
||||
@@ -55,29 +59,77 @@ Item {
|
||||
height: parent.height - y
|
||||
clip: true
|
||||
|
||||
Behavior on contentY {
|
||||
id: contentYBehavior
|
||||
PropertyAnimation {
|
||||
id: scrollViewAnim
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: scrollView.width
|
||||
spacing: 1
|
||||
|
||||
Repeater {
|
||||
id: compositionRepeater
|
||||
id: repeater
|
||||
|
||||
width: root.width
|
||||
model: EffectMakerBackend.effectMakerModel
|
||||
|
||||
delegate: EffectCompositionNode {
|
||||
width: root.width
|
||||
|
||||
Behavior on y {
|
||||
PropertyAnimation {
|
||||
duration: 300
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
onStartDrag: (section) => {
|
||||
root.draggedSec = section
|
||||
root.moveFromIdx = index
|
||||
|
||||
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
|
||||
EffectMakerBackend.effectMakerModel.moveNode(root.moveFromIdx, root.moveToIdx)
|
||||
|
||||
highlightBorder = false
|
||||
root.draggedSec = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // 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
|
||||
root.moveToIdx = i
|
||||
} else {
|
||||
currItem.y = root.secsY[i]
|
||||
}
|
||||
} else if (i < root.moveFromIdx) {
|
||||
if (root.draggedSec.y < currItem.y + (currItem.height - root.draggedSec.height) * .5) {
|
||||
currItem.y = root.secsY[i] + root.draggedSec.height
|
||||
root.moveToIdx = Math.min(root.moveToIdx, i)
|
||||
} else {
|
||||
currItem.y = root.secsY[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Timer
|
||||
} // Column
|
||||
} // ScrollView
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ Rectangle {
|
||||
id: root
|
||||
|
||||
width: 140
|
||||
height: 22
|
||||
height: 32
|
||||
|
||||
color: mouseArea.containsMouse ? StudioTheme.Values.themeControlBackgroundInteraction
|
||||
: "transparent"
|
||||
@@ -38,8 +38,8 @@ Rectangle {
|
||||
IconImage {
|
||||
id: nodeIcon
|
||||
|
||||
width: 22
|
||||
height: 22
|
||||
width: 32
|
||||
height: 32
|
||||
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
source: modelData.nodeIcon
|
||||
|
@@ -10,6 +10,8 @@ Rectangle {
|
||||
id: root
|
||||
|
||||
signal clicked()
|
||||
signal pressed()
|
||||
signal released()
|
||||
|
||||
property alias icon: icon.text
|
||||
property alias tooltip: toolTip.text
|
||||
@@ -20,6 +22,7 @@ Rectangle {
|
||||
property alias iconStyleColor: icon.styleColor
|
||||
|
||||
property alias containsMouse: mouseArea.containsMouse
|
||||
property alias drag: mouseArea.drag
|
||||
|
||||
property bool enabled: true
|
||||
property bool transparentBg: false
|
||||
@@ -55,12 +58,22 @@ Rectangle {
|
||||
if (root.enabled)
|
||||
root.clicked()
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
if (root.enabled)
|
||||
root.pressed()
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (root.enabled)
|
||||
root.released()
|
||||
}
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
id: toolTip
|
||||
|
||||
visible: mouseArea.containsMouse
|
||||
visible: mouseArea.containsMouse && text !== ""
|
||||
delay: 1000
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,9 @@ Item {
|
||||
property alias showCloseButton: closeButton.visible
|
||||
property alias closeButtonToolTip: closeButton.tooltip
|
||||
property alias spacing: column.spacing
|
||||
property alias draggable: dragButton.visible
|
||||
property alias fillBackground: sectionBackground.visible
|
||||
property alias highlightBorder: sectionBorder.visible
|
||||
|
||||
property int leftPadding: StudioTheme.Values.sectionLeftPadding
|
||||
property int rightPadding: 0
|
||||
@@ -82,6 +85,8 @@ Item {
|
||||
signal expand()
|
||||
signal collapse()
|
||||
signal closeButtonClicked()
|
||||
signal startDrag(var section)
|
||||
signal stopDrag()
|
||||
|
||||
DropArea {
|
||||
id: dropArea
|
||||
@@ -128,7 +133,7 @@ Item {
|
||||
height: 4
|
||||
source: "image://icons/down-arrow"
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 4 + (section.level * section.levelShift)
|
||||
anchors.leftMargin: 4 + (section.level * section.levelShift) + (section.draggable ? 20 : 0)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
@@ -136,7 +141,7 @@ Item {
|
||||
id: label
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
x: 22 + (section.level * section.levelShift)
|
||||
x: arrow.x + 18
|
||||
font.pixelSize: StudioTheme.Values.myFontSize
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
@@ -174,8 +179,34 @@ Item {
|
||||
|
||||
onClicked: root.closeButtonClicked()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: dragButton
|
||||
|
||||
icon: StudioTheme.Constants.dragmarks
|
||||
buttonSize: 22
|
||||
iconScale: containsMouse ? 1.2 : 1
|
||||
transparentBg: true
|
||||
|
||||
visible: false
|
||||
drag.target: section
|
||||
drag.axis: Drag.YAxis
|
||||
|
||||
onPressed: {
|
||||
section.startDrag(section)
|
||||
|
||||
section.z = ++section.parent.z // put the dragged section on top
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
section.stopDrag()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Drag.active: dragButton.drag.active
|
||||
Drag.source: dragButton
|
||||
|
||||
Rectangle {
|
||||
id: topSeparator
|
||||
height: 1
|
||||
@@ -193,6 +224,23 @@ Item {
|
||||
|
||||
implicitHeight: Math.round(column.height + header.height + topSpacer.height + bottomSpacer.height)
|
||||
|
||||
Rectangle {
|
||||
id: sectionBackground
|
||||
anchors.top: header.bottom
|
||||
width: section.width
|
||||
height: topSpacer.height + column.height + bottomSpacer.height
|
||||
color: StudioTheme.Values.themePanelBackground
|
||||
visible: false
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sectionBorder
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border.color: StudioTheme.Values.themeInteraction
|
||||
border.width: 1
|
||||
visible: false
|
||||
}
|
||||
Item {
|
||||
id: topSpacer
|
||||
height: section.addTopPadding && column.height > 0 ? section.topPadding : 0
|
||||
|
@@ -49,6 +49,17 @@ void EffectMakerModel::addNode(const QString &nodeQenPath)
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void EffectMakerModel::moveNode(int fromIdx, int toIdx)
|
||||
{
|
||||
if (fromIdx == toIdx)
|
||||
return;
|
||||
|
||||
int toIdxAdjusted = fromIdx < toIdx ? toIdx + 1 : toIdx; // otherwise beginMoveRows() crashes
|
||||
beginMoveRows({}, fromIdx, fromIdx, {}, toIdxAdjusted);
|
||||
m_nodes.move(fromIdx, toIdx);
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void EffectMakerModel::removeNode(int idx)
|
||||
{
|
||||
beginRemoveRows({}, idx, idx);
|
||||
|
@@ -44,6 +44,7 @@ public:
|
||||
|
||||
void addNode(const QString &nodeQenPath);
|
||||
|
||||
Q_INVOKABLE void moveNode(int fromIdx, int toIdx);
|
||||
Q_INVOKABLE void removeNode(int idx);
|
||||
|
||||
bool shadersUpToDate() const;
|
||||
|
Reference in New Issue
Block a user