docs: the node editor's gestures, its new probe assertions and its invariants

Each invariant records what went wrong rather than only the rule: a port hit
that lost its node, a hit test at the identity view that asserts nothing, a
`Delete` that must not fall through to the selected node, and a column pitch
too narrow for a wire's own tread. The warning baseline drops to four.
This commit is contained in:
Martino Ferrari committed 2026-10-07 02:56:36 +02:00
1 parent 8918494acb
commit 300b33159e
5 files changed
+123 -34

No files matched your search

+15 -9
View File
@@ -703,18 +703,24 @@ is what makes branching — the sum of a raw and a filtered channel — expressi
The editor is a compact node graph: each node is a box, its inputs are the squares on its left edge
and its output the square on its right. Click a box to select it and its parameters appear in the
form beside the canvas; click an output square and then an input square to wire them; drag a box to
move it. The graph is a *list* walked in order, so a node can only read the ones above it — a cycle
is not detected, it is unrepresentable, and an input square is only offered the nodes that qualify.
The node carrying the channel's value is the **last one** of a graph built top to bottom (as the
orange dot on the canvas says, and settable with *set as output*): it defaulted to the first node —
the source — so every operation was computed and discarded, and a gain or a filter produced a
channel identical to its input. Numeric fields are seeded with their own identity values too, since
form beside the canvas; **drag from an output square to an input square to wire them** (the old
two-click protocol is gone); drag a wired input square off its port to detach it; click a wire and
press `Delete` to remove it; drag a box to move it. **Wheel zooms about the pointer, drag the
background to pan, `f` to fit, `Ctrl+0` to reset.** `Tidy` in the toolbar lays out all nodes in
topological columns. The op is chosen when the node is added — the picker appears at the `+` — so
there is no opless placeholder to build past. The graph is a *list* walked in order, so a node can
only read the ones above it; a wire drawn right to left re-sorts the list silently, so the graph
stays evaluable without requiring the user to add nodes in order. A cycle is unrepresentable:
`math_connect()` checks the trial edge set with Kahn's algorithm before writing anything. The node
carrying the channel's value is the **last one** of a graph built top to bottom (as the orange dot
on the canvas says, and settable with *set as output*): it defaulted to the first node — the source
— so every operation was computed and discarded, and a gain or a filter produced a channel identical
to its input. Numeric fields are seeded with their own identity values too, since
`gtk_spin_button_new_with_range()` leaves a spin button at its range's minimum: the offset started
at -1e6, which turned `x*2` into `x*2 - 2000000`.
Wiring is checked before the channel is created, and the reason is shown rather than the dialog
closing on the work.
A live validation line beneath the form says why the graph cannot be saved; Apply is insensitive
while it is non-empty. The two modal alert boxes that used to appear are gone.
A `Source` node lists only the channels the scope is actually **acquiring**: naming a disabled
signal would read as no data for ever, and the stream's timestamp signal has no samples at all. The