Let the curve widget plot whichever curve is asked for

An operation with four curves and a panel that draws one plot needs a way to
say which. The panel finds out the way it finds out everything else: the
points are faceted with the subject they act on, consecutive parameters
sharing a subject are one curve, and a widget spanning several of them gets
a selector over their names. Nothing in ui/ contains the word "red", and an
operation that grows a fifth curve arrives with a fifth chip.

The names ride on the panel rather than on the curve's row, because a Slint
model is compared by identity: a fresh list built on every parameter event
would make the row look changed every time, and rewriting a row rebuilds the
element holding the drag in progress. That is the hazard the in-place point
update already exists to avoid.

Which curve is on show is interface state, not an edit. It changes no pixel,
so it takes no history step, reaches no sidecar, and redraws nothing — the
photograph on screen is already right.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-22 16:06:21 +02:00
co-authored by Claude Opus 5
parent d64a61d677
commit 13d003b89d
5 changed files with 468 additions and 59 deletions
+34
View File
@@ -581,8 +581,24 @@ pub(crate) fn sync_rows(
// curve must be drawn whatever shape it is in.
rows.set_vec(current);
curve_moved = true;
// The curves the widget can switch between, named. They can only
// change with the operation set, which is what this branch means, so
// the walk that derives them is not on the parameter-event path.
let channels: Vec<slint::SharedString> = match session.borrow().as_ref() {
Some(s) => s.curve_channels().into_iter().map(Into::into).collect(),
None => Vec::new(),
};
window.set_curve_channels(slint::ModelRc::new(slint::VecModel::from(channels)));
}
// Which curve is plotted, on every pass. Picking one that happens to be
// shaped like the last — two untouched curves are both the diagonal —
// moves no point, so this cannot ride on the resample below: the chips
// would go on highlighting the curve the user just navigated away from.
let channel = session.borrow().as_ref().map_or(0, |s| s.curve_channel());
window.set_curve_channel(channel);
if !curve_moved {
return;
}
@@ -1802,6 +1818,24 @@ pub fn run(paths: Vec<PathBuf>) -> Result<()> {
redraw(&w);
});
}
{
// Which of the curve's curves the plot is showing. **No redraw**, and
// that is the whole character of this control: it changes no
// parameter, so the photograph is already correct on screen and
// recomputing it would be a frame spent to produce the same pixels.
// For the same reason it records no history step — there is nothing
// to undo — and the sidecar never hears about it.
let weak = window.as_weak();
let session = session.clone();
let rows = rows.clone();
window.on_curve_channel_picked(move |index| {
let Some(w) = weak.upgrade() else { return };
if let Some(s) = session.borrow_mut().as_mut() {
s.set_curve_channel(index);
}
sync_rows(&w, &rows, &session);
});
}
// ---- undo and redo (FR-DEV-5) ---------------------------------------
//