import type { Graphics } from 'pixi.js'; import { blockOf, FIND } from '../../core/graph/findBlock'; import type { Graph } from '../../core/graph/Graph'; import { Theme } from '../../ui/Theme'; import { type Bounds, type Box, boundsOf } from '../framing'; /** Room between a block's frame and the nodes it holds. */ export const BLOCK_PAD = 14; export interface BlockFrame { find: string; bounds: Bounds; } /** One frame per closed `Find` … `Match` block, around every node of it that is drawn. */ export function blockFrames(graph: Graph, boxOf: (id: string) => Box | null): BlockFrame[] { const frames: BlockFrame[] = []; for (const node of graph.nodes) { if (node.type !== FIND) continue; const boxes = (blockOf(graph, node) ?? []).map(boxOf).filter((b): b is Box => b !== null); const b = boundsOf(boxes); if (!b) continue; frames.push({ find: node.id, bounds: { minX: b.minX - BLOCK_PAD, minY: b.minY - BLOCK_PAD, maxX: b.maxX + BLOCK_PAD, maxY: b.maxY + BLOCK_PAD, }, }); } return frames; } export function drawBlockFrames(g: Graphics, frames: readonly BlockFrame[]): void { const color = Theme.colors.categoryFlow; g.clear(); for (const { bounds: b } of frames) g.roundRect(b.minX, b.minY, b.maxX - b.minX, b.maxY - b.minY, 8) .fill({ color, alpha: 0.1 }) .stroke({ width: 1, color, alpha: 0.6 }); }