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.
This commit is contained in:
prxnvt committed 2026-11-02 02:41:19 -05:00
1 parent be0882a148
commit 8495cc99e1
4 files changed
+40 -6

No files matched your search

+8 -1
View File
@@ -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;
}
}
+5 -4
View File
@@ -165,12 +165,13 @@ fn grid_events(app: &mut SheetApp, ctx: &egui::Context, sh: &Sheet) -> Vec<egui:
}
/// Whether the focused form control takes `ev`: arrows, Page Up and Down, Home, End, Space and
/// Enter without Ctrl, Cmd or Alt, and the space a Space press types (it presses a focused button
/// and doesn't start typing in a cell). A key press the control doesn't take goes to the grid,
/// and a focused button gives the keyboard back with it.
/// Enter without Ctrl, Cmd or Alt, and, for a button, the space a Space press types (Space
/// presses the button and doesn't start typing in a cell; a slider or spin button doesn't take
/// Space, so its space starts a cell edit like any other character). A key press the control
/// doesn't take goes to the grid, and a focused button gives the keyboard back with it.
fn form_control_event(app: &mut SheetApp, sh: &Sheet, ev: &egui::Event) -> 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;
+26
View File
@@ -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]
+1 -1
View File
@@ -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) |