docs: the signal badges, the signal pages and the six-badge overflow (step 2 of the redesign)

Also wrap the signals page's hint line, which at 375 px minimum widened the whole slide-over panel to 376.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-03 01:48:43 +01:00
1 parent f315c677f3
commit 5242babf99
8 files changed
+55 -21

No files matched your search

+9 -5
View File
@@ -99,19 +99,23 @@ touching the data path.
- **`SlideOver`** (`src/ui_slideover.cpp`) is one `GtkRevealer` holding a `GtkStack`, added as the second
child placed *over* the plot (after the layout editor's buttons) in `GtkOverlay#plot_overlay`. A page is
a `slideover_add_page(app, id, title, widget)`: the widget is wrapped in a `GtkScrolledWindow` of its
own and registered under its id (`trigger`, `source-<id>`; `signal:<name>`, `signals`, `measure`,
`cursors` and `events` are reserved for later steps). One page is open at a time and `App::slideover.page`
own and registered under its id (`trigger`, `source-<id>`, `signals` (the signal list) and
`signal:<name>` (one signal's page, `src/ui_signal_page.cpp`, created on demand by `signal_page_ensure()`
and pruned by `signal_pages_sync()`, which `rebuild_signal_panels()` ends with); `measure`, `cursors`
and `events` are reserved for later steps). One page is open at a time and `App::slideover.page`
is its id, empty when closed. The open page is **not** a session value. Esc, *Close*, a second click on the
badge and a click on the plot close it; the click-away is a capture-phase observer (see
[invariants-gtk-and-chrome.md](invariants-gtk-and-chrome.md)). With two or more `source-*` pages, an
`AdwToggleGroup` under the header is the segmented switch between them.
- **`BadgeBar`** (`src/ui_badges.cpp`) is the fixed-height row between the plot and the status line
(`main-window.ui` `badge_bar`, two slots: signals, left, empty until step 2; system, right, holding the
**Trigger** and **Source** badges). A badge is a flat button whose `page` is the slide-over page it
(`main-window.ui` `badge_bar`, two slots: signals, left, a scroller holding one badge per enabled signal
and the `+`, or a single "N signals" badge past six; system, right, holding the **Trigger** and
**Source** badges). `sync_signal_badges()` rebuilds the signal badges (from `rebuild_signal_panels()`);
their order is `App::badge_order`, in memory only. A badge is a flat button whose `page` is the slide-over page it
toggles; the Source badge's page is the first `source-*` page, and a kind with none (UDPS, Flat UDP, a
file) leaves it a read-out with `can_target` off.
- **The dock** is the `AdwOverlaySplitView` sidebar (`side_box` > `dock_scroller` > `dock_page`): the
signal list, the cursors and the measurements in one scroller. It holds no tab switcher and no
cursors and the measurements only, in one scroller (the signal list is the `signals` page). It holds no tab switcher and no
revealer, and it does not hold a source kind's panels (those are slide-over pages).
**When each is built and when it is read.** `build_slideover()` runs in `on_activate` right after the tour
+1 -1
View File
@@ -225,7 +225,7 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
take room has to be hidden and not merely unrevealed; the revealer keeps the slide while the pane
*is* open. The allocated width is how this was found -- the revealer's own measure said 0.
**The sidebar is one dock now, and has no `GtkRevealer` left in it**: a single `GtkScrolledWindow`
(`dock_scroller`) holding the signal list, the cursors and the measurements one under another. It
(`dock_scroller`) holding the cursors and the measurements one under another. It
replaced an `AdwViewSwitcher` over an `AdwViewStack`, whose four text tabs did not fit 320 px (and a source
can add more); a source kind's own panels are slide-over pages, not dock sections. The reason is the one
this trap teaches: sections competing for one 320 px column each left every one of them short of room, and
+13 -2
View File
@@ -110,7 +110,9 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
does not propagate its child's height), and content that is taller than the plot -- the trigger form
on a 470 px window -- scrolls inside the panel instead of growing it. The widgets that go in a page
are reparented into it; their widths must fit 360 minus the border (the trigger form measures 267
minimum, the E-1608's panels 197).
minimum, the E-1608's panels 197). **One page wider than that widens the panel
for all of them** (the stack measures every page): the signals page's hint line once did, unwrapped, and
`[slideover] panel=` read 376 instead of 360; the label now wraps.
- **The badge bar has a fixed height and sits outside the overlay.** `badge_bar` is 36 px
(`height-request`) between `plot_overlay` and the status line, so the plot above it never moves when a
badge's text changes (`bar_h` = `bar_h_after` in `[badges]`). This is "layout must not depend on
@@ -119,8 +121,17 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
spare on the right) and never its height. The badge labels are not ellipsized: a name long enough to
need it would be a defect of the kind's `display_name()`. Rows that appear by trigger condition appear
inside the slide-over's scroller, never in the bar.
- **The signal badges live in a scroller, so the bar's minimum width never depends on the signal count.**
The bar's signals slot holds a `GtkScrolledWindow` (horizontal `EXTERNAL`, vertical `NEVER`) around one
row of badges and the `+`, because a button row's minimum width is the sum of its children: nine badges
(the E-1608: eight inputs and the counter) would push the window's minimum width past a laptop screen.
Past `kMaxSignalBadges` (6) the row is replaced by one "N signals" badge, which also stands for the `+`.
The bar's height stays 36 px in every one of these states (`bar_h_fixed` in `[sigbadges]`), and
`bar_min_w` reads the same with one signal, nine signals and the overflow (329 on the E-1608, 336 on UDPS:
the Source badge of each kind reads differently). A change that makes it grow with the signal count has
taken the scroller out of the measurement.
- **The dock's width is fixed too** (`side_column` `width-request` 300, the split view's 320 px floor
and cap), and it holds one scroller with the signal list, the cursors and the measurements. A
and cap), and it holds one scroller with the cursors and the measurements. A
section's visibility is never what makes the dock taller; the scroller is what absorbs the extra.
- **Trace slots are identified by signal name, not channel index.** Enabling a signal
or a new CONFIG renumbers the channel list, so an index would silently re-point a
+3 -2
View File
@@ -987,7 +987,8 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
in the `[helpui]` entry above, where `raw`, `target` and `inside` are explained). `clear=0` is read as geometry, not
as a placement bug, on the plot stop (the target is the whole content) and on the trigger stop at the
documented 756 px window (the panel is 360 px of it, so the card has no side wide enough and goes flush
left over the plot, overlapping the panel's edge by a few pixels).
left over the plot, overlapping the panel's edge by a few pixels), and on the `signals` stop for the same
reason (the dock beside it is 320 px and the card has no side wide enough).
- `[toursurface] finished: running=0 slideover=none` -- the last Next ended the walk and **the panel is
closed with it**.
- `[toursurface] restarted at trigger: running=1 slideover=trigger` then
@@ -2664,7 +2665,7 @@ signals list while the title and the badge marker still name `trigger`; `-1` whe
(`kMaxSignalBadges`); beyond that `badges=0 overflow=1 overflow_text=<N> signals plus_visible=0` (the "N signals" badge replaces the badges and the "+"). `dot_plotted` is the number of
badges whose signal is on a plot (its dot is then the trace colour, not the unplotted grey). `bar_h` is the bar's allocated height and `bar_h_fixed=1` that neither it nor its natural
height moved while one signal was switched off and on again (`rebuild_signal_panels()` each time), and that the badge count followed; `0` is a bar whose height depends on its content.
`bar_min_w` is only a record: the scroller must keep it the same however many signals there are (it reads 336 with the mock's 4 and with the overflow forced on). `opens=1`: clicking the
`bar_min_w` is only a record: the scroller must keep it the same however many signals there are (it reads 336 with the UDPS mock's 4 and with the overflow forced on, and 329 against the E-1608 mock with one signal and with nine -- the overflow, `enabled=9 badges=0 overflow=1 overflow_text=9 signals plus_visible=0 bar_h=36 bar_h_fixed=1`; a value that grows with the signal count is a scroller that has stopped constraining the bar). `opens=1`: clicking the
first signal badge opens `signal:<name>` with the badge marked open and a second click closes it (`-1` when overflowed, there being no signal badges); `plus_opens=1` the same for the "+"
(the overflow badge when overflowed) and the `signals` page.
+5
View File
@@ -447,6 +447,11 @@ precedent, not an exception.
read `click_inside_closes=0 still_open=1 click_outside_closes=1 esc_closes=1 closed=1`. For a screenshot
add `UDPSCOPE_PROBE_SLIDEOVER_HOLD=1`, which leaves the page open after line 1 (run with `GSK_RENDERER=cairo`
and `import -window root`): the panel must be drawn over the traces, opaque.
- **Slide-over and page probes (`SLIDEOVER`, `BADGES`, `SIGNAL_PAGES`, `SIGNAL_BADGES`) need a config that has already seen
the first-run tour**: a fresh `XDG_CONFIG_HOME` auto-starts the tour at about 1.5 s, and a tour stop with no page closes the
slide-over under the probe. Seed it with `mkdir -p $D/udpscope && printf 'tour_seen = true\n' > $D/udpscope/settings.toml`
(or one short throw-away run, which writes the key when the tour starts) and run with `XDG_CONFIG_HOME=$D`. Delete the
per-source subdirectory (`$D/udpscope/<host>_<port>`) between runs that must start from a first-run layout.
- `UDPSCOPE_PROBE_SIGNAL_PAGES_MS=1500` with `UDPSCOPE_EXIT_AFTER_MS=5000` and `UDPSCOPE_ENABLE_ALL_MS=500` -- the
per-signal `signal:<name>` slide-over pages. **Against a config that has already seen the tour** (a first run's
auto-tour closes the slide-over at about 1.5 s, which is when this probe opens its page). One `[signalpage]` line;