fix: a fit undoes an x zoom instead of redefining the time window
The previous commit took "fit x sets the window properly" to mean a fit should frame the data and propagate that as the new time scale. It should not: a fit is a plot interaction, and the window is also the trigger's event span and how the samples are stored, so a fit that framed the data could re-plan the rings and drop the history on a menu click. What a fit means here is the undo of a zoom -- a 2 s window zoomed into reads 2 s again. `fit_x()` therefore reads `window_s_` and never writes it. Live it takes the window-control path with the window already set, which re-arms the follow and parks the newest span at the live edge. Pinned -- a held event, a filling capture or a paused view -- it restores the pin's full range, which is the snapshot's own span and may be narrower than the requested window, and it writes the per-row member axes as well as the link group: `hold_pinned_window()` prefers a member that differs from `pinned_stated_`, so writing the group alone is reverted to the zoomed range one frame later. `apply_window_scale()` is folded back into `apply_time_window()`, which the window control is again the only caller of. The probe now zooms in before fitting, since otherwise there is nothing to undo, and reports `pinned=`. `window` and `event_span` must be unchanged on every line. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
9888fd9977
commit
3d7e214295
7 files changed
+193
-150
No files matched your search
+24
-23
@@ -657,24 +657,27 @@ void RowSet::unpin_pause_window() {
|
||||
set_time_window(window_s_);
|
||||
}
|
||||
|
||||
bool RowSet::fit_x(double& span) {
|
||||
Row& first = row(0);
|
||||
if (!first.plot || !figure_) return false;
|
||||
first.plot->auto_fit_x();
|
||||
const plot::Range fitted = first.plot->x_range(first.axis_x);
|
||||
const double fitted_span = fitted.span();
|
||||
if (!std::isfinite(fitted_span) || !(fitted_span > 0.0)) return false;
|
||||
if (pinned_) {
|
||||
// Fitting a captured or paused view: the window is the snapshot's own span, and
|
||||
// `set_time_window()` would re-arm the follow and re-frame on a live edge that a frozen
|
||||
// view has nothing bound to.
|
||||
window_s_ = fitted_span;
|
||||
figure_->set_x_link_range(x_group_, fitted);
|
||||
} else {
|
||||
set_time_window(fitted_span);
|
||||
void RowSet::fit_x() {
|
||||
if (!figure_) return;
|
||||
if (!pinned_) {
|
||||
// Live: the same path the window control and a resume take, with the window it already has.
|
||||
// That re-arms the follow and parks the newest `window_s_` at the live edge, which is the
|
||||
// whole of what a live view may show.
|
||||
set_time_window(window_s_);
|
||||
return;
|
||||
}
|
||||
span = window_s_;
|
||||
return true;
|
||||
// Pinned (a held event or a paused view): the pin's full range, and the pin stays. The
|
||||
// *members* have to be written as well as the group, because `hold_pinned_window()` prefers a
|
||||
// member that has moved since our own last statement -- that is how it tells a gesture from its
|
||||
// own echo -- so writing the group alone would be reverted to the zoomed-in member next frame.
|
||||
const plot::Range pin{-pinned_pre_, pinned_post_};
|
||||
if (!(pin.span() > 0.0) || !std::isfinite(pin.min) || !std::isfinite(pin.max)) return;
|
||||
for (int i = 0; i < rows_; ++i) {
|
||||
Row& r = row(i);
|
||||
if (r.plot) r.plot->set_x_range(r.axis_x, pin);
|
||||
}
|
||||
pinned_stated_ = pin;
|
||||
figure_->set_x_link_range(x_group_, pin);
|
||||
}
|
||||
|
||||
void RowSet::sync_cursors(int drag_row) {
|
||||
@@ -788,16 +791,14 @@ void RowSet::pin_event_window(double pre_s, double post_s) {
|
||||
figure_->set_x_link_range(x_group_, {-pre_s, post_s});
|
||||
}
|
||||
|
||||
bool RowSet::fit_all(double& span) {
|
||||
void RowSet::fit_all() {
|
||||
for (int i = 0; i < rows_; ++i) {
|
||||
Row& r = row(i);
|
||||
if (r.plot) r.plot->auto_fit_y(r.axis_y);
|
||||
}
|
||||
// The x half is `fit_x()`'s exactly -- row 0's data span, stated through the link group so
|
||||
// every row lands on it -- and sharing it is what keeps the two fits from drifting apart.
|
||||
// The y fit above has already happened either way: a row 0 that holds nothing still gets
|
||||
// every row's y scaled, it just has no span to report.
|
||||
return fit_x(span);
|
||||
// The x half is `fit_x()`'s exactly -- the zoom undone, the time window untouched -- and
|
||||
// sharing it is what keeps the two fits from drifting apart.
|
||||
fit_x();
|
||||
}
|
||||
|
||||
void RowSet::note_y_gutter(double need_px) {
|
||||
|
||||
Reference in new issue
Block a user