Let a gesture name the manual section that shows it
The help sheet says which move does a thing, and the manual has a picture of the thing being done, but nothing joined the two: a user reading "Pinch it with two fingers" had no way from there to the GIF of it. A GESTURE tag takes an optional `manual:` field naming a heading of docs/manual/README.md by its anchor. The scan checks every one against the anchors the bundled page is rendered with and fails when the manual has no such heading, so renaming a section cannot leave the sheet linking to the top of the page; gestures-check carries the same failure into CI. The anchor goes into gesture_book.rs as a new field, and into docs/gestures.md as a "See it" link to manual/README.md#anchor. The help sheet draws a "See it" button beside the title of each gesture that has one, which opens the bundled manual at that section. The field is additive: a tag without it is unchanged, and no gesture carries one yet.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -57,6 +57,15 @@
|
||||
//! field before it, which is what lets `why` run to a sentence. An unrecognised
|
||||
//! key is an error rather than a silently dropped line: `pointr:` should not
|
||||
//! quietly cost a gesture its desktop half.
|
||||
//!
|
||||
//! # `manual:`, the section that shows it
|
||||
//!
|
||||
//! Optional. It names a heading of `docs/manual/README.md` by its anchor —
|
||||
//! `manual: looking-closer`, with or without the `#` — and the help sheet then
|
||||
//! offers "See it", opening the bundled manual there, where a picture shows
|
||||
//! the move being made. The anchor must exist: [`check_manual`] fails the scan
|
||||
//! when the manual has no such heading, so renaming a section cannot leave a
|
||||
//! link on the sheet that opens the manual at the top.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@@ -79,6 +88,8 @@ pub struct Gesture {
|
||||
/// a user consulting the help sheet wants the gesture, and a reader of the
|
||||
/// document wants the argument.
|
||||
pub why: Option<String>,
|
||||
/// The manual section that shows it, as a heading anchor without `#`.
|
||||
pub manual: Option<String>,
|
||||
pub file: String,
|
||||
pub line: usize,
|
||||
}
|
||||
@@ -105,7 +116,7 @@ impl Gesture {
|
||||
}
|
||||
|
||||
/// A key that may appear in a gesture block.
|
||||
const KEYS: &[&str] = &["where", "touch", "pointer", "keys", "why"];
|
||||
const KEYS: &[&str] = &["where", "touch", "pointer", "keys", "why", "manual"];
|
||||
|
||||
/// Something wrong with a tag, reported rather than dropped.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -211,6 +222,7 @@ pub fn extract_from_text(text: &str, path: &str) -> (Vec<Gesture>, Vec<GesturePr
|
||||
pointer: take("pointer"),
|
||||
keys: take("keys"),
|
||||
why: take("why"),
|
||||
manual: take("manual").map(|m| m.trim_start_matches('#').to_string()),
|
||||
file: path.to_string(),
|
||||
line: start + 1,
|
||||
};
|
||||
@@ -285,6 +297,29 @@ fn split_key(body: &str) -> Option<(String, String)> {
|
||||
Some((key.to_ascii_lowercase(), tail.to_string()))
|
||||
}
|
||||
|
||||
/// Every `manual:` that names a section the manual does not have.
|
||||
///
|
||||
/// `anchors` is [`crate::manual::anchors`] of the README — the ids the bundled
|
||||
/// page gives its headings — so this and the page cannot disagree about what
|
||||
/// exists.
|
||||
pub fn check_manual(gestures: &[Gesture], anchors: &[String]) -> Vec<GestureProblem> {
|
||||
gestures
|
||||
.iter()
|
||||
.filter_map(|g| {
|
||||
let m = g.manual.as_ref()?;
|
||||
(!anchors.iter().any(|a| a == m)).then(|| GestureProblem {
|
||||
file: g.file.clone(),
|
||||
line: g.line,
|
||||
what: format!(
|
||||
"gesture `{}` names manual section `#{m}`, which docs/manual/README.md \
|
||||
has no heading for",
|
||||
g.title
|
||||
),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Group gestures under their `where:`, keeping the order the sections were
|
||||
/// first seen so the document reads in the order a user meets them.
|
||||
pub fn by_section(gestures: &[Gesture]) -> Vec<(String, Vec<&Gesture>)> {
|
||||
@@ -339,6 +374,11 @@ pub fn render_markdown(gestures: &[Gesture]) -> String {
|
||||
for (modality, how) in g.routes() {
|
||||
m.push_str(&format!("- **{modality}** — {how}\n"));
|
||||
}
|
||||
if let Some(anchor) = &g.manual {
|
||||
m.push_str(&format!(
|
||||
"- **See it** — [in the manual](manual/README.md#{anchor})\n"
|
||||
));
|
||||
}
|
||||
if let Some(why) = &g.why {
|
||||
m.push_str(&format!("\n{why}\n"));
|
||||
}
|
||||
@@ -381,6 +421,8 @@ pub fn render_rust(gestures: &[Gesture]) -> String {
|
||||
r.push_str(" pub touch: &'static str,\n");
|
||||
r.push_str(" pub pointer: &'static str,\n");
|
||||
r.push_str(" pub keys: &'static str,\n");
|
||||
r.push_str(" /// The manual section that shows it, a heading anchor; empty for none.\n");
|
||||
r.push_str(" pub manual: &'static str,\n");
|
||||
r.push_str("}\n\n");
|
||||
|
||||
r.push_str("/// Every gesture, in the order the sections were first seen in the source.\n");
|
||||
@@ -402,6 +444,10 @@ pub fn render_rust(gestures: &[Gesture]) -> String {
|
||||
" keys: {},\n",
|
||||
quote(g.keys.as_deref().unwrap_or(""))
|
||||
));
|
||||
r.push_str(&format!(
|
||||
" manual: {},\n",
|
||||
quote(g.manual.as_deref().unwrap_or(""))
|
||||
));
|
||||
r.push_str(" },\n");
|
||||
}
|
||||
}
|
||||
@@ -590,6 +636,38 @@ pub fn zoom() {}
|
||||
assert_eq!(g[1].title, "Second");
|
||||
}
|
||||
|
||||
/// `manual:` is read, with or without its `#`, and a section the manual
|
||||
/// does not have is a problem rather than a link to the top of the page.
|
||||
#[test]
|
||||
fn a_manual_anchor_must_name_a_section_the_manual_has() {
|
||||
let text = "\
|
||||
// GESTURE: Zoom
|
||||
// where: Develop
|
||||
// touch: Pinch
|
||||
// manual: #looking-closer
|
||||
// GESTURE: Pan
|
||||
// where: Develop
|
||||
// touch: Drag
|
||||
// manual: looking-further
|
||||
";
|
||||
let (g, p) = extract_from_text(text, "x.slint");
|
||||
assert!(p.is_empty(), "{p:?}");
|
||||
assert_eq!(g[0].manual.as_deref(), Some("looking-closer"));
|
||||
let anchors = crate::manual::anchors("## Looking closer\n");
|
||||
let problems = check_manual(&g, &anchors);
|
||||
assert_eq!(problems.len(), 1, "{problems:?}");
|
||||
assert!(problems[0].what.contains("looking-further"));
|
||||
assert_eq!(problems[0].line, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_manual_anchor_is_linked_from_the_document_and_carried_in_the_table() {
|
||||
let text = "// GESTURE: Zoom\n// where: Develop\n// touch: Pinch\n// manual: looking-closer\n";
|
||||
let (g, _) = extract_from_text(text, "x.slint");
|
||||
assert!(render_markdown(&g).contains("(manual/README.md#looking-closer)"));
|
||||
assert!(render_rust(&g).contains("manual: \"looking-closer\","));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sections_keep_the_order_they_were_first_seen() {
|
||||
let text = "\
|
||||
|
||||
@@ -161,6 +161,15 @@ fn run_gestures(base: &Path, check: bool) -> Result<()> {
|
||||
problems.extend(p);
|
||||
}
|
||||
|
||||
// A `manual:` must name a section the manual has, checked against the
|
||||
// same anchors the bundled page is rendered with.
|
||||
let manual_source = std::fs::read_to_string(base.join(MANUAL_SOURCE))
|
||||
.with_context(|| format!("reading {MANUAL_SOURCE}"))?;
|
||||
problems.extend(gestures::check_manual(
|
||||
&found,
|
||||
&manual::anchors(&manual_source),
|
||||
));
|
||||
|
||||
println!("files scanned {}", files.len());
|
||||
println!("gestures found {}", found.len());
|
||||
println!("places {}", gestures::by_section(&found).len());
|
||||
|
||||
@@ -18,6 +18,8 @@ pub struct Gesture {
|
||||
pub touch: &'static str,
|
||||
pub pointer: &'static str,
|
||||
pub keys: &'static str,
|
||||
/// The manual section that shows it, a heading anchor; empty for none.
|
||||
pub manual: &'static str,
|
||||
}
|
||||
|
||||
/// Every gesture, in the order the sections were first seen in the source.
|
||||
@@ -28,6 +30,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press \"pick\" in the group's heading, then tap something neutral in the picture",
|
||||
pointer: "Press \"pick\", then click something neutral",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Magnify the photograph by any amount",
|
||||
@@ -35,6 +38,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Pinch it with two fingers",
|
||||
pointer: "The scroll wheel over it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Move a magnified photograph about",
|
||||
@@ -42,6 +46,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Drag it",
|
||||
pointer: "Drag it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Paint a mask by hand",
|
||||
@@ -49,6 +54,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Choose Paint or Erase, then drag on the photograph",
|
||||
pointer: "Choose Paint or Erase, then drag",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Take back the last change",
|
||||
@@ -56,6 +62,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the step above the current one in the History list",
|
||||
pointer: "Click it, or press Undo in the History header",
|
||||
keys: "Ctrl+Z",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Do it again after taking it back",
|
||||
@@ -63,6 +70,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the step below the current one in the History list",
|
||||
pointer: "Click it, or press Redo in the History header",
|
||||
keys: "Ctrl+Shift+Z",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Copy the settings from this photograph",
|
||||
@@ -70,6 +78,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press Copy in the top bar",
|
||||
pointer: "Press Copy in the top bar",
|
||||
keys: "Ctrl+C",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Paste the settings onto this photograph",
|
||||
@@ -77,6 +86,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press Paste in the top bar",
|
||||
pointer: "Press Paste in the top bar",
|
||||
keys: "Ctrl+V",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Choose which kinds of edit a copy carries",
|
||||
@@ -84,6 +94,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Open Presets and toggle the kinds",
|
||||
pointer: "Open Presets and toggle the kinds",
|
||||
keys: "Ctrl+Shift+C, which offers Copy beside them",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Export this photograph as the last one was",
|
||||
@@ -91,6 +102,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press Export in the top bar",
|
||||
pointer: "Press Export in the top bar",
|
||||
keys: "Ctrl+Shift+E",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Choose how to export, then export",
|
||||
@@ -98,6 +110,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Open Settings, then Export defaults",
|
||||
pointer: "Open Settings, then Export defaults",
|
||||
keys: "Ctrl+E",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Change which group of adjustments is on screen",
|
||||
@@ -105,6 +118,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap a group in the rail down the left",
|
||||
pointer: "Click a group in the strip above the develop column",
|
||||
keys: "[ and ] step through them, wrapping round through \"everything\"",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Look at the photograph at 1:1",
|
||||
@@ -112,6 +126,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Double-tap the photograph",
|
||||
pointer: "Double-click it, or press the zoom readout floating over the canvas",
|
||||
keys: "Z",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Give this photograph a colour label",
|
||||
@@ -119,6 +134,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap Label in the top bar, then a colour",
|
||||
pointer: "Click Label in the top bar, then a colour",
|
||||
keys: "6 red, 7 yellow, 8 green, 9 blue; the same key again takes it off",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Move to the next or previous photograph",
|
||||
@@ -126,6 +142,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap a frame in the roll along the foot of the canvas",
|
||||
pointer: "Click a frame in the roll",
|
||||
keys: "Right arrow, D or space for the next; left arrow or A for the one before",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "See the photograph before you edited it",
|
||||
@@ -133,6 +150,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press and hold \"Before\"",
|
||||
pointer: "Press and hold \"Before\"",
|
||||
keys: "Hold \\",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Put one control back to its default",
|
||||
@@ -140,6 +158,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Double-tap its track",
|
||||
pointer: "Double-click its track, or right-click it",
|
||||
keys: "R, for the control last moved",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "See the photograph as a snapshot had it",
|
||||
@@ -147,6 +166,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press and hold the eye beside the snapshot",
|
||||
pointer: "Press and hold the eye beside the snapshot",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Keep the photograph as it is now, under a name",
|
||||
@@ -154,6 +174,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Type a name in the History panel and press Snapshot",
|
||||
pointer: "Type a name in the History panel and press Snapshot",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Show or hide one mask layer",
|
||||
@@ -161,6 +182,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the ring at the head of its row",
|
||||
pointer: "Click the ring at the head of its row",
|
||||
keys: "H, for the selected layer history step, unlike holding \"Before\" — the layer really is off until it is switched back on.",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Show or hide one mask on the photograph",
|
||||
@@ -168,6 +190,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the eye on its row",
|
||||
pointer: "Click the eye on its row",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Change how a part joins its mask",
|
||||
@@ -175,6 +198,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the + / − / ∩ chip on the part's row",
|
||||
pointer: "Click the + / − / ∩ chip on the part's row",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Leave one part out of a mask, and put it back",
|
||||
@@ -182,6 +206,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the ring on the part's row",
|
||||
pointer: "Click the ring on the part's row",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Pick a collection up to rearrange the tree",
|
||||
@@ -189,6 +214,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press and hold it until it lifts, then drag it",
|
||||
pointer: "Drag it, or hold it until it lifts and then drag",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Act on a collection — rename, nest, un-nest, delete",
|
||||
@@ -196,6 +222,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press and hold the collection, then let go without moving",
|
||||
pointer: "Right-click it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Take a collection back out of the one it is nested in",
|
||||
@@ -203,6 +230,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Hold it, then drag it onto \"All photographs\" — or let go and choose \"Move to top level\"",
|
||||
pointer: "Drag it onto \"All photographs\", or right-click it and choose \"Move to top level\"",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Rename a collection",
|
||||
@@ -210,6 +238,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Hold the collection, then \"Rename\"",
|
||||
pointer: "Double-click its name, or right-click it and choose \"Rename\"",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Pull a face out of the wrong person",
|
||||
@@ -217,6 +246,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap the faces that do not belong, then \"Split off\"",
|
||||
pointer: "Click the faces that do not belong, then \"Split off\"",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Rule on a suggested face",
|
||||
@@ -224,6 +254,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tick to confirm it, cross to reject it",
|
||||
pointer: "Tick to confirm it, cross to reject it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "See a person's photographs",
|
||||
@@ -231,6 +262,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Choose them in the rail, then \"Show photos\"",
|
||||
pointer: "Choose them in the rail, then \"Show photos\"",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Change how faces are grouped",
|
||||
@@ -238,6 +270,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "\"Grouping…\", move the dials, then Regroup",
|
||||
pointer: "\"Grouping…\", move the dials, then Regroup",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Start selecting several photographs",
|
||||
@@ -245,6 +278,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press and hold a photograph, or press Select in the header",
|
||||
pointer: "Ctrl-click, or press Select in the header",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Add or remove one photograph",
|
||||
@@ -252,6 +286,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "While selecting, tap it",
|
||||
pointer: "Ctrl-click it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Leave selecting",
|
||||
@@ -259,6 +294,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press Done in the header",
|
||||
pointer: "Press Done in the header",
|
||||
keys: "Escape",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Pick a photograph up to drag it",
|
||||
@@ -266,6 +302,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press and hold it until a ring opens around it, then drag",
|
||||
pointer: "Drag it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Select a range",
|
||||
@@ -273,6 +310,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "While selecting, press \"Select to…\", then tap the last photograph of the run",
|
||||
pointer: "Shift-click the last photograph of the run",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Take the blinks out of a burst",
|
||||
@@ -280,6 +318,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Narrow to a person, then tap \"Eyes open\" beside their name on the filter bar",
|
||||
pointer: "Narrow to a person, then click \"Eyes open\" beside their name on the filter bar",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Find photographs with two people in them",
|
||||
@@ -287,6 +326,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Open the People chip on the filter bar, tap each name, then switch the chip beside them to \"all of them\"",
|
||||
pointer: "Open the People chip on the filter bar, click each name, then switch the chip beside them to \"all of them\"",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Show only photographs with one colour label",
|
||||
@@ -294,6 +334,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap its chip in the filter bar",
|
||||
pointer: "Click its chip in the filter bar",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Export the selection as the last export was",
|
||||
@@ -301,6 +342,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Select them, then Export in the selection bar",
|
||||
pointer: "Select them, then Export in the selection bar",
|
||||
keys: "Ctrl+Shift+E, or Ctrl+E to see the export settings first",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Paste copied settings onto the selection",
|
||||
@@ -308,6 +350,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Select them, then \"Paste to N\" in the selection bar",
|
||||
pointer: "Select them, then \"Paste to N\"",
|
||||
keys: "Ctrl+V",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Show only photographs with some number of stars",
|
||||
@@ -315,6 +358,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap a star chip in the filter bar",
|
||||
pointer: "Click a star chip in the filter bar",
|
||||
keys: "Hold F and tap a digit for exactly that many stars, or two digits for everything between them; tap F alone to show every rating again",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Give photographs a colour label",
|
||||
@@ -322,6 +366,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Select them, then Label in the selection bar and tap a colour",
|
||||
pointer: "Select them, then Label in the selection bar and click a colour",
|
||||
keys: "6 red, 7 yellow, 8 green, 9 blue, with the pointer over it or on the selection; the same key again takes the label off",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Resize the thumbnails",
|
||||
@@ -329,6 +374,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Pinch the grid with two fingers",
|
||||
pointer: "Ctrl and the scroll wheel",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "File photographs in a collection",
|
||||
@@ -336,6 +382,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Drag a photograph — or a whole selection — onto a collection in the sidebar. Starting a drag stops the press becoming a hold, so it cannot leave you in selection mode.",
|
||||
pointer: "Drag a photograph — or a whole selection — onto a collection in the sidebar",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Open a photograph",
|
||||
@@ -343,6 +390,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap it — a single tap, any length",
|
||||
pointer: "Click it",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Rate a photograph without opening it",
|
||||
@@ -350,6 +398,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Tap a star on the cell",
|
||||
pointer: "Hover the cell, then click a star",
|
||||
keys: "0 to 5 with the pointer over it, or on the selection",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Choose the frame a folded burst shows",
|
||||
@@ -357,6 +406,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Open the burst, then tap the ring on the frame you want",
|
||||
pointer: "Open the burst, then click the ring on the frame you want",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Drop the selection but keep selecting",
|
||||
@@ -364,6 +414,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Press Clear in the selection strip",
|
||||
pointer: "Press Clear in the selection strip",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Select everything the grid is showing",
|
||||
@@ -371,6 +422,7 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "While selecting, press \"Select all\"",
|
||||
pointer: "While selecting, press \"Select all\"",
|
||||
keys: "Ctrl+A",
|
||||
manual: "",
|
||||
},
|
||||
Gesture {
|
||||
title: "Take photographs out of a collection",
|
||||
@@ -378,5 +430,6 @@ pub const GESTURES: &[Gesture] = &[
|
||||
touch: "Select them, then \"Collections…\" in the selection bar",
|
||||
pointer: "Select them, then \"Collections…\" in the selection bar",
|
||||
keys: "",
|
||||
manual: "",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -38,6 +38,9 @@ pub struct Row {
|
||||
pub touch: String,
|
||||
pub pointer: String,
|
||||
pub keys: String,
|
||||
/// The manual section that shows the gesture, as a heading anchor; empty
|
||||
/// where there is none, and the sheet then offers no "See it".
|
||||
pub manual: String,
|
||||
}
|
||||
|
||||
/// Build the sheet's rows from the generated table.
|
||||
@@ -67,6 +70,7 @@ fn rows_from(gestures: &[Gesture]) -> Vec<Row> {
|
||||
touch: g.touch.to_string(),
|
||||
pointer: g.pointer.to_string(),
|
||||
keys: g.keys.to_string(),
|
||||
manual: g.manual.to_string(),
|
||||
});
|
||||
}
|
||||
out
|
||||
@@ -83,6 +87,7 @@ mod tests {
|
||||
touch: "Tap",
|
||||
pointer: "",
|
||||
keys: "",
|
||||
manual: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,7 @@ pub fn wire<F>(
|
||||
touch: r.touch.into(),
|
||||
pointer: r.pointer.into(),
|
||||
keys: r.keys.into(),
|
||||
manual: r.manual.into(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)));
|
||||
|
||||
@@ -38,6 +38,10 @@ export struct GestureRow {
|
||||
touch: string,
|
||||
pointer: string,
|
||||
keys: string,
|
||||
// The manual section that shows the gesture being made, as a heading
|
||||
// anchor; empty where the manual has none. Checked against the manual by
|
||||
// the generator, so a non-empty one always lands on a heading.
|
||||
manual: string,
|
||||
}
|
||||
|
||||
// One route: how a modality performs the gesture.
|
||||
@@ -148,12 +152,28 @@ export component GestureSheet inherits Rectangle {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
if r.heading == "": Text {
|
||||
text: r.title;
|
||||
color: Theme.ink;
|
||||
font-size: Theme.text;
|
||||
font-weight: 600;
|
||||
wrap: word-wrap;
|
||||
// The title, and beside it "See it" where the manual
|
||||
// shows the gesture. On the title's line rather than
|
||||
// under the routes, so it is found while reading the
|
||||
// title — the moment of "what does that look like?".
|
||||
if r.heading == "": HorizontalLayout {
|
||||
spacing: Theme.gap;
|
||||
|
||||
Text {
|
||||
text: r.title;
|
||||
color: Theme.ink;
|
||||
font-size: Theme.text;
|
||||
font-weight: 600;
|
||||
wrap: word-wrap;
|
||||
horizontal-stretch: 1;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
if r.manual != "": Button {
|
||||
text: "See it";
|
||||
accessible-label: "See " + r.title + " in the manual";
|
||||
clicked => { root.open-manual(r.manual); }
|
||||
}
|
||||
}
|
||||
|
||||
if r.touch != "": Route {
|
||||
|
||||
Reference in New Issue
Block a user