Open Help from develop as well as from the grid

The "Controls and shortcuts" sheet was drawn by LibraryGrid, so only the
grid's Help button and its F1 could open it. Develop, where most of the
keys it lists are bound (Ctrl+E, Ctrl+Shift+C, A/D, Z, R, H, [ ]), had no
way to it: a photographer who wanted to look a shortcut up had to leave
the photograph they wanted it for.

The sheet now hangs off the shell beside the export and copy sheets, on a
`help-open` property both views set. The grid's Help button and F1 raise
it through a callback, and its keys stand down through the `sheet-open`
they already honour for the export sheet, so Escape falls through to the
shell, which closes it. Develop gains a Help button beside Settings in
its top bar, as in the library header, and F1 in its key scope; its keys
decline while the sheet is up, as they do for the other two sheets, so
nothing behind it is rated or stepped. The book already begins with the
Develop section, so from develop it opens where the reader wants it.

Tests hold the shape: the sheet is drawn by the shell and not the grid,
and develop's opening guard names all three sheets and its F1 opens this
one. The new GESTURE: block puts the develop route in the book.
This commit is contained in:
2026-09-25 23:24:52 -04:00
parent 19dd3257e3
commit d9f259656a
7 changed files with 224 additions and 127 deletions
+49
View File
@@ -113,6 +113,55 @@ mod tests {
assert_eq!(rows.iter().filter(|r| !r.heading.is_empty()).count(), 1);
}
/// The develop view's key handler, from its `KEYMAP:` tag to the end of
/// the file — enough to hold its opening guard and its bindings.
fn develop_keys() -> &'static str {
let app = include_str!("../ui/app.slint");
let tag = "// KEYMAP: Develop\n key-pressed(event)";
let at = app
.find(tag)
.expect("app.slint no longer has develop's key-pressed handler");
&app[at..]
}
/// TRACES: FR-UI-4
/// The sheet is drawn by the shell, so both views can open it. Drawn
/// inside the grid, it was unreachable from develop — where most of the
/// keys it lists are bound.
#[test]
fn the_help_sheet_is_drawn_by_the_shell_and_not_by_the_grid() {
let app = include_str!("../ui/app.slint");
let library = include_str!("../ui/library.slint");
assert!(app.contains("if root.help-open: GestureSheet {"));
assert!(!library.contains("GestureSheet {"));
}
/// TRACES: FR-UI-4 | FR-UI-5
/// F1 opens it from develop, and develop's keys stand down while it is
/// up, as they do for the export and copy sheets — a key acting behind
/// the sheet would change a photograph the reader cannot see.
#[test]
fn develop_opens_help_on_f1_and_stands_down_behind_it() {
let keys = develop_keys();
let guard = keys
.find("return reject;")
.expect("develop's handler never declines");
let opening = &keys[..guard];
for sheet in ["export-sheet-open", "copy-sheet-open", "help-open"] {
assert!(
opening.contains(sheet),
"develop's keys do not stand down behind `{sheet}`"
);
}
let f1 = keys
.find("Keys.chord(event) == \"F1\"")
.expect("develop does not bind F1");
assert!(
keys[f1..].lines().nth(1).unwrap_or("").trim() == "root.help-open = true;",
"develop's F1 does not open the help sheet"
);
}
#[test]
fn nothing_in_makes_nothing_out() {
assert!(rows_from(&[]).is_empty());