import { Button, Theme } from '../../ui'; import { HEADER_ICON_SVG } from '../panels/headerIcons'; /** Whatever a tab snaps: the graph canvas, the vector art canvas. A graph arranges its nodes too. */ export interface Snappable { setSnapping(on: boolean): void; arrange?(): void; } /** A graph, any of them, snaps from the start (#391); a curve and a vector art wait for the magnet. */ export const GRAPH_SNAPS_AT_FIRST = true; /** * The magnet every tab that snaps carries in its header (#194): an icon toggle, lit at first where * its target starts snapping, as every graph does (#391). A graph's tab has *Arrange* beside it * (#429), which is there and greyed out exactly when the magnet is. */ export class SnapToggle { readonly button: Button; readonly arrangeButton: Button | null; constructor( private readonly target: () => Snappable, private on = false, arranges = false, ) { this.button = new Button('', { width: Theme.controlHeight, icon: HEADER_ICON_SVG.snap, toggle: true, tooltip: 'Snap to the grid', onClick: () => this.set(!this.on), }); this.button.setToggled(on); this.arrangeButton = arranges ? new Button('Arrange', { tooltip: 'Arrange the selected nodes, or all of them, left to right', onClick: () => this.target().arrange?.(), }) : null; } get snapping(): boolean { return this.on; } get widgets(): readonly Button[] { return this.arrangeButton ? [this.button, this.arrangeButton] : [this.button]; } set(on: boolean): void { this.on = on; this.target().setSnapping(on); this.button.setToggled(on); } setEnabled(on: boolean): void { this.button.setEnabled(on); this.arrangeButton?.setEnabled(on); } }