Commit Graph
100 Commits
Author SHA1 Message Date
Martino FerrariandClaude Opus 4.6 7b8c932ab7 udpsclient: a TCP transport mode (SUBSCRIBE, no CONNECT) and a TCP mock server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-06 13:44:26 +01:00
Martino Ferrari 21b1945769 docs: TCPStreamer source kind spec and plan 2026-11-06 13:41:31 +01:00
Martino Ferrari 91ca29d181 scope windows: the same instruments as the main window
A scope or detached window drew its traces and nothing else: no cursors, no gate band, no trigger
marker, no measurement marks. They are not per-window state to be recreated -- the cursors are one
pair of times, the gate one band, the trigger one instant -- so the main window's row set stays the
**owner** and every window is written from it.

`sync_scope_instruments()` runs in the main tick after the main's own `sync_cursors()`/
`sync_gate()`: a gesture inside a scope window is read back from *that* window's controllers first
(those two calls only adopt while their own plot holds the grab, which is exactly "the drag
happened here"), adopted by the owner, and then every window -- the dragged one included -- is
written from the owner with the same cursor pair, mode and visibility, gate bounds and visibility,
and trigger marker. `RowSet::set_cursors()` is the new pair setter; `trigger_marker_x()`/`_visible()`
are the getters the mirror reads. The measurement marks travel by signal name
(`RowSet::MeasureMark::signal`, filled by the measures pass), so each window finds the row that
plots the signal and draws its ruler or mark there -- or none, when it does not plot it. The search
marks are times on the window and are placed on every window by the same per-frame path, and the
crosshair-axis-labels preference is restated to open windows when it changes.

Probe: `[scope-probe] instruments windows=N cursors=N gate=N trigger=N marks=N (main trigger
on=..)`, after adding a real gated `Top` measurement on `sine` -- the gate is restated visible each
frame by `update_measures()` and marks come only from `show_on_plot` measurements, so the leg uses
the app's own path. Docs: README, the cursors invariant, and the probe readings.
2026-11-06 12:21:38 +01:00
Martino Ferrari a29f38eaa9 session: remember extra windows, and reopen them from the menu
A scope or detached window was never written to the session, and a detached figure vanished from
the layout at the next start -- the figure had been removed from the main rows, and nothing kept
the window that held it.

Each window is now a `[[window]]` block in the session -- `name`, `detached`, and its own
`[[window.plot]]` rows with the same keys the main `[[plot]]` rows carry (signals, row weight,
cell width). `collect_layout()` writes the open windows' present arrangement plus the ones already
closed; loading puts **all** of them in `App::closed_windows` and never opens one: a window is a
view the user closed, and a launch that tiled windows onto the desktop would take that decision
for them (a tiling WM would tile them straight away). The overflow menu gains **Reopen closed
windows (N)**, which opens every remembered window through `open_scope_window_from_state()` -- the
one window constructor, then its rows, weights and signals dealt into its row set.

Closing a window records it, by name (a close/reopen cycle replaces its entry rather than
multiplying them), and schedules the save; **attaching** records nothing, because that window's
figure is on the main window again. A detached figure therefore survives a quit through its
window's entry.

Probe: `[scope-probe] loaded closed=N scopes=0` (remembered, none opened) and `reopen
scopes=..->.. remembered=.. left=0` (close, remember, the menu item's own click reopens).
Docs: README, the Mallard layout page, the probe readings and the session invariant.
2026-11-06 12:06:21 +01:00
Martino Ferrari 0c9333858c scope windows: their own layout editor, and the same shortcuts
A detached window is a view with an arrangement of its own -- and there was no way to change it:
the layout editor was the main window's, and a second window's rows could not be added or removed.

Every scope window now carries its own editor: `L` (or the grid toggle in its corner, revealed by
the same proximity rule as the attach button) shows the main editor's `+` / `×` / Done controls,
and they act on **that window's** row set (`set_scope_layout_editing()`, every button tagged with
its window), so a window holds as many figures as the user gives it and the two editors cannot
move each other's rows. Nothing a scope window arranges is written to the main window's session:
the windows themselves are not persisted.

The keyboard: each scope window gets a `GtkEventControllerKey` running the application's one
accelerator table -- `L` acts on the window the key arrived in, every other action reaches the
application through `run_app_action()`. The plot's own keys ('f', the arrows, Escape) already
worked there, through its plot controller.

The window struct now always builds its overlay (the corner controls' host); the attach button
stays detached-only, and both corner toggles step aside while the editor is up (Done is the way
out).

Probe: `[scope-probe] layout buttons=3 rows=1->2` -- the toggle builds 2*rows+1 buttons and a
boundary `+` adds a row. `L` in a real scope window verified by OCR ("Done" appears, the row's
`×` at its left). Docs: README, the Mallard layout page, the probe readings, and the layout
invariant (a view's arrangement is the view's).
2026-11-06 10:54:50 +01:00
Martino Ferrari ecdbf4f0e1 scope windows: mirror a pin as a range, and restore the tick rebuild
**The blank scope window in trigger mode.** A held event pins the main window to
`[-pre, +post]`, and the tick mirrors that pin onto every scope window. It passed
`pinned_range().min/max` to `pin_event_window()`, which takes **spans** (`pre, post`): `min` is
signed, so `pre` came out negative and the group range became `[+pre, +post]` — an inverted x
window. The plotter then had nothing to draw: no trace, no x-axis labels, an empty plot that
looked like a broken window. `RowSet::pin_display_range(x0, x1)` states the pin as the range a
mirroring view actually has, and the tick uses it; live mode was never affected, which is why the
defect only showed under the trigger.

Also restores the scope-window `rebuild_if_dirty()` in the tick, which a reproduction experiment
had left commented out (`REPRO-TEMP`) and a later commit carried: a window opened empty and filled
by a drop kept the figure it was built with.

Probe: `[scope-probe] pin_mirror=1 main=[..] scope=[..] x=[..]` pins the main window, reads the
scope's pin and plot x range a frame later, and reads `0` for an inverted or mismatched pin.
Docs: probe readings and the trigger/pinning invariant (range vs spans).
2026-11-06 10:39:10 +01:00
Martino Ferrari 2279e2140a scope windows: their own frame pump, and a diagnosis that names the GSK renderer
A second toplevel's frame clock is not the main window's: the tick binds, queues a render and
mirrors the span, but with nothing asking GTK for frames on *that* window the area can sit with
its queue full and present nothing -- a blank plot. Every scope window now carries a tick
callback on its own area (`gtk_gl_area_queue_render` per frame), which is the request that keeps
its frame clock running.

The "cannot paint" diagnosis now names the window's GSK renderer (`[GSK renderer: GskVulkanRenderer]`)
and says to restart with `GSK_RENDERER=gl` when it is the Vulkan one -- the interaction between
the Vulkan GSK renderer and an embedded `GtkGLArea` in a second toplevel is a known trouble spot,
and a tiling WM has no title bar to carry a title, so the sentence goes to stderr and the status
bar instead.
2026-11-06 10:09:28 +01:00
Martino Ferrari fa2d0f12fc scope windows: Fit X axis / Fit all in the menu, and a window that cannot paint says so
The scope menu carried a y fit only: with one shared time span, the x fit *is* the main window's
fit, and the next frame mirrors the result back -- so `Fit X axis` and `Fit all` now sit in the
menu beside the y entries and reset the shared range.

And a blank plot becomes a sentence: a scope window whose GL context failed, or whose area has
painted no frame two seconds after opening, writes the reason into its own title and to stderr
(`[scope] window 'plot 1' is not drawing: GL context failed: ...`). A blank rectangle is
indistinguishable from a failed context or an area that never got a frame, and the report "the
plot is not there, no x axis" is exactly what this answers: if the title stays unchanged, the
area is painting and the question moves to the compositor presenting the second window.
2026-11-06 09:03:54 +01:00
Martino Ferrari 2924f7627d scope windows: a right-click menu of their own
A scope window is a view with its own arrangement, but its plot had no menu: every right-click
went nowhere, because the main window's row menu acts on the main window's rows.

`on_scope_right_click()` wires each scope window's GL area (beside its drop target) to a menu
that acts on **that window's** row set: y axis auto scale, y axis fixed range (the main menu's
dialog, aimed at the window's rows through `FixedRangeContext::rows`), fit, and one
*Remove '<signal>'* per trace on the plot. A detached window's menu also carries **Attach back
to the main window**. What it deliberately does not carry is an x fit: the window follows the
main window's time span, so an x fit here would be undone by the next frame's mirror.

`remove_trace()` and `FixedRangeContext` are generalized to take the row set they act on (the
main window passes its own). Probe: `[scope-probe] rclick=1` asserts the click gesture is wired
per window; the menu build is exercised by the real right-clicks the smoke makes.
2026-11-06 08:55:29 +01:00
Martino Ferrari b90a99ec39 scope probe: read the windows' own GL account, and drop into the empty window
`[scope-probe]` grows the two readings a "blank scope window" report needs before it can be
blamed: `empty_drop=`/`empty_slot0=` (the same drop onto the empty window, the user's own
path) and `gl copy=/gl empty=/gl detached ok= frames=` -- each window's adapter context
status and staged-frame count. A scope whose context failed draws nothing at all: no axes,
no traces, exactly the "blank plot widget, no x axis" report -- and that is a driver/context
finding, not a layout one. The detached window is left open by the probe, so a run's
screenshots can answer "does the detached figure draw" with pixels.
2026-11-06 08:19:50 +01:00
Martino Ferrari 5ed75eb470 layout: detach a figure to its own window, and attach it back
Beside each figure row's full-screen toggle -- same corner, same show-on-approach reveal, same
one-figure/never-maximized rules -- a **detach** button moves the figure into a window of its
own: copied into a new scope window (titled "detached") and removed from the main window's rows,
which then save the change. The detached window is the one scope window with an **attach**
control: an overlay wrapping its GL area, a button in the top-right corner revealed by the same
pointer-proximity rule from the overlay's own motion controller, and one click appends the
figure back to the main window's rows (cells, weights, every slot's signal in its colour) and
closes the window.

`detach_figure()` / `attach_scope_window()`; the reveal and placement share the maximize
buttons' geometry and pointer state, per row. A detached window's rows participate everywhere a
scope window's do (drops, the signal page's *Plot on* groups), which the previous commit gave
them.

