Skip to content
D
Documentation

SelectionToolsController

reference
2 min readUpdated

Import it from @grafloria/renderer.

ts
class SelectionToolsController

Methods

  • constructor(config: Partial<SelectionToolsConfig> = {})
  • getConfig(): SelectionToolsConfig
  • updateConfig(patch: Partial<SelectionToolsConfig>): void
  • isActive(): boolean — True while a resize / rotate / vertex drag owns the pointer.
  • activeGesture(): 'resize' | 'rotate' | 'vertex' | null — The kind of gesture in flight (null when idle) — hosts branch on it.
  • activeGestureNodeId(): string | null — The node the in-flight gesture is acting on (null when idle). Lets a host exclude it from a snap's sibling set — a box must not snap to itself.
  • computeLayer(engine: DiagramEngine, zoom = 1): SelectionToolLayer — Compute the tool layer for the CURRENT selection.
  • hitTest(layer: SelectionToolLayer, worldX: number, worldY: number): ToolHandle | null — Which tool (if any) is under a world point.
  • hitTestResize( layer: SelectionToolLayer, worldX: number, worldY: number, slop = 0 ): ToolHandle | null — resize-ux: the RESIZE handle under a world point, with optional extra grab slop (world units). One entry point for the mouse ladder (slop 0) and the touch ladder (finger-sized slop), so bands and dots grow identically.
  • beginResize( handle: ToolHandle, engine: DiagramEngine, worldX: number, worldY: number ): boolean — Arm a resize. Returns false when the handle/node is not resizable.
  • updateResize( engine: DiagramEngine, worldX: number, worldY: number, modifiers: ToolModifierState = {}, snap?: (box: Rectangle) => Rectangle ): boolean — Live-resize the node (direct model mutation, like the drag tool: smooth, no command churn — the single undo entry is minted at {@link endGesture}). snap optionally quantises the resulting box (grid / alignment) — the host passes the SnapController's hook so snapping composes with resizing.
  • beginRotate(handle: ToolHandle, engine: DiagramEngine, worldX: number, worldY: number): boolean
  • updateRotate( engine: DiagramEngine, worldX: number, worldY: number, modifiers: ToolModifierState = {} ): boolean — Live-rotate; Shift snaps to rotationSnapDegrees.
  • beginVertexDrag(handle: ToolHandle, engine: DiagramEngine): boolean
  • updateVertexDrag( engine: DiagramEngine, worldX: number, worldY: number, snapPoint?: (p: Point) => Point ): boolean
  • endGesture(engine: DiagramEngine): Command | null — End the active gesture and return the ONE command that makes it undoable (null for a no-op gesture). The model already sits at its final state — the command re-applies it (a no-op) and records the inverse, exactly like the node-drag commit.
  • cancelGesture(engine: DiagramEngine): void — Abandon the gesture, restoring the model to its pre-gesture state.
  • addVertexCommand(handle: ToolHandle, engine: DiagramEngine): Command | null — Insert a vertex at the clicked segment midpoint. Undoable.
  • removeVertexCommand(handle: ToolHandle, engine: DiagramEngine): Command | null — Remove the vertex under the tool. Undoable.
  • removeSelectionCommand(engine: DiagramEngine): Command | null — The command behind a remove button / halo delete: drop the whole selection (every selected node AND link) in ONE undo step.
  • cloneNodeCommand( engine: DiagramEngine, nodeId: string, offset: Point = { x: 40, y: 40 } ): Command | null — Halo clone: a copy of the node, offset, as one undoable AddNodeCommand. Ports get fresh ids (via the engine's shared {@link remapNodePortIds}) so the clone never shares port identity with its source — the bug paste/duplicate already learned.
  • forkNodeCommand( engine: DiagramEngine, nodeId: string, offset: Point = { x: 160, y: 0 } ): Command | null — Halo fork: clone the node AND link the original to the clone — one undo step (MacroCommand). The link runs from an output-capable port on the source to an input-capable port on the clone; null when either side has no usable port.

Was this page helpful?

SelectionToolsController — Grafloria