feat: the locked trigger pane carries Arm/Disarm, and one function states both arm buttons
The compact line -- the pane's locked, "what is it set to" mode -- showed the arm state in words and gave
no way to change it, so arming from there meant unfolding the panel first, which is the thing the lock
exists to avoid. The control is built into the pane's *heading*, the row that stays on screen when the
body goes, and it is wired to the same `on_arm_clicked` the body's button uses, so both do one thing.
Its label, sensitivity and visibility are stated by `sync_arm_buttons()`, called from the four places any of
its inputs can move: the click, the mode toggle, the curator's per-tick re-read (a single-shot latch disarms
by itself) and `apply_pane_lock()`. The label comes from the producer's `trigger_armed()` atomic, the other
two from the toolbar toggle that owns `enabled`, so no caller needs the model lock. Visibility is
`enabled && locked`: with trigger mode off the line beside it already reads "stream (trigger off)" and there
is no engine to arm, and with the pane open the body's own button is the one on screen. Never both -- two
arm buttons would be two controls for one state.
Verified with the arm probe, which locks the pane the way a user does (the [edit] click):
compact arm with the trigger off: visible=0; with the trigger on and the pane locked:
visible=1 sensitive=1 width=51 label=Disarm
[udpscope] compact arm probe: locked=1 enabled=1 own=1 effective=1 width=51 panel_width=-1 label=Disarm
`panel_width=-1` is the "not both" assertion: the body's button is not on screen while the compact one is.
The width cost a defect to read. The control is created hidden and shown for the first time inside the
handler, so a same-tick `gtk_widget_get_width()` reads 0 while `gtk_widget_is_visible()` already says 1 --
and the body button's *stale* allocation (270 px, from when the body was still up) reads as a live one,
because `gtk_widget_get_visible()` is the widget's own flag and stays true under a hidden parent. The
reading is therefore taken one frame later, by a step of its own, and the control is compared with
`is_visible()`. Both defects are in the invariants, because the next control read this way will meet them.
0 Gtk-CRITICAL; clean build with the documented four warnings (the help resource re-measured); test-ui
14/14. Docs: the rule and both readings in `invariants-trigger-and-pinning.md`, the probe's entry in
`probe-readings.md`, and the user-facing sentence in `src/help/08-trigger.txt`.
This commit is contained in:
1 parent
908286ee89
commit
620473a5be
8 files changed
+160
-17
No files matched your search
@@ -18,6 +18,23 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
|
||||
reports it as `zoom ... span=.. window=.. limited=1`.
|
||||
Its pan clamping is likewise gated on the data being wider than the view, or the empty
|
||||
left-hand side drags the live edge off the right-hand edge.
|
||||
- **The compact pane's arm control is built in the heading, and *one* function states both arm
|
||||
buttons.** Arming is a runtime decision and the locked pane is exactly where it is made, so the
|
||||
control cannot live in the body — that is the part which goes away. `sync_arm_buttons()` is what
|
||||
states the label, the sensitivity and the visibility of both buttons, and it is called from the four
|
||||
places any of its three inputs can change (the click, the toolbar toggle, the curator's re-read,
|
||||
`apply_pane_lock()`). Visibility is `enabled && locked`: with trigger mode off the line beside it
|
||||
already says "stream (trigger off)" and there is no engine to arm, and with the pane open the body's
|
||||
button is the one on screen — **two arm buttons at once would be two controls for one state**, which
|
||||
is why the probe reads the body's allocation as `-1` while the compact one is up.
|
||||
- **A widget's allocation is not readable in the tick it is first shown.** The compact arm control is
|
||||
created hidden and shown for the first time inside a signal handler, so `gtk_widget_get_width()` in
|
||||
that same tick reads `0` while `gtk_widget_is_visible()` already says `1` — and its sibling's stale
|
||||
allocation (270 px, from when the *body* was still on screen) reads as a live one, because
|
||||
`gtk_widget_get_visible()` is the widget's *own* flag and stays true under a hidden parent. The width
|
||||
only becomes the proof that a control is on the surface **one frame later**, which is why the probe
|
||||
has a `compact_arm_step()` of its own; and the control to compare against must be measured with
|
||||
`is_visible()` or not at all.
|
||||
- **Signals start disabled** — enabling is what starts acquisition. A trigger on a
|
||||
signal nobody acquires can never fire, so selecting/arming enables it.
|
||||
- **The trigger's event window is separate from the display window**, and
|
||||
|
||||
@@ -1207,6 +1207,16 @@ its pane.
|
||||
a trigger is configured before it is switched on — so this reads `1` always, and a `0` means the
|
||||
settings have been made unreachable again. The *cursors'* body is disabled with the cursors, and that
|
||||
is the pane whose readout has nothing to show.
|
||||
- **`compact arm with the trigger off: visible=0` / `with the trigger on and the pane locked:
|
||||
visible=1 sensitive=1 width=51 label=Disarm`** is the compact pane's arm control, in the two states
|
||||
that define it. The first says it is *not* on the line when there is no engine to arm; the second says
|
||||
it is, and that it is live (`sensitive=1`) and laid out (`width` > 0 — a width can only be read the
|
||||
frame *after* it is first shown, see the invariants). `label` must agree with `model->trigger_armed()`
|
||||
rather than with a fixed word, because a single-shot latch may have disarmed it by the time the probe
|
||||
looks. `[udpscope] compact arm probe: locked=1 enabled=1 own=1 effective=1 width=51 panel_width=-1
|
||||
label=Disarm` prints the inputs beside the outcome, and **`panel_width=-1` is the assertion that the
|
||||
body's own Arm button is not on screen at the same time** — two arm controls for one state is the
|
||||
defect it exists to catch.
|
||||
- **`arm sensitive with the trigger off=0`** is the one exception inside that body: `Arm` is a *runtime*
|
||||
control, so with trigger mode off there is no engine to arm and it is disabled (and labelled `Arm`
|
||||
again). `1` here is an Arm button that does nothing when clicked.
|
||||
|
||||
@@ -15,7 +15,7 @@ xvfb-run -a env UDPSCOPE_EXIT_AFTER_MS=8000 UDPSCOPE_ENABLE_ALL_MS=1000 \
|
||||
|
||||
Two baselines every run is read against. A clean build emits **four** warnings and no more: two
|
||||
`-Wmissing-field-initializers` on `MathNode::source` and `-Woverlength-strings` on **both**
|
||||
generated GResource `.c` files — the help pages' (**515700** bytes) and the icons', whose blob is
|
||||
generated GResource `.c` files — the help pages' (**516044** bytes) and the icons', whose blob is
|
||||
**12352** against C99's 4095-byte string-literal limit with the seven action icons and the two app icons
|
||||
that remain (a note about a generated file, which GCC itself supports) -- re-measured when
|
||||
the tab work changed the set (that icon left, the two tab glyphs arrived, and this file's
|
||||
|
||||
Reference in new issue
Block a user