Commit Graph
397 Commits
Author SHA1 Message Date
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 bfe13630f9 Merge pull request 'Feature/source plugins' (#1) from feature/source-plugins into main
Reviewed-on: #1
2026-11-04 07:35:21 +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