module

Tryst::UI::GridValidator

@api private

A grid's own contract: every direct child needs a cell (g.cell(row:, col:) { }), and no two children can claim the same one. This is the primary detection either way a grid gets built, so the mistake surfaces pre-realize, collected alongside every other problem, instead of crashing mid-realize: the initial realize runs it via Validator.validate!, and Session#add runs the same checks over the parent it's adding into via Validator.validate_subtree!. Rooting that at the PARENT rather than the new children is what lets .check_cell_collisions below see an addition colliding with a sibling placed during the initial realize. Realizer#arrange_grid still raises on a missing cell as a belt-and-suspenders backstop for a path that reaches it with no validation at all (nothing in-tree does today - Handle#realize!'s on-demand lazy realize is the nearest candidate). Composed into WidgetValidators via :grid's own WidgetType#validator (see widget_types/grid.cr).

Class methods

call(node : Node, parent : Node | Nil, document : Document, errors : Array(String)) : Nil

node is a :grid node - WidgetValidators only dispatches here for that type.

Source
check_stray_cell(node : Node, parent : Node | Nil, errors : Array(String)) : Nil

The opposite direction from .check_missing_cell: a node carrying a grid-cell position (#cell_position) whose actual parent isn't a :grid at all - only reachable via direct Node/Document manipulation, since WidgetDSL#cell already refuses to run outside a ui.grid block. Cell intent can land on any node type (whatever #cell's block happens to build), so unlike .call above (dispatched through the registry only when visiting a :grid), this can't be keyed off a single node type there - Validator calls this directly for every node instead, in the same single tree walk.

Source