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).
This commit is contained in:
1 parent
bfe13630f9
commit
bdf0ff7ddc
39 files changed
+2267
-136
No files matched your search
@@ -63,6 +63,16 @@
|
||||
<item><p>A marker past the newest sample reads <code>--</code>. With only one marker
|
||||
over data the row reads <code>partial</code>: a difference between a number and nothing
|
||||
is not a number.</p></item>
|
||||
<item><p>The hover crosshair also writes its two coordinates where the eye already
|
||||
looks: the value where its horizontal line meets the y axis, and the time where its
|
||||
vertical line meets the x axis — each in a small box among that axis' own tick labels,
|
||||
in the axis' own format. Each box is centred on the line it names, and its background
|
||||
covers what is behind it, so a tick label underneath never prints through the number.
|
||||
The preference's <gui>Crosshair axis labels</gui> turns the pair off.</p></item>
|
||||
<item><p>In a split row the horizontal line runs across <em>every</em> plot of the row,
|
||||
not just the one under the pointer: the plots share one y range, so it is one value
|
||||
along the whole row. It stops at the row's edges — another row has a scale of its
|
||||
own.</p></item>
|
||||
<item><p>In <gui>mix</gui> each marker also places a crossing annotation per trace,
|
||||
which is what lets you see on the plot which sample a number came from. It is <em>on
|
||||
that sample</em>, so when the marker falls between two it sits a little off its own
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
add a trace.</p>
|
||||
</item>
|
||||
<item>
|
||||
<p>Press <key>l</key>, or pick <gui>Layout editor</gui> from the overflow menu, to add
|
||||
<p>Press <key>l</key>, pick <gui>Layout editor</gui> from the overflow menu, or pick
|
||||
<gui>Edit the layout…</gui> from a plot's right-click menu, to add
|
||||
and remove rows: a <gui>×</gui> appears at the top left of each plot and a <gui>+</gui>
|
||||
on each boundary between rows, including above the first and below the last.</p>
|
||||
</item>
|
||||
@@ -58,12 +59,33 @@
|
||||
<p>All the plots of a row, and of the whole figure, share one time window: zooming or
|
||||
panning along time in any of them moves all of them, and the vertical cursors are drawn in
|
||||
every plot. The plots of a split row also share one y range: the y labels are drawn at the
|
||||
left of the first plot only, the horizontal cursors sit at the same values in every plot, and a
|
||||
left of the first plot only, the horizontal cursors sit at the same values in every plot, the
|
||||
hover crosshair's horizontal line spans all of them, and a
|
||||
zoom, pan, fit or fixed range in any of them applies to the whole row. The time labels
|
||||
sit under the bottom row, and under any row above it whose columns differ from the row below. A row holds at most 4 plots and the figure at most 8
|
||||
in total; the <gui>+</gui> buttons go grey at the limit.</p>
|
||||
</section>
|
||||
|
||||
<section id="fullscreen">
|
||||
<title>A row full screen, and a second window</title>
|
||||
<list>
|
||||
<item><p>Every row carries a <gui>full-screen</gui> button in its top-right corner: it comes
|
||||
out of hiding when the pointer moves near that corner and hides again when it leaves, so the
|
||||
plot is not decorated by a control you are not reaching for. One click makes that row fill the plot area — the
|
||||
other rows step aside with everything they were plotting — and the same button (now the
|
||||
restore icon) brings the whole layout back exactly as it was. It is a view, not an edit:
|
||||
nothing is saved, nothing is dropped, and the rows' traces, colours and cursors come back
|
||||
where they were. The plot's right-click menu offers the same as <gui>Full screen this
|
||||
figure</gui> (and <gui>Restore the layout</gui> while one is enlarged). A layout of a single
|
||||
figure has nothing to enlarge *to*, so it carries no button.</p></item>
|
||||
<item><p>A plot's right-click menu has <gui>Open this plot in a new window</gui>: a second
|
||||
window showing the same stream through a copy of that figure (its cells, their widths and
|
||||
every trace), with its own axes following the main window's time window. The overflow menu's
|
||||
<gui>New scope window</gui> opens the same kind of window with an empty figure. Closing one
|
||||
closes that view only; the main window keeps acquiring.</p></item>
|
||||
</list>
|
||||
</section>
|
||||
|
||||
<section id="knowing">
|
||||
<title>Worth knowing</title>
|
||||
<list>
|
||||
|
||||
@@ -80,8 +80,19 @@
|
||||
shorter than a level's own resolution, or one read through <gui>hf</gui> — where
|
||||
<gui>top</gui>/<gui>bottom</gui> fall back to the mean of each side of the split and
|
||||
<gui>amplitude</gui> to the window's peak to peak.</p></item>
|
||||
<item><p>Each row names the <em>channel</em> it measures: its number among the active
|
||||
channels (1., 2., … the same number the signal's badge in the bar carries), its name, and
|
||||
the type — <code>1. sine · average</code>. The measurement dialog's signal dropdown
|
||||
numbers its entries the same way. A channel list that changes (a signal switched off, a
|
||||
new one enabled) renumbers, because the number is the answer to "which active channel is
|
||||
this".</p></item>
|
||||
<item><p>The on-plot marks come in two kinds and the mix is the reading: a <em>level</em>
|
||||
mark is a ruler at a value, a <em>time</em> mark is a marker at a position. An average
|
||||
mark is a ruler at a value — its value written in a small box on the ruler, the way the
|
||||
axis writes its own ticks — and a <em>time</em> mark is a marker at a position, with the
|
||||
position's own badge beside it. A level ruler's badge carries its number; a time
|
||||
marker's carries its time. Marks whose badges meet share one panel with one line each,
|
||||
so a column of close readings is one boxed readout rather than a smear of texts; and a
|
||||
box over a noisy trace is what keeps the number readable. An average
|
||||
draws one level mark; a max draws a level mark <em>and</em> a time mark at the first
|
||||
sample that reached it; <gui>peak to peak</gui> draws a ruler at each extreme and
|
||||
<gui>amplitude</gui> a ruler at each of its two flat levels — the pair is the span, so
|
||||
@@ -136,6 +147,25 @@
|
||||
</list>
|
||||
</section>
|
||||
|
||||
<section id="gate">
|
||||
<title>The gate</title>
|
||||
<p>A measurement's dialog carries <gui>Gate enabled</gui>. Every measurement
|
||||
with it set reads only the samples inside one shared band — violet, labelled <em>gate</em>,
|
||||
carried by its own two draggable edges on the plots, which are not the cursors (those keep
|
||||
meaning what the cursors pane reads). Measurements without it are untouched: they read the
|
||||
whole window and share the walks they always shared.</p>
|
||||
<p>The band is shown exactly while some measurement is gated — gate one and it appears,
|
||||
gate or delete the last one and it goes — because it is one area that all of the gated
|
||||
measurements share, not a property of any one of them. Drag an edge to resize it, grab the
|
||||
middle to move it.</p>
|
||||
<p>The band lives in the same relative time the axis labels use, so it stays where it was
|
||||
put in both modes: live, a band at 300 ms to 100 ms ago stays put on screen while the data
|
||||
streams beneath it — the gated read of the newest data a bench scope gives — and on a held
|
||||
event it names a fixed slice of the frozen frame. A band with no samples in it — dragged
|
||||
outside the view, or over a gap — reads <code>--</code> like any empty window. The band's
|
||||
position and each measurement's gate flag are saved with the session.</p>
|
||||
</section>
|
||||
|
||||
<section id="example">
|
||||
<title>Example</title>
|
||||
<p>On a 1 Hz ±1 sine: <code>average=0</code>, <code>top=0.957988</code>,
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
not a working badge. Of the two steady colours, <em>grey</em> is no stream at all or a
|
||||
pipeline you stopped (the tooltip says which), and <em>yellow</em> is a source that
|
||||
answered but has sent no configuration.</p></item>
|
||||
<item><p>Left of the badge is the <em>trigger circle</em>, and it is the trigger's own
|
||||
light: solid green while the trigger has fired (an event is held, or a capture is
|
||||
filling), <em>flashing</em> green while armed and waiting for an event, red while the
|
||||
trigger mode is on but disarmed, and hidden entirely while the trigger mode is off — a
|
||||
light for a mode you are not in is noise. Its tooltip names the state in words.</p></item>
|
||||
<item><p>The state field is one word from a fixed set: <code>connecting</code>,
|
||||
<code>live</code>, <code>paused</code>, <code>armed</code>, <code>capturing</code>,
|
||||
<code>event held</code>, <code>disarmed</code>. Two states add one field each: in trigger
|
||||
|
||||
@@ -169,7 +169,9 @@
|
||||
<section id="cache">
|
||||
<title>The event cache, replay and compare</title>
|
||||
<p><em>Every triggered acquisition is kept.</em> Latches are written to the event cache
|
||||
(<file>~/.cache/udpscope/events/<source>/</file>) as a <file>.npy</file> of the
|
||||
(<file>~/.cache/udpscope/events/<source>/<configuration>/</file> -- one folder per
|
||||
source and configuration, so two configurations of one source keep their events apart) as a
|
||||
<file>.npy</file> of the
|
||||
event, a <file>.txt</file> of what it was, and a <file>.bmp</file> picture drawn from the
|
||||
samples. The <gui>Events</gui> block at the foot of the dock lists them, newest first, one
|
||||
short row each: a marker for the event on screen, its title and its number. It is dimmed
|
||||
|
||||
Reference in new issue
Block a user