feat: the manual is a Mallard set opened in Yelp, not a GResource in the binary
The help was 14 Pango-markup `.txt` bodies in a second GResource, drawn into a paged `GtkWindow` built in `help_window.cpp`. That made F1 a viewer of ours with no search index, no cross-references and no translation, and it kept the manual in the *binary* when every other desktop application's is a document on disk. It is now a real Mallard set: help/C/org.udpscope.app/ index.page + 14 topic pages + figures/*.png and `show_help()` hands `help:org.udpscope.app` to whatever the desktop registered for the `help:` scheme -- Yelp on GNOME -- through a `GtkUriLauncher`, reporting a launch failure with a `GtkAlertDialog` rather than a click that silently does nothing. The paged window's builder, the page table and `help_self_check()`'s markup validation are gone with the resource. The document identifier is the desktop file's own basename (its desktop-file id), derived in CMakeLists from `data/org.udpscope.app.desktop.in`, so the same string is the `.desktop` name, the GApplication id and the install directory at once. The set is installed by a new `install()` rule to `<datadir>/help/C/org.udpscope.app/` -- where the freedesktop Help System Specification's `help:` URI resolves `help:<id>` -- so the manual is read from a datadir by another process even though the binary has no install step. `UDPSCOPE_HELP_NAME` and `UDPSCOPE_HELP_DIR` are compiled in from that one place. The 14 pages were migrated fact for fact, but restructured the Mallard way: a `<desc>` per page (what a search result shows), `<steps>` for procedures, `<terms>` for option lists, `<gui>`/`<key>`/`<keyseq>` for interface words and keys, `<note>` for the asides, and a topic graph via `<link type="guide" xref="index#main"/>`. The figures are annotated screenshots produced by `tools/make-help-shots.sh`, which drives the app headlessly against `tools/mock_udpstreamer.py` and draws the boxes with ImageMagick; the side panel's box is measured from the app's own `side=NNNx` dump reading, the header and status bands come from a documented table, and a crop whose standard deviation is 0 fails the script. `cmake --build build --target test-help` checks the set the way `test-ui` checks the `.ui` files: `yelp-check`'s offline subcommands (links, media, orphans, ids) and a `yelp-build html` render. `yelp-check validate` is deliberately absent -- it fetches the Mallard RelaxNG schema over the network and fails offline for that reason, not for a fault in the pages. The `[help]` probe reading changes with the resource it was written for. `parsed == pages` over in-binary markup cannot exist now, so `help_self_check()` scans `UDPSCOPE_HELP_DIR` and the line reads `topics=14 index=1 figures=3`; `topics=0 index=0` is the manual missing from the tree, which is the finding the old count named. Verified: clean build with the documented three warnings (the help bundle's `-Woverlength-strings` is gone, so the baseline moves from four to three); test-ui 14/14; test-help clean (the four subcommands and 15 pages rendered); a temp-prefix install lands 15 `.page` files and 3 figures at `share/help/C/org.udpscope.app/`; the headless run reads `[help] topics=14 index=1 figures=3 dir=...` with 0 Gtk-CRITICAL. Yelp's own window could not be exercised on this box -- it starts under Xvfb, activates its portals and never maps, the same WebKit/portal limitation that stops a grab -- so its rendering and its search index are unverified here; the content pipeline was (`yelp-build` renders the whole set). Docs: the manual's build/install/open story in `build-and-run.md` and README; the warning baseline in `verification.md`/CLAUDE.md; the help bullets in `invariants-gtk-and-chrome.md`; the `[help]` line in `probe-readings.md`.
This commit is contained in:
1 parent
620473a5be
commit
c1460a6977
47 files changed
+1910
-1056
No files matched your search
@@ -0,0 +1,104 @@
|
||||
<page xmlns="http://projectmallard.org/1.0/"
|
||||
type="topic" style="task"
|
||||
id="navigate">
|
||||
|
||||
<info>
|
||||
<link type="guide" xref="index#viewing"/>
|
||||
<link type="seealso" xref="window"/>
|
||||
<desc>Panning, zooming and fitting the plot with the mouse and the keyboard, and what a
|
||||
pinned view refuses to do.</desc>
|
||||
<credit type="author copyright">
|
||||
<name>Martino Ferrari</name>
|
||||
</credit>
|
||||
</info>
|
||||
|
||||
<title>Navigating the plot</title>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<section id="reach">
|
||||
<title>How to reach it</title>
|
||||
<terms>
|
||||
<item>
|
||||
<title>Wheel</title>
|
||||
<p><gui>Wheel</gui> zooms both axes · <gui>Shift</gui>+<gui>Wheel</gui> zooms x only ·
|
||||
<gui>Ctrl</gui>+<gui>Wheel</gui> zooms y only.</p>
|
||||
</item>
|
||||
<item>
|
||||
<title>Drag</title>
|
||||
<p><gui>Drag</gui> pans · <gui>Shift</gui>+<gui>Drag</gui> is a box zoom on both axes ·
|
||||
<gui>Ctrl</gui>+<gui>Drag</gui> on x only · <gui>Alt</gui>+<gui>Drag</gui> on values
|
||||
only. The area being chosen is framed while you drag it, so you can see what the
|
||||
release will apply.</p>
|
||||
</item>
|
||||
<item>
|
||||
<title>Keyboard</title>
|
||||
<p><key>+</key> and <key>-</key> zoom both axes; <key>Ctrl</key> with them restricts
|
||||
to x, <key>Alt</key> to y. <gui>Arrow keys</gui> pan, <key>f</key> fits,
|
||||
<key>Escape</key> cancels a gesture in progress.</p>
|
||||
</item>
|
||||
</terms>
|
||||
|
||||
<p>The full table is in the shortcut overview (<keyseq><key>Ctrl</key><key>/</key></keyseq>).</p>
|
||||
</section>
|
||||
|
||||
<section id="knowing">
|
||||
<title>Worth knowing</title>
|
||||
<list>
|
||||
<item><p>The keyboard zoom's modifiers are <em>not</em> the wheel's, and that is
|
||||
deliberate: on common layouts <key>+</key> <em>is</em> <keyseq><key>Shift</key><key>=</key></keyseq>,
|
||||
so a bare zoom-in already arrives with Shift set and Shift could not mean anything.
|
||||
Ctrl/Alt mirror the box-zoom drags instead.</p></item>
|
||||
<item><p>A <em>pinned</em> 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 <em>in</em>
|
||||
works normally — "not outside the event" is not "not readable" — but a pan or a zoom out
|
||||
is clamped to the data.</p></item>
|
||||
<item><p>Nothing you do on the plot changes the <em>time window</em> — only the header
|
||||
control does. A zoom or a pan moves the view inside the window; <key>f</key> (and
|
||||
<gui>Fit X axis</gui>) is the <em>undo</em> 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.</p></item>
|
||||
<item><p>The axis does not scroll — the <em>data</em> does. A live axis is a fixed
|
||||
<code>[-window .. 0]</code> 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.</p></item>
|
||||
<item><p>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.</p></item>
|
||||
<item><p>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.</p></item>
|
||||
<item><p>A trace holding far more samples than the plot has pixels is drawn <em>one
|
||||
pixel column at a time</em>: each column is a single vertical line from the lowest to
|
||||
the highest value that falls in it. Drawn as a polyline instead, such a window puts
|
||||
three or four near-vertical lines in every column at slightly different sub-pixel
|
||||
positions, and how they overlap beats against the pixel grid — which reads as bands of
|
||||
light and dark that <em>crawl</em> as you pan. One line per column removes the beat, and
|
||||
it is also much faster: a 1 MS/s view costs a couple of thousand line segments a frame
|
||||
instead of a couple of hundred thousand.</p></item>
|
||||
<item><p>Those columns are <em>graded by brightness</em>, the way a digital-phosphor
|
||||
scope reads: bright where the signal spent its time, faint where it only passed through.
|
||||
A column's highest and lowest value are the same whether the samples in it are spread
|
||||
evenly or piled at its two ends, so the grading is what tells the two apart — the flat
|
||||
parts of a square wave come out solid and the edges between them faint. It is read from
|
||||
a finer division of each column rather than from the line that is drawn, and it costs
|
||||
about a millisecond a frame.</p></item>
|
||||
</list>
|
||||
</section>
|
||||
|
||||
<section id="example">
|
||||
<title>Example</title>
|
||||
<p>Pause a live view, then press <keyseq><key>Ctrl</key><key>+</key></keyseq>: x narrows
|
||||
and y does not move. Press <keyseq><key>Alt</key><key>+</key></keyseq>: y narrows and x
|
||||
does not. Eight doublings into a held 2 s capture, the trace still reaches both margins —
|
||||
the zoom probe reports <code>gap_px</code> and <code>end_px</code> within a pixel or two
|
||||
at every step.</p>
|
||||
</section>
|
||||
|
||||
</page>
|
||||
Reference in new issue
Block a user