Probe: `[maximize-probe]` now counts the detach buttons (`detach_single=0` for one figure,
`detach=2` for two, absent while maximized) and reads their corner reveal
(`detach_near=1 detach_other=0`, the pointer parked on the detach button's own centre -- the
strictest zone of the pair). Real-pointer smoke: hover reveals the pair, clicking detach opens
the window, clicking attach closes it with the figure back. Docs: README, the Mallard layout
page, the probe readings, the layout invariant, and the tour's plot stop.
2026-11-05 23:35:26 +01:00
Martino Ferrari 51b4fad386 scope windows take drops, and the signal page lists them
The second windows were read-only by accident: nothing accepted a drop on them, and the
signal page's *Plot on* buttons knew only the main window's rows.

- **Drop target per scope window**: the same string payload a badge drags (the signal index),
  handled by `on_scope_drop_channel()` -- the target carries its own window, the row is that
  window's cell under the pointer, and `assign_signal_to_scope()` lands the signal in the
  window's own row set (enabling an unacquired signal first, exactly as the main drop does).
  The rebuild and the area's re-point are the window's next frame in the tick: a drop arrives
  from inside the very widget it rearranges, and a synchronous rebuild would reset the drag
  controller under it.
- **Plot on, per window**: the signal page carries one named group per scope window ("In
  \"plot 2\""), one button per plot of that window, sensitive on that window's own rows. A
  window closing refreshes the pages in its destroy handler, before the deferred delete could
  dangle a button's scope pointer.
