diff --git a/src/ui_signal_page.cpp b/src/ui_signal_page.cpp index 529cd0e..7643b6e 100644 --- a/src/ui_signal_page.cpp +++ b/src/ui_signal_page.cpp @@ -66,6 +66,18 @@ std::size_t tagged(GtkButton* b) { return static_cast(GPOINTER_TO_SIZE(g_object_get_data(G_OBJECT(b), "udpscope-signal"))); } +/// The wire types and quantisations the CONFIG names (`UDPS_T_*`, `UDPS_QUANT_*`; every source fills the same +/// codes). A code outside the table is shown as the number, not guessed at. +std::string type_name(unsigned code) { + static const char* const names[] = {"uint8", "int8", "uint16", "int16", "uint32", + "int32", "uint64", "int64", "float32", "float64"}; + return code < 10 ? names[code] : "unknown (" + std::to_string(code) + ")"; +} +std::string quant_name(unsigned code) { + static const char* const names[] = {"none", "uint8", "int8", "uint16", "int16"}; + return code < 5 ? names[code] : "unknown (" + std::to_string(code) + ")"; +} + /// One row of the details grid: the name left, the value right-aligned in tabular figures, the value's /// unit in a column of its own (so the digits line up whatever the unit is), and, for a value the user can /// change, a pencil that edits just that one. @@ -100,8 +112,8 @@ GtkWidget* build_info_grid(App& app, std::size_t index, const SignalInfo& sig, {"Offset:", format_calibration(cal.second), sig.unit, "udpscope-offset", "edit the offset, applied at ingest", 2}, - {"Type:", std::to_string(int(sig.type_code)), "", nullptr, nullptr, -1}, - {"Quantisation:", std::to_string(int(sig.quant_type)), "", nullptr, nullptr, -1}, + {"Type:", type_name(sig.type_code), "", nullptr, nullptr, -1}, + {"Quantisation:", quant_name(sig.quant_type), "", nullptr, nullptr, -1}, {"Size:", size, "", nullptr, nullptr, -1}, {"Range:", format_calibration(sig.range_min) + " .. " + format_calibration(sig.range_max), sig.unit, nullptr, nullptr, -1}, @@ -119,20 +131,25 @@ GtkWidget* build_info_grid(App& app, std::size_t index, const SignalInfo& sig, GtkWidget* name_label = gtk_label_new(row.label); gtk_widget_set_halign(name_label, GTK_ALIGN_START); gtk_grid_attach(GTK_GRID(grid), name_label, 0, r, 1, 1); + // An editable value sits against its label with the pencil right after it; a read-only one is pushed to + // the right edge, so the two kinds read as two columns. + const bool editable = row.edit >= 0; + GtkWidget* cell = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); + gtk_widget_set_hexpand(cell, true); + gtk_widget_set_halign(cell, editable ? GTK_ALIGN_START : GTK_ALIGN_END); GtkWidget* value = gtk_label_new(row.value.c_str()); gtk_widget_add_css_class(value, "numeric"); if (row.id != nullptr) gtk_widget_set_name(value, row.id); - gtk_label_set_xalign(GTK_LABEL(value), 1.0f); - gtk_label_set_width_chars(GTK_LABEL(value), 14); - gtk_widget_set_hexpand(value, true); - gtk_widget_set_halign(value, GTK_ALIGN_END); - gtk_grid_attach(GTK_GRID(grid), value, 1, r, 1, 1); - GtkWidget* unit = gtk_label_new(row.unit.c_str()); - gtk_widget_add_css_class(unit, "dim-label"); - gtk_label_set_xalign(GTK_LABEL(unit), 0.0f); - gtk_label_set_width_chars(GTK_LABEL(unit), 4); - gtk_label_set_ellipsize(GTK_LABEL(unit), PANGO_ELLIPSIZE_END); - gtk_grid_attach(GTK_GRID(grid), unit, 2, r, 1, 1); + gtk_label_set_xalign(GTK_LABEL(value), editable ? 0.0f : 1.0f); + gtk_label_set_wrap(GTK_LABEL(value), !editable); + gtk_box_append(GTK_BOX(cell), value); + if (!row.unit.empty()) { + GtkWidget* unit = gtk_label_new(row.unit.c_str()); + gtk_widget_add_css_class(unit, "dim-label"); + gtk_label_set_ellipsize(GTK_LABEL(unit), PANGO_ELLIPSIZE_END); + gtk_box_append(GTK_BOX(cell), unit); + } + gtk_grid_attach(GTK_GRID(grid), cell, 1, r, 1, 1); if (row.edit >= 0) { GtkWidget* edit = gtk_button_new_from_icon_name("document-edit-symbolic"); gtk_widget_add_css_class(edit, "flat"); @@ -151,7 +168,7 @@ GtkWidget* build_info_grid(App& app, std::size_t index, const SignalInfo& sig, } }), &app); - gtk_grid_attach(GTK_GRID(grid), edit, 3, r, 1, 1); + gtk_box_append(GTK_BOX(cell), edit); } ++r; } @@ -558,11 +575,9 @@ gboolean signal_page_probe(gpointer user) { return std::string(gtk_widget_get_name(w)) == "udpscope-calibration"; }); int seen = 0; - for (GtkWidget* c = grid == nullptr ? nullptr : gtk_widget_get_first_child(grid); c != nullptr; - c = gtk_widget_get_next_sibling(c)) { - if (GTK_IS_BUTTON(c) && gtk_button_get_icon_name(GTK_BUTTON(c)) != nullptr && seen++ == n) return c; - } - return nullptr; + return grid == nullptr ? nullptr : find_descendant(grid, [&](GtkWidget* c) { + return GTK_IS_BUTTON(c) && gtk_button_get_icon_name(GTK_BUTTON(c)) != nullptr && seen++ == n; + }); }; // Click pencil `n`, find the dialog titled `title`, set its `Spin`/`Entry`, press Apply. Returns the number // of editing widgets the dialog had, or -1 when there was no dialog.