help: the search block's (i) on its header, a 12 px mark, and a real search page
This commit is contained in:
1 parent
d549223889
commit
fe499bfe41
10 files changed
+178
-53
No files matched your search
@@ -544,26 +544,34 @@ The `Help` submenu, the contextual help's "?" and the guided tour, and the traps
|
|||||||
sits *on* whatever is under it -- and every panel heading already has a switch or a pencil in a
|
sits *on* whatever is under it -- and every panel heading already has a switch or a pencil in a
|
||||||
corner. `src/ui_context_help.cpp` is a table of (id, title, body, shortcut, host) where the host is
|
corner. `src/ui_context_help.cpp` is a table of (id, title, body, shortcut, host) where the host is
|
||||||
the *row* -- a panel's heading usually, and the row of a specific control (the "record events"
|
the *row* -- a panel's heading usually, and the row of a specific control (the "record events"
|
||||||
switch, the pre-trigger share) where that is the thing being explained. The one exception is the
|
switch, the pre-trigger share, the search block's expander *header*) where that is the thing being
|
||||||
|
explained. The one exception is the
|
||||||
plot, which has no heading: its "(i)" is an overlay child of the overlay the layout editor already
|
plot, which has no heading: its "(i)" is an overlay child of the overlay the layout editor already
|
||||||
uses, and its corner is free. The icon is **`dialog-information-symbolic`** -- `help-about-symbolic`
|
uses, and its corner is free. The icon is **`dialog-information-symbolic`** -- `help-about-symbolic`
|
||||||
is *already* the status bar's information button, and two "help" glyphs meaning different things on
|
is *already* the status bar's information button, and two "help" glyphs meaning different things on
|
||||||
the same line is the trap the seven app icons exist to avoid; the dump reads the name back through
|
the same line is the trap the seven app icons exist to avoid; the dump reads the name back through
|
||||||
the theme for the same reason the pane [edit] buttons do. `math_head` exists only while the math
|
the theme for the same reason the pane [edit] buttons do. `math_head` exists only while the math
|
||||||
editor is open, so that row is skipped when it is null.
|
editor is open, so that row is skipped when it is null.
|
||||||
- **A `GtkMenuButton` ignores both `min-width` and a size request; its subnodes are where a small
|
- **A `GtkMenuButton` ignores both `min-width` and a size request, and the icon is a node *below*
|
||||||
one is made.** The "(i)" is meant to be a *mark*, not a button, and the default is 34x34 (a 24 px
|
its `button` subnode.** The "(i)" is meant to be a *mark*, not a button, and the default is 34x34 (a
|
||||||
floor plus 5 px of padding from Adwaita's `button` rule). Measured on libadwaita 1.10: setting
|
24 px floor plus 5 px of padding from Adwaita's `button` rule). Measured on libadwaita 1.10: setting
|
||||||
`min-width`/`min-height` on the widget changed nothing, and neither did `gtk_widget_set_size_request()`
|
`min-width`/`min-height` on the widget changed nothing, and neither did `gtk_widget_set_size_request()`
|
||||||
-- the menu button's own measure wins. Three selectors are needed, all in `install_css()`:
|
-- the menu button's own measure wins. The node tree is `menubutton > button > box > image` (read off
|
||||||
`menubutton.udpscope-hint` (the outer node), `menubutton.udpscope-hint > button` (its subnode) and
|
the CSS node dump), so `install_css()` reaches the glyph as
|
||||||
`... > button > image` (the glyph), with `min-width: 0; min-height: 0; padding: 0` -- and the result
|
`menubutton.udpscope-hint > button > box > image`. The direct-grandchild form `> button > image`
|
||||||
is **16x16**, the glyph's own size, because a `min-width` is a floor and not a cap. (A class on the
|
matches **nothing** and is silent about it -- the glyph keeps its natural 16 px, which is why an
|
||||||
outer node alone leaves the subnode at 34; a class on the subnode alone shrank the width to 16 and
|
earlier version shipped a 16x16 mark and took that for the floor it was not. Zeroing the outer node
|
||||||
left the height at 26.) The dump's `hint=` reading is that number, and it is measured with
|
and the `button` subnode and asking the glyph for **12 px** (`min-width`/`min-height` *and*
|
||||||
`gtk_widget_compute_bounds()` on the first *visible* hint -- a hint inside a collapsed `GtkExpander`
|
`-gtk-icon-size`, the latter what actually *scales* the drawing rather than clamping its box) gives
|
||||||
is not in the widget-parent chain at all and reads 0x0, which would look like a mark shrunk to
|
**12x12**. (A class on the outer node alone leaves the subnode at 34; a class on the subnode alone
|
||||||
nothing.
|
shrank the width to 16 and left the height at 26.) There is no lower floor: the symbolic glyph renders
|
||||||
|
at any request (measured down to 4 px), so 12 px is a legibility choice and not a limit. The dump's
|
||||||
|
`hint=` reading is that number, measured with `gtk_widget_compute_bounds()` on the first *visible*
|
||||||
|
hint -- a hint inside a collapsed `GtkExpander`'s *child* is not in the widget-parent chain at all and
|
||||||
|
reads 0x0, which would look like a mark shrunk to nothing. That is why the search block's hint rides
|
||||||
|
the expander's **header** (a `label-widget` box, `search_head` in `src/ui/trigger-panel.ui`, which
|
||||||
|
*is* in the tree) rather than its child, and why the `[helpui] collapsed search:` reading asserts the
|
||||||
|
header hint is mapped and 12x12 while the block is collapsed.
|
||||||
- **Off is gone, not greyed, and the buttons are found by a data key rather than kept in a list.** The
|
- **Off is gone, not greyed, and the buttons are found by a data key rather than kept in a list.** The
|
||||||
list is what the math editor cannot survive: its heading lives in a builder that is dropped and
|
list is what the math editor cannot survive: its heading lives in a builder that is dropped and
|
||||||
rebuilt on every opening, so a stored pointer into it would go stale one dialog later. A key on the
|
rebuilt on every opening, so a stored pointer into it would go stale one dialog later. A key on the
|
||||||
|
|||||||
@@ -395,15 +395,17 @@ Two lines of the self-check output are assertions in disguise:
|
|||||||
on the first tick for the same reason the toolbar's are. **Both must read `(ok)`**: the page titles are
|
on the first tick for the same reason the toolbar's are. **Both must read `(ok)`**: the page titles are
|
||||||
empty on purpose, so an icon that does not resolve leaves a *blank* pill, and a blank pill looks
|
empty on purpose, so an icon that does not resolve leaves a *blank* pill, and a blank pill looks
|
||||||
exactly like a page with nothing in it.
|
exactly like a page with nothing in it.
|
||||||
- `help layer: contextual=on hints=11 ids={events plot status cursors measures trigger trigger_advanced events_record signals signals_config window} icon=dialog-information-symbolic(ok) hint=16x16; tour=idle steps=5 step=0 auto=1 requested=0` (in the exit
|
- `help layer: contextual=on hints=12 ids={events plot status cursors measures trigger trigger_advanced events_record trigger_search signals signals_config window} icon=dialog-information-symbolic(ok) hint=12x12; tour=idle steps=5 step=0 auto=1 requested=0` (in the exit
|
||||||
dump, beside `switcher:`) — the help affordance layer as the last tick found it. **`hints=` must equal
|
dump, beside `switcher:`) — the help affordance layer as the last tick found it. **`hints=` must equal
|
||||||
the number of ids**, and the ids are the surfaces the contextual help is on: ten of the window
|
the number of ids**, and the ids are the surfaces the contextual help is on: eleven of the window
|
||||||
itself, and `math` only while the math editor is open (its heading lives in a builder that is rebuilt
|
itself, and `math` only while the math editor is open (its heading lives in a builder that is rebuilt
|
||||||
on every opening, so it is not one of the window's own). Three of the ten are not a pane's *heading*
|
on every opening, so it is not one of the window's own). Four of the eleven are not a pane's *heading*
|
||||||
but the row of a specific control — `events_record` (the "record events" switch in the trigger
|
but the row of a specific control — `events_record` (the "record events" switch in the trigger
|
||||||
panel), `trigger_advanced` (the pre-trigger share row) and `signals_config` (the signals pane's hint
|
panel), `trigger_advanced` (the pre-trigger share row), `trigger_search` (the *header* of the search
|
||||||
line, whose box exists so a hint can join it) — which is the rule the layer follows: a hint is a
|
block's expander, which is what lets it be on screen while the block is collapsed) and
|
||||||
sibling of the thing it explains and never an overlay on it. The layer is **off by default**
|
`signals_config` (the signals pane's hint line, whose box exists so a hint can join it) — which is
|
||||||
|
the rule the layer follows: a hint is a sibling of the thing it explains and never an overlay on
|
||||||
|
it. The layer is **off by default**
|
||||||
(`contextual_help` in `settings.toml` is false for a missing file), so a fresh-config run reads
|
(`contextual_help` in `settings.toml` is false for a missing file), so a fresh-config run reads
|
||||||
`contextual=off hints=0` and that line above is the state *after* the Help row was switched on;
|
`contextual=off hints=0` and that line above is the state *after* the Help row was switched on;
|
||||||
`contextual=off` beside a non-zero count is the toggle not having removed its buttons — **off is
|
`contextual=off` beside a non-zero count is the toggle not having removed its buttons — **off is
|
||||||
@@ -412,11 +414,17 @@ Two lines of the self-check output are assertions in disguise:
|
|||||||
is `dialog-information-symbolic`, the plain information mark; `help-about-symbolic` is the status
|
is `dialog-information-symbolic`, the plain information mark; `help-about-symbolic` is the status
|
||||||
bar's ⓘ and a second meaning for it is what the app's own icons exist to avoid. `hint=WxH` is the
|
bar's ⓘ and a second meaning for it is what the app's own icons exist to avoid. `hint=WxH` is the
|
||||||
size the **first visible** hint was allocated, measured the way every other rectangle here is
|
size the **first visible** hint was allocated, measured the way every other rectangle here is
|
||||||
(`gtk_widget_compute_bounds()`), and **16x16 is the reading a "much tinier" mark must keep**: the
|
(`gtk_widget_compute_bounds()`), and **12x12 is the reading a "much tinier" mark must keep**: the
|
||||||
class zeroes the outer `menubutton` node, its `button` subnode and the glyph, which is what a
|
class zeroes the outer `menubutton` node and its `button` subnode (a `GtkMenuButton`'s measure
|
||||||
`GtkMenuButton` needs (its measure ignores both `min-width` on the widget and a size request) — the
|
ignores both `min-width` on the widget and a size request), and the glyph is a third node *below*
|
||||||
default 34x34 is the number to compare against. Hints inside a collapsed expander are skipped, so the
|
the subnode — `menubutton > button > box > image`, read off the CSS node dump. The direct-grandchild
|
||||||
number is never a hidden widget's 0x0. `tour=` is `running`/`idle` with the plan's `steps=` and the
|
form `> button > image` matches **nothing** and silently leaves the glyph at its natural 16 px,
|
||||||
|
which is the 16x16 an earlier version shipped by mistake; and there is no lower floor to find
|
||||||
|
(the symbolic glyph renders at any request, measured down to 4 px), so 12 px is a legibility
|
||||||
|
choice. The default 34x34 is the number to compare against. A hint inside a collapsed expander's
|
||||||
|
*child* is skipped, so the number is never a hidden widget's 0x0 — but a hint on the expander's
|
||||||
|
*header* is in the widget tree and reads its real size while the block is collapsed (see the
|
||||||
|
`collapsed search:` entry below). `tour=` is `running`/`idle` with the plan's `steps=` and the
|
||||||
current `step=`; `auto=1` is the first-run auto-start having fired *in this process* — the flag is
|
current `step=`; `auto=1` is the first-run auto-start having fired *in this process* — the flag is
|
||||||
`tour_seen` in `settings.toml`, so a second run against the same config directory reads `auto=0` —
|
`tour_seen` in `settings.toml`, so a second run against the same config directory reads `auto=0` —
|
||||||
and `requested=1` is the **chooser's** tour having handed over (`Config::tour_pending`), which is
|
and `requested=1` is the **chooser's** tour having handed over (`Config::tour_pending`), which is
|
||||||
@@ -506,7 +514,7 @@ Two lines of the self-check output are assertions in disguise:
|
|||||||
the saved-source list and the waveforms page's action row; the form's `AdwEntryRow`s are *not*
|
the saved-source list and the waveforms page's action row; the form's `AdwEntryRow`s are *not*
|
||||||
hosts (a row is not a box and its editor is internal, so a hint cannot join it as a sibling) and
|
hosts (a row is not a box and its editor is internal, so a hint cannot join it as a sibling) and
|
||||||
the connection fields are explained by their group's `description` instead. `hint=WxH` is the
|
the connection fields are explained by their group's `description` instead. `hint=WxH` is the
|
||||||
same 16x16 the window's line reads: the button is `ui_impl::context_help_button()`, the one
|
same 12x12 the window's line reads: the button is `ui_impl::context_help_button()`, the one
|
||||||
`udpscope-hint` affordance both windows draw.
|
`udpscope-hint` affordance both windows draw.
|
||||||
- `[sources] tour: first run -- auto_started=1 in the chooser` then
|
- `[sources] tour: first run -- auto_started=1 in the chooser` then
|
||||||
`[sources] chooser tour: visible=1 steps=5 step=0` (stderr) — **a first run's tour starts in the
|
`[sources] chooser tour: visible=1 steps=5 step=0` (stderr) — **a first run's tour starts in the
|
||||||
@@ -751,16 +759,16 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
|
|||||||
touches anything: `auto_started=1 visible=1` is the tour that started itself, and the parenthetical is
|
touches anything: `auto_started=1 visible=1` is the tour that started itself, and the parenthetical is
|
||||||
`settings.tour_seen` as the process found it — `tour_seen already set` with `auto=0` is the *second*
|
`settings.tour_seen` as the process found it — `tour_seen already set` with `auto=0` is the *second*
|
||||||
run against the same config directory, which is the assertion that the flag persisted. Then:
|
run against the same config directory, which is the assertion that the flag persisted. Then:
|
||||||
- `[helpui] contextual on: hints=11 ids={events plot status cursors measures trigger trigger_advanced events_record signals signals_config window} hint=16x16` —
|
- `[helpui] contextual on: hints=12 ids={events plot status cursors measures trigger trigger_advanced events_record trigger_search signals signals_config window} hint=12x12` —
|
||||||
the eleven "(i)" affordances, by id, and the size the first visible one was allocated. Ten are the
|
the twelve "(i)" affordances, by id, and the size the first visible one was allocated. Eleven are
|
||||||
window's own surfaces (three of them a specific control's row rather than a heading — see the
|
the window's own surfaces (four of them a specific control's row rather than a heading — see the
|
||||||
`help layer:` entry) and the eleventh is `math`, which is present only while the math editor
|
`help layer:` entry) and the twelfth is `math`, which is present only while the math editor
|
||||||
window is open; it reads 10 with the editor shut. **On a fresh config this reads `hints=0 ids={}`
|
window is open; it reads 11 with the editor shut. **On a fresh config this reads `hints=0 ids={}`
|
||||||
and `hint=0x0`**, because the layer is off by default; the example is the state after the row below
|
and `hint=0x0`**, because the layer is off by default; the example is the state after the row below
|
||||||
was switched on, and a fresh run's `hints=0` beside a `settings.toml` with no `contextual_help`
|
was switched on, and a fresh run's `hints=0` beside a `settings.toml` with no `contextual_help`
|
||||||
key is the default being read rather than assumed. **`hint=16x16` is the "much tinier" assertion**
|
key is the default being read rather than assumed. **`hint=12x12` is the "much tinier" assertion**
|
||||||
— the default menu-button mark is 34x34 (see `help layer:`), and anything near that is the class
|
— the default menu-button mark is 34x34 (see `help layer:`), and anything near that is the class
|
||||||
not reaching the outer `menubutton` node.
|
not reaching the glyph's own node.
|
||||||
- `[helpui] main view: rows=7 help_row=1` and one `[helpui] entry N '<label>' accel='<key>' order=O`
|
- `[helpui] main view: rows=7 help_row=1` and one `[helpui] entry N '<label>' accel='<key>' order=O`
|
||||||
per row of the **Help view** — `entry 0 'Back'` with no accelerator and then the four the submenu
|
per row of the **Help view** — `entry 0 'Back'` with no accelerator and then the four the submenu
|
||||||
promises: `entry 1 'Keyboard shortcuts' accel='Ctrl+/'`, `entry 2 'Documentation' accel='F1'`,
|
promises: `entry 1 'Keyboard shortcuts' accel='Ctrl+/'`, `entry 2 'Documentation' accel='F1'`,
|
||||||
@@ -771,10 +779,10 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
|
|||||||
`toggle=` being the contextual-help row's check, which *is* `settings.contextual_help`. It reads `0`
|
`toggle=` being the contextual-help row's check, which *is* `settings.contextual_help`. It reads `0`
|
||||||
on a fresh config (the default) and `1` on one where the setting is on; the probe's next step drives
|
on a fresh config (the default) and `1` on one where the setting is on; the probe's next step drives
|
||||||
it both ways, which is why the example here is the `1` side.
|
it both ways, which is why the example here is the `1` side.
|
||||||
- `[helpui] toggle: off -> hints=0 ids={}; on -> hints=11 ids={…}; setting=on` — the toggle's effect
|
- `[helpui] toggle: off -> hints=0 ids={}; on -> hints=12 ids={…}; setting=on` — the toggle's effect
|
||||||
read both ways through the row itself. **`hints=0` with `off` is the assertion**: off means the
|
read both ways through the row itself. **`hints=0` with `off` is the assertion**: off means the
|
||||||
affordances are *gone*, not greyed, so anything else is a row that hid its buttons instead of
|
affordances are *gone*, not greyed, so anything else is a row that hid its buttons instead of
|
||||||
removing them. The count comes back to the same eleven, which is the other half — a toggle that
|
removing them. The count comes back to the same twelve, which is the other half — a toggle that
|
||||||
removed and could not restore is a one-way switch.
|
removed and could not restore is a one-way switch.
|
||||||
- `[helpui] tour started from the probe: visible=1 steps=5 step=0` — the tour started the way
|
- `[helpui] tour started from the probe: visible=1 steps=5 step=0` — the tour started the way
|
||||||
`Ctrl+T` starts it. `steps=5` is the plan: the table's five steps whose surface is on screen or
|
`Ctrl+T` starts it. `steps=5` is the plan: the table's five steps whose surface is on screen or
|
||||||
@@ -804,6 +812,13 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
|
|||||||
rather than leaving them to find the mode. `trigger_panel`'s height differs between them (508 px in
|
rather than leaving them to find the mode. `trigger_panel`'s height differs between them (508 px in
|
||||||
configuration mode against 72 locked — the body is replaced by the summary), which is the check
|
configuration mode against 72 locked — the body is replaced by the summary), which is the check
|
||||||
that the mode really moved.
|
that the mode really moved.
|
||||||
|
- `[helpui] collapsed search: expanded=0 mapped=1 mapped_header=1 hint=12x12` (the last step, in
|
||||||
|
configuration mode, after the figures line) — the search block's "(i)" read on the expander's
|
||||||
|
**header** with the block **collapsed**. **`expanded=0 mapped=1` is the assertion**: a hint on the
|
||||||
|
expander's own *child* is not in the widget-parent chain while the block is collapsed and would
|
||||||
|
read `mapped=0` (and `0x0`), which is exactly why the header box exists (`search_head` in
|
||||||
|
`src/ui/trigger-panel.ui`) and why the hint joins it as its last child. `mapped_header=` is the
|
||||||
|
header box beside it, and `hint=WxH` is the same 12x12 the layer's own line reads.
|
||||||
- `[toursurface] …` (stderr, `UDPSCOPE_PROBE_TOUR_SURFACE_MS`) — a stop that stands on a page it is
|
- `[toursurface] …` (stderr, `UDPSCOPE_PROBE_TOUR_SURFACE_MS`) — a stop that stands on a page it is
|
||||||
not on, entered from the page it is not on. It puts the sidebar on **Measure**, starts the window's
|
not on, entered from the page it is not on. It puts the sidebar on **Measure**, starts the window's
|
||||||
tour, and walks it a stop per tick (400 ms), because a stack allocates the new page's widgets on
|
tour, and walks it a stop per tick (400 ms), because a stack allocates the new page's widgets on
|
||||||
|
|||||||
@@ -314,8 +314,9 @@ as distinct from the fault injection below, which exercises ingest:
|
|||||||
figures:` read in both of the trigger pane's modes. Its lines and what each asserts are in
|
figures:` read in both of the trigger pane's modes. Its lines and what each asserts are in
|
||||||
[probe-readings.md](probe-readings.md); the two things to read first are **`hints=0`** while the
|
[probe-readings.md](probe-readings.md); the two things to read first are **`hints=0`** while the
|
||||||
toggle is off (off is *gone*, not greyed) and **`controllers=12 (was 12)`** after the dismissal (no
|
toggle is off (off is *gone*, not greyed) and **`controllers=12 (was 12)`** after the dismissal (no
|
||||||
lingering input grab — a tour of ordinary overlay widgets takes none), and **`hint=16x16`** is the
|
lingering input grab — a tour of ordinary overlay widgets takes none), and **`hint=12x12`** is the
|
||||||
size the shrunk "(i)" must keep (the default menu-button mark is 34x34). The chooser's own tour is
|
size the shrunk "(i)" must keep (the default menu-button mark is 34x34). The `collapsed search:` line
|
||||||
|
is the header hint read on the search block's expander while it is collapsed. The chooser's own tour is
|
||||||
the other half and has its own entry points — see the **chooser** bullet below. Give it
|
the other half and has its own entry points — see the **chooser** bullet below. Give it
|
||||||
`UDPSCOPE_EXIT_AFTER_MS=9500 UDPSCOPE_EXIT_DUMP=1` to get the `help layer:`/`help figures:` dump
|
`UDPSCOPE_EXIT_AFTER_MS=9500 UDPSCOPE_EXIT_DUMP=1` to get the `help layer:`/`help figures:` dump
|
||||||
lines as well, and note the tour **auto-starts** in any run whose settings file does not carry
|
lines as well, and note the tour **auto-starts** in any run whose settings file does not carry
|
||||||
@@ -345,7 +346,7 @@ as distinct from the fault injection below, which exercises ingest:
|
|||||||
configuration carried, into the `Config` the model is built from. **With no `--server` and no probe
|
configuration carried, into the `Config` the model is built from. **With no `--server` and no probe
|
||||||
the chooser blocks in its own nested loop** (no frame to end and no dump), so a chooser run is
|
the chooser blocks in its own nested loop** (no frame to end and no dump), so a chooser run is
|
||||||
always this probe. It also prints the dialog's frame *and its own help layer*:
|
always this probe. It also prints the dialog's frame *and its own help layer*:
|
||||||
`[sources] chooser ui: … hints=[2 {chooser_sources chooser_waveform}] hint=16x16` with the setting
|
`[sources] chooser ui: … hints=[2 {chooser_sources chooser_waveform}] hint=12x12` with the setting
|
||||||
on, `hints=[0 {}] hint=0x0` with it off. `UDPSCOPE_PROBE_CHOOSER_HELP=1` drives the **Enable
|
on, `hints=[0 {}] hint=0x0` with it off. `UDPSCOPE_PROBE_CHOOSER_HELP=1` drives the **Enable
|
||||||
contextual help** row and reads the file back; `UDPSCOPE_PROBE_CHOOSER_TOUR=1` drives the **Guided
|
contextual help** row and reads the file back; `UDPSCOPE_PROBE_CHOOSER_TOUR=1` drives the **Guided
|
||||||
tour** row and walks the chooser's own tour to its last stop, printing `[sources] chooser tour: …`
|
tour** row and walks the chooser's own tour to its last stop, printing `[sources] chooser tour: …`
|
||||||
|
|||||||
@@ -114,12 +114,54 @@
|
|||||||
|
|
||||||
<section id="search">
|
<section id="search">
|
||||||
<title>Search the buffer</title>
|
<title>Search the buffer</title>
|
||||||
<p><gui>Search the buffer</gui> runs the same condition over the whole retained ring and
|
<p><gui>Search the buffer</gui>, at the foot of the trigger panel and collapsed until you open
|
||||||
lists every place it holds. The arrows step through hits; each step pauses on the hit,
|
it, answers the question the trigger answers — <em>where does this condition hold?</em> — over
|
||||||
centred, exactly as the Pause button does. Up to 16 hits in the visible window are marked
|
the <em>whole</em> retained buffer rather than at the live edge. It runs the trigger's own
|
||||||
on every row; when there are more the panel says how many and suggests zooming in. The
|
evaluator over the ring in stream order, so a <gui>hit</gui> is not a level you point at: it is
|
||||||
search uses the trigger's own condition, set in one place, so a hit is by construction an
|
an <em>instant</em> the trigger would have fired on, timed the way an acquisition would have
|
||||||
instant the trigger would have fired.</p>
|
timed it. A pulse-width finding, for instance, is the closing edge of a qualifying excursion,
|
||||||
|
not the excursion itself.</p>
|
||||||
|
|
||||||
|
<p>The condition is the one the rest of the panel is set to — the same signal, shape, level and
|
||||||
|
options — so there is no second condition to keep in step: change the panel and the next search
|
||||||
|
asks the new question. Nothing is searched until you ask, and the status line says
|
||||||
|
<gui>not searched</gui>.</p>
|
||||||
|
|
||||||
|
<steps>
|
||||||
|
<item>
|
||||||
|
<p>Set the condition above, then press <gui>Search</gui>. Covering the whole ring takes a
|
||||||
|
moment, and the scan runs in chunks so the stream keeps arriving while it does; the status
|
||||||
|
line counts the ground covered — <gui>scanning 1.2 s of 8.0 s, 40 found</gui>.
|
||||||
|
<gui>Stop</gui> ends a scan early and keeps the hits found so far.</p>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<p>Step through the hits with the arrows either side of the position readout
|
||||||
|
(<gui>3 of 40</gui>). The first <gui>next</gui> goes to the first hit, and the ends do not
|
||||||
|
wrap — a wrap from the last hit to the first would look exactly like the view not having
|
||||||
|
moved. Each step <em>pauses</em> on its hit, centred, exactly as the Pause button does, so
|
||||||
|
what you read is the frozen window cut around that instant; press the pause button again to
|
||||||
|
go back to the stream.</p>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<p>Every plot row marks the hits that fall in the window, up to sixteen of them. When more
|
||||||
|
are in view the pane says so and suggests zooming in — <gui>16 of 38 marks shown — zoom in
|
||||||
|
to see the rest</gui> — and when the selected hit has scrolled off the window it says that
|
||||||
|
instead. A hit the live stream has since overwritten reads <gui>no longer in the buffer</gui>
|
||||||
|
beside its position.</p>
|
||||||
|
</item>
|
||||||
|
</steps>
|
||||||
|
|
||||||
|
<p>How a scan ended is part of the answer: <gui>N found in 8.0 s</gui> when it covered the whole
|
||||||
|
ring; <gui>N found; the stream overtook the oldest samples</gui> when the producer overwrote
|
||||||
|
samples before the scan reached them, so the count is of what was left; and
|
||||||
|
<gui>N found (the limit) in the newest …</gui> when a condition that holds almost everywhere —
|
||||||
|
an edge on a noisy signal — reached the ten-thousand-hit ceiling. The last is a stop, not a
|
||||||
|
crash: a hit list nobody could navigate is not worth building.</p>
|
||||||
|
|
||||||
|
<p>A result describes the ring it was taken from, so it is <em>dropped</em> when that ring is
|
||||||
|
replaced: a new <gui>CONFIG</gui> from the source, or a change to the signal set, re-describes
|
||||||
|
the stream and clears the hits. The condition above is untouched — only the answer to it
|
||||||
|
is.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="knowing">
|
<section id="knowing">
|
||||||
|
|||||||
+16
-1
@@ -214,8 +214,23 @@
|
|||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkExpander" id="search_exp">
|
<object class="GtkExpander" id="search_exp">
|
||||||
<property name="label" translatable="yes">Search the buffer</property>
|
|
||||||
<property name="tooltip-text" translatable="yes">find every place in the retained buffer where the condition above holds, and step through them</property>
|
<property name="tooltip-text" translatable="yes">find every place in the retained buffer where the condition above holds, and step through them</property>
|
||||||
|
<!-- The header is a box, not a plain label, so the contextual help's "(i)" has a row to join
|
||||||
|
as its last child and sits beside the text while the block is collapsed. The block's own
|
||||||
|
*child* is not in the widget-parent chain until the expander is expanded (see
|
||||||
|
docs/claude/invariants-gtk-and-chrome.md), so a hint hung there would be off screen. -->
|
||||||
|
<child type="label">
|
||||||
|
<object class="GtkBox" id="search_head">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label" translatable="yes">Search the buffer</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
<property name="child">
|
<property name="child">
|
||||||
|
|
||||||
<object class="GtkBox" id="search_sbox">
|
<object class="GtkBox" id="search_sbox">
|
||||||
|
|||||||
+8
-1
@@ -246,6 +246,9 @@ struct App {
|
|||||||
GtkWidget* search_marks_label = nullptr;
|
GtkWidget* search_marks_label = nullptr;
|
||||||
GtkWidget* search_prev_button = nullptr;
|
GtkWidget* search_prev_button = nullptr;
|
||||||
GtkWidget* search_next_button = nullptr;
|
GtkWidget* search_next_button = nullptr;
|
||||||
|
/// The expander the block lives in, so the probe can read its collapsed state when it reads the
|
||||||
|
/// header hint.
|
||||||
|
GtkWidget* search_exp = nullptr;
|
||||||
/// Set true when the last `search_jump()` produced an empty cut — the hit was so close to the
|
/// Set true when the last `search_jump()` produced an empty cut — the hit was so close to the
|
||||||
/// oldest retained sample that `publish_pause_view()` held nothing. Cleared at every jump.
|
/// oldest retained sample that `publish_pause_view()` held nothing. Cleared at every jump.
|
||||||
bool search_jump_empty = false;
|
bool search_jump_empty = false;
|
||||||
@@ -284,10 +287,14 @@ struct App {
|
|||||||
GtkWidget* status_row = nullptr;
|
GtkWidget* status_row = nullptr;
|
||||||
GtkWidget* window_control_slot = nullptr;
|
GtkWidget* window_control_slot = nullptr;
|
||||||
/// The hint hosts that are *not* a pane's heading row: a specific control's own row, so the "?" sits
|
/// The hint hosts that are *not* a pane's heading row: a specific control's own row, so the "?" sits
|
||||||
/// beside the thing it explains -- the "record events" switch, the search block's action row, and the
|
/// beside the thing it explains -- the "record events" switch, the pre-trigger share row, and the
|
||||||
/// signals pane's hint line (whose box exists so a hint can join it beside the text).
|
/// signals pane's hint line (whose box exists so a hint can join it beside the text).
|
||||||
GtkWidget* trigger_record_row = nullptr;
|
GtkWidget* trigger_record_row = nullptr;
|
||||||
GtkWidget* trigger_pre_row = nullptr;
|
GtkWidget* trigger_pre_row = nullptr;
|
||||||
|
/// The search block's expander *header* -- the box the contextual help's "trigger_search" hint joins
|
||||||
|
/// as its last child. The header, not the block: the expander's child is out of the widget-parent
|
||||||
|
/// chain until the block is expanded, so a hint there is invisible while it is collapsed.
|
||||||
|
GtkWidget* trigger_search = nullptr;
|
||||||
GtkWidget* signals_note = nullptr;
|
GtkWidget* signals_note = nullptr;
|
||||||
/// The guided tour. `tour.overlay` is a `GtkOverlay` inserted above the window's content, and the
|
/// The guided tour. `tour.overlay` is a `GtkOverlay` inserted above the window's content, and the
|
||||||
/// four dim rectangles, the spotlight and the card are its overlay children; `tour.plan` is the
|
/// four dim rectangles, the spotlight and the card are its overlay children; `tour.plan` is the
|
||||||
|
|||||||
@@ -109,6 +109,12 @@ constexpr HelpHint kHelpHints[] = {
|
|||||||
"is the quiet time after a latch in which nothing new can be armed -- the two that decide what a "
|
"is the quiet time after a latch in which nothing new can be armed -- the two that decide what a "
|
||||||
"capture looks like. The condition rows above appear and disappear with the condition chosen.",
|
"capture looks like. The condition rows above appear and disappear with the condition chosen.",
|
||||||
"", &App::trigger_pre_row},
|
"", &App::trigger_pre_row},
|
||||||
|
{"trigger_search", "Searching the buffer",
|
||||||
|
"Applies the condition above to the whole retained ring -- the *same* evaluator the trigger runs, "
|
||||||
|
"so a hit is an instant the trigger would have fired on -- and lists every place it holds. The "
|
||||||
|
"arrows step through the hits, pausing centred on each, and up to sixteen in view are marked on "
|
||||||
|
"every row.",
|
||||||
|
"", &App::trigger_search},
|
||||||
{"signals_config", "Configuring signals",
|
{"signals_config", "Configuring signals",
|
||||||
"The list is locked until the pencil above opens the per-signal controls: the calibration that "
|
"The list is locked until the pencil above opens the per-signal controls: the calibration that "
|
||||||
"maps raw counts to a unit, the colour a trace is drawn in, and which plot a signal is dragged "
|
"maps raw counts to a unit, the colour a trace is drawn in, and which plot a signal is dragged "
|
||||||
|
|||||||
@@ -4773,6 +4773,24 @@ gboolean helpui_probe_step(gpointer user) {
|
|||||||
helpui_probe_next(*a, 8, 400);
|
helpui_probe_next(*a, 8, 400);
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
// The search block's "(i)" rides the expander's *header* box, which is in the widget tree and on
|
||||||
|
// screen while the block is collapsed -- unlike the expander's child, which is out of the
|
||||||
|
// widget-parent chain until it is expanded (see the invariant). Read here, in config mode with the
|
||||||
|
// pane and the sidebar up and the block still collapsed: `mapped=1` and a real size *on a collapsed
|
||||||
|
// expander* is the whole point, and a hint hung on the child would read 0x0 here.
|
||||||
|
if (a->trigger_search != nullptr) {
|
||||||
|
GtkWidget* hint = gtk_widget_get_last_child(a->trigger_search);
|
||||||
|
int sw = 0;
|
||||||
|
int sh = 0;
|
||||||
|
context_help_size_in(hint, &sw, &sh);
|
||||||
|
std::fprintf(stderr,
|
||||||
|
"[helpui] collapsed search: expanded=%d mapped=%d mapped_header=%d hint=%dx%d\n",
|
||||||
|
a->search_exp != nullptr && gtk_expander_get_expanded(GTK_EXPANDER(a->search_exp))
|
||||||
|
? 1
|
||||||
|
: 0,
|
||||||
|
hint != nullptr && gtk_widget_get_mapped(hint) ? 1 : 0,
|
||||||
|
gtk_widget_get_mapped(a->trigger_search) ? 1 : 0, sw, sh);
|
||||||
|
}
|
||||||
std::fflush(stderr);
|
std::fflush(stderr);
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -599,6 +599,11 @@ GtkWidget* build_trigger_panel(App& app) {
|
|||||||
app.search_pos_label = GTK_WIDGET(gtk_builder_get_object(ui, "search_pos"));
|
app.search_pos_label = GTK_WIDGET(gtk_builder_get_object(ui, "search_pos"));
|
||||||
app.search_next_button = GTK_WIDGET(gtk_builder_get_object(ui, "search_next"));
|
app.search_next_button = GTK_WIDGET(gtk_builder_get_object(ui, "search_next"));
|
||||||
app.search_marks_label = GTK_WIDGET(gtk_builder_get_object(ui, "search_marks"));
|
app.search_marks_label = GTK_WIDGET(gtk_builder_get_object(ui, "search_marks"));
|
||||||
|
app.search_exp = GTK_WIDGET(gtk_builder_get_object(ui, "search_exp"));
|
||||||
|
// The expander's header box, where the contextual help's "trigger_search" hint joins as its last
|
||||||
|
// child (see `ui_context_help.cpp`): a hint on the block's own child would leave it unreachable
|
||||||
|
// while the block is collapsed.
|
||||||
|
app.trigger_search = GTK_WIDGET(gtk_builder_get_object(ui, "search_head"));
|
||||||
if (app.search_run_button != nullptr) {
|
if (app.search_run_button != nullptr) {
|
||||||
g_signal_connect(app.search_run_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer user) {
|
g_signal_connect(app.search_run_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer user) {
|
||||||
App* a = static_cast<App*>(user);
|
App* a = static_cast<App*>(user);
|
||||||
|
|||||||
+16
-8
@@ -71,16 +71,24 @@ void install_css() {
|
|||||||
" border-radius: 12px; padding: 12px; box-shadow: 0 3px 12px rgba(0, 0, 0, 0.45); }\n"
|
" border-radius: 12px; padding: 12px; box-shadow: 0 3px 12px rgba(0, 0, 0, 0.45); }\n"
|
||||||
// The contextual-help "(i)": a *mark*, not a button. Adwaita's menu button is a 34x34 control
|
// The contextual-help "(i)": a *mark*, not a button. Adwaita's menu button is a 34x34 control
|
||||||
// (a 24 px floor plus 5 px of padding) with a 16 px glyph, which beside a heading reads as a
|
// (a 24 px floor plus 5 px of padding) with a 16 px glyph, which beside a heading reads as a
|
||||||
// second toolbar button -- the size the ask calls too big. Measured on libadwaita 1.10: the
|
// second toolbar button. Measured on libadwaita 1.10: the outer `menubutton` node *and* its
|
||||||
// outer `menubutton` node *and* its `button` subnode both carry a floor and padding, and a class
|
// `button` subnode both carry a floor and padding, and a class selector on either alone leaves
|
||||||
// selector on either alone leaves the other at 34 (`min-width` on the widget itself is ignored
|
// the other at 34 (`min-width` on the widget itself is ignored by `GtkMenuButton`'s measure, and
|
||||||
// by `GtkMenuButton`'s measure, and so is a size request -- tried both). Zeroing all three --
|
// so is a size request -- tried both). Beyond those two there is a third node, and getting its
|
||||||
// the outer node, the subnode and its glyph -- is what brings it to **16x16**: the icon's own
|
// path wrong is silent: the button's own tree is `menubutton > button > box > image` (read off
|
||||||
// size and nothing else, because a `min-width` is a floor, not a cap, so 16 px is where a 16 px
|
// the CSS node dump), so the direct-grandchild form `> button > image` matches *nothing* and
|
||||||
// Adwaita glyph stops. That is the reading `hint=WxH` in the dump prints.
|
// leaves the glyph at its natural 16 px -- which is the 16x16 the first version shipped and
|
||||||
|
// mistook for a floor. The glyph is reached through the `box`; trimming the outer node, the
|
||||||
|
// `button` subnode and the glyph together, and asking the glyph for 12 px with
|
||||||
|
// `-gtk-icon-size` (which `GtkImage` honours when it is `GTK_ICON_SIZE_INHERIT`, and which
|
||||||
|
// *scales* the drawing rather than merely clamping its box), is what brings the mark to
|
||||||
|
// **12x12**. There is no lower floor to find: the symbolic glyph renders at any request
|
||||||
|
// (measured down to 4 px), so 12 px is a legibility choice, and it is the size the rule always
|
||||||
|
// meant -- the first version already wrote 12 px, on a selector that never matched. That is
|
||||||
|
// the reading `hint=WxH` in the dump prints.
|
||||||
"menubutton.udpscope-hint { min-width: 0; min-height: 0; padding: 0; margin: 0; }\n"
|
"menubutton.udpscope-hint { min-width: 0; min-height: 0; padding: 0; margin: 0; }\n"
|
||||||
"menubutton.udpscope-hint > button { min-width: 0; min-height: 0; padding: 0; }\n"
|
"menubutton.udpscope-hint > button { min-width: 0; min-height: 0; padding: 0; }\n"
|
||||||
"menubutton.udpscope-hint > button > image { min-width: 12px; min-height: 12px;"
|
"menubutton.udpscope-hint > button > box > image { min-width: 12px; min-height: 12px;"
|
||||||
" -gtk-icon-size: 12px; }\n";
|
" -gtk-icon-size: 12px; }\n";
|
||||||
GtkCssProvider* p = gtk_css_provider_new();
|
GtkCssProvider* p = gtk_css_provider_new();
|
||||||
gtk_css_provider_load_from_string(p, kCss);
|
gtk_css_provider_load_from_string(p, kCss);
|
||||||
|
|||||||
Reference in new issue
Block a user