feat: Enable double-click on subgraph slot labels for renaming (#4833)

This commit is contained in:
Chenlei Hu
2025-08-08 21:11:21 -04:00
committed by GitHub
parent 8bf60777e7
commit 7bbbf59722
5 changed files with 402 additions and 196 deletions

View File

@@ -170,6 +170,21 @@ export abstract class SubgraphIONodeBase<
}
}
/**
* Handles double-click on an IO slot to rename it.
* @param slot The slot that was double-clicked.
* @param event The event that triggered the double-click.
*/
protected handleSlotDoubleClick(
slot: TSlot,
event: CanvasPointerEvent
): void {
// Only allow renaming non-empty slots
if (slot !== this.emptySlot) {
this.#promptForSlotRename(slot, event)
}
}
/**
* Shows the context menu for an IO slot.
* @param slot The slot to show the context menu for.
@@ -239,16 +254,7 @@ export abstract class SubgraphIONodeBase<
// Rename the slot
case 'rename':
if (slot !== this.emptySlot) {
this.subgraph.canvasAction((c) =>
c.prompt(
'Slot name',
slot.name,
(newName: string) => {
if (newName) this.renameSlot(slot, newName)
},
event
)
)
this.#promptForSlotRename(slot, event)
}
break
}
@@ -256,6 +262,24 @@ export abstract class SubgraphIONodeBase<
this.subgraph.setDirtyCanvas(true)
}
/**
* Prompts the user to rename a slot.
* @param slot The slot to rename.
* @param event The event that triggered the rename.
*/
#promptForSlotRename(slot: TSlot, event: CanvasPointerEvent): void {
this.subgraph.canvasAction((c) =>
c.prompt(
'Slot name',
slot.name,
(newName: string) => {
if (newName) this.renameSlot(slot, newName)
},
event
)
)
}
/** Arrange the slots in this node. */
arrange(): void {
const { minWidth, roundedRadius } = SubgraphIONodeBase

View File

@@ -4,7 +4,6 @@ import { LLink } from '@/lib/litegraph/src/LLink'
import type { RerouteId } from '@/lib/litegraph/src/Reroute'
import type { LinkConnector } from '@/lib/litegraph/src/canvas/LinkConnector'
import { SUBGRAPH_INPUT_ID } from '@/lib/litegraph/src/constants'
import { Rectangle } from '@/lib/litegraph/src/infrastructure/Rectangle'
import type {
DefaultConnectionColors,
INodeInputSlot,
@@ -51,18 +50,17 @@ export class SubgraphInputNode
// Left-click handling for dragging connections
if (e.button === 0) {
for (const slot of this.allSlots) {
const slotBounds = Rectangle.fromCentre(
slot.pos,
slot.boundingRect.height
)
if (slotBounds.containsXy(e.canvasX, e.canvasY)) {
// Check if click is within the full slot area (including label)
if (slot.boundingRect.containsXy(e.canvasX, e.canvasY)) {
pointer.onDragStart = () => {
linkConnector.dragNewFromSubgraphInput(this.subgraph, this, slot)
}
pointer.onDragEnd = (eUp) => {
linkConnector.dropLinks(this.subgraph, eUp)
}
pointer.onDoubleClick = () => {
this.handleSlotDoubleClick(slot, e)
}
pointer.finally = () => {
linkConnector.reset(true)
}

View File

@@ -4,7 +4,6 @@ import type { LLink } from '@/lib/litegraph/src/LLink'
import type { RerouteId } from '@/lib/litegraph/src/Reroute'
import type { LinkConnector } from '@/lib/litegraph/src/canvas/LinkConnector'
import { SUBGRAPH_OUTPUT_ID } from '@/lib/litegraph/src/constants'
import { Rectangle } from '@/lib/litegraph/src/infrastructure/Rectangle'
import type {
DefaultConnectionColors,
INodeInputSlot,
@@ -51,18 +50,17 @@ export class SubgraphOutputNode
// Left-click handling for dragging connections
if (e.button === 0) {
for (const slot of this.allSlots) {
const slotBounds = Rectangle.fromCentre(
slot.pos,
slot.boundingRect.height
)
if (slotBounds.containsXy(e.canvasX, e.canvasY)) {
// Check if click is within the full slot area (including label)
if (slot.boundingRect.containsXy(e.canvasX, e.canvasY)) {
pointer.onDragStart = () => {
linkConnector.dragNewFromSubgraphOutput(this.subgraph, this, slot)
}
pointer.onDragEnd = (eUp) => {
linkConnector.dropLinks(this.subgraph, eUp)
}
pointer.onDoubleClick = () => {
this.handleSlotDoubleClick(slot, e)
}
pointer.finally = () => {
linkConnector.reset(true)
}