docs: design spec for the badge bar, readouts dock and slide-over panel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
3ac7a8f230
commit
c572ec280f
1 file changed
+175
@@ -0,0 +1,175 @@
|
||||
# Badge bar, readouts dock and slide-over panel -- design
|
||||
|
||||
Date: 2026-11-02. Status: approved in conversation, awaiting written-spec review.
|
||||
|
||||
## Goal
|
||||
|
||||
Replace the sidebar's tab switcher and the separate events pane with a layout built the way bench
|
||||
scopes build theirs: setup is reached by *the object it configures* (a badge under the plot), results
|
||||
are always on screen (a compact dock), and anything bigger than a readout opens in one slide-over
|
||||
panel. The sidebar tabs and the left events pane go away.
|
||||
|
||||
## Why (the problems, as found in the code)
|
||||
|
||||
- **Unreadable tab titles.** `side_view` is pinned at 320 px (`min-sidebar-width` = `max-sidebar-width`
|
||||
in `main-window.ui`), so four text tabs ("Measure / Signals / Analog out / Digital I/O") ellipsize,
|
||||
and a source can add more.
|
||||
- **Hard to find things.** The Signals tab stacks a trigger form of up to 15 rows (plus two
|
||||
expanders) on top of the signal list. Cursors and measurements are in Measure, source controls are
|
||||
in their own tabs, the header is icon-only, and the trigger/cursor toggles live apart from their
|
||||
panels.
|
||||
- **The events pane is a different application.** A `GtkPaned` + `GtkRevealer` on the left with its
|
||||
own bold title and header, a dragged width that is not saved, thumbnails the rest of the UI does
|
||||
not have, and a header toggle that is hidden until events exist.
|
||||
|
||||
## State of the art this follows
|
||||
|
||||
- Tektronix 5/6 Series: a badge bar under the waveform (a badge per channel/math waveform, plus
|
||||
Horizontal, Trigger, Acquisition badges); a tap opens *only that item's* settings; results
|
||||
(measurements, cursors, search) are a separate bar that does not cover the waveform.
|
||||
- Scopy and PicoScope 7: a channel list at the edge and a settings panel that slides in for the
|
||||
selected item (PicoScope lets it overlay or squeeze the trace).
|
||||
- Saleae Logic 2: one side panel at a time; decoded results also in a list beside the waveform.
|
||||
- Keysight InfiniiVision: dialogs that can be undocked so cursor and measurement values show together.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
┌ header: [window 2 s ▾] [Trigger] [Pause] [Cursors] [Dock] [☰] ┐
|
||||
├──────────────────────────────────────────────┬────────────────────┤
|
||||
│ plot rows ┌───────────┐ │ READOUTS │
|
||||
│ │ slide-over│ │ cursors, measures │
|
||||
│ │ settings │ ├────────────────────┤
|
||||
│ └───────────┘ │ EVENTS (n) │
|
||||
├───────────────────────────────────────────────┴────────────────────┤
|
||||
│ [●sine][●square][+] … [Trigger ▸][Source ▸]│
|
||||
├ status line ───────────────────────────────────────────────────────┤
|
||||
```
|
||||
|
||||
### Header bar
|
||||
|
||||
Keeps the time-window control, the Trigger, Pause and Cursors toggles and the overflow menu. The
|
||||
Events toggle is removed (Events is always in the dock). The sidebar toggle becomes the **Dock**
|
||||
toggle, so a narrow window can still hide the dock. There is no "Window" badge: the header's control
|
||||
is the timebase, and a second one would duplicate it.
|
||||
|
||||
### Right dock ("Readouts" and "Events")
|
||||
|
||||
- Fixed width, about 280 px; always on screen, shown but insensitive until the stream has signals
|
||||
("disable, do not hide"). It stays an `AdwOverlaySplitView` sidebar, which already gives it its
|
||||
own fixed width, the hide toggle and the overlay behaviour on a narrow window
|
||||
(`invariants-plot-and-layout.md`).
|
||||
- **Readouts** (top): the active cursor values and measurement values, read-only, one compact line per
|
||||
value, through the one formatter both panes share (`invariants-readouts-and-cursors.md`).
|
||||
An "Edit" affordance opens the slide-over's `measure` or `cursors` page; clicking a measurement row
|
||||
opens that measurement's editor.
|
||||
- **Events** (bottom): compact rows -- title, time, a small marker; no thumbnails. Insensitive outside
|
||||
trigger mode. A "Manage" affordance opens the slide-over's `events` page.
|
||||
|
||||
### Badge bar
|
||||
|
||||
A fixed-height row between the plot and the status line.
|
||||
|
||||
- **Signals** (left): one badge per enabled signal, up to 6; beyond that a single "N signals" badge.
|
||||
A badge shows a colour dot and the name, is a drag handle (reorder, or drop on a plot row, which
|
||||
replaces today's drag from the signal list), and opens that signal's page (colour, calibration,
|
||||
row, math). A trailing `+` opens the `signals` page (the full list, to enable more; the math editor
|
||||
entry).
|
||||
- **System** (right): **Trigger** shows its state (off / armed / triggered) and opens the trigger
|
||||
form; **Source** shows the connection state and the source name and opens that source's pages
|
||||
(`SourcePanel` pages, behind a small segmented switch inside the panel when there are several, as
|
||||
E-1608 has Analog out and Digital I/O).
|
||||
|
||||
### Slide-over panel
|
||||
|
||||
- Overlays the plot's right edge (about 360 px wide), never the dock; one page at a time; Esc or a
|
||||
click outside closes it. The plot is not resized by it.
|
||||
- Pages, by id: `trigger`, `signal:<name>`, `signals`, `measure`, `cursors`, `events`,
|
||||
`source-<id>`. Each page has its own scroller, so a tall page does not leave a shorter one scrolled
|
||||
(the reason the sidebar had a scroller per page).
|
||||
- Content: the trigger form (conditional rows, Advanced, Search the buffer), signal and calibration
|
||||
settings, measurement add/edit/remove and statistics, cursor options, event actions (Live, Compare,
|
||||
Accumulate), the math editor entry, and source pages.
|
||||
|
||||
### Status line
|
||||
|
||||
Unchanged.
|
||||
|
||||
## Components
|
||||
|
||||
New files, because `ui.cpp` is already very large.
|
||||
|
||||
| Unit | File | Responsibility |
|
||||
| --- | --- | --- |
|
||||
| `BadgeBar` | `ui_badges.cpp` | Builds signal / Trigger / Source badges from the model; emits "open page X"; owns badge drag. |
|
||||
| `SlideOver` | `ui_slideover.cpp` | A `GtkOverlay` child of the plot area: revealer + page stack keyed by id; Esc/click-away; open/close API. |
|
||||
| `ReadoutsDock` | `ui_dock.cpp` | The compact readouts and the compact events list, reading the same model the panes read today. |
|
||||
|
||||
Reuse, not rewrite:
|
||||
|
||||
- The trigger form, signal list and calibration, measurement editor and cursor options are
|
||||
**reparented** into slide-over pages.
|
||||
- `SourcePanel{id, title, widget}` is unchanged, so the E-1608 and Flat UDP panels need no change.
|
||||
- Only the events *list and actions* of the old pane move; the left `GtkPaned`/`GtkRevealer` and its
|
||||
divider sync are deleted.
|
||||
|
||||
## Invariants kept
|
||||
|
||||
- **Layout must not depend on content** (`invariants-plot-and-layout.md`): the dock has a fixed width,
|
||||
the badge bar a fixed height, and the slide-over overlays instead of resizing the plot. Rows that
|
||||
appear by trigger condition appear inside the slide-over's scroller.
|
||||
- **A `GtkOverlay` child is picked wherever its allocation is**: the slide-over is one opaque widget
|
||||
aligned to the end edge by margin and width, never a full-area transparent child, so pan, drop and
|
||||
hover on the rest of the plot are untouched.
|
||||
- The header's Trigger/Cursors/Pause toggles keep their two-way mirroring with the panels.
|
||||
|
||||
## State and session file
|
||||
|
||||
- The session file drops `side_tab` and gains the dock's shown state and width. An old file's
|
||||
`side_tab` is ignored (an unknown name is already harmless to `select_side_tab`).
|
||||
- The open slide-over page is not saved.
|
||||
- The tab ids `measure`, `signals` and `source-<id>` stop being a session format; they remain page ids.
|
||||
|
||||
## What must be rewritten around it
|
||||
|
||||
- **Tour and context help:** steps and help-figure surfaces that point at `side_switcher`,
|
||||
`side_stack` and `side_box` (`ui_tour.cpp`, `ui_context_help.cpp`) are re-pointed at the badge bar,
|
||||
slide-over and dock, and the tour text is rewritten.
|
||||
- **Probes:** the `switcher: policy=... pills=... labels=... images=... pages=...` line and
|
||||
`side_tab_probe` become probes that count badges, dock rows and the open slide-over page; the events
|
||||
divider probe goes away with the divider.
|
||||
- **Keyboard:** `SideTabMeasure` / `SideTabSignals` become "open the measure / signals page".
|
||||
- **Docs:** `README.md`, `USER-GUIDE.md`, `docs/claude/*` (architecture, verification,
|
||||
probe-readings, the plot-and-layout and gtk-and-chrome invariants), and the Mallard manual's
|
||||
figures.
|
||||
|
||||
## Rollout
|
||||
|
||||
Four steps, each its own plan, each leaving the app building, passing the probes and usable.
|
||||
|
||||
1. **Shell.** The plot overlay, the badge bar with Trigger and Source, the slide-over holding the
|
||||
existing trigger form and source pages. The sidebar tabs are removed; the existing Measure and
|
||||
Signals panels move into a temporary dock so nothing is lost.
|
||||
2. **Signal badges.** Per-signal badges, the `+` and "N signals" overflow, drag to reorder and to
|
||||
move to a row.
|
||||
3. **Compact readouts.** Read-only cursors and measurements in the dock; their editors in the
|
||||
slide-over.
|
||||
4. **Events.** The compact events section in the dock, the left pane and divider deleted, then the
|
||||
tour / help / docs sweep.
|
||||
|
||||
## Risks
|
||||
|
||||
- **Overlay above the GL plot.** The panel must composite and take input correctly above the
|
||||
plotter's GL area. The layout editor already places overlay children over the plot, so this is
|
||||
expected to work; step 1 confirms it before anything else is built on it.
|
||||
- **Reparenting the trigger form.** Its two-way mirroring with the header toggle, `sync_trigger_rows`
|
||||
and the locked summary view must keep working from a hidden-by-default page. Step 1 verifies it with
|
||||
the existing trigger probes.
|
||||
- **Many signals.** The badge bar's six-badge limit and horizontal behaviour are the one place the
|
||||
E-1608 (up to about 17 signals) stresses the design; step 2 includes a run on it.
|
||||
|
||||
## Out of scope
|
||||
|
||||
User-arranged or undockable panels, saved layouts of the panels themselves, a touch-specific mode,
|
||||
and any change to the plot, trigger, measurement or source engines. Per-source tab names do not
|
||||
change.
|
||||
Reference in new issue
Block a user