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
|
||||
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"
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
one is made.** The "(i)" is meant to be a *mark*, not a button, and the default is 34x34 (a 24 px
|
||||
floor plus 5 px of padding from Adwaita's `button` rule). Measured on libadwaita 1.10: setting
|
||||
- **A `GtkMenuButton` ignores both `min-width` and a size request, and the icon is a node *below*
|
||||
its `button` subnode.** The "(i)" is meant to be a *mark*, not a button, and the default is 34x34 (a
|
||||
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()`
|
||||
-- the menu button's own measure wins. Three selectors are needed, all in `install_css()`:
|
||||
`menubutton.udpscope-hint` (the outer node), `menubutton.udpscope-hint > button` (its subnode) and
|
||||
`... > button > image` (the glyph), with `min-width: 0; min-height: 0; padding: 0` -- and the result
|
||||
is **16x16**, the glyph's own size, because a `min-width` is a floor and not a cap. (A class on the
|
||||
outer node alone leaves the subnode at 34; a class on the subnode alone shrank the width to 16 and
|
||||
left the height at 26.) The dump's `hint=` reading is that number, and it is measured with
|
||||
`gtk_widget_compute_bounds()` on the first *visible* hint -- a hint inside a collapsed `GtkExpander`
|
||||
is not in the widget-parent chain at all and reads 0x0, which would look like a mark shrunk to
|
||||
nothing.
|
||||
-- the menu button's own measure wins. The node tree is `menubutton > button > box > image` (read off
|
||||
the CSS node dump), so `install_css()` reaches the glyph as
|
||||
`menubutton.udpscope-hint > button > box > image`. The direct-grandchild form `> button > image`
|
||||
matches **nothing** and is silent about it -- the glyph keeps its natural 16 px, which is why an
|
||||
earlier version shipped a 16x16 mark and took that for the floor it was not. Zeroing the outer node
|
||||
and the `button` subnode and asking the glyph for **12 px** (`min-width`/`min-height` *and*
|
||||
`-gtk-icon-size`, the latter what actually *scales* the drawing rather than clamping its box) gives
|
||||
**12x12**. (A class on the outer node alone leaves the subnode at 34; a class on the subnode alone
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
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.
|
||||
- `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
|
||||
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
|
||||
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
|
||||
panel), `trigger_advanced` (the pre-trigger share row) and `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**
|
||||
panel), `trigger_advanced` (the pre-trigger share row), `trigger_search` (the *header* of the search
|
||||
block's expander, which is what lets it be on screen while the block is collapsed) and
|
||||
`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=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
|
||||
@@ -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
|
||||
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
|
||||
(`gtk_widget_compute_bounds()`), and **16x16 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
|
||||
`GtkMenuButton` needs (its measure ignores both `min-width` on the widget and a size request) — the
|
||||
default 34x34 is the number to compare against. Hints inside a collapsed expander are skipped, so the
|
||||
number is never a hidden widget's 0x0. `tour=` is `running`/`idle` with the plan's `steps=` and the
|
||||
(`gtk_widget_compute_bounds()`), and **12x12 is the reading a "much tinier" mark must keep**: the
|
||||
class zeroes the outer `menubutton` node and its `button` subnode (a `GtkMenuButton`'s measure
|
||||
ignores both `min-width` on the widget and a size request), and the glyph is a third node *below*
|
||||
the subnode — `menubutton > button > box > image`, read off the CSS node dump. The direct-grandchild
|
||||
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
|
||||
`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
|
||||
@@ -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*
|
||||
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
|
||||
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.
|
||||
- `[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
|
||||
@@ -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
|
||||
`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:
|
||||
- `[helpui] contextual on: hints=11 ids={events plot status cursors measures trigger trigger_advanced events_record signals signals_config window} hint=16x16` —
|
||||
the eleven "(i)" affordances, by id, and the size the first visible one was allocated. Ten are the
|
||||
window's own surfaces (three 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
|
||||
window is open; it reads 10 with the editor shut. **On a fresh config this reads `hints=0 ids={}`
|
||||
- `[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 twelve "(i)" affordances, by id, and the size the first visible one was allocated. Eleven are
|
||||
the window's own surfaces (four of them a specific control's row rather than a heading — see the
|
||||
`help layer:` entry) and the twelfth is `math`, which is present only while the math editor
|
||||
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
|
||||
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
|
||||
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`
|
||||
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'`,
|
||||
@@ -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`
|
||||
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.
|
||||
- `[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
|
||||
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.
|
||||
- `[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
|
||||
@@ -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
|
||||
configuration mode against 72 locked — the body is replaced by the summary), which is the check
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
[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
|
||||
lingering input grab — a tour of ordinary overlay widgets takes none), and **`hint=16x16`** is the
|
||||
size the shrunk "(i)" must keep (the default menu-button mark is 34x34). The chooser's own tour is
|
||||
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 `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
|
||||
`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
|
||||
@@ -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
|
||||
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*:
|
||||
`[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
|
||||
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: …`
|
||||
|
||||
@@ -114,12 +114,54 @@
|
||||
|
||||
<section id="search">
|
||||
<title>Search the buffer</title>
|
||||
<p><gui>Search the buffer</gui> runs the same condition over the whole retained ring and
|
||||
lists every place it holds. The arrows step through hits; each step pauses on the hit,
|
||||
centred, exactly as the Pause button does. Up to 16 hits in the visible window are marked
|
||||
on every row; when there are more the panel says how many and suggests zooming in. The
|
||||
search uses the trigger's own condition, set in one place, so a hit is by construction an
|
||||
instant the trigger would have fired.</p>
|
||||
<p><gui>Search the buffer</gui>, at the foot of the trigger panel and collapsed until you open
|
||||
it, answers the question the trigger answers — <em>where does this condition hold?</em> — over
|
||||
the <em>whole</em> retained buffer rather than at the live edge. It runs the trigger's own
|
||||
evaluator over the ring in stream order, so a <gui>hit</gui> is not a level you point at: it is
|
||||
an <em>instant</em> the trigger would have fired on, timed the way an acquisition would have
|
||||
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 id="knowing">
|
||||
|
||||
+16
-1
@@ -214,8 +214,23 @@
|
||||
</child>
|
||||
<child>
|
||||
<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>
|
||||
<!-- 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">
|
||||
|
||||
<object class="GtkBox" id="search_sbox">
|
||||
|
||||
+8
-1
@@ -246,6 +246,9 @@ struct App {
|
||||
GtkWidget* search_marks_label = nullptr;
|
||||
GtkWidget* search_prev_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
|
||||
/// oldest retained sample that `publish_pause_view()` held nothing. Cleared at every jump.
|
||||
bool search_jump_empty = false;
|
||||
@@ -284,10 +287,14 @@ struct App {
|
||||
GtkWidget* status_row = 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
|
||||
/// 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).
|
||||
GtkWidget* trigger_record_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;
|
||||
/// 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
|
||||
|
||||
@@ -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 "
|
||||
"capture looks like. The condition rows above appear and disappear with the condition chosen.",
|
||||
"", &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",
|
||||
"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 "
|
||||
|
||||
@@ -4773,6 +4773,24 @@ gboolean helpui_probe_step(gpointer user) {
|
||||
helpui_probe_next(*a, 8, 400);
|
||||
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);
|
||||
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_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_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) {
|
||||
g_signal_connect(app.search_run_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer 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"
|
||||
// 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
|
||||
// second toolbar button -- the size the ask calls too big. Measured on libadwaita 1.10: the
|
||||
// outer `menubutton` node *and* its `button` subnode both carry a floor and padding, and a class
|
||||
// selector on either alone leaves the other at 34 (`min-width` on the widget itself is ignored
|
||||
// by `GtkMenuButton`'s measure, and so is a size request -- tried both). Zeroing all three --
|
||||
// the outer node, the subnode and its glyph -- is what brings it to **16x16**: the icon's own
|
||||
// size and nothing else, because a `min-width` is a floor, not a cap, so 16 px is where a 16 px
|
||||
// Adwaita glyph stops. That is the reading `hint=WxH` in the dump prints.
|
||||
// second toolbar button. Measured on libadwaita 1.10: the outer `menubutton` node *and* its
|
||||
// `button` subnode both carry a floor and padding, and a class selector on either alone leaves
|
||||
// the other at 34 (`min-width` on the widget itself is ignored by `GtkMenuButton`'s measure, and
|
||||
// so is a size request -- tried both). Beyond those two there is a third node, and getting its
|
||||
// path wrong is silent: the button's own tree is `menubutton > button > box > image` (read off
|
||||
// the CSS node dump), so the direct-grandchild form `> button > image` matches *nothing* and
|
||||
// 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 > 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";
|
||||
GtkCssProvider* p = gtk_css_provider_new();
|
||||
gtk_css_provider_load_from_string(p, kCss);
|
||||
|
||||
Reference in new issue
Block a user