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>
45 lines
2.9 KiB
Plaintext
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.
|