Put the adjustment groups in the rail where a finger is driving
Reported from the tablet: the tool rail is very useful there, and the same interface under a mouse and keyboard is not. That is `ui-navigation.md` D-N2's central assumption failing in use, and the interesting part is which half of it failed. D-N2 was right that platform is the wrong axis and width is the wrong axis: a tablet in landscape wants what a desktop wants, and a desktop window dragged narrow wants what a small screen wants. `apply_layout_class` still decides the layout class from the window and nothing here changes that. What D-N2 got wrong is the sentence "touch changes hit regions, not layout" — it identified input as the real difference between the targets and then assumed that difference could never reach the layout. Two controls answer one question — which group of adjustments am I looking at — and neither is better in general. A horizontal strip above the column is one gesture to a target the eye has already found, and it pans when the operation set is rich, so a group can sit off the end with nothing saying so: a pointer user tolerates that, a finger user never discovers it. The same list down the rail is every entry visible at once, each finger-sized, on the edge of the screen the hand is already holding, and it costs no width because the rail is already there. So `ToolRail` grows a second section, and `GroupStrip` stands down when it does. The two are never both on screen, which is why they can share `adjust-tab-picked`: Rust is not told which was pressed and has no reason to want to. Mode and group stay independent axes as N1 requires — one entry lit in each section, and choosing a group while a tool is held still filters without putting the tool down. They stay drawn differently, which N1 also required. The tools fill with `active-dim` and invert their ink; the groups take a bar down the leading edge — the strip's underline turned ninety degrees — so a lit entry says which kind of state it is without the reader having to remember which section it was in. The rule between the sections is the second signal. The rail scrolls now. Its own note argued against a Flickable because "this list is four entries written in this file"; with the groups in it the list comes from the operation set, which is exactly the "something the user's data decides" that note excluded this control from. The axis is input, and it is a preference because the automatic answer is a guess that cannot be made reliable. Neither platform can be asked what the user is holding: an Android tablet in a keyboard case is being driven like a desktop, and a touchscreen laptop is whichever its owner says. `dr_plat::is_touch_first` reports the usual case per platform, and `GroupNavigation` lets it be overridden. Settings names what Automatic resolves to on this device rather than leaving it to be found by pressing. D-N6 records the reversal beside the decision it reverses, including the half that still stands and the question it opens: whether Local is a mode at all, or a scope that would collapse the two sections into one list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -101,8 +101,16 @@ export component SettingsPage inherits Rectangle {
|
||||
/// TRACES: FR-DEV-6
|
||||
/// Which kinds of edit a copy or preset carries. Supersedes the boolean
|
||||
/// above, which named only the one kind anybody wanted to exclude.
|
||||
/// TRACES: FR-UI-1
|
||||
/// Where the develop view's adjustment groups are chosen from.
|
||||
in property <[string]> group-nav-labels;
|
||||
in property <int> group-nav-selected: 0;
|
||||
/// What "Automatic" resolves to on this device, so the caption can say it
|
||||
/// rather than leaving the photographer to press it and find out.
|
||||
in property <string> group-nav-auto-says;
|
||||
in property <[ScopeKind]> copy-scope-kinds;
|
||||
in property <bool> copy-scope-empty: false;
|
||||
callback group-nav-picked(int);
|
||||
callback copy-scope-toggled(string);
|
||||
/// What the cache currently holds. Empty hides the line.
|
||||
in property <string> cache-usage;
|
||||
@@ -554,6 +562,36 @@ export component SettingsPage inherits Rectangle {
|
||||
|
||||
PanelHeading { text: "DEVELOP"; }
|
||||
|
||||
// TRACES: FR-UI-1 | FR-UI-7
|
||||
// Where the adjustment groups are chosen from.
|
||||
//
|
||||
// A preference rather than a fixed rule because the
|
||||
// automatic answer is a guess and cannot be otherwise.
|
||||
// Neither platform can be asked what the user is
|
||||
// actually holding: an Android tablet in a keyboard
|
||||
// case is being driven like a desktop, and a
|
||||
// touchscreen laptop is whichever its owner says. The
|
||||
// guess is right often enough to be the default and
|
||||
// wrong often enough to need a way out.
|
||||
VerticalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
Segmented {
|
||||
label: "Adjustment groups";
|
||||
options: root.group-nav-labels;
|
||||
selected: root.group-nav-selected;
|
||||
picked(i) => { root.group-nav-picked(i); }
|
||||
}
|
||||
|
||||
Caption {
|
||||
text: "Down the tool rail, or in a strip above "
|
||||
+ "the panel. Automatic follows how this "
|
||||
+ "device is driven — here, "
|
||||
+ root.group-nav-auto-says + ".";
|
||||
wrap: word-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
// TRACES: FR-DEV-6
|
||||
// Which kinds of edit a copy, a paste or a preset
|
||||
// carries.
|
||||
|
||||
Reference in New Issue
Block a user