scope windows: mirror a pin as a range, and restore the tick rebuild
**The blank scope window in trigger mode.** A held event pins the main window to `[-pre, +post]`, and the tick mirrors that pin onto every scope window. It passed `pinned_range().min/max` to `pin_event_window()`, which takes **spans** (`pre, post`): `min` is signed, so `pre` came out negative and the group range became `[+pre, +post]` — an inverted x window. The plotter then had nothing to draw: no trace, no x-axis labels, an empty plot that looked like a broken window. `RowSet::pin_display_range(x0, x1)` states the pin as the range a mirroring view actually has, and the tick uses it; live mode was never affected, which is why the defect only showed under the trigger. Also restores the scope-window `rebuild_if_dirty()` in the tick, which a reproduction experiment had left commented out (`REPRO-TEMP`) and a later commit carried: a window opened empty and filled by a drop kept the figure it was built with. Probe: `[scope-probe] pin_mirror=1 main=[..] scope=[..] x=[..]` pins the main window, reads the scope's pin and plot x range a frame later, and reads `0` for an inverted or mismatched pin. Docs: probe readings and the trigger/pinning invariant (range vs spans).
This commit is contained in:
1 parent
2279e2140a
commit
ecdbf4f0e1
6 files changed
+75
-9
No files matched your search
+12
-6
@@ -4633,17 +4633,23 @@ gboolean tick(gpointer user) {
|
||||
const double window_s = app->rows->time_window();
|
||||
for (const std::unique_ptr<App::ScopeWindow>& scope : app->scopes) {
|
||||
if (pinned) {
|
||||
scope->rows->pin_event_window(pin.min, pin.max);
|
||||
// The pin as a *range*: `pin_event_window()` takes spans (pre, post), and handing it
|
||||
// `pin.min` -- a signed time -- inverted the window, so a scope in Held or Paused mode
|
||||
// drew no trace and no x labels at all.
|
||||
scope->rows->pin_display_range(pin.min, pin.max);
|
||||
} else if (std::fabs(scope->rows->time_window() - window_s) > 1.0e-12) {
|
||||
scope->rows->set_time_window(window_s);
|
||||
}
|
||||
// An arrangement change (a drop, a *Plot on* button) rebuilt the row set: point the area at
|
||||
// the new figure here, in the tick -- the change arrives from inside this very widget (a drop
|
||||
// signal), and a synchronous rebuild would reset the drag controller under it.
|
||||
// REPRO-TEMP: rebuild disabled
|
||||
// if (scope->rows->rebuild_if_dirty() && scope->area != nullptr) {
|
||||
// scope->area->set_figure(&scope->rows->figure());
|
||||
// }
|
||||
// signal), and a synchronous rebuild would reset the drag controller under it. The traces
|
||||
// themselves are `SlotSeries` rebinds, so a slot that gains or loses a source draws either
|
||||
// way; what *does* need this is the figure's own state: a row's legend, its cell structure,
|
||||
// and the trace objects `install()` creates only for the slots that hold a signal at rebuild
|
||||
// time -- a window opened empty and filled by a drop has none until this runs.
|
||||
if (scope->rows->rebuild_if_dirty() && scope->area != nullptr) {
|
||||
scope->area->set_figure(&scope->rows->figure());
|
||||
}
|
||||
if (scope->detached) sync_scope_attach(*app, *scope);
|
||||
// **A window that cannot paint says so.** A blank plot is indistinguishable from a
|
||||
// context that failed or an area that never got a frame, and the report ("nothing is
|
||||
|
||||
Reference in new issue
Block a user