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:
+59
-13
@@ -365,10 +365,17 @@ component ParamControl inherits Rectangle {
|
||||
in property <ParamRow> data;
|
||||
/// Curve rows only; ignored by every other kind.
|
||||
in property <[float]> curve-samples;
|
||||
/// The curves this widget can plot, named. Empty, or one entry, where
|
||||
/// there is nothing to choose between — see `curve-channel-picked`.
|
||||
in property <[string]> curve-channels;
|
||||
/// Which of `curve-channels` is on the grid.
|
||||
in property <int> curve-channel;
|
||||
|
||||
callback param-changed(int, int, float);
|
||||
callback param-reset(int, int);
|
||||
callback curve-reset(int);
|
||||
/// Plot a different one of the operation's curves.
|
||||
callback curve-channel-picked(int);
|
||||
callback drag-changed(bool);
|
||||
|
||||
height: layout.preferred-height;
|
||||
@@ -420,20 +427,49 @@ component ParamControl inherits Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
if root.data.kind == "curve": CurveEditor {
|
||||
points: root.data.points;
|
||||
samples: root.curve-samples;
|
||||
drag-changed(on) => { root.drag-changed(on); }
|
||||
// A point carries two parameters, so the parameter index is the
|
||||
// row's base plus the point's offset. This component still knows
|
||||
// nothing about which operation it belongs to.
|
||||
point-moved(point, x, y) => {
|
||||
root.param-changed(
|
||||
root.data.op-index, root.data.param-index + point * 2, x);
|
||||
root.param-changed(
|
||||
root.data.op-index, root.data.param-index + point * 2 + 1, y);
|
||||
// A curve, and — where the operation offers more than one — the choice
|
||||
// of which curve is on the grid.
|
||||
//
|
||||
// One plot rather than four stacked ones: the curves are read against
|
||||
// the diagonal and against each other, which needs the grid large, and
|
||||
// four grids at a quarter of the width would each be too small to
|
||||
// place a point in. So the selector switches the subject of a single
|
||||
// plot, and the names in it come from the core — this file does not
|
||||
// know that a colour channel is what is being chosen between, only
|
||||
// that the widget said it spans several named things.
|
||||
if root.data.kind == "curve": VerticalLayout {
|
||||
spacing: Theme.gap-sm;
|
||||
|
||||
if root.curve-channels.length > 1: Segmented {
|
||||
// The operation's own name, which nothing else in this row
|
||||
// draws: a curve row heads no group, so without this the plot
|
||||
// would sit in the panel unlabelled.
|
||||
label: root.data.op-label;
|
||||
options: root.curve-channels;
|
||||
selected: root.curve-channel;
|
||||
picked(i) => { root.curve-channel-picked(i); }
|
||||
}
|
||||
|
||||
CurveEditor {
|
||||
points: root.data.points;
|
||||
samples: root.curve-samples;
|
||||
drag-changed(on) => { root.drag-changed(on); }
|
||||
// A point carries two parameters, so the parameter index is
|
||||
// the row's base plus the point's offset. The base is the
|
||||
// first point of the curve *on show*, so switching curve
|
||||
// re-points the drag and this component still knows nothing
|
||||
// about which operation — or which curve — it is drawing.
|
||||
point-moved(point, x, y) => {
|
||||
root.param-changed(
|
||||
root.data.op-index, root.data.param-index + point * 2, x);
|
||||
root.param-changed(
|
||||
root.data.op-index, root.data.param-index + point * 2 + 1, y);
|
||||
}
|
||||
// Resetting a curve resets the operation, which is all four of
|
||||
// them — a photographer who double-clicks to start again means
|
||||
// the control, not the curve that happens to be on show.
|
||||
reset => { root.curve-reset(root.data.op-index); }
|
||||
}
|
||||
reset => { root.curve-reset(root.data.op-index); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -710,9 +746,16 @@ export component AdjustPanel inherits Rectangle {
|
||||
/// The tone curve's sampled shape, evaluated in Rust by the same spline
|
||||
/// the shader runs so the drawn line cannot disagree with the applied one.
|
||||
in property <[float]> curve-samples;
|
||||
/// The curves the tone curve widget can plot, named by the core. Fewer
|
||||
/// than two of them means there is nothing to choose and no selector.
|
||||
in property <[string]> curve-channels;
|
||||
/// Which of them `curve-samples` and the row's points describe.
|
||||
in property <int> curve-channel;
|
||||
callback param-changed(int, int, float);
|
||||
callback param-reset(int, int);
|
||||
callback curve-reset(int);
|
||||
/// Plot a different one of the curve's curves.
|
||||
callback curve-channel-picked(int);
|
||||
/// Return every parameter of one operation to its default — the reset on
|
||||
/// a section's own header, beside the panel-wide one.
|
||||
callback op-reset(int);
|
||||
@@ -861,12 +904,15 @@ export component AdjustPanel inherits Rectangle {
|
||||
ParamControl {
|
||||
data: row;
|
||||
curve-samples: root.curve-samples;
|
||||
curve-channels: root.curve-channels;
|
||||
curve-channel: root.curve-channel;
|
||||
drag-changed(on) => { root.slider-dragging = on; }
|
||||
param-changed(op, param, v) => {
|
||||
root.param-changed(op, param, v);
|
||||
}
|
||||
param-reset(op, param) => { root.param-reset(op, param); }
|
||||
curve-reset(op) => { root.curve-reset(op); }
|
||||
curve-channel-picked(i) => { root.curve-channel-picked(i); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user