- Probe: `[scope-probe]` drops through the wired handler (`drop=1 slot1='square'`) and counts
  the page's groups (`page_groups=2`); the section documents that it must not run with
  `UDPSCOPE_ENABLE_ALL_MS` -- the enable-all probe's second leg clears the front plot, which
  is the slot this probe copies. README, help and the layout invariant follow.
2026-11-05 19:37:42 +01:00
Martino Ferrari 706d247b58 signal page: the header names it, numbered; no duplicate title or back button
The slide-over's header already prints the open page's title beside its Close button, so the
signal page's body carried the name twice and a "Back to signals" button that only repeated
navigation the header owns. Both are gone.

The header's title is now the **numbered** name -- `<n>. <name>`, `measure_channel_number()`'s
number, the same one the signal badges and the measurements pane use -- so the panel says
*which acquired channel* it is and not only what it is called. `slideover_set_title()`
retitles a page in place (the open one included): the number follows the stream's channel
numbering, and the page is refilled whenever the model's signal list changes.

Probe: `[signalpage]` reads `title='1. sine' title_ok=1` (the header text against the numbered
name) and `no_dup=1` (no "Back to signals" button and no `title-3` label in the body); the old
`back_to_list` reading is gone with the button. Help, README and the probe doc follow.
2026-11-05 18:08:50 +01:00
Martino Ferrari bdf0ff7ddc scope: full-screen figures, second windows, gated measurements, per-configuration events
A batch of view and instrument work, with the probes and docs for each.

