mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-13 09:21:35 -06:00
Resize drag: spend Esc on the cancelled drag
Esc during a header-boundary resize was only peeked at, so the grid's own Esc handling saw it as well and dropped a marked copy and Format Painter. The cancel now removes the Esc presses from the frame's input, with any modifiers, as before, cancelling the drag. The regression test covers a pending copy and sticky Format Painter for rows and columns, with the release in a later frame or the same frame, and Shift+Esc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3e64ddbd80
commit
7cd0a6cc72
@@ -634,8 +634,18 @@ fn handle_dragging(app: &mut SheetApp, input: &InteractionInput<'_>) {
|
||||
let (geo, sh, wb, sel, pos) = (input.geo, input.sheet, input.workbook, &input.selection, input.position);
|
||||
let resp = input.response;
|
||||
// Esc during a header-boundary drag cancels it: undo the preview, ignore the release. egui
|
||||
// aborts the drag on Esc, so `resp.dragged()` is already false in this frame.
|
||||
if matches!(app.grid.drag, Drag::ResizeCol { .. } | Drag::ResizeRow { .. }) && input.context.input(|i| i.key_pressed(egui::Key::Escape)) {
|
||||
// aborts the drag on Esc, so `resp.dragged()` is already false in this frame. The key is
|
||||
// spent on the drag, so the grid's Esc doesn't also drop a pending copy or Format Painter.
|
||||
if matches!(app.grid.drag, Drag::ResizeCol { .. } | Drag::ResizeRow { .. })
|
||||
&& input.context.input_mut(|i| {
|
||||
let pressed = i.key_pressed(egui::Key::Escape);
|
||||
if pressed {
|
||||
// With any modifiers, as before: the drag is cancelled and every Esc press spent.
|
||||
i.events.retain(|e| !matches!(e, egui::Event::Key { key: egui::Key::Escape, pressed: true, .. }));
|
||||
}
|
||||
pressed
|
||||
})
|
||||
{
|
||||
// Undo back to where the drag began, but never past it into an earlier edit.
|
||||
let steps = resize_steps(app);
|
||||
if steps > 0 {
|
||||
|
||||
@@ -374,3 +374,44 @@ fn escaping_a_resize_drag_leaves_redo_history_as_it_was() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escaping_a_resize_drag_keeps_a_pending_copy_and_format_painter() {
|
||||
// Esc cancels the drag only: the marked copy and Format Painter stay, whether the release comes
|
||||
// in a later frame or in the same frame as Esc.
|
||||
for rows in [false, true] {
|
||||
for (same_frame, modifiers) in [(false, Modifiers::NONE), (true, Modifiers::NONE), (false, Modifiers::SHIFT)] {
|
||||
let mut h = harness(if rows { "1:3" } else { "A:C" });
|
||||
h.state_mut().session.execute("edit.copy", json!({"range": "A1:B2"})).unwrap();
|
||||
h.state_mut().session.execute("edit.formatPainter", json!({"sticky": true})).unwrap();
|
||||
h.run_steps(2);
|
||||
assert!(h.state().session.clipboard.is_some() && h.state().session.format_painter.is_some());
|
||||
let before = sizes(&h, rows);
|
||||
let (start, _) = edge(&h, rows, 1);
|
||||
let delta = if rows { vec2(0.0, 30.0) } else { vec2(30.0, 0.0) };
|
||||
button(&mut h, start, true);
|
||||
h.input_mut().events.push(Event::PointerMoved(start + delta / 2.0));
|
||||
h.step();
|
||||
h.input_mut().events.push(Event::PointerMoved(start + delta));
|
||||
h.step();
|
||||
assert_ne!(sizes(&h, rows), before, "the drag previews");
|
||||
let pos = start + delta;
|
||||
let esc = Event::Key { key: egui::Key::Escape, physical_key: None, pressed: true, repeat: false, modifiers };
|
||||
if same_frame {
|
||||
h.input_mut().events.extend([esc, Event::PointerButton { pos, button: PointerButton::Primary, pressed: false, modifiers }]);
|
||||
} else {
|
||||
h.input_mut().events.push(esc);
|
||||
h.step();
|
||||
h.input_mut()
|
||||
.events
|
||||
.extend([Event::PointerMoved(pos), Event::PointerButton { pos, button: PointerButton::Primary, pressed: false, modifiers }]);
|
||||
}
|
||||
h.step();
|
||||
h.run_steps(2);
|
||||
let what = format!("rows: {rows}, same frame: {same_frame}, modifiers: {modifiers:?}");
|
||||
assert_eq!(sizes(&h, rows), before, "the drag is cancelled ({what})");
|
||||
assert!(h.state().session.clipboard.is_some(), "the copy is still marked ({what})");
|
||||
assert!(h.state().session.format_painter.is_some(), "Format Painter is still on ({what})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user