Offer the lens profile as a tick box, since applying it silently reads as absent
The develop panel's Optics group is three manual sliders: distortion, chromatic aberration and lens vignetting. The automatic correction was already there — the file's EXIF lens is matched against the bundled Lensfun database on open and the coefficients are fanned out to all three — but nothing in the interface said so except a line of grey text under the camera reading "· corrected", and there was no way to decline it. From the outside that is indistinguishable from the feature not existing, which is how it was read. `dr-lens` states the rule this breaks: an automatic correction that silently does nothing is worse than one the user can see is unavailable. The caption satisfied the letter of it and not the point — a photographer looking for "apply the lens profile" found three sliders and no switch. So the profile is now a control. It is a capability rather than a flag on the session, because everything a photographer sets travels one road: the capability list feeds the generated panel, `Preset` captures it, the sidecar stores it and the undo stack replays it. A bool on the side would have needed adding to each of those four by hand and would have been forgotten in at least one — which is exactly how the mask stack came to be missing from the history. It is on by default, which is what `switch_on` is for: the coefficients are a measurement of the lens that took the photograph, so accepting them is neutral and declining them is the edit. The sidecar therefore stores nothing for the ordinary case and the correction still happens. The switch appears only where a profile was matched. A tick box on a photograph whose lens the database has never heard of would be a control that looks available and does nothing, which is the failure the rule above names rather than an instance of following it — those photographs are told "· no profile" in words instead, and one whose box is unticked now says "· profile off", which is a third fact and not either of the other two. Two things had to be built underneath. `ParamKind::Bool` was in the core's closed enum and mapped to a row kind here, and had no control behind it in `adjust.slint`: a parameter declaring itself a switch was flattened into a row that drew nothing at all. Nothing shipped had one until now, so the gap cost nothing and was invisible. And `Check` self-toggled, which is right for a settings page that owns its value and wrong for a panel row that is a view of the edit graph — the click would have answered by replacing the binding with a literal, and the next undo or pasted preset would have moved the value with the tick left where the finger put it. It now takes `controlled`, and the generated row uses it. The manual sliders are unchanged and still trim whatever the profile leaves, so switching it off is "correct this by hand" rather than "stop correcting".
This commit is contained in:
@@ -432,9 +432,35 @@ export component Check inherits Rectangle {
|
||||
/// switches makes the user guess at what each one costs.
|
||||
in property <string> hint;
|
||||
in-out property <bool> checked;
|
||||
/// Whether the tick is decided here or by whoever supplied `checked`.
|
||||
///
|
||||
/// A settings page and a generated panel want opposite things, and the
|
||||
/// difference is not cosmetic. A page owns its switches: ticking one is
|
||||
/// the whole event, and the box flipping under the finger is the feedback.
|
||||
/// A panel row is a *view of a model* — the value lives in the edit graph,
|
||||
/// the same graph an undo step or a pasted preset can move — so a box that
|
||||
/// set its own state would answer the click with a binding replaced by a
|
||||
/// literal, and the next time the value changed from anywhere else the
|
||||
/// tick would stay where the finger left it.
|
||||
///
|
||||
/// Controlled, the click is reported and nothing else happens; the tick
|
||||
/// follows `checked`, which is what it was always drawing.
|
||||
in property <bool> controlled: false;
|
||||
|
||||
callback toggled(bool);
|
||||
|
||||
// One toggle, called from the pointer and from the accessibility action
|
||||
// alike, so the two cannot drift — the keyboard route had already been
|
||||
// written twice.
|
||||
function toggle() {
|
||||
if (root.controlled) {
|
||||
root.toggled(!root.checked);
|
||||
} else {
|
||||
root.checked = !root.checked;
|
||||
root.toggled(root.checked);
|
||||
}
|
||||
}
|
||||
|
||||
// The hint becomes the description rather than part of the name. It exists
|
||||
// to say what a setting *costs* — "location is stripped", "upscaling is
|
||||
// off" — which is the second thing a reader wants and never the first, and
|
||||
@@ -445,10 +471,7 @@ export component Check inherits Rectangle {
|
||||
accessible-description: root.hint;
|
||||
accessible-checkable: true;
|
||||
accessible-checked: root.checked;
|
||||
accessible-action-default => {
|
||||
root.checked = !root.checked;
|
||||
root.toggled(root.checked);
|
||||
}
|
||||
accessible-action-default => { root.toggle(); }
|
||||
|
||||
height: max(row.preferred-height, Theme.control-height);
|
||||
|
||||
@@ -458,10 +481,7 @@ export component Check inherits Rectangle {
|
||||
height: max(parent.height, Theme.touch-target);
|
||||
y: (parent.height - self.height) / 2;
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.checked = !root.checked;
|
||||
root.toggled(root.checked);
|
||||
}
|
||||
clicked => { root.toggle(); }
|
||||
}
|
||||
|
||||
row := HorizontalLayout {
|
||||
|
||||
Reference in New Issue
Block a user