fix: a wire is picked by distance and a refusal is spoken, so the editor answers

A review of the whole node editor. The hit test measured the distance to the
24 curve samples rather than to the segments between them, so a wire spanning
several rows was unpickable between two samples -- the probe now places its
boxes 280 units apart and prints the nearest sample's own 8.4 against a 3.0
tolerance, which the point test would have missed. A refused connection said
nothing: the message is now carried in `MathDialog::refusal` and shown once by
the single writer of the label, and a self-wire is refused through the real
drag-end path instead of only through `math_connect()`.

Two defects were found only by the new assertions. `math_dialog_sync()`
re-entered itself -- `gtk_drop_down_set_selected()` emits `notify::selected`
for a programmatic set too, and the handler answers by syncing again, which
consumed the refusal before it could be drawn -- so the body is now guarded
one level deep. And a deleted node left `selected_wire` naming an index that
afterwards belongs to a different wire, so `Delete` cleared an input on the
wrong node.

A node is placed in the first free grid cell rather than at the end of the
list's own cell, so a node added after a delete no longer lands on top of a
survivor; the label ellipsizes with a tooltip rather than wrapping, because a
wrapped line makes the dialog's height depend on the text in it.
This commit is contained in:
Martino Ferrari committed 2026-10-07 07:09:49 +02:00
1 parent 300b33159e
commit f238e717b2
5 files changed
+318 -57

No files matched your search

+4 -3
View File
@@ -706,9 +706,10 @@ and its output the square on its right. Click a box to select it and its paramet
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
background to pan, `f` to fit, `Ctrl+0` to reset.** *tidy*, a button in the editor dialog beside
*fit*, lays out all nodes in topological columns. The op is chosen when the node is added — *add
node* in the same row of the dialog is a menu button whose popover lists every op — 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