scope: full-screen figures, second windows, gated measurements, per-configuration events
A batch of view and instrument work, with the probes and docs for each. - **Full screen per figure row**: a toggle on each row's top-right corner, revealed by pointer proximity (`kMaximizeRevealPx` around its placed rect, per row, read from an overlay-level motion controller so a revealed button under the pointer cannot flicker); the plot menu offers the same as *Full screen this figure* / *Restore the layout*. The arrangement is saved and restored through `RowState`, so nothing plotted moves. A layout of one figure carries no toggle. - **Second window**: `open_scope_window()` copies a figure (cells, width shares, signals in their colours) or opens an empty one, with its own `RowSet` and `PlotArea`; the main window's tick binds, acquires and repaints it, mirroring the time window and pin. Entries: the plot menu's *Open this plot in a new window* and the overflow menu's *New scope window*. - **Layout editor from the plot**: the plot menu gains *Edit the layout...* / *Done editing the layout*, flipping the app's one toggle. - **Measurements gate**: `MeasureOptions::gate` restricts a measurement to the held/pause snapshot (live falls back to the live ring), persisted with the session and shown in the measure dialog. - **Crosshair axis badges**: a preference (`crosshair_axis_labels`, on by default) and the plotter's badges where the lines meet the axes, in the axes' own formats; the plot menu and the probe read them. - **Event cache per configuration**: `EventStore` is keyed `<source>/<configuration>/`, `retarget_event_store()` follows every configuration switch, and a pre-configuration cache (loose files) is adopted into the configuration's folder on first start. - **GTK4 lifecycle**: the main window's handlers move from the non-existent `"destroy"` signal to `close-request`; scope windows are closed with it and the application quits explicitly (the exit run's hang). The exit probe closes with `gtk_window_close()`. - Probes: `[maximize-probe]` (single-figure rule and the corner reveal), `[scope-probe]`, `[split-probe]` cell crosshair leg, `[prefs-probe]` store keying, `[configs]` store key, `[rowmenu]` layout-editor entry; docs, help pages, README and AGENT.md updated. Also fixes a probe-only use-after-free: `toggle_maximize_figure_row` replaces the figure object, so the area must be re-pointed (the button's path does; the probe's raw call did not).
This commit is contained in:
1 parent
bfe13630f9
commit
bdf0ff7ddc
39 files changed
+2267
-136
No files matched your search
+26
-8
@@ -10,8 +10,9 @@
|
||||
// layout does not depend on what a value reads; the full text is the label's tooltip.
|
||||
//
|
||||
// The same strings are shown a third time in the readouts strip under the plot (`readouts_strip`, one
|
||||
// fixed-height line: a "Cursors" button, one chip per cursor line with its delta, a "Measures" button, one
|
||||
// chip per measurement with its value), which is on screen whenever the dock is not beside the plot (hidden
|
||||
// fixed-height line: a "Cursors" button, one chip per cursor line with its delta, one chip per
|
||||
// measurement with its value and a `[+]` to add one), which is on screen whenever the dock is not
|
||||
// beside the plot (hidden
|
||||
// with the Dock button, or the window collapsed and the dock an overlay). The setters below
|
||||
// write the strip's labels in the same call as the dock's, from the same argument, so there is still one
|
||||
// string and no second formatter.
|
||||
@@ -148,7 +149,12 @@ void dock_cursors_header(GtkGrid* grid) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fills the strip `main-window.ui` declares: the two buttons and the two boxes the rebuilds fill.
|
||||
/// The strip's `[+]`: a new measurement, through the same dialog the pane's own `+` opens.
|
||||
void on_add_measure(GtkButton*, gpointer user) {
|
||||
open_measure_dialog(*static_cast<App*>(user), -1);
|
||||
}
|
||||
|
||||
/// Fills the strip `main-window.ui` declares: the two groups and the two boxes the rebuilds fill.
|
||||
void build_readouts_strip(App& app) {
|
||||
if (app.strip_box == nullptr) return;
|
||||
clear_box(app.strip_box);
|
||||
@@ -163,10 +169,13 @@ void build_readouts_strip(App& app) {
|
||||
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"));
|
||||
// The chips, then the `[+]` after the last one: the compact strip is where the readings are
|
||||
// watched, so that is where adding one belongs -- and it replaces the old "Measures" button,
|
||||
// which only opened the panel any chip already opens its own measurement from (the dock and
|
||||
// the page keep their Edit).
|
||||
gtk_box_append(GTK_BOX(app.strip_measure_group), app.strip_measure_box);
|
||||
gtk_box_append(GTK_BOX(app.strip_measure_group),
|
||||
strip_button("+", G_CALLBACK(on_add_measure), &app, "add a measurement"));
|
||||
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);
|
||||
@@ -274,6 +283,12 @@ void dock_rebuild_measures(App& app) {
|
||||
}
|
||||
for (std::size_t i = 0; i < app.measures.size(); ++i) {
|
||||
const Measure& m = app.measures[i];
|
||||
// The row's channel number, the same one the pane's row carries: the dock line says which
|
||||
// channel it is about with one word, and the chip beside it says which colour.
|
||||
const int number = measure_channel_number(app, m.signal);
|
||||
const std::string who =
|
||||
number > 0 ? std::to_string(number) + ". " + measure_type_name(m.type)
|
||||
: std::string(measure_type_name(m.type));
|
||||
GtkWidget* line = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
g_object_set_data(G_OBJECT(line), "udpscope-measure-index",
|
||||
GINT_TO_POINTER(static_cast<int>(i) + 1));
|
||||
@@ -281,7 +296,7 @@ void dock_rebuild_measures(App& app) {
|
||||
gtk_label_set_markup(GTK_LABEL(chip), measure_chip_markup(app, m.signal).c_str());
|
||||
gtk_widget_set_tooltip_text(chip, m.signal.c_str());
|
||||
gtk_box_append(GTK_BOX(line), chip);
|
||||
GtkWidget* kind = fixed_label(measure_type_name(m.type), 12, GTK_ALIGN_START);
|
||||
GtkWidget* kind = fixed_label(who.c_str(), 12, GTK_ALIGN_START);
|
||||
gtk_widget_set_hexpand(kind, true);
|
||||
gtk_widget_set_tooltip_text(kind, (m.signal + "\n" + measure_type_name(m.type)).c_str());
|
||||
gtk_box_append(GTK_BOX(line), kind);
|
||||
@@ -306,7 +321,10 @@ void dock_rebuild_measures(App& app) {
|
||||
gtk_label_set_markup(GTK_LABEL(schip), measure_chip_markup(app, m.signal).c_str());
|
||||
gtk_widget_set_tooltip_text(schip, m.signal.c_str());
|
||||
gtk_box_append(GTK_BOX(sline), schip);
|
||||
GtkWidget* skind = fixed_label(measure_type_name(m.type), kStripTypeChars, GTK_ALIGN_START);
|
||||
const std::string swho =
|
||||
number > 0 ? std::to_string(number) + ". " + measure_type_name(m.type)
|
||||
: std::string(measure_type_name(m.type));
|
||||
GtkWidget* skind = fixed_label(swho.c_str(), kStripTypeChars, GTK_ALIGN_START);
|
||||
gtk_widget_set_tooltip_text(skind, (m.signal + "\n" + measure_type_name(m.type)).c_str());
|
||||
gtk_box_append(GTK_BOX(sline), skind);
|
||||
GtkWidget* svalue = fixed_label("--", kValueChars, GTK_ALIGN_END);
|
||||
|
||||
Reference in new issue
Block a user