diff --git a/docs/claude/probe-readings.md b/docs/claude/probe-readings.md index 4914dd4..27de394 100644 --- a/docs/claude/probe-readings.md +++ b/docs/claude/probe-readings.md @@ -1190,3 +1190,15 @@ The signals panel's frame read from the window: the heading and the hint the `.u the rows go in. `labels=1` is a `.ui` that lost one of the two, `list=0` one that lost the list -- both of which otherwise show as a panel quietly missing a piece. `panels: … signals=WxH row_h=26` is the other half: the list's own geometry and the height a row really takes, which is what the compact-row CSS rule is for. + +## `math panel:` + +``` +[udpscope] math panel: head=2 buttons=1 list=1 title='Math channels' +``` + +The math panel's frame read from the window: the head row the `.ui` gives it (the title and the add +button), and the list the channel rows go in. `buttons=0` is a `.ui` that lost the `+` -- a panel that +cannot add a channel, with nothing else complaining -- and `title=` is the file's own text read back, so a +`.ui` that lost the label shows as `title='-'`. `[math-probe]` is the other half of the reading: it drives +the add and the editor through the same code a user does. diff --git a/src/ui.cpp b/src/ui.cpp index 938c412..eb525da 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -5423,6 +5423,24 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit } std::printf("[udpscope] signals panel: labels=%d list=%d\n", labels, lists); } + { + // The math panel's frame, read from the window: the head row with the title and the add button, and the + // list. `buttons=0` is a `.ui` that lost the `+` -- otherwise a panel that cannot add anything, with + // nothing else complaining -- and the title is read out to show the file's own text arrived. + GtkWidget* panel = app.math_list != nullptr ? gtk_widget_get_parent(app.math_list) : nullptr; + GtkWidget* head = panel != nullptr ? gtk_widget_get_first_child(panel) : nullptr; + GtkWidget* title = head != nullptr ? gtk_widget_get_first_child(head) : nullptr; + int head_children = 0; + int buttons = 0; + for (GtkWidget* c = head != nullptr ? gtk_widget_get_first_child(head) : nullptr; c != nullptr; + c = gtk_widget_get_next_sibling(c)) { + ++head_children; + if (GTK_IS_BUTTON(c)) ++buttons; + } + std::printf("[udpscope] math panel: head=%d buttons=%d list=%d title='%s'\n", head_children, + buttons, app.math_list != nullptr ? 1 : 0, + GTK_IS_LABEL(title) ? gtk_label_get_text(GTK_LABEL(title)) : "-"); + } std::printf("[udpscope] panels: side=%dx%d (visible=%d) signals=%dx%d row_h=%d " "(revealed=%d) trigger=%dx%d (revealed=%d) toggles=%d cursors=%d window=%.3fs " "window_cap=%.1fs\n", diff --git a/src/ui/math-panel.ui b/src/ui/math-panel.ui new file mode 100644 index 0000000..9738111 --- /dev/null +++ b/src/ui/math-panel.ui @@ -0,0 +1,49 @@ + + + + + + + vertical + 4 + 6 + 6 + 6 + 6 + + + horizontal + 8 + + + Math channels + start + 1 + + + + + list-add-symbolic + flat + add a math channel + + + + + + + vertical + 2 + + + + diff --git a/src/ui/udpscope-ui.gresource.xml b/src/ui/udpscope-ui.gresource.xml index f40c8e0..b55de40 100644 --- a/src/ui/udpscope-ui.gresource.xml +++ b/src/ui/udpscope-ui.gresource.xml @@ -17,6 +17,7 @@ main-window.ui cursors-panel.ui measures-panel.ui + math-panel.ui trigger-panel.ui signals-panel.ui diff --git a/src/ui_math.cpp b/src/ui_math.cpp index 87d9cbb..02e7422 100644 --- a/src/ui_math.cpp +++ b/src/ui_math.cpp @@ -1033,29 +1033,22 @@ GtkWidget* math_row(const char* label, GtkWidget* widget, GtkWidget** row_out) { } GtkWidget* build_math_panel(App& app) { - GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); - gtk_widget_set_margin_top(box, 6); - gtk_widget_set_margin_bottom(box, 6); - gtk_widget_set_margin_start(box, 6); - gtk_widget_set_margin_end(box, 6); - - GtkWidget* head = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - GtkWidget* title = gtk_label_new("Math channels"); - gtk_widget_set_halign(title, GTK_ALIGN_START); - gtk_widget_set_hexpand(title, true); - gtk_box_append(GTK_BOX(head), title); - GtkWidget* add = gtk_button_new_from_icon_name("list-add-symbolic"); - gtk_widget_add_css_class(add, "flat"); - gtk_widget_set_tooltip_text(add, "add a math channel"); + // The panel's frame -- the heading row with its add button, and the list -- is a UI file; the rows are + // not, because each one is a channel and the whole list is rebuilt whenever the set changes. `make test-ui` + // checks the file's types against the GIR; the ids below are what keeps the code and the file agreeing. + GtkBuilder* ui = ui_load(app, "/org/udpscope/ui/math-panel.ui"); + GtkWidget* box = GTK_WIDGET(gtk_builder_get_object(ui, "math_panel")); + GtkWidget* add = GTK_WIDGET(gtk_builder_get_object(ui, "math_add")); + app.math_list = GTK_WIDGET(gtk_builder_get_object(ui, "math_list")); + if (box == nullptr || add == nullptr || app.math_list == nullptr) { + // A missing id is a mistake in the `.ui`: the panel comes up empty rather than taking the window with + // it, and `[udpscope] math panel:` reads the difference. + return box != nullptr ? box : gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); + } g_signal_connect(add, "clicked", G_CALLBACK(+[](GtkButton*, gpointer user) { add_math_channel(*static_cast(user)); }), &app); - gtk_box_append(GTK_BOX(head), add); - gtk_box_append(GTK_BOX(box), head); - - app.math_list = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2); - gtk_box_append(GTK_BOX(box), app.math_list); return box; }