diff --git a/docs/gestures.md b/docs/gestures.md index 06d4f85..cbb5f00 100644 --- a/docs/gestures.md +++ b/docs/gestures.md @@ -53,8 +53,8 @@ A model's mask stops inside a shoulder and leaks into the hair, and no single ed ### Open this list -- **Touch** — Press Help in the top bar, and Done to put it away -- **Pointer** — Press Help in the top bar, and Done to put it away +- **Touch** — Press "?" in the top bar, beside Settings, and Done to put it away +- **Pointer** — Press "?" in the top bar, beside Settings, and Done to put it away - **Keyboard** — `F1`; the key that closes any sheet puts it away Most of the keys are develop's, and a reference that could only be opened from the grid had to be looked up before opening the photograph they were wanted for. diff --git a/ui/dr-ui/src/gesture_book.rs b/ui/dr-ui/src/gesture_book.rs index 01b8077..7bea276 100644 --- a/ui/dr-ui/src/gesture_book.rs +++ b/ui/dr-ui/src/gesture_book.rs @@ -59,8 +59,8 @@ pub const GESTURES: &[Gesture] = &[ Gesture { title: "Open this list", section: "Develop", - touch: "Press Help in the top bar, and Done to put it away", - pointer: "Press Help in the top bar, and Done to put it away", + touch: "Press \"?\" in the top bar, beside Settings, and Done to put it away", + pointer: "Press \"?\" in the top bar, beside Settings, and Done to put it away", keys: "F1; the key that closes any sheet puts it away", manual: "", }, diff --git a/ui/dr-ui/ui/app.slint b/ui/dr-ui/ui/app.slint index fe0606b..551bf22 100644 --- a/ui/dr-ui/ui/app.slint +++ b/ui/dr-ui/ui/app.slint @@ -2307,10 +2307,10 @@ in property panel-visible: true; } // GESTURE: Open this list // where: Develop - // touch: Press Help in the top bar, and Done to - // put it away - // pointer: Press Help in the top bar, and Done to - // put it away + // touch: Press "?" in the top bar, beside + // Settings, and Done to put it away + // pointer: Press "?" in the top bar, beside + // Settings, and Done to put it away // keys: `F1`; the key that closes any sheet // puts it away // why: Most of the keys are develop's, and a diff --git a/ui/dr-ui/ui/develop.slint b/ui/dr-ui/ui/develop.slint index 2aa80b2..0a87ba5 100644 --- a/ui/dr-ui/ui/develop.slint +++ b/ui/dr-ui/ui/develop.slint @@ -10,7 +10,7 @@ import { Theme } from "theme.slint"; import { Develop } from "session.slint"; import { Transfer } from "adjust.slint"; -import { Button, PanelHeading, Label, Value, Caption, Panel } from "widgets.slint"; +import { Button, IconButton, PanelHeading, Label, Value, Caption, Panel } from "widgets.slint"; import { Labels, LabelMark, LabelPicker } from "labels.slint"; import { StarStrip } from "library.slint"; @@ -99,6 +99,11 @@ export component StatusBar inherits Rectangle { viewport-height: self.height; viewport-width: max(self.width, strip.preferred-width); + // Related controls sit closer together than unrelated ones: Pick and + // Reject, Undo and Redo, Copy, Paste and Presets, Help and Settings are + // each a group at `gap-sm`, with `gap` between groups. It reads as the + // pairs it is, and it is also what keeps Settings on screen at 1600 + // pixels wide once Help joined the strip. strip := HorizontalLayout { width: parent.viewport-width; height: parent.viewport-height; @@ -175,23 +180,27 @@ export component StatusBar inherits Rectangle { rate(n) => { root.rated(n); } } - // Pressed again, a flag comes off: two buttons that each toggle, - // rather than a third for "none" that is only ever pressed to undo - // one of the other two. - Button { - text: root.flag == 1 ? "Picked" : "Pick"; - active: root.flag == 1; - visible: root.rating >= 0; - y: (parent.height - self.height) / 2; - clicked => { root.flagged(root.flag == 1 ? 0 : 1); } - } + HorizontalLayout { + spacing: Theme.gap-sm; - Button { - text: root.flag == 2 ? "Rejected" : "Reject"; - active: root.flag == 2; - visible: root.rating >= 0; - y: (parent.height - self.height) / 2; - clicked => { root.flagged(root.flag == 2 ? 0 : 2); } + // Pressed again, a flag comes off: two buttons that each toggle, + // rather than a third for "none" that is only ever pressed to undo + // one of the other two. + Button { + text: root.flag == 1 ? "Picked" : "Pick"; + active: root.flag == 1; + visible: root.rating >= 0; + y: (parent.height - self.height) / 2; + clicked => { root.flagged(root.flag == 1 ? 0 : 1); } + } + + Button { + text: root.flag == 2 ? "Rejected" : "Reject"; + active: root.flag == 2; + visible: root.rating >= 0; + y: (parent.height - self.height) / 2; + clicked => { root.flagged(root.flag == 2 ? 0 : 2); } + } } Rectangle { horizontal-stretch: 1; } @@ -227,18 +236,22 @@ export component StatusBar inherits Rectangle { // mis-drag must not go away with it. Disabled rather than hidden, so // the pair keeps its place and the keyboard shortcut has something // visible to correspond to. - Button { - text: "Undo"; - enabled: root.can-undo; - y: (parent.height - self.height) / 2; - clicked => { root.undo(); } - } + HorizontalLayout { + spacing: Theme.gap-sm; - Button { - text: "Redo"; - enabled: root.can-redo; - y: (parent.height - self.height) / 2; - clicked => { root.redo(); } + Button { + text: "Undo"; + enabled: root.can-undo; + y: (parent.height - self.height) / 2; + clicked => { root.undo(); } + } + + Button { + text: "Redo"; + enabled: root.can-redo; + y: (parent.height - self.height) / 2; + clicked => { root.redo(); } + } } // TRACES: FR-DEV-6 @@ -251,30 +264,34 @@ export component StatusBar inherits Rectangle { // The paste button names what would be pasted — "3 adjustments", and // whether the crop is staying behind — because "Paste" alone asks the // user to remember what they copied. - Button { - text: "Copy"; - enabled: Develop.enabled; - y: (parent.height - self.height) / 2; - clicked => { Transfer.copy(); } - } + HorizontalLayout { + spacing: Theme.gap-sm; - // Enabled on `armed` rather than on a non-empty summary, so pasting a - // neutral copy — which clears this image — stays available. - Button { - text: !Transfer.armed ? "Paste" - : "Paste " + Transfer.summary - + (Transfer.framing-withheld ? ", no crop" : ""); - enabled: Develop.enabled && Transfer.armed; - y: (parent.height - self.height) / 2; - clicked => { Transfer.paste(); } - } + Button { + text: "Copy"; + enabled: Develop.enabled; + y: (parent.height - self.height) / 2; + clicked => { Transfer.copy(); } + } - // The saved half: this edit, kept under a name. - Button { - text: "Presets…"; - enabled: Develop.enabled; - y: (parent.height - self.height) / 2; - clicked => { Transfer.open-presets(); } + // Enabled on `armed` rather than on a non-empty summary, so pasting a + // neutral copy — which clears this image — stays available. + Button { + text: !Transfer.armed ? "Paste" + : "Paste " + Transfer.summary + + (Transfer.framing-withheld ? ", no crop" : ""); + enabled: Develop.enabled && Transfer.armed; + y: (parent.height - self.height) / 2; + clicked => { Transfer.paste(); } + } + + // The saved half: this edit, kept under a name. + Button { + text: "Presets…"; + enabled: Develop.enabled; + y: (parent.height - self.height) / 2; + clicked => { Transfer.open-presets(); } + } } // Show or hide the develop column. On a tablet the panel is 280px of a @@ -289,7 +306,10 @@ export component StatusBar inherits Rectangle { clicked => { root.toggle-panel(); } } - Caption { + // Only while there is something to say. Empty, it still took a slot + // and the spacing either side of it, and this strip has no pixels to + // spare: at 1600 wide they are what kept Settings on screen. + if root.export-status != "": Caption { text: root.export-status; vertical-alignment: center; overflow: elide; @@ -306,24 +326,32 @@ export component StatusBar inherits Rectangle { clicked => { root.export-image(); } } - // TRACES: FR-UI-4 - // The pointer and touch way to the reference F1 opens. Beside - // Settings, as in the library header, because it is about the - // application rather than about the photograph — and in the same - // place on both screens, so it is found where it was last seen. - Button { - text: "Help"; - y: (parent.height - self.height) / 2; - clicked => { root.open-help(); } - } + HorizontalLayout { + spacing: Theme.gap-sm; - // Reachable from develop as well as from the grid: export defaults are - // most likely to be wanted with a finished photograph on screen, which - // is exactly where this bar is and the library header is not. - Button { - text: "Settings"; - y: (parent.height - self.height) / 2; - clicked => { root.open-settings(); } + // TRACES: FR-UI-4 + // The pointer and touch way to the reference F1 opens. Beside + // Settings, as Help is in the library header, because it is about the + // application rather than about the photograph. + // + // A square "?" rather than a word: this strip is already full at + // 1600 pixels, and a labelled button pushed Settings off its end. + // Screen readers still hear "Help". + IconButton { + icon: "help"; + label: "Help"; + y: (parent.height - self.height) / 2; + clicked => { root.open-help(); } + } + + // Reachable from develop as well as from the grid: export defaults are + // most likely to be wanted with a finished photograph on screen, which + // is exactly where this bar is and the library header is not. + Button { + text: "Settings"; + y: (parent.height - self.height) / 2; + clicked => { root.open-settings(); } + } } } diff --git a/ui/dr-ui/ui/icons.slint b/ui/dr-ui/ui/icons.slint index 521f1d4..f93d112 100644 --- a/ui/dr-ui/ui/icons.slint +++ b/ui/dr-ui/ui/icons.slint @@ -61,6 +61,7 @@ component Ink inherits Path { // offline offline-held // photo crop mask repair // eye eye-closed +// help export component Icon inherits Rectangle { in property name; /// The single colour the whole drawing takes. Named `ink` rather than @@ -363,6 +364,17 @@ export component Icon inherits Rectangle { + "M 12 19.2 L 12 22 M 6.6 18 L 5 20.4 M 17.4 18 L 19 20.4"; } + // TRACES: FR-UI-4 + // Help: a question mark, drawn rather than typed for the reason at the + // top of this file. The dot is a zero-length stroke, which the round cap + // turns into a disc the weight of the hook above it. + if root.name == "help": Ink { + stroke: root.ink; + stroke-width: root.weight; + commands: "M 8.2 8.6 C 8.2 6.2 9.9 4.6 12.1 4.6 C 14.3 4.6 15.9 6.1 15.9 8.1 " + + "C 15.9 10.6 12.1 11.2 12.1 14.4 M 12.1 18.9 L 12.1 19"; + } + // TRACES: FR-DEV-8 // A repair: two circles, one sampling into the other. That is literally // what a spot is here — a source and a destination, which is why its