From 8495cc99e151f8fd61a0e767f7eedacd8a74a3ca Mon Sep 17 00:00:00 2001 From: prxnvt <53838599+prxnvt@users.noreply.github.com> Date: Mon, 2 Nov 2026 02:41:19 -0500 Subject: [PATCH] Form controls: Space on a focused slider or spin button starts a cell edit The space a Space press types was dropped while any control was focused, because Space presses a focused button. A slider or spin button doesn't take Space, so with one focused Space neither worked the control nor started a cell edit, while every other character did. Now the space is dropped only for a focused button; on a slider or spin button it reaches the grid like any other character and starts a cell edit. The control keeps the keyboard, as the control last worked: Space is a key it doesn't take, exactly like a letter, and letting go on Space alone would make Space differ from every other printable key. Test (kittest): space_starts_a_cell_edit_while_a_slider_or_spin_button_is_focused (a cell edit starts with a space, the control's value is unchanged, Escape cancels, the arrows still step it). docs/ui-parity.md says so. --- crates/ui-egui/src/form_controls.rs | 9 +++++++- crates/ui-egui/src/grid/keyboard.rs | 9 ++++---- crates/ui-egui/tests/it/form_controls.rs | 26 ++++++++++++++++++++++++ docs/ui-parity.md | 2 +- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/crates/ui-egui/src/form_controls.rs b/crates/ui-egui/src/form_controls.rs index 10b6388b2..27385847f 100644 --- a/crates/ui-egui/src/form_controls.rs +++ b/crates/ui-egui/src/form_controls.rs @@ -357,11 +357,18 @@ fn step_part(app: &mut SheetApp, c: &FormControl, part: Part) { }; } +/// Whether the focused control is a button. Space presses one, so the space it types must not +/// start a cell edit; a slider or spin button doesn't take Space, and its space reaches the grid +/// like any other character. +pub fn focused_button(app: &SheetApp, sh: &Sheet) -> bool { + app.grid.focused_control.and_then(|id| find(sh, id)).is_some_and(|c| c.kind == ControlKind::Button) +} + /// The grid takes a key while a control is focused: a button gives the keyboard back, so a later /// Enter or Space doesn't press it again and Space starts a cell edit; a slider or spin button /// keeps it, as the control last worked, which the arrows still step. pub fn key_to_grid(app: &mut SheetApp, sh: &Sheet) { - if app.grid.focused_control.and_then(|id| find(sh, id)).is_some_and(|c| c.kind == ControlKind::Button) { + if focused_button(app, sh) { app.grid.focused_control = None; } } diff --git a/crates/ui-egui/src/grid/keyboard.rs b/crates/ui-egui/src/grid/keyboard.rs index f72badef6..8f3dfb141 100644 --- a/crates/ui-egui/src/grid/keyboard.rs +++ b/crates/ui-egui/src/grid/keyboard.rs @@ -165,12 +165,13 @@ fn grid_events(app: &mut SheetApp, ctx: &egui::Context, sh: &Sheet) -> Vec bool { match ev { - egui::Event::Text(text) => text == " " && app.grid.focused_control.is_some() && app.selected_object.is_none(), + egui::Event::Text(text) => text == " " && app.selected_object.is_none() && crate::form_controls::focused_button(app, sh), egui::Event::Key { key, pressed: true, repeat, modifiers: m, .. } => { if !m.command && !m.ctrl && !m.alt && crate::form_controls::key(app, sh, *key, *repeat) { return true; diff --git a/crates/ui-egui/tests/it/form_controls.rs b/crates/ui-egui/tests/it/form_controls.rs index 325ad1a29..f202df1be 100644 --- a/crates/ui-egui/tests/it/form_controls.rs +++ b/crates/ui-egui/tests/it/form_controls.rs @@ -321,6 +321,32 @@ fn a_button_gives_the_keyboard_back_when_the_grid_takes_a_key() { assert_eq!(active(&h), "A1"); } +/// Space is a key a slider or spin button doesn't take, so it reaches the grid like any other +/// character: a cell edit starts with a space and the control's value is unchanged. The control +/// keeps the keyboard, as the control last worked: after the edit, the arrows still step it. +#[test] +fn space_starts_a_cell_edit_while_a_slider_or_spin_button_is_focused() { + let (mut h, ids) = fixture(); + let spin = rect(&h, ids.spin); + for (id, at, step) in + [(ids.slider, thumb(&h, ids.slider).center(), Key::ArrowRight), (ids.spin, Pos2::new(spin.center().x, spin.top() + 5.0), Key::ArrowUp)] + { + click(&mut h, at); + assert_eq!(h.state().grid.focused_control, Some(id)); + let value = control(&h, id).value; + space(&mut h); + assert_eq!(h.state().editor.as_ref().map(|e| e.text.as_str()), Some(" "), "Space starts editing the cell with a space"); + assert_eq!(control(&h, id).value, value, "the control is unchanged"); + assert_eq!(h.state().grid.focused_control, Some(id), "the control last worked keeps the keyboard"); + key(&mut h, Key::Escape); + assert!(h.state().editor.is_none(), "Escape cancels the edit"); + key(&mut h, step); + assert_eq!(control(&h, id).value, value + control(&h, id).step, "the arrows still step it"); + key(&mut h, Key::Escape); + assert_eq!(h.state().grid.focused_control, None); + } +} + /// A right-click on a cell takes the keyboard from a button, like any other click on the grid: /// the Enter that follows does not press it again. #[test] diff --git a/docs/ui-parity.md b/docs/ui-parity.md index b3c467e5e..f0ead2518 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -69,7 +69,7 @@ this logic, with one undo step. | Copy as HTML table for other apps | done (#36, 10-10) | | Context menu on cells | 16 items (Cut, Copy, Paste, Paste Special, Insert, Delete, Clear Contents, Filter by value, Sort, New Comment, New Note, Format Cells, Pick From Drop-down List, Define Name, Link). Insert Copied Cells (Insert Cut Cells for whole rows/columns) while the clipboard holds a copy (#21). Show Details on a PivotTable's value, subtotal or grand total cell (`pivot.showDetails`). Missing: Insert Cut Cells for a cell block, paste-option icons, Quick Analysis, Get Data from Table, Show Changes, Smart Lookup | | Move and resize charts, pictures and shapes | done (#190, #213): charts, pictures, shapes and slicers select with a frame of eight handles; each handle resizes only its own edges (they never cross), the body moves the object, and the pointer shows a resize or move cursor; Delete or Backspace deletes the selected object and Escape drops the selection; double-click edits a text box, opens Format Chart for a chart. Rotation handle, Shift for proportional resizing, Alt to snap to cells and multi-object selection missing | -| Form controls: buttons, scroll bars (sliders), spin buttons | done (10-31): Insert › Controls (Button, Slider, Spin Button; Excel has them under Developer › Insert) places one by a drag, or at its default size by a click; a click works a control: drag the thumb, page on the track, click or hold an arrow (a drag or a hold is one undo step), press a button, which runs a macro or a command and asks first in a workbook opened from a file; the control last worked takes the arrows, Page Up and Page Down, Home, End, and Space or Enter (a button gives the keyboard back as soon as the grid takes a key or a right-click); Ctrl or Cmd+click or a right-click selects it to move or resize; its menu has Edit Text, Assign Action, Format Control and Delete. Check boxes, option buttons, list boxes and drop-downs (form controls) are kept from files but not shown | +| Form controls: buttons, scroll bars (sliders), spin buttons | done (10-31): Insert › Controls (Button, Slider, Spin Button; Excel has them under Developer › Insert) places one by a drag, or at its default size by a click; a click works a control: drag the thumb, page on the track, click or hold an arrow (a drag or a hold is one undo step), press a button, which runs a macro or a command and asks first in a workbook opened from a file; the control last worked takes the arrows, Page Up and Page Down, Home, End, and Space or Enter (a button gives the keyboard back as soon as the grid takes a key or a right-click; Space on a slider or spin button starts a cell edit like any other character); Ctrl or Cmd+click or a right-click selects it to move or resize; its menu has Edit Text, Assign Action, Format Control and Delete. Check boxes, option buttons, list boxes and drop-downs (form controls) are kept from files but not shown | | Context menus on row/column headers, sheet tabs, charts, shapes | headers and tabs done; objects partial | | Quick Analysis (Ctrl+Q) | missing | | Smooth scrolling, scrollbars | done; vertical scrollbar added 10-09 (#73); horizontal scrollbar in the tab bar (60/40 split, drag, track click pages) 10-13 (#176, #840); dragging the handle at the scrollbar's left edge gives the tabs more or less of the bar; each workbook keeps its share while it is open (not saved in the file) |