ui: the readouts strip hides when there are no cursors or measurements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Sonnet 4.6 committed 2026-11-03 11:14:49 +01:00
1 parent 61d0925144
commit 5653a3a66b
5 files changed
+63 -25

No files matched your search

+3
View File
@@ -618,6 +618,9 @@ struct App {
GtkWidget* strip_box = nullptr;
GtkWidget* strip_cursor_box = nullptr; ///< the cursor chips; insensitive with the cursors off
GtkWidget* strip_measure_box = nullptr; ///< the measurement chips
GtkWidget* strip_cursor_group = nullptr; ///< the Cursors button and its chips; shown with the cursors on
GtkWidget* strip_measure_group = nullptr; ///< the Measures button and its chips; shown with measurements
GtkWidget* strip_sep = nullptr; ///< between the groups; shown when both are
std::vector<GtkWidget*> strip_cursor_who;
std::vector<GtkWidget*> strip_cursor_deltas;
std::vector<GtkWidget*> strip_measure_labels;
+1
View File
@@ -154,6 +154,7 @@ void on_cursors_toggled(GtkToggleButton* button, gpointer user) {
// The dock's copy and the strip's chips follow: switched off they stay on screen, insensitive, reading
// `--`. One function, so the two cannot disagree.
dock_set_cursors_sensitive(*app, on);
sync_readouts_strip(*app); // the strip's Cursors group (and the strip itself) follows at once
if (!on) update_cursors_pane(*app);
if (on) {
app->rows->reset_cursors();
+32 -19
View File
@@ -154,17 +154,22 @@ void build_readouts_strip(App& app) {
clear_box(app.strip_box);
app.strip_cursor_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
app.strip_measure_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append(GTK_BOX(app.strip_box),
// Each section is a group of its own so the strip can show only the one that has something to say.
app.strip_cursor_group = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append(GTK_BOX(app.strip_cursor_group),
strip_button("Cursors", G_CALLBACK(on_edit_cursors), &app, "the cursors' full panel"));
gtk_box_append(GTK_BOX(app.strip_box), app.strip_cursor_box);
GtkWidget* sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
gtk_widget_set_margin_top(sep, 5);
gtk_widget_set_margin_bottom(sep, 5);
gtk_box_append(GTK_BOX(app.strip_box), sep);
gtk_box_append(GTK_BOX(app.strip_box),
gtk_box_append(GTK_BOX(app.strip_cursor_group), app.strip_cursor_box);
app.strip_sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
gtk_widget_set_margin_top(app.strip_sep, 5);
gtk_widget_set_margin_bottom(app.strip_sep, 5);
app.strip_measure_group = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append(GTK_BOX(app.strip_measure_group),
strip_button("Measures", G_CALLBACK(on_edit_measures), &app,
"the measurements' full panel"));
gtk_box_append(GTK_BOX(app.strip_box), app.strip_measure_box);
gtk_box_append(GTK_BOX(app.strip_measure_group), app.strip_measure_box);
gtk_box_append(GTK_BOX(app.strip_box), app.strip_cursor_group);
gtk_box_append(GTK_BOX(app.strip_box), app.strip_sep);
gtk_box_append(GTK_BOX(app.strip_box), app.strip_measure_group);
}
} // namespace
@@ -264,12 +269,7 @@ void dock_rebuild_measures(App& app) {
gtk_widget_add_css_class(none, "caption");
gtk_widget_add_css_class(none, "dim-label");
gtk_box_append(GTK_BOX(app.dock_measures_box), none);
if (app.strip_measure_box != nullptr) {
GtkWidget* strip_none = gtk_label_new("no measurements");
gtk_widget_add_css_class(strip_none, "caption");
gtk_widget_add_css_class(strip_none, "dim-label");
gtk_box_append(GTK_BOX(app.strip_measure_box), strip_none);
}
// The strip has no placeholder: its Measures group is hidden while there are no measurements.
return;
}
for (std::size_t i = 0; i < app.measures.size(); ++i) {
@@ -351,12 +351,25 @@ void sync_readouts_strip(App& app) {
// open -- and is not a readout you can keep an eye on while looking at the trace. `collapsed` is the
// split view's value from the previous frame (the tick calls this before `set_collapsed()`), so the
// strip follows a collapse or a widening one tick late; `show-sidebar` is the wish just re-asserted.
//
// And only with something to read: a section is there when its feature is (cursors switched on,
// at least one measurement), and with neither the strip is gone -- it is a readout, not a control
// strip, and an empty line under the plot is 26 px of nothing. (The one place "hide" beats "disable":
// the dock keeps both blocks on screen, so the empty state is never invisible.)
AdwOverlaySplitView* split = ADW_OVERLAY_SPLIT_VIEW(app.side_view);
const bool want = !adw_overlay_split_view_get_show_sidebar(split) ||
adw_overlay_split_view_get_collapsed(split);
if ((gtk_widget_get_visible(app.readouts_strip) != FALSE) != want) {
gtk_widget_set_visible(app.readouts_strip, want);
}
const bool cursors = app.cursors_toggle != nullptr &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(app.cursors_toggle));
const bool measures = !app.measures.empty();
const bool want = (!adw_overlay_split_view_get_show_sidebar(split) ||
adw_overlay_split_view_get_collapsed(split)) &&
(cursors || measures);
auto show = [](GtkWidget* w, bool v) {
if (w != nullptr && (gtk_widget_get_visible(w) != FALSE) != v) gtk_widget_set_visible(w, v);
};
show(app.strip_cursor_group, cursors);
show(app.strip_measure_group, measures);
show(app.strip_sep, cursors && measures);
show(app.readouts_strip, want);
}
namespace {
+1
View File
@@ -112,6 +112,7 @@ void rebuild_measures_pane(App& app) {
app.measure_text.emplace_back();
}
dock_rebuild_measures(app);
sync_readouts_strip(app); // the strip's Measures group (and the strip itself) follows at once, not a tick later
update_measures(app, /*force=*/true, /*accumulate=*/true);
}
+26 -6
View File
@@ -4339,9 +4339,10 @@ static int dock_width_fits(App& a, int* dock_w, int* side_w) {
/// The readouts strip against the dock it mirrors: `same_text=1` when every strip label's text equals the
/// dock's (the cursors' `who` and delta cells, the measurements' values) and the counts agree. The strip is
/// shown whenever the dock is not beside the plot, so `expected` is `!dock_shown || collapsed` (`dock_shown`
/// is `show-sidebar`, `collapsed` the split view's, both read in the same frame as `visible`), `visible_ok`
/// is `visible == expected`, and `h` is the strip's fixed 26 whenever it is visible.
/// shown whenever the dock is not beside the plot and there is something to read, so `expected` is
/// `(!dock_shown || collapsed) && (cursors on || a measurement)` (`dock_shown` is `show-sidebar`, `collapsed`
/// the split view's, both read in the same frame as `visible`), `visible_ok` is `visible == expected`, and
/// `h` is the strip's fixed 26 whenever it is visible.
/// `sens_same` is the strip's cursor chips sharing the dock grid's sensitivity.
static void strip_report(App& a, const char* tag, const char* what) {
const auto text = [](GtkWidget* w) { return std::string(gtk_label_get_text(GTK_LABEL(w))); };
@@ -4365,19 +4366,35 @@ static void strip_report(App& a, const char* tag, const char* what) {
const bool collapsed =
a.side_view != nullptr &&
adw_overlay_split_view_get_collapsed(ADW_OVERLAY_SPLIT_VIEW(a.side_view)) != FALSE;
const bool expected = !dock_shown || collapsed;
// And with something to read: the cursors on, or a measurement (`sync_readouts_strip()`).
const bool has_content =
(a.cursors_toggle != nullptr &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(a.cursors_toggle))) ||
!a.measures.empty();
const bool expected = (!dock_shown || collapsed) && has_content;
const bool sens_same =
a.strip_cursor_box != nullptr && a.dock_cursor_grid != nullptr &&
gtk_widget_get_sensitive(a.strip_cursor_box) == gtk_widget_get_sensitive(a.dock_cursor_grid);
// `groups=<cursors><measures><separator>`: which sections of the strip are shown, each against its own
// feature (cursors on, a measurement present, both); `groups_ok=1` when all three agree.
const bool cur_on = a.cursors_toggle != nullptr &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(a.cursors_toggle));
const bool mea_on = !a.measures.empty();
const bool g_cur = a.strip_cursor_group != nullptr && gtk_widget_get_visible(a.strip_cursor_group);
const bool g_mea = a.strip_measure_group != nullptr && gtk_widget_get_visible(a.strip_measure_group);
const bool g_sep = a.strip_sep != nullptr && gtk_widget_get_visible(a.strip_sep);
const bool groups_ok = g_cur == cur_on && g_mea == mea_on && g_sep == (cur_on && mea_on);
std::fprintf(stderr,
"[%s-probe] %-14s strip: visible=%d expected=%d visible_ok=%d dock_shown=%d cursors=%zu "
"measures=%zu same_text=%d h=%d sens_same=%d collapsed=%d window=%d\n",
"measures=%zu same_text=%d h=%d sens_same=%d collapsed=%d window=%d groups=%d%d%d "
"groups_ok=%d\n",
tag, what, visible ? 1 : 0, expected ? 1 : 0, visible == expected ? 1 : 0,
dock_shown ? 1 : 0, a.strip_cursor_deltas.size(),
a.strip_measure_labels.size(), same, a.readouts_strip != nullptr
? gtk_widget_get_height(a.readouts_strip) : -1,
sens_same ? 1 : 0, collapsed ? 1 : 0,
a.window != nullptr ? gtk_widget_get_width(a.window) : -1);
a.window != nullptr ? gtk_widget_get_width(a.window) : -1,
g_cur ? 1 : 0, g_mea ? 1 : 0, g_sep ? 1 : 0, groups_ok ? 1 : 0);
}
/// Puts the dock away through the wish the tick re-asserts and reads the strip with it hidden
@@ -4761,6 +4778,9 @@ gboolean measures_probe_step(gpointer user) {
std::fprintf(stderr, "[measures-probe] no acquired signal to measure\n");
return G_SOURCE_REMOVE;
}
// The "neither" state: no measurement yet and (from a fresh config) the cursors off, so the strip is
// hidden -- `visible=0 expected=0 groups=000`. (The other readings need a state with something in it.)
strip_report(*a, "measures", "start");
for (int i = 0; i < measure_type_count(); ++i) {
Measure m;
m.signal = signal;