- **Full screen per figure row**: a toggle on each row's top-right corner, revealed by
  pointer proximity (`kMaximizeRevealPx` around its placed rect, per row, read from an
  overlay-level motion controller so a revealed button under the pointer cannot flicker);
  the plot menu offers the same as *Full screen this figure* / *Restore the layout*. The
  arrangement is saved and restored through `RowState`, so nothing plotted moves. A layout
  of one figure carries no toggle.
- **Second window**: `open_scope_window()` copies a figure (cells, width shares, signals in
  their colours) or opens an empty one, with its own `RowSet` and `PlotArea`; the main
  window's tick binds, acquires and repaints it, mirroring the time window and pin. Entries:
  the plot menu's *Open this plot in a new window* and the overflow menu's *New scope window*.
- **Layout editor from the plot**: the plot menu gains *Edit the layout...* / *Done editing
  the layout*, flipping the app's one toggle.
- **Measurements gate**: `MeasureOptions::gate` restricts a measurement to the held/pause
  snapshot (live falls back to the live ring), persisted with the session and shown in the
  measure dialog.
- **Crosshair axis badges**: a preference (`crosshair_axis_labels`, on by default) and the
  plotter's badges where the lines meet the axes, in the axes' own formats; the plot menu
  and the probe read them.
- **Event cache per configuration**: `EventStore` is keyed `<source>/<configuration>/`,
  `retarget_event_store()` follows every configuration switch, and a pre-configuration cache
  (loose files) is adopted into the configuration's folder on first start.
