ui: the signal list is the signals slide-over page, opened by a + badge or g

This commit is contained in:
Martino Ferrari committed 2026-11-03 00:54:25 +01:00
1 parent e36f2a202b
commit 0dd235e41c
11 files changed
+98 -75

No files matched your search

+42 -24
View File
@@ -93,17 +93,14 @@ int on_render_probe(GtkGLArea*, GdkGLContext*, gpointer user) {
return FALSE; // same reason the adapter does: never stop the emission
}
gboolean exit_probe_step3(gpointer user) {
gboolean exit_probe_step3b(gpointer user) {
App* a = static_cast<App*>(user);
a->dbg_mode_live = a->status_detail;
GtkWidget* window = a->window;
a->window = nullptr; // stop the tick before the widgets go
a->dbg_side_w = gtk_widget_get_width(a->side_box);
a->dbg_side_h = gtk_widget_get_height(a->side_box);
// The signal list is the `signals` page, opened by step 3 300 ms ago: its allocation is only real once
// the page is open and the reveal has run.
a->dbg_signal_w = gtk_widget_get_width(a->signal_panel);
a->dbg_signal_h = gtk_widget_get_height(a->signal_panel);
a->dbg_trigger_w = gtk_widget_get_width(a->trigger_panel);
a->dbg_trigger_h = gtk_widget_get_height(a->trigger_panel);
// How many rows of the signal list carry a drag source: dragging a signal onto a plot is how a plot is
// filled, so it has to survive both pane modes -- the locked list drops the tick, the menu and the `+`,
// and this is the reading that says it did not drop the drag with them. One row is the `MATH` divider,
@@ -211,11 +208,25 @@ gboolean exit_probe_step3(gpointer user) {
}
// `dbg_window_text` is kept by `sync_window_display()`, the only place that knows the span the
// window control is showing: there is no label to read it back from any more.
slideover_close(*a); // opened by step 1 for the allocations read above
slideover_close(*a); // opened by step 3 for the signal list's allocations read above
if (window != nullptr) gtk_window_destroy(GTK_WINDOW(window));
return G_SOURCE_REMOVE;
}
/// Reads the sizes that need the `trigger` page open (step 1 opened it), then swaps it for the `signals`
/// page -- the slide-over holds one page -- and leaves step 3b the 300 ms the reveal needs.
gboolean exit_probe_step3(gpointer user) {
App* a = static_cast<App*>(user);
a->dbg_mode_live = a->status_detail;
a->dbg_side_w = gtk_widget_get_width(a->side_box);
a->dbg_side_h = gtk_widget_get_height(a->side_box);
a->dbg_trigger_w = gtk_widget_get_width(a->trigger_panel);
a->dbg_trigger_h = gtk_widget_get_height(a->trigger_panel);
slideover_open(*a, "signals");
g_timeout_add(300, exit_probe_step3b, a);
return G_SOURCE_REMOVE;
}
/// The frame after the pane was locked: read the compact arm control's *allocation*, then leave the
/// configuration mode and trigger mode as step 2 used to, and hand the chain back its 400 ms. The button
/// is created hidden and this is the first tick it is shown, so its width in the same tick would always
@@ -1794,15 +1805,16 @@ gboolean stats_probe(gpointer user) {
}
/// Which section the dock's scroller is showing at its top: "measure" once it has been scrolled to the
/// cursors panel or past it, "signals" above that. Read from the adjustment, so it is the state the user
/// would see and not the last call made.
/// measurements' heading or past it, "cursors" above that (the cursors panel is the dock's first section;
/// the signal list is a slide-over page). Read from the adjustment, so it is the state the user would see
/// and not the last call made.
static const char* dock_section_in_view(App& a) {
if (a.dock_scroller == nullptr || a.cursors_panel == nullptr || a.dock_page == nullptr) return "none";
if (a.dock_scroller == nullptr || a.measures_head == nullptr || a.dock_page == nullptr) return "none";
graphene_point_t zero = GRAPHENE_POINT_INIT(0.f, 0.f);
graphene_point_t at;
if (!gtk_widget_compute_point(a.cursors_panel, a.dock_page, &zero, &at)) return "none";
if (!gtk_widget_compute_point(a.measures_head, a.dock_page, &zero, &at)) return "none";
GtkAdjustment* adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(a.dock_scroller));
return gtk_adjustment_get_value(adj) > 0.5 * at.y ? "measure" : "signals";
return gtk_adjustment_get_value(adj) > 0.5 * at.y ? "measure" : "cursors";
}
/// Phase two of the dock-section probe: the accumulators must have advanced while the Measure section was
@@ -1825,7 +1837,7 @@ gboolean dock_section_probe_report(gpointer user) {
}
}
if (a->dock_page != nullptr) gtk_widget_set_size_request(a->dock_page, -1, -1);
if (a->signal_panel != nullptr) gtk_widget_set_size_request(a->signal_panel, -1, -1);
if (a->cursors_panel != nullptr) gtk_widget_set_size_request(a->cursors_panel, -1, -1);
std::fprintf(stderr,
"[side-tab-probe] section=%s rows=%zu accums=%zu advanced=%" G_GUINT64_FORMAT
" min_n=%" G_GUINT64_FORMAT "\n",
@@ -1847,10 +1859,11 @@ gboolean dock_section_probe(gpointer user) {
if (!padded && a->dock_page != nullptr) {
padded = true;
gtk_widget_set_size_request(a->dock_page, -1, 3000);
// ... and the signal list taller than any window too, which is what pushes the Measure section below
// the viewport at offset 0 (padding the page's end only makes it scrollable, and on a window taller than
// the section's y the section would stay in view). Undone in the report.
if (a->signal_panel != nullptr) gtk_widget_set_size_request(a->signal_panel, -1, 3000);
// ... and the cursors panel (the dock's first section, above the measurements) taller than any window
// too, which is what pushes the measurements below the viewport at offset 0 (padding the page's end only
// makes it scrollable, and on a window taller than the section's y the section would stay in view).
// Undone in the report.
if (a->cursors_panel != nullptr) gtk_widget_set_size_request(a->cursors_panel, -1, 3000);
g_timeout_add(400, dock_section_probe, a);
return G_SOURCE_REMOVE;
}
@@ -1892,16 +1905,16 @@ gboolean dock_section_probe(gpointer user) {
gtk_check_button_set_active(GTK_CHECK_BUTTON(a->measures_stats_check), TRUE);
}
GtkAdjustment* dock_adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(a->dock_scroller));
// From the top, is the measure section (the cursors panel, where `dock_show_section("measure")` lands)
// below the viewport? Only then is scrolling to it a move *into* view and back out a move *away*; a
// From the top, is the measure section (the measurements' heading) below the viewport? Only then is scrolling to it a move *into* view and back out a move *away*; a
// section already in view at offset 0 would make the whole probe a reading of nothing.
gtk_adjustment_set_value(dock_adj, 0.0);
graphene_point_t zero = GRAPHENE_POINT_INIT(0.f, 0.f);
graphene_point_t measure_at = GRAPHENE_POINT_INIT(-1.f, -1.f);
const bool located =
a->cursors_panel != nullptr && gtk_widget_compute_point(a->cursors_panel, a->dock_page, &zero, &measure_at);
a->measures_head != nullptr && gtk_widget_compute_point(a->measures_head, a->dock_page, &zero, &measure_at);
const bool outside_at_top = located && static_cast<double>(measure_at.y) >= gtk_adjustment_get_page_size(dock_adj);
dock_show_section(*a, "measure");
dock_show_section(*a, "measure"); // lands on the cursors panel, the dock's top: a no-op scroll
if (located) gtk_adjustment_set_value(dock_adj, measure_at.y); // ... so go to the measurements themselves
// Where the dock went: `scrolled` is its offset and `reach` the most it can scroll. A reach of 0 would
// mean the content fits and "away from the section" is not a state this run can reach.
const double scrolled = gtk_adjustment_get_value(dock_adj);
@@ -1911,7 +1924,7 @@ gboolean dock_section_probe(gpointer user) {
for (const MeasureStatsAccum& s : a->measure_stats) g_dock_section_n_before.push_back(s.n);
// Away from the section the measurements are in: they are scrolled out of the viewport (the widgets
// stay mapped, only clipped), and the tick keeps calling `update_measures()` regardless.
dock_show_section(*a, "signals");
gtk_adjustment_set_value(dock_adj, 0.0);
std::fprintf(stderr,
"[side-tab-probe] section=%s accums=%zu baseline recorded (measure at scroll %.0f of %.0f, "
"outside_at_top=%d)\n",
@@ -6427,12 +6440,17 @@ gboolean keys_probe(gpointer user) {
line += buf;
}
{
// `g` is the signal list's slide-over page now: it opens it, the dock does not move, and a second `g`
// closes it again.
const double before = dock_value();
run_app_action(*a, AppAction::ShowSignals);
const bool opened = slideover_page(*a) == "signals";
const double after = dock_value();
run_app_action(*a, AppAction::ShowSignals);
const bool closed = slideover_page(*a).empty();
char buf[96];
std::snprintf(buf, sizeof(buf), " g: dock %.0f->%.0f at_top=%d |", before, after,
std::fabs(after) < 1.0 ? 1 : 0);
std::snprintf(buf, sizeof(buf), " g: page=%d dock_still=%d closed=%d |", opened ? 1 : 0,
std::fabs(after - before) < 1.0 ? 1 : 0, closed ? 1 : 0);
line += buf;
}
before_after("l: layout", a->layout_toggle, AppAction::LayoutEditor);