graph editor progress & fixes

This commit is contained in:
Jakob Pinterits
2024-11-17 12:26:40 +01:00
parent f98633818f
commit 82e3257bfb
5 changed files with 67 additions and 13 deletions
@@ -107,17 +107,29 @@ export class DraggingConnectionStrategy {
toPortComponent = fixedPortComponent;
}
console.log("From node:", fromPortComponent);
console.log("To node:", toPortComponent);
// Prepare all data needed to make the connection
const fromNodeComponent = getNodeFromPort(fromPortComponent);
const toNodeComponent = getNodeFromPort(toPortComponent);
// Input nodes can only have one connection at a time. If the target
// port already has a connection, stop here.
let existingConnections = ge.graphStore.getConnectionsForPort(
toNodeComponent.id,
toPortComponent.id
);
if (existingConnections.length > 0) {
return;
}
// Create a real connection between the two ports
let connectionElement = makeConnectionElement();
ge.svgChild.appendChild(connectionElement);
let augmentedConn: AugmentedConnectionState = {
fromNode: getNodeFromPort(fromPortComponent).id,
fromNode: fromNodeComponent.id,
fromPort: fromPortComponent.id,
toNode: getNodeFromPort(toPortComponent).id,
toNode: toNodeComponent.id,
toPort: toPortComponent.id,
element: connectionElement,
};
@@ -1,8 +1,6 @@
import { ComponentId } from "../../dataModels";
import { ComponentBase, ComponentState } from "../componentBase";
import { pixelsPerRem } from "../../app";
import { NodeInputComponent } from "../nodeInput";
import { NodeOutputComponent } from "../nodeOutput";
import {
AugmentedConnectionState,
AugmentedNodeState,
@@ -20,7 +18,6 @@ import {
makeConnectionElement,
updateConnectionFromObject,
} from "./utils";
import { componentsByElement, componentsById } from "../../componentManagement";
import { CuttingConnectionStrategy } from "./cuttingConnectionStrategy";
export type GraphEditorState = ComponentState & {
@@ -175,21 +172,48 @@ export class GraphEditorComponent extends ComponentBase {
return true;
}
// Case: New connection from a port
// Case: Create / move connection from a port
if (
isLeftClick &&
targetElement.classList.contains("rio-graph-editor-port-circle")
) {
let portComponent = getPortFromCircle(targetElement);
// If this is an input port, and it already has a connection
// attached, drag that connection.
let fixedNodeId: ComponentId = getNodeFromPort(portComponent).id;
let fixedPortId: ComponentId = portComponent.id;
if (portComponent instanceof NodeInputComponent) {
let connections = this.graphStore.getConnectionsForPort(
fixedNodeId,
fixedPortId
);
console.assert(
connections.length <= 1,
`Input ports should have at most one connection, but port ${portComponent.id} has ${connections.length}`
);
// If a connection was found, remove it and drag that one
if (connections.length === 1) {
let connection = connections[0];
this.graphStore.removeConnection(connection);
connection.element.remove();
fixedNodeId = connection.fromNode;
fixedPortId = connection.fromPort;
}
}
// Add a new connection to the SVG
let connectionElement = makeConnectionElement();
this.svgChild.appendChild(connectionElement);
// Store the strategy
this.dragStrategy = new DraggingConnectionStrategy(
getNodeFromPort(portComponent).id,
portComponent.id,
fixedNodeId,
fixedPortId,
connectionElement
);
@@ -113,6 +113,23 @@ export class GraphStore {
return connections;
}
getConnectionsForPort(
nodeId: number,
portId: number
): AugmentedConnectionState[] {
// Get all connections for this node
let connections = this.nodeIdsToConnections.get(nodeId);
if (connections === undefined) {
return [];
}
// Filter out connections that don't involve the port
return connections.filter(
(conn) => conn.fromPort === portId || conn.toPort === portId
);
}
getAllConnections(): AugmentedConnectionState[] {
let result: AugmentedConnectionState[] = [];
@@ -25,7 +25,7 @@ export function devel_getComponentByKey(key: string): ComponentBase {
}
/// Given the circle HTML element of a port, walk up the DOM to find the port
/// component that contains it.A
/// component that contains it.
export function getPortFromCircle(
circleElement: HTMLElement
): NodeInputComponent | NodeOutputComponent {