diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index fb899c702..dc063ac7e 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -1812,7 +1812,12 @@ fn find(app: &mut SheetApp, ui: &mut egui::Ui, d: &mut Dialog) { let mut with = d.values.get("with").and_then(Json::as_str).unwrap_or("").to_string(); ui.horizontal(|ui| { ui.label("Find what:"); - ui.add(egui::TextEdit::singleline(&mut what).desired_width(260.0)); + let r = ui.add(egui::TextEdit::singleline(&mut what).desired_width(260.0)); + // Like Excel, the cursor starts in "Find what" - asked for once, so clicking another field still works. + if !d.values.contains_key("focused") { + r.request_focus(); + d.values.insert("focused".into(), json!(true)); + } }); if d.tab == "Replace" { ui.horizontal(|ui| { diff --git a/crates/ui-egui/tests/find_dialog_focus.rs b/crates/ui-egui/tests/find_dialog_focus.rs new file mode 100644 index 000000000..08cee3fc8 --- /dev/null +++ b/crates/ui-egui/tests/find_dialog_focus.rs @@ -0,0 +1,48 @@ +//! Opening Find and Replace puts the cursor in "Find what", so the user can type at once. + +use egui::{Event, Key, Modifiers}; +use gridcraft_engine::Session; +use gridcraft_ui_egui::SheetApp; +use serde_json::json; + +type Harness = egui_kittest::Harness<'static, SheetApp>; + +/// Ctrl on Windows and Linux sets both `ctrl` and `command`. +const CTRL: Modifiers = Modifiers { alt: false, ctrl: true, shift: false, mac_cmd: false, command: true }; + +fn harness() -> Harness { + let mut session = Session::new(); + session.new_workbook(); + let mut h = Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state( + |ui, app: &mut SheetApp| { + let ctx = ui.ctx().clone(); + app.logic(&ctx); + app.ui(ui); + }, + SheetApp::new(session, Default::default()), + ); + h.run_steps(6); + h +} + +fn type_after_shortcut(k: Key) -> Option { + let mut h = harness(); + h.input_mut().events.push(Event::Key { key: k, physical_key: Some(k), pressed: true, repeat: false, modifiers: CTRL }); + h.input_mut().events.push(Event::Key { key: k, physical_key: Some(k), pressed: false, repeat: false, modifiers: CTRL }); + h.run_steps(6); + h.input_mut().events.push(Event::Text("abc".into())); + h.run_steps(6); + let d = h.state().dialog.as_ref().expect("find dialog is open"); + assert_eq!(d.name, "find"); + d.values.get("what").cloned() +} + +#[test] +fn typing_right_after_ctrl_f_fills_find_what() { + assert_eq!(type_after_shortcut(Key::F), Some(json!("abc"))); +} + +#[test] +fn typing_right_after_ctrl_h_fills_find_what() { + assert_eq!(type_after_shortcut(Key::H), Some(json!("abc"))); +}