fix: the trigger stays editable while it is off, and the locked pane says "stream"
Two things the lock got wrong, and they are the same mistake seen twice: trigger-off was treated as "the
pane is disabled".
**The configuration was unreachable exactly when it was wanted.** `on_trigger_toggled()` set the trigger
*body* insensitive with the mode — a rule carried over from the five-revealer sidebar, where a closed pane
had nothing to edit. A trigger is configured *before* it is switched on, so switching it off to change it,
or to read what it is set to, is the ordinary way to work. The body is now never disabled; only the
*cursors'* readout still is, which is the pane whose content has nothing to show with the instruments off.
**The locked pane described a trigger that was not running.** With trigger mode off the summary is one
line — `mode: stream (trigger off)` — because the four lines it used to show (signal, condition, level,
mode) describe a trigger that is not there. With the trigger on it is those four plus whatever is not at
its default (`noise band`, `HF reject`, `pre-trigger`, `hold-off`).
The reading changes with it: `trigger panel sensitive …=1` is now a **regression guard** rather than a
state — the trigger's body is always live, so a `0` there means the settings have been locked out again.
Verified in both states, from sessions whose only difference is `trigger_enabled`:
panes: trigger=locked signals=locked body_visible=0 summary='mode: stream (trigger off)'
panes: trigger=locked signals=locked body_visible=0 summary='signal: square | condition: window, rising | level: 0.3 .. 0.6 | mode: single | pre-trigger: 20 %'
trigger panel sensitive before the probe toggled it: 1
The locked trigger pane is 72 px with the trigger off and 192 px with it on. Docs: the invariants' rule
for which body is disabled and why the trigger's is not, the `summary`'s two forms with what each means,
the README's deviation note, and the second `panes:` line renamed to say what it is — the line as the
probe found it, because only a run whose *session* has the trigger off shows the stream form.
This commit is contained in:
1 parent
4f4851f4e3
commit
796dda4ad5
7 files changed
+48
-15
No files matched your search
@@ -2412,8 +2412,9 @@ now — they are listed so they are not mistaken for anything else:
|
|||||||
measured), so the pages carry an empty title and the pills are named in code. With the math
|
measured), so the pages carry an empty title and the pills are named in code. With the math
|
||||||
list folded into the signal list under a `MATH` divider whose `+` creates a channel — a derived channel already *is* a channel in
|
list folded into the signal list under a `MATH` divider whose `+` creates a channel — a derived channel already *is* a channel in
|
||||||
the model, so the two lists were the same list drawn twice. A tab is one-of-*N*, so no
|
the model, so the two lists were the same list drawn twice. A tab is one-of-*N*, so no
|
||||||
toggle hides a pane any more: trigger-off and cursors-off **disable** their pane and leave
|
toggle hides a pane any more: cursors-off **disables** its readout and leaves it in place, and
|
||||||
it in place, and the measurements' and math panes' toolbar toggles are gone with the panes.
|
trigger-off leaves the trigger panel fully editable — a trigger is configured *before* it is
|
||||||
|
switched on, and the locked view says `stream (trigger off)` instead of the settings — and the measurements' and math panes' toolbar toggles are gone with the panes.
|
||||||
- **A plot holds at most eight signals** (`RowSet::kSlotsPerRow`), because a `Plot`
|
- **A plot holds at most eight signals** (`RowSet::kSlotsPerRow`), because a `Plot`
|
||||||
cannot give up a trace and the slots are therefore created up front.
|
cannot give up a trace and the slots are therefore created up front.
|
||||||
- **One toggle drives both cursor orientations.** The vertical markers and the
|
- **One toggle drives both cursor orientations.** The vertical markers and the
|
||||||
|
|||||||
@@ -166,9 +166,13 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
|
|||||||
heights, so one shared scroller would leave a switch scrolled where the new page never asked to
|
heights, so one shared scroller would leave a switch scrolled where the new page never asked to
|
||||||
be). The reason is the one this trap teaches: five sections competing for one 320 px column left
|
be). The reason is the one this trap teaches: five sections competing for one 320 px column left
|
||||||
every one of them short of room. A *feature's* on/off is no longer a visibility at all -- the
|
every one of them short of room. A *feature's* on/off is no longer a visibility at all -- the
|
||||||
trigger's and the cursors' toggles set their pane's **body** insensitive, so the pane stays where it
|
**cursors'** toggle sets its pane's **body** insensitive -- the readout has nothing to show with the
|
||||||
is and the settings you are about to switch back on do not vanish while you look for them. The *body*
|
instruments off -- and the *body* and not the pane, because the pane's heading carries its own switch
|
||||||
and not the pane, because each pane's heading carries its own switch (see the next bullet). The
|
(see the next bullet). The **trigger's body is deliberately never disabled**: a trigger is configured
|
||||||
|
*before* it is switched on, so switching it off to change it, or to read what it is set to, is the
|
||||||
|
ordinary way to work. It used to go insensitive with the mode, which left the settings unreachable
|
||||||
|
exactly when a user wanted to change them; `trigger panel sensitive …=1` is the regression guard, and a
|
||||||
|
`0` there means the configuration has been locked out again. The
|
||||||
trap itself does not go away with the widget: a stack's hidden page measures 0x0 too and is still
|
trap itself does not go away with the widget: a stack's hidden page measures 0x0 too and is still
|
||||||
given the leftover width, so **ask about state, not about size** carries over unchanged. Every
|
given the leftover width, so **ask about state, not about size** carries over unchanged. Every
|
||||||
allocation read in the sidebar is a debug capture, and each reads 0 on the page that is *not*
|
allocation read in the sidebar is a debug capture, and each reads 0 on the page that is *not*
|
||||||
|
|||||||
@@ -1145,6 +1145,7 @@ library measures and draws the rect in tests of its own.
|
|||||||
[udpscope] pane edits: locked=document-edit-symbolic(ok) config=object-select-symbolic(ok)
|
[udpscope] pane edits: locked=document-edit-symbolic(ok) config=object-select-symbolic(ok)
|
||||||
[udpscope] panes: trigger=locked signals=locked body_visible=0 summary='signal: square | condition: window, falling | level: 0.3 .. 0.6 | mode: single | noise band: 0.2 | pre-trigger: 20 % | hold-off: 1000 ms'
|
[udpscope] panes: trigger=locked signals=locked body_visible=0 summary='signal: square | condition: window, falling | level: 0.3 .. 0.6 | mode: single | noise band: 0.2 | pre-trigger: 20 % | hold-off: 1000 ms'
|
||||||
[udpscope] panes: trigger=config signals=config body_visible=1 summary=''
|
[udpscope] panes: trigger=config signals=config body_visible=1 summary=''
|
||||||
|
[udpscope] panes: the same line as the probe found it: 'mode: stream (trigger off)'
|
||||||
```
|
```
|
||||||
|
|
||||||
**`pane edits:`** is the two `[edit]` buttons in each mode, by name and verdict, and it exists because of
|
**`pane edits:`** is the two `[edit]` buttons in each mode, by name and verdict, and it exists because of
|
||||||
@@ -1160,6 +1161,14 @@ changes the configuration — and **config** is the full pane, which is what a *
|
|||||||
session file that loaded is what "we have been here before" means. Each heading's `[edit]` button flips
|
session file that loaded is what "we have been here before" means. Each heading's `[edit]` button flips
|
||||||
its pane.
|
its pane.
|
||||||
|
|
||||||
|
- **With trigger mode off the summary is one line**: `mode: stream (trigger off)`. The four lines below
|
||||||
|
describe a trigger that is not running, so quoting them would describe nothing. The dump carries the line
|
||||||
|
twice — once as the probe found it and once at the end — because only a run whose *session* has the
|
||||||
|
trigger off shows the stream form, and a run whose session has it on shows the settings.
|
||||||
|
- **`trigger panel sensitive …=1` is now a guard, not a state.** The trigger's body is never disabled —
|
||||||
|
a trigger is configured before it is switched on — so this reads `1` always, and a `0` means the
|
||||||
|
settings have been made unreachable again. The *cursors'* body is disabled with the cursors, and that
|
||||||
|
is the pane whose readout has nothing to show.
|
||||||
- **`summary`** is the locked trigger pane's whole content, as `key: value` pairs separated by ` |`. The
|
- **`summary`** is the locked trigger pane's whole content, as `key: value` pairs separated by ` |`. The
|
||||||
pane draws it as a small definition list — `signal`, `condition`, `level`, `mode` on four lines, and
|
pane draws it as a small definition list — `signal`, `condition`, `level`, `mode` on four lines, and
|
||||||
then only the figures that are *not* at their defaults (`noise band`, `HF reject`, `pre-trigger`,
|
then only the figures that are *not* at their defaults (`noise band`, `HF reject`, `pre-trigger`,
|
||||||
|
|||||||
+6
-5
@@ -4852,11 +4852,10 @@ void on_activate(GtkApplication* application, gpointer user) {
|
|||||||
app->signal_panel = build_signal_panel(*app);
|
app->signal_panel = build_signal_panel(*app);
|
||||||
gtk_box_append(GTK_BOX(signals_page), app->signal_panel);
|
gtk_box_append(GTK_BOX(signals_page), app->signal_panel);
|
||||||
|
|
||||||
// Both instruments start off, so both *bodies* start insensitive -- stated here by the one place
|
// The cursors start off, so their readout starts insensitive -- stated here by the one place that
|
||||||
// that knows the default, rather than left to whichever widget happened to be built first. The
|
// knows the default, and the *body* and not the panel, because the panel's heading carries the
|
||||||
// bodies and not the panels: each panel's heading carries the switch that turns it on, and a
|
// switch that turns it back on. The trigger's body is deliberately *not* disabled: a trigger is
|
||||||
// control inside an insensitive parent cannot be clicked.
|
// configured before it is switched on, so its settings have to stay editable while it is off.
|
||||||
gtk_widget_set_sensitive(app->trigger_body, FALSE);
|
|
||||||
gtk_widget_set_sensitive(app->cursors_body, FALSE);
|
gtk_widget_set_sensitive(app->cursors_body, FALSE);
|
||||||
gtk_widget_set_sensitive(app->cursors_reset, FALSE);
|
gtk_widget_set_sensitive(app->cursors_reset, FALSE);
|
||||||
|
|
||||||
@@ -5790,6 +5789,8 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
|||||||
app.dbg_trigger_locked ? "locked" : "config",
|
app.dbg_trigger_locked ? "locked" : "config",
|
||||||
app.dbg_signals_locked ? "locked" : "config", app.dbg_trigger_body_visible,
|
app.dbg_signals_locked ? "locked" : "config", app.dbg_trigger_body_visible,
|
||||||
app.dbg_trigger_summary.c_str());
|
app.dbg_trigger_summary.c_str());
|
||||||
|
std::printf("[udpscope] panes: the same line as the probe found it: '%s'\n",
|
||||||
|
app.dbg_trigger_summary_early.c_str());
|
||||||
std::printf("[udpscope] panel switches: trigger=%d/%d cursors=%d/%d drove_toolbar=%d "
|
std::printf("[udpscope] panel switches: trigger=%d/%d cursors=%d/%d drove_toolbar=%d "
|
||||||
"(pane switch / header bar button; `drove_toolbar` is the pane's own switch having "
|
"(pane switch / header bar button; `drove_toolbar` is the pane's own switch having "
|
||||||
"moved the button)\n",
|
"moved the button)\n",
|
||||||
|
|||||||
@@ -283,6 +283,10 @@ struct App {
|
|||||||
/// The compact line the locked trigger pane shows. It is the pane's whole content in that mode, so it
|
/// The compact line the locked trigger pane shows. It is the pane's whole content in that mode, so it
|
||||||
/// is read rather than assumed: empty here is a locked pane showing nothing at all.
|
/// is read rather than assumed: empty here is a locked pane showing nothing at all.
|
||||||
std::string dbg_trigger_summary;
|
std::string dbg_trigger_summary;
|
||||||
|
/// The same line as the exit probe found it, captured before the probe touches the trigger. The locked
|
||||||
|
/// pane says one thing about a trigger that is running and another about one that is not, and only a run
|
||||||
|
/// whose session has it off shows the second -- so the dump carries both rather than assuming either.
|
||||||
|
std::string dbg_trigger_summary_early;
|
||||||
/// The two [edit] buttons' icons, read in each mode by clicking into it and back: a button whose icon
|
/// The two [edit] buttons' icons, read in each mode by clicking into it and back: a button whose icon
|
||||||
/// does not resolve is *blank*, and that is how the missing "done" icon was found.
|
/// does not resolve is *blank*, and that is how the missing "done" icon was found.
|
||||||
std::string dbg_pane_edit_icon;
|
std::string dbg_pane_edit_icon;
|
||||||
|
|||||||
@@ -2340,6 +2340,7 @@ gboolean exit_probe_step1(gpointer user) {
|
|||||||
a->trigger_body != nullptr && gtk_widget_get_visible(a->trigger_body) ? 1 : 0;
|
a->trigger_body != nullptr && gtk_widget_get_visible(a->trigger_body) ? 1 : 0;
|
||||||
// The summary's text comes from the sync that wrote it: the container is a grid of key/value rows,
|
// The summary's text comes from the sync that wrote it: the container is a grid of key/value rows,
|
||||||
// and asking it for a label's text was itself a critical.
|
// and asking it for a label's text was itself a critical.
|
||||||
|
a->dbg_trigger_summary_early = a->dbg_trigger_summary; // as found, before this probe touches it
|
||||||
a->dbg_panel_switch_live =
|
a->dbg_panel_switch_live =
|
||||||
a->trigger_switch != nullptr && gtk_widget_get_sensitive(a->trigger_switch) &&
|
a->trigger_switch != nullptr && gtk_widget_get_sensitive(a->trigger_switch) &&
|
||||||
a->cursors_switch != nullptr && gtk_widget_get_sensitive(a->cursors_switch)
|
a->cursors_switch != nullptr && gtk_widget_get_sensitive(a->cursors_switch)
|
||||||
|
|||||||
+18
-5
@@ -183,6 +183,18 @@ void sync_trigger_summary(App& app) {
|
|||||||
channel = channels[static_cast<std::size_t>(tc.channel)].name;
|
channel = channels[static_cast<std::size_t>(tc.channel)].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// With trigger mode off the scope is streaming, and that is the whole of what this pane has to say:
|
||||||
|
// the four lines below describe a trigger that is not running.
|
||||||
|
if (!tc.enabled) {
|
||||||
|
put("mode", "stream (trigger off)");
|
||||||
|
for (int i = row; i < App::kTriggerSummaryRows; ++i) {
|
||||||
|
gtk_widget_set_visible(app.trigger_summary_keys[i], FALSE);
|
||||||
|
gtk_widget_set_visible(app.trigger_summary_values[i], FALSE);
|
||||||
|
}
|
||||||
|
app.dbg_trigger_summary = reading;
|
||||||
|
gtk_widget_set_visible(app.trigger_summary, app.trigger_locked);
|
||||||
|
return;
|
||||||
|
}
|
||||||
put("signal", channel.empty() ? std::string("none acquired") : channel);
|
put("signal", channel.empty() ? std::string("none acquired") : channel);
|
||||||
// The condition: the shape, and whatever qualifies it. A pulse width carries its comparison and its
|
// The condition: the shape, and whatever qualifies it. A pulse width carries its comparison and its
|
||||||
// width, which is what the shape *is*; a window carries its two levels on the line below.
|
// width, which is what the shape *is*; a window carries its two levels on the line below.
|
||||||
@@ -386,11 +398,12 @@ void on_trigger_toggled(GtkToggleButton* button, gpointer user) {
|
|||||||
if (on && signal >= 0) {
|
if (on && signal >= 0) {
|
||||||
app->model->set_signal_enabled(static_cast<std::size_t>(signal), true);
|
app->model->set_signal_enabled(static_cast<std::size_t>(signal), true);
|
||||||
}
|
}
|
||||||
// Disabled, not hidden: a panel you can still see is a panel you can read, and the settings you
|
// The panel's body stays *live* whether or not the trigger is running: a trigger is configured
|
||||||
// are about to switch back on must not vanish while you look for them. The *body* is what goes
|
// before it is switched on, and switching it off to edit it -- or to check what it is set to --
|
||||||
// insensitive and not the panel, because the panel's heading row carries the switch that turns
|
// is the ordinary way to work. (It used to go insensitive with the mode, which left the settings
|
||||||
// this back on -- and a control inside an insensitive parent cannot be clicked.
|
// unreachable exactly when a user wanted to change them.) What that costs is the reading: the
|
||||||
gtk_widget_set_sensitive(app->trigger_body, on);
|
// `trigger panel sensitive` line is now a regression guard, and a `0` there means the
|
||||||
|
// configuration has been locked out again.
|
||||||
// The event-history button is part of trigger mode and the pane it opens is *on demand*; leaving
|
// The event-history button is part of trigger mode and the pane it opens is *on demand*; leaving
|
||||||
// trigger mode takes the button away and collapses the pane, so going back to streaming is not a
|
// trigger mode takes the button away and collapses the pane, so going back to streaming is not a
|
||||||
// column of stale events beside the plot. Recording is the other half of that answer, so this is
|
// column of stale events beside the plot. Recording is the other half of that answer, so this is
|
||||||
|
|||||||
Reference in new issue
Block a user