Meshroom/meshroom/ui/qml/GraphEditor/Edge.qml

155 lines
4.9 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Shapes 1.6
import GraphEditor 1.0
import MaterialIcons 2.2
/**
* A cubic spline representing an edge, going from point1 to point2, providing mouse interaction.
*/
Item {
id: root
property var edge
property real point1x
property real point1y
property real point2x
property real point2y
property alias thickness: path.strokeWidth
property alias color: path.strokeColor
property bool isForLoop: false
property int loopSize: 0
property int iteration: 0
// BUG: edgeArea is destroyed before path, need to test if not null to avoid warnings
readonly property bool containsMouse: (loopArea && loopArea.containsMouse) || (edgeArea && edgeArea.containsMouse)
signal pressed(var event)
signal released(var event)
x: point1x
y: point1y
width: point2x - point1x
height: point2y - point1y
property real startX: 0
property real startY: 0
property real endX: width
property real endY: height
Shape {
anchors.fill: parent
// Cause rendering artifacts when enabled (and don't support hot reload really well)
vendorExtensionsEnabled: false
opacity: 0.7
ShapePath {
id: path
startX: root.startX
startY: root.startY
fillColor: "transparent"
strokeColor: "#3E3E3E"
strokeStyle: edge !== undefined && ((edge.src !== undefined && edge.src.isOutput) || edge.dst === undefined) ? ShapePath.SolidLine : ShapePath.DashLine
strokeWidth: 1
// Final visual width of this path (never below 1)
readonly property real visualWidth: Math.max(strokeWidth, 1)
dashPattern: [6 / visualWidth, 4 / visualWidth]
capStyle: ShapePath.RoundCap
PathCubic {
id: cubic
property real ctrlPtDist: 30
x: root.isForLoop ? (root.startX + root.endX) / 2 - loopArea.width / 2 : root.endX
y: root.isForLoop ? (root.startY + root.endY) / 2 : root.endY
relativeControl1X: ctrlPtDist
relativeControl1Y: 0
control2X: x - ctrlPtDist
control2Y: y
}
}
ShapePath {
id: pathSecondary
startX: (root.startX + root.endX) / 2 + loopArea.width / 2
startY: (root.startY + root.endY) / 2
fillColor: "transparent"
strokeColor: root.isForLoop ? root.color : "transparent"
strokeStyle: edge !== undefined && ((edge.src !== undefined && edge.src.isOutput) || edge.dst === undefined) ? ShapePath.SolidLine : ShapePath.DashLine
strokeWidth: root.thickness
// Final visual width of this path (never below 1)
readonly property real visualWidth: Math.max(strokeWidth, 1)
dashPattern: [6 / visualWidth, 4 / visualWidth]
capStyle: ShapePath.RoundCap
PathCubic {
id: cubicSecondary
property real ctrlPtDist: 30
x: root.endX
y: root.endY
relativeControl1X: ctrlPtDist
relativeControl1Y: 0
control2X: x - ctrlPtDist
control2Y: y
}
}
}
Item {
// Place the label at the middle of the edge
x: (root.startX + root.endX) / 2
y: (root.startY + root.endY) / 2
visible: root.isForLoop
Rectangle {
anchors.centerIn: parent
property int margin: 2
width: icon.width + 2 * margin
height: icon.height + 2 * margin
radius: width
color: path.strokeColor
MaterialToolLabel {
id: icon
anchors.centerIn: parent
iconText: MaterialIcons.loop
label: (root.iteration + 1) + "/" + root.loopSize + " "
labelIconColor: palette.base
ToolTip.text: "Foreach Loop"
}
MouseArea {
id: loopArea
anchors.fill: parent
hoverEnabled: true
onClicked: root.pressed(arguments[0])
}
}
}
EdgeMouseArea {
id: edgeArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
thickness: root.thickness + 4
onPressed: function(event) {
root.pressed(event)
}
onReleased: function(event) {
root.released(event)
}
Component.onCompleted: {
/* The curve scale must be set only once the component has been fully created, so
* that all the events following the update of the curve scale can be taken into
* account. */
curveScale = Qt.binding(() => cubic.ctrlPtDist / root.width) // Normalize by width
}
}
}