- **GTK4 lifecycle**: the main window's handlers move from the non-existent `"destroy"`
  signal to `close-request`; scope windows are closed with it and the application quits
  explicitly (the exit run's hang). The exit probe closes with `gtk_window_close()`.
- Probes: `[maximize-probe]` (single-figure rule and the corner reveal), `[scope-probe]`,
  `[split-probe]` cell crosshair leg, `[prefs-probe]` store keying, `[configs]` store key,
  `[rowmenu]` layout-editor entry; docs, help pages, README and AGENT.md updated.

Also fixes a probe-only use-after-free: `toggle_maximize_figure_row` replaces the figure
object, so the area must be re-pointed (the button's path does; the probe's raw call did not).
2026-11-05 17:58:59 +01:00
Martino Ferrari 931b0d108c layout editor: in-between split buttons sit above the divider handle; doc nits 2026-11-04 07:26:30 +01:00
Martino FerrariandClaude Opus 4.6 7972646dd2 layout editor: horizontal-resize icon, divider drag follows the pointer; x caption on every labelled plot; probes and docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-04 07:20:03 +01:00
Martino Ferrari 0c228c4822 pin deps/plotter: per-column x axes, tighter cell gap; docs 2026-11-04 07:04:07 +01:00
Martino Ferrari 03cb85e015 shared-y: final review fixes 2026-11-04 01:14:36 +01:00
Martino FerrariandClaude Opus 4.6 fa9f0c6da9 docs: split rows share one y axis
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-04 01:04:21 +01:00
Martino Ferrari b8177cc25a layout editor: column drag measures plot widths, not cell rects 2026-11-04 01:01:42 +01:00
Martino FerrariandClaude Opus 4.6 5f0bc75c27 plot host: split rows share y, rulers per row
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-04 00:55:59 +01:00
Martino FerrariandClaude Opus 4.6 135310ceca pin deps/plotter: shared y axis for split rows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-04 00:43:41 +01:00
Martino FerrariandClaude Opus 4.6 4c54b2dead docs: plan for the shared y axis in split rows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 23:57:27 +01:00
Martino FerrariandClaude Opus 4.6 10a8f2e33c docs: design spec for shared y axis in split rows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 23:52:43 +01:00
Martino FerrariandClaude Opus 4.6 053edd521a final review fixes: reject inf plot width, nearest-cell distance in double, tour wording
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 19:28:24 +01:00
Martino FerrariandClaude Opus 4.6 4fab14949c layout editor: column drag follows the pointer through the cell floor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 19:18:18 +01:00
Martino Ferrari 2183317953 docs: horizontal plot split 2026-11-03 19:14:57 +01:00
Martino FerrariandClaude Opus 4.6 7730b35fe3 probes: print cells and column weights; split-row ruler label
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 19:06:04 +01:00
Martino Ferrari 9f3e3597af signals: label plots by row and cell, drop onto a cell 2026-11-03 18:04:58 +01:00
Martino FerrariandClaude Opus 4.6 645cb6f4fa layout editor: split a row into cells, resize cells by drag
Add cell `+` buttons (n+1 per figure row), column resize handles with
drag, and update the `x` handler to call remove_cell instead of
remove_row. Fix row_weights_ misalignment in insert_row/remove_row.
Split probe steps 9-15 exercise content movement, column drag clamp,
row-weight tracking, and sensitivity at caps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 17:33:29 +01:00
Martino Ferrari 62ceb69278 session: plots carry row and width; files without row load one cell per row 2026-11-03 17:16:08 +01:00
Martino FerrariandClaude Opus 4.6 ae1d262be4 plot host: rows hold 1..4 cells; split probe scaffold
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 17:11:01 +01:00
Martino Ferrari 79e69c28fa deps/plotter: figure rows can hold several plots 2026-11-03 17:04:16 +01:00
Martino Ferrari 18b91c8016 docs: implementation plan for the horizontal plot split 2026-11-03 15:13:45 +01:00
Martino FerrariandClaude Opus 4.6 50078f0217 docs: design spec for the horizontal plot split
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 14:57:53 +01:00
Martino FerrariandClaude Opus 4.6 c15c89c00a ui: editable signal values and their pencil align right with the read-only ones
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 12:04:01 +01:00
Martino FerrariandClaude Opus 4.6 e29c889483 ui: signal details name the type and quantisation; editable values sit by the pencil, read-only ones align right
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 12:01:05 +01:00
Martino FerrariandClaude Opus 4.6 87f61ea364 ui: a signal's details sit directly under its name; its unit is user-changeable and saved with the session
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 11:42:30 +01:00
Martino FerrariandClaude Opus 4.6 bbef7faf3d ui: a signal's page shows gain and offset as aligned rows with a pencil each, replacing Calibrate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 11:36:58 +01:00
Martino FerrariandClaude Opus 4.6 6ff7dd786e ui: the Dock toggle carries the ruler icon, the dock being the readouts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 11:30:05 +01:00
Martino FerrariandClaude Sonnet 4.6 d82d9f8213 docs: the readouts strip hides when empty
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 11:15:19 +01:00
Martino FerrariandClaude Sonnet 4.6 5653a3a66b ui: the readouts strip hides when there are no cursors or measurements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 11:14:49 +01:00
Martino FerrariandClaude Sonnet 4.6 61d0925144 docs: the readouts strip follows the collapsed state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 10:50:55 +01:00
Martino FerrariandClaude Sonnet 4.6 1d144663b9 ui: the readouts strip is also shown in a collapsed window
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 10:50:55 +01:00
Martino FerrariandClaude Sonnet 4.6 3526ce0541 docs: the readouts strip
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 10:47:11 +01:00
Martino FerrariandClaude Sonnet 4.6 c8d9d04f59 ui: the readouts show in a strip under the plot when the dock is hidden
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 10:47:11 +01:00
Martino FerrariandClaude Sonnet 4.6 54f2722fea ui: the tour names the dock button; the user guide's key table follows shortcuts.cpp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:32:20 +01:00
Martino FerrariandClaude Sonnet 4.6 328588a8b9 docs: the manual and the user guide describe the badge bar, the dock and the slide-over pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:28:16 +01:00
Martino FerrariandClaude Sonnet 4.6 86ea0bac38 ui: stale tooltip wording
The dock button's tooltip, the guided-tour menu row's tooltip and the m / g shortcut labels still described a side panel and tabs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:28:16 +01:00
Martino FerrariandClaude Sonnet 4.6 c4b79da057 docs: events in the dock and on its page
The dock's Events block, the events slide-over page, the availability-rule deviation, the probe lines and the removal of the left pane are described; the false remembered-width claim is gone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:19:33 +01:00
Martino FerrariandClaude Sonnet 4.6 9db5e4a49c ui: tour and help describe the events block
The dock tour stop names the Events block (one click replays, Manage opens the list) and the event-history and record hints point at the page and the dock instead of a left pane.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:15:38 +01:00
Martino FerrariandClaude Sonnet 4.6 794df9b4d0 ui: one way to open the events page, and stale wording after the pane's removal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:11:34 +01:00
Martino FerrariandClaude Sonnet 4.6 8c866300d8 ui: the events list is a slide-over page; the left pane, its divider and the header toggle are gone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 07:07:57 +01:00
Martino FerrariandClaude Sonnet 4.6 cb098eff75 ui: cap and cheapen the dock's events rebuild
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 06:56:24 +01:00
Martino FerrariandClaude Sonnet 4.6 baf1c73b21 ui: compact events block in the dock
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 06:48:35 +01:00
Martino Ferrari b08494dd36 docs: plan for the events dock block and the left pane's removal (step 4 of the redesign) 2026-11-03 06:43:19 +01:00
Martino FerrariandClaude Sonnet 4.6 ce3cc97b91 docs: the readouts dock, the cursors and measurement pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 06:37:57 +01:00
Martino FerrariandClaude Sonnet 4.6 a2ce02db92 ui: tour and help follow the readouts dock
The dock tour stop describes the read-only readouts and their Edit buttons, and the cursors and measures hints point to the dock copy and the pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 06:37:57 +01:00
Martino FerrariandClaude Sonnet 4.6 38b31360cc ui: the cursors and measure pages are insensitive until the stream has signals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 06:29:32 +01:00
Martino FerrariandClaude Sonnet 4.6 3d307a0185 ui: the cursors and measurements panels are slide-over pages; the dock is the readouts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 06:24:52 +01:00
Martino FerrariandClaude Sonnet 4.6 a0fc0762d5 ui: compact cursor and measurement readouts at the top of the dock
Both views are written from the same variable at the same call site, so the dock cannot disagree with the full panels.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-11-03 05:22:41 +01:00
Martino Ferrari a7a1609d48 docs: plan for the compact readouts dock (step 3 of the redesign) 2026-11-03 05:19:19 +01:00
Martino FerrariandClaude Opus 4.6 1627abcd4a docs: the sample budget in samples per signal, the memory limit and the planner probe lines
Converts every --buffer-mb / buffer_mb mention to --buffer-samples / buffer_samples,
records the unit change as a deviation (README, SPECS, CLAUDE.md), documents the
buffer: and planner: dump lines and the new Preferences row, and updates the help
pages and the help-shot script.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 02:49:21 +01:00
Martino FerrariandClaude Opus 4.6 034c82f7d7 Budget the sample buffer in samples per signal, under a hard memory limit
--buffer-samples (k/M/G) replaces --buffer-mb: the request is rounded down to a
power of two for every signal and the shared time ring. A separate memory limit
(--memory-limit-mb, a Preferences row, default 8 GiB) halves the plan until the
real ring bytes fit and says so on stderr and in the status line. The per-source
key buffer_mb becomes buffer_samples; an old buffer_mb is ignored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 02:47:04 +01:00
Martino FerrariandClaude Opus 4.6 616cde5b13 badges: hide the Source badge when the source has no panel of its own
A Source pill that opens nothing (UDPS, Flat UDP, files) was noise. It is now shown only while the slide-over has a source page; the [badges] source line gains visible=.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 02:38:12 +01:00
Martino FerrariandClaude Opus 4.6 d8f82bd610 docs: source badge name only, no signals lock, the Add-a-signal page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 02:14:37 +01:00
Martino FerrariandClaude Opus 4.6 b98a3478ff badges: source badge shows the name only; drop the signals lock; the signals page proposes what can be added
The link state is the status bar's, so the Source badge loses its state text. The signals have no lock
(the badges and signal pages are direct manipulation), and the signals page lists only unacquired
signals and uncomputed math channels (plus the acquired ones while the badge bar has overflowed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 02:14:37 +01:00
Martino Ferrari dad424f1de ui: read the signal count under the lock in the badge bar; validate the drop payload 2026-11-03 01:53:09 +01:00
Martino FerrariandClaude Opus 4.6 5242babf99 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>
2026-11-03 01:48:43 +01:00
Martino FerrariandClaude Opus 4.6 f315c677f3 ui: reword the docs that still spoke of the list drag; keep disabled signals' badge order; stamp the signal generation before the snapshot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 01:37:31 +01:00
Martino FerrariandClaude Opus 4.6 ca10dfb323 ui: the signal badge is the drag handle (to a plot row, or to reorder); the list rows stop dragging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 01:30:55 +01:00
Martino Ferrari f27925da59 ui: one badge per enabled signal, an N signals overflow, and the order kept in memory 2026-11-03 01:19:13 +01:00
Martino Ferrari ad5e30f338 ui: park the slide-over stack only when the dying signal page is the visible one 2026-11-03 01:11:06 +01:00
Martino FerrariandClaude Opus 4.6 3b1cda50e5 ui: signal pages honour the signal lock and disable the plot a signal is already on
The per-signal page bypassed the signals lock for the acquire tick and the math
Edit/Delete buttons, and offered "Plot on r" for a plot the signal was already on.
A removed page also let another signal's page show during the close animation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 01:09:29 +01:00
Martino FerrariandClaude Opus 4.6 baf4a1f20f ui: per-signal slide-over pages; the drop's assignment and the colour reset as shared functions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-03 01:03:51 +01:00
Martino Ferrari 0dd235e41c ui: the signal list is the signals slide-over page, opened by a + badge or g 2026-11-03 00:54:25 +01:00
Martino Ferrari e36f2a202b docs: plan for the signal badges (step 2 of the redesign) 2026-11-03 00:46:43 +01:00
Martino FerrariandClaude Opus 4.6 54d7f63f35 ui: the s shortcut says dock, not side panel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 21:07:56 +01:00
Martino FerrariandClaude Opus 4.6 0c94caf866 docs: the badge bar, the slide-over and the dock (step 1 of the redesign)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 21:03:03 +01:00
Martino FerrariandClaude Opus 4.6 a1672acc70 ui: tighten the badge/dock/tour probes after review and fix the tour's stale hole
The session old-file probe and save_scheduled now discriminate, Esc is read through the real key path, the dock-section probe proves the Measure section starts out of view, and the tour's spotlight is measured independently of the helper it is drawn from. A target scrolled out of its scroller no longer leaves the previous hole standing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 20:56:09 +01:00
Martino FerrariandClaude Opus 4.6 2826042156 ui: the tour and the contextual help follow the badge bar, the slide-over and the dock
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 20:46:59 +01:00
Martino FerrariandClaude Opus 4.6 4b65197f56 ui: the sidebar's tabs become one dock; Measure and Signals by keyboard section; session keeps the dock's state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 20:37:55 +01:00
Martino Ferrari 31ff778e07 ui: the Source badge, and the source panels as slide-over pages 2026-11-02 20:19:47 +01:00
Martino FerrariandClaude Opus 4.6 5fb479bd69 ui: a badge bar with a Trigger badge, and the trigger form in the slide-over
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 20:12:16 +01:00
Martino FerrariandClaude Opus 4.6 a40863fa45 ui: a slide-over panel over the plot's right edge, with its probe
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 19:57:17 +01:00
Martino FerrariandClaude Opus 4.6 73f74ca495 docs: plan for step 1 of the badge bar / slide-over / dock redesign
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 19:50:12 +01:00
Martino FerrariandClaude Opus 4.6 c572ec280f docs: design spec for the badge bar, readouts dock and slide-over panel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 19:28:40 +01:00
Martino Ferrari 3ac7a8f230 Merge feature/gen-rate-and-tabs into feature/source-plugins 2026-11-02 14:21:08 +01:00
Martino FerrariandClaude Opus 4.6 0d8c583bbb e1608: a configurable generator update rate, and the achieved rate in the Analog out panel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 12:19:23 +01:00
Martino FerrariandClaude Opus 4.6 0c6e69957d ui: draw the sidebar tabs without the placeholder icon
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 12:11:16 +01:00
Martino FerrariandClaude Opus 4.6 5bb23e6a0a probe: name the MathNode fields; the build baseline is now one warning
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 12:06:45 +01:00
Martino Ferrari 7b9c62c911 Merge feature/e1608-scan into feature/source-plugins 2026-11-02 11:51:25 +01:00
Martino FerrariandClaude Opus 4.6 f74df49d33 e1608: scan review fixes (EINTR in Scan::poll, cfg-based broadcast test, no per-tick copy)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 10:27:00 +01:00
Martino FerrariandClaude Opus 4.6 8245324b51 docs: reconcile the E-1608 README with the real-board run and the scan lookup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 10:22:47 +01:00
Martino FerrariandClaude Opus 4.6 dbf145094a e1608: probe and docs for the network scan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 10:20:16 +01:00
Martino FerrariandClaude Opus 4.6 24bdd6b930 e1608: a Scan network row in the connection form, with click-to-fill results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 10:17:01 +01:00
Martino FerrariandClaude Opus 4.6 43c21a0cc2 e1608: discover boards on every interface, not only the default route's
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 10:14:47 +01:00
Martino Ferrari 9426a61919 docs: implementation plan for the E-1608 network scan 2026-11-02 10:07:50 +01:00
Martino Ferrari eb4e59ac50 Merge feature/text-tabs into feature/source-plugins 2026-11-02 10:03:28 +01:00
Martino FerrariandClaude Opus 4.6 16e6d7fa75 ui: sidebar tab selector uses text labels instead of icons
The two drawn tab glyphs were judged not understandable enough; the
switcher goes to the wide policy with titles only, and the glyphs,
their gresource entries and the icon-naming code are removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-02 09:49:55 +01:00