From ed2c0e22542ffa2afab2020bc38c10226783bedd Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 30 Aug 2025 14:33:14 -0400 Subject: [PATCH] Implement #18 --- src/MouseHandler.ts | 42 ++++++++++++++++++++++++++++++++++++++++ src/Sankey/SankeyNode.ts | 4 ++++ src/Sankey/SlotsGroup.ts | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/src/MouseHandler.ts b/src/MouseHandler.ts index 71fa42d..bc96025 100644 --- a/src/MouseHandler.ts +++ b/src/MouseHandler.ts @@ -178,6 +178,48 @@ export class MouseHandler extends EventTarget } } + public nodeClicked(event: MouseEvent, node: SankeyNode) + { + if (this._mouseStatus === MouseHandler.MouseStatus.ConnectingInputSlot) { + if (this._firstConnectingSlot == undefined) + throw Error("First connecting slot wasn't saved."); + + // Find a group of output slots in the target node matching the resource + const matchingOutputGroup = node.outputSlotGroups.find( + g => g.resourceId === this._firstConnectingSlot!.resourceId + ); + if (!matchingOutputGroup) return; + + const targetSlot = matchingOutputGroup.getOrCreateConnectableOutputSlot( + Math.min( + this._firstConnectingSlot.resourcesAmount, + matchingOutputGroup.vacantResourcesAmount + ) + ); + + this.outputSlotClicked(event, targetSlot); + } + else if (this._mouseStatus === MouseHandler.MouseStatus.ConnectingOutputSlot) { + if (this._firstConnectingSlot == undefined) + throw Error("First connecting slot wasn't saved."); + + // Find a group of input slots in the target node matching the resource + const matchingInputGroup = node.inputSlotGroups.find( + g => g.resourceId === this._firstConnectingSlot!.resourceId + ); + if (!matchingInputGroup) return; + + const targetSlot = matchingInputGroup.getOrCreateConnectableInputSlot( + Math.min( + this._firstConnectingSlot.resourcesAmount, + matchingInputGroup.vacantResourcesAmount + ) + ); + + this.inputSlotClicked(event, targetSlot); + } + } + private dragNodeTo(position: Point) { if (this._draggedNode == undefined) diff --git a/src/Sankey/SankeyNode.ts b/src/Sankey/SankeyNode.ts index adcb3e1..91aca9b 100644 --- a/src/Sankey/SankeyNode.ts +++ b/src/Sankey/SankeyNode.ts @@ -12,6 +12,7 @@ import { CanvasGrid } from "../CanvasGrid"; import { Settings } from "../Settings"; import { AppData } from "../DataSaves/AppData"; import { SankeyLink } from "./SankeyLink"; +import { MouseHandler } from "../MouseHandler"; export class SankeyNode extends EventTarget { @@ -343,6 +344,9 @@ export class SankeyNode extends EventTarget nodeContextMenu.addEventListener(NodeContextMenu.configureNodeOptionClickedEvent, openConfigurator); this.nodeSvg.addEventListener("dblclick", openConfigurator); + this.nodeSvg.addEventListener("click", (e) => { + MouseHandler.getInstance().nodeClicked(e, this) + }); configurator.addEventListener(NodeConfiguration.configurationUpdatedEvent, () => { diff --git a/src/Sankey/SlotsGroup.ts b/src/Sankey/SlotsGroup.ts index fe39e2e..813aefd 100644 --- a/src/Sankey/SlotsGroup.ts +++ b/src/Sankey/SlotsGroup.ts @@ -95,6 +95,45 @@ export class SlotsGroup extends EventTarget return newSlot; } + public getOrCreateConnectableSlot( + resourcesAmount: number, + expectedType: "input", + SlotClass: typeof SankeySlotMissing + ): SankeySlotMissing; + public getOrCreateConnectableSlot( + resourcesAmount: number, + expectedType: "output", + SlotClass: typeof SankeySlotExceeding + ): SankeySlotExceeding; + public getOrCreateConnectableSlot( + resourcesAmount: number, + expectedType: "input" | "output", + SlotClass: typeof SankeySlotMissing | typeof SankeySlotExceeding + ): SankeySlotMissing | SankeySlotExceeding { + if (this._type !== expectedType) { + throw new Error("Mismatched slots group type"); + } + + resourcesAmount = Math.min(resourcesAmount, this._lastSlot.resourcesAmount); + + if (this._lastSlot instanceof SlotClass) { + return this._lastSlot; + } + + return new SlotClass(this, this._groupSvg, { + id: this.resourceId, + amount: resourcesAmount, + }); + } + + public getOrCreateConnectableInputSlot(resourcesAmount: number): SankeySlotMissing { + return this.getOrCreateConnectableSlot(resourcesAmount, "input", SankeySlotMissing); + } + + public getOrCreateConnectableOutputSlot(resourcesAmount: number): SankeySlotExceeding { + return this.getOrCreateConnectableSlot(resourcesAmount, "output", SankeySlotExceeding); + } + public delete() { AppData.instance.lockSaving();