-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[UI] Add an auto-scroll feature to connect edges on huge scenes #3159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
f04e27f
4893f33
41f997c
21a3e3d
1e02d5a
96fc92e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import QtQuick | ||
| import QtQuick.Controls | ||
| import QtQuick.Layouts | ||
| import Qt5Compat.GraphicalEffects | ||
|
|
||
| import Controls 1.0 | ||
| import MaterialIcons 2.2 | ||
|
|
@@ -18,6 +19,22 @@ Item { | |
| property variant nodeTypesModel: null /// The list of node types that can be instantiated | ||
| property real maxZoom: 2.0 | ||
| property real minZoom: 0.1 | ||
|
|
||
| // Autoscroll properties | ||
| readonly property int autoscrollMargin: 100 // Border thickness (width in pixels) | ||
| readonly property int autoscrollSpeed: 15 // Speed factor | ||
| readonly property real maxScrollSpeed: 3.0 // Clamp scroll speed | ||
| property bool isDraggingEdge: false // Tracks whether we are dragging an AttributePin | ||
| property point dragMousePos: Qt.point(0, 0) // Position of the mouse during edge dragging | ||
|
|
||
| readonly property real borderHighlightOpacity: 0.05 | ||
| readonly property color borderHighlightColor: Colors.blue | ||
| readonly property real borderHighlightWidth: 3 | ||
| property bool highlightedBorderLeft: false | ||
| property bool highlightedBorderRight: false | ||
| property bool highlightedBorderTop: false | ||
| property bool highlightedBorderBottom: false | ||
|
|
||
| property var edgeAboutToBeRemoved: undefined | ||
|
|
||
| property var _attributeToDelegate: ({}) | ||
|
|
@@ -156,6 +173,102 @@ Item { | |
| } | ||
| } | ||
|
|
||
| // Listen to the UIGraph edge drag infos | ||
| Connections { | ||
| target: _currentScene | ||
| ignoreUnknownSignals: true | ||
|
|
||
| function onEdgeDraggingChanged(dragging) { | ||
| root.isDraggingEdge = dragging | ||
| root.highlightedBorderRight=false | ||
| root.highlightedBorderLeft=false | ||
| root.highlightedBorderTop=false | ||
| root.highlightedBorderBottom=false | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since those attributes are always reset together, maybe regroup all those booleans inside a single object ? |
||
| } | ||
|
|
||
| function onEdgeDragMousePosChanged(windowX, windowY) { | ||
| // Translate window coordinates into the GraphEditor coordinates | ||
| var localPos = root.mapFromItem(null, windowX, windowY) | ||
| root.dragMousePos = Qt.point(localPos.x, localPos.y) | ||
| } | ||
| } | ||
|
|
||
| // Add a timer to auto-scroll on the graph when edge dragging is active | ||
| Timer { | ||
| id: autoscrollTimer | ||
| interval: 20 | ||
| running: root.isDraggingEdge | ||
| repeat: true | ||
|
|
||
| onTriggered: { | ||
| var mouseX = root.dragMousePos.x | ||
| var mouseY = root.dragMousePos.y | ||
| var deltaX = 0 | ||
| var deltaY = 0 | ||
|
|
||
| // Left | ||
| if (mouseX < root.autoscrollMargin) { | ||
| var factorX = Math.min(root.maxScrollSpeed, (root.autoscrollMargin - mouseX) / root.autoscrollMargin) | ||
| deltaX = root.autoscrollSpeed * factorX | ||
| } | ||
| // Right | ||
| else if (mouseX > root.width - root.autoscrollMargin) { | ||
| var factorX = Math.min(root.maxScrollSpeed, (mouseX - (root.width - root.autoscrollMargin)) / root.autoscrollMargin) | ||
| deltaX = -root.autoscrollSpeed * factorX | ||
| } | ||
| // Top | ||
| if (mouseY < root.autoscrollMargin) { | ||
| var factorY = Math.min(root.maxScrollSpeed, (root.autoscrollMargin - mouseY) / root.autoscrollMargin) | ||
| deltaY = root.autoscrollSpeed * factorY | ||
| } | ||
| // Bottom | ||
| else if (mouseY > root.height - root.autoscrollMargin) { | ||
| var factorY = Math.min(root.maxScrollSpeed, (mouseY - (root.height - root.autoscrollMargin)) / root.autoscrollMargin) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The computations for factorX and factorY are almost identical in each case. Maybe this could be refactored within a function ? |
||
| deltaY = -root.autoscrollSpeed * factorY | ||
| } | ||
|
Alxiice marked this conversation as resolved.
|
||
|
|
||
| root.highlightedBorderRight=false | ||
| root.highlightedBorderLeft=false | ||
| root.highlightedBorderTop=false | ||
| root.highlightedBorderBottom=false | ||
|
|
||
| // Apply scroll on workspaxe | ||
| if (deltaX !== 0 || deltaY !== 0) { | ||
| draggable.x += deltaX | ||
| draggable.y += deltaY | ||
| workspaceMoved() | ||
|
|
||
| if (deltaX>0) { root.highlightedBorderLeft=true } | ||
| else if (deltaX<0) { root.highlightedBorderRight=true } | ||
| if (deltaY>0) { root.highlightedBorderTop=true } | ||
| else if (deltaY<0) { root.highlightedBorderBottom=true } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Display scroll direction | ||
| Rectangle { | ||
| enabled: root.isDraggingEdge | ||
| z: 100 | ||
| color: "transparent" | ||
| border.color: root.borderHighlightColor | ||
| border.width: root.borderHighlightWidth | ||
|
|
||
| // Combine fill and margins into one anchor block | ||
| anchors { | ||
| fill: parent | ||
| leftMargin: root.highlightedBorderLeft ? 0 : -root.borderHighlightWidth | ||
| rightMargin: root.highlightedBorderRight ? 0 : -root.borderHighlightWidth | ||
| topMargin: root.highlightedBorderTop ? 0 : -root.borderHighlightWidth | ||
| bottomMargin: root.highlightedBorderBottom ? 0 : -root.borderHighlightWidth | ||
| } | ||
|
|
||
| Behavior on anchors.leftMargin { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } } | ||
| Behavior on anchors.rightMargin { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } } | ||
| Behavior on anchors.topMargin { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } } | ||
| Behavior on anchors.bottomMargin { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } } | ||
| } | ||
|
|
||
| MouseArea { | ||
| id: mouseArea | ||
| anchors.fill: parent | ||
|
|
@@ -208,8 +321,8 @@ Item { | |
| root.forceActiveFocus() | ||
| workspaceClicked() | ||
| } | ||
|
|
||
| onPositionChanged: { | ||
| onPositionChanged: function(mouse) { | ||
| if (drag.active) | ||
| workspaceMoved() | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.