Files
udpscope/src/help/06-navigate.txt
T
Martino FerrariandClaude Opus 4.6 b313cac46e feat: the x axis is relative to now, and an export carries both clocks
Three asked-for changes, one commit because they are one coordinate system.

The live axis is a fixed [-window, 0] with the newest sample at 0, so x reads
as an age and the labels stand still while the trace rolls under them. That
makes the display clock distinct from the stream clock for the first time, so
`ScopeModel::stream_at_x0()` becomes the single conversion between them
(`display_x = stream_t - stream_at_x0()` in all four modes) and a snapshot
carries its own origin in `EventSnapshot::x_offset`. The pause view is now
rebased like an event's, reversing an earlier deliberate choice: a frozen
absolute-stamped picture would sit a whole uptime right of a newest-relative
axis. That also fixed a latent bug, the export adding `trigger_time()` to a
*paused* view's stamps.

The status bar says how long you have been paused -- wall time, since the
producer never stops, through `format_elapsed()` so the field cannot widen.

The export writes two time columns: `time`, the axis as displayed, and
`abs_seconds`, the stream's own clock for the same sample. f64 seconds and
not the wire's integer, because `udps_frame_t::values` is a `const double*`
and the integer never exists in this process.

Cursors and measurement marks move in opposite directions under the rolling
axis, deliberately: a cursor is a position on screen and stays put, a mark
names a sample and travels with it. `App::measure_window` is stream-clocked
for a sharper reason -- a display-coordinate live window never moves, so the
"the window moved" recompute would never fire again.

Moves the deps/plotter pin to 58473db, which stops a time label's mantissa
reaching its own radix: a one-second tick differenced off a live axis read
`1e+3ms`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-10-05 21:49:12 +02:00

45 lines
2.9 KiB
Plaintext

<b>Navigating the plot</b>
The plot pans and zooms with the mouse and with the keyboard. Every gesture acts on the row the
pointer is over, and because the rows share one time axis, an x change moves all of them.
<b>How to reach it</b>
<b>Wheel</b> zooms both axes · <b>Shift+wheel</b> zooms x only · <b>Ctrl+wheel</b> zooms y only.
<b>Drag</b> pans · <b>Ctrl+drag</b> is a box zoom on x · <b>Alt+drag</b> a box zoom on y.
<b>+</b> and <b>-</b> zoom both axes; <b>Ctrl</b> with them restricts to x, <b>Alt</b> to y.
<b>Arrow keys</b> pan, <b>f</b> fits, <b>Escape</b> cancels a gesture in progress.
The full table is in the shortcut overview (<tt>Ctrl+/</tt>).
<b>Worth knowing</b>
• The keyboard zoom's modifiers are <i>not</i> the wheel's, and that is deliberate: on common
layouts <tt>+</tt> <i>is</i> shift+<tt>=</tt>, so a bare zoom-in already arrives with Shift
set and Shift could not mean anything. Ctrl/Alt mirror the box-zoom drags instead.
• A <i>pinned</i> view is navigable within its own data but cannot leave it. While an event is
held, a capture is filling, or the view is paused, a zoom <i>in</i> works normally — "not
outside the event" is not "not readable" — but a pan or a zoom out is clamped to the data.
• Nothing you do on the plot changes the <i>time window</i> — only the header control does. A
zoom or a pan moves the view inside the window; <b>f</b> (and Fit X axis) is the <i>undo</i> of a
zoom, so a 2 s window zoomed into reads 2 s again. The window is more than the axis: it is also
the trigger's event span and how the samples are stored, so a wheel notch that redefined it
would re-plan the buffer and drop your history.
• The axis does not scroll — the <i>data</i> does. A live axis is a fixed <tt>[-window .. 0]</tt>
with the newest sample at 0, so the labels stand still and the trace rolls under them. The
cursors stand still with the labels (they are positions on screen, so a cursor you placed stays
where you put it, over newer data each frame), while a measurement's marks travel with the
sample they measured and leave the view when it does.
• A live view is clamped to the window you asked for, not to what the ring happens to hold.
That is why a buffer that has only just started filling leaves its left-hand side empty
instead of squeezing the window down to the first few samples.
• Zooming hard into a held capture is exact. The renderer finds the visible samples by binary
search over the real timestamps, never over a nominal sample grid, so a capture whose clock
wandered does not drift away from its axis as you zoom.
<b>Example</b>
Pause a live view, then press <tt>Ctrl++</tt>: x narrows and y does not move. Press
<tt>Alt++</tt>: y narrows and x does not. Eight doublings into a held 2 s capture, the trace
still reaches both margins — the zoom probe reports <tt>gap_px</tt> and <tt>end_px</tt> within
a pixel or two at every step.