Part of #793: Artboard Options lists Name, Width, Height; one-key shortcuts follow the key on any layout

- Artboard Options listed its fields by key (Height, Name, Width); it now
  lists Name, then Width and Height.
- One-key tool and command shortcuts (V, P, X, D…) matched the character
  typed, so with a layout without Latin letters (Persian, Arabic, Russian,
  Greek…) they did nothing. When the text typed holds no ASCII character,
  the key's position stands in: the V key selects the Selection tool
  whatever it types. Latin layouts (AZERTY…) keep the letter typed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
bflatasticandClaude Opus 5.5 committed 2026-10-10 00:51:18 +07:00
1 parent 0b14b45610
commit f300321e28
3 files changed
+51 -2

No files matched your search

+1
View File
@@ -67,6 +67,7 @@ fn order(kind: &str) -> &'static [&'static str] {
match kind {
"offsetPath" => &["offset", "joins", "miterLimit"],
"splitIntoGrid" => &["rows", "columns", "gutter"],
"artboardOptions" => &["name", "width", "height"],
_ => &[],
}
}
+11
View File
@@ -370,3 +370,14 @@ fn a_dialog_opens_with_its_first_field_focused_so_typing_and_enter_apply() {
let after = bounds(&app);
assert!((after.x0 - before.x0 - 15.0).abs() < 1e-6 && (after.y0 - before.y0).abs() < 1e-6, "{before:?} → {after:?}");
}
/// #793: Artboard Options lists its fields as Name, Width, Height, not by key.
#[test]
fn artboard_options_lists_name_then_width_and_height() {
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 612, "height": 792})).unwrap();
open(&mut app, "artboardOptions", json!({"index": 0, "name": "Artboard 1", "width": 612, "height": 792, "x": 0, "y": 0}));
let text = crate::tests_labels::painted_text(&mut app, |app, ui| show(app, ui.ctx()));
let at = |s: &str| text.find(s).unwrap_or_else(|| panic!("{s} in {text}"));
assert!(at("Name") < at("Width") && at("Width") < at("Height"), "{text}");
}
+39 -2
View File
@@ -414,12 +414,18 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
{
let _ = app.run("edit.clear", json!({}));
}
// Single-key tool shortcuts (no Cmd/Ctrl/Alt).
// Single-key tool shortcuts (no Cmd/Ctrl/Alt). With a layout without Latin letters (Persian,
// Arabic, Russian, Greek…) the key's position stands in for what it types (#793).
let events: Vec<(String, Modifiers)> = ctx.input(|i| {
let mut physical = None;
i.events
.iter()
.filter_map(|e| match e {
egui::Event::Text(t) => Some((t.clone(), i.modifiers)),
egui::Event::Key { physical_key, pressed: true, .. } => {
physical = *physical_key;
None
}
egui::Event::Text(t) => Some((latin(t, physical), i.modifiers)),
_ => None,
})
.collect()
@@ -445,6 +451,16 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
}
}
/// What a single-key shortcut reads for `text`, typed by the key at `physical`: the text itself,
/// or, when it holds no ASCII character (a layout without Latin letters), what that key types on a
/// US layout, so V selects the Selection tool whatever the V key types.
fn latin(text: &str, physical: Option<Key>) -> String {
match physical {
Some(k) if !text.is_ascii() => k.symbol_or_name().to_lowercase(),
_ => text.to_string(),
}
}
/// The digit a number-row or keypad key types.
fn digit_of(k: Key) -> Option<u8> {
const DIGITS: [Key; 10] = [Key::Num0, Key::Num1, Key::Num2, Key::Num3, Key::Num4, Key::Num5, Key::Num6, Key::Num7, Key::Num8, Key::Num9];
@@ -678,6 +694,27 @@ mod tests {
assert_eq!(app.session.tool_id(), "curvature");
}
/// #793: with a layout without Latin letters the one-key shortcuts go by the key's position:
/// the P key typing Persian `ح` chooses the Pen, the V key typing Russian `м` the Selection
/// tool. A Latin layout keeps the letter typed: AZERTY's A (the Q key's place) is A.
#[test]
fn one_key_shortcuts_follow_the_key_on_layouts_without_latin_letters() {
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 200, "height": 200})).unwrap();
let typed = |key, physical, text: &str| {
vec![
egui::Event::Key { key, physical_key: Some(physical), pressed: true, repeat: false, modifiers: Modifiers::NONE },
egui::Event::Text(text.into()),
]
};
frame(&mut app, typed(Key::P, Key::P, "ح"));
assert_eq!(app.session.tool_id(), "pen");
frame(&mut app, typed(Key::V, Key::V, "м"));
assert_eq!(app.session.tool_id(), "selection");
frame(&mut app, typed(Key::A, Key::Q, "a"));
assert_eq!(app.session.tool_id(), "directSelection", "AZERTY: the letter typed");
}
#[test]
fn plus_typed_any_way_zooms_in() {
assert_eq!(parse("Cmd++"), parse("Cmd+="), "`+` and `=` are one chord key");