collective

Browse / github.com/storytold/pdfcraft / patch

fix(ui): allow Delete key to remove selected items in Edit PDF (#4915)

[BUG] edit pdf selects items but does not delete them in the edit PDF, the items are selected successully. but using (Delete) button does not delete the selected items.

Status
open
Score
0.00
Adopters
0 other operators
Author
YusufMntm (imported from pull request #5012, open)
Base
1dd2737b47a9c1c9562f0af563053d1bf510e4bf
Size
+52 −4 in 4 files
Review
pending
Shared
2026-10-28
Id
da70cae2c955a6a8ee04c111

How it went

No other operator has reported using it yet.

Diff

raw · crates/ui-egui/src/tools/edit_text_ui/image.rs crates/ui-egui/src/tools/object_ui.rs crates/ui-egui/tests/it/editing.rs crates/ui-egui/tests/it/object_selection.rs

diff --git a/crates/ui-egui/src/tools/edit_text_ui/image.rs b/crates/ui-egui/src/tools/edit_text_ui/image.rs--- a/crates/ui-egui/src/tools/edit_text_ui/image.rs+++ b/crates/ui-egui/src/tools/edit_text_ui/image.rs@@ -180,7 +180,7 @@ fn crop_input(         ui.ctx().set_cursor_icon(icon);     }     let clicked = |r: Rect| allow_interaction && resp.clicked() && hover_pos.is_some_and(|p| r.contains(p));-    let keys = |key: egui::Key| allow_interaction && ui.input(|inp| inp.key_pressed(key)) && !ui.ctx().egui_wants_keyboard_input();+    let keys = |key: egui::Key| allow_interaction && ui.input(|inp| inp.key_pressed(key)) && !ui.ctx().text_edit_focused();     if clicked(done) || keys(egui::Key::Enter) {         let keep = mode.keep;         if let Some(s) = view.image_selection.as_mut() {@@ -505,7 +505,7 @@ pub(crate) fn image_input(         }         if allow_interaction             && ui.input(|inp| inp.key_pressed(egui::Key::Delete) || inp.key_pressed(egui::Key::Backspace))-            && !ui.ctx().egui_wants_keyboard_input()+            && !ui.ctx().text_edit_focused()         {             view.image_selection = None;             view.pending_edit = Some(Edit::EditPageImage { page, index: i, change: pdfcraft_engine::ImageEdit::Delete });diff --git a/crates/ui-egui/src/tools/object_ui.rs b/crates/ui-egui/src/tools/object_ui.rs--- a/crates/ui-egui/src/tools/object_ui.rs+++ b/crates/ui-egui/src/tools/object_ui.rs@@ -360,7 +360,7 @@ const FRAME_REACH: f32 = 6.0; /// The arrow keys move the selected image or objects a point, Shift and an arrow ten points, /// as in Acrobat. They are taken before the view turns the page with them. pub(crate) fn nudge_keys(ctx: &egui::Context, view: &mut DocView, doc: &Document) {-    if ctx.egui_wants_keyboard_input() || view.pending_edit.is_some() {+    if ctx.text_edit_focused() || view.pending_edit.is_some() {         return;     }     let image = view.image_selection.as_ref().filter(|s| !s.dragging()).map(|s| (s.page, s.index));@@ -411,7 +411,7 @@ pub(crate) fn nudge_keys(ctx: &egui::Context, view: &mut DocView, doc: &Document /// frame, or everything an area selection took, goes at once instead of one typed character at a /// time. pub(crate) fn delete_keys(ctx: &egui::Context, view: &mut DocView) {-    if ctx.egui_wants_keyboard_input() || view.pending_edit.is_some() || view.objects.gesture.is_some() {+    if ctx.text_edit_focused() || view.pending_edit.is_some() || view.objects.gesture.is_some() {         return;     }     let Some(page) = view.objects.page.filter(|_| !view.objects.selected.is_empty()) else { return };diff --git a/crates/ui-egui/tests/it/editing.rs b/crates/ui-egui/tests/it/editing.rs--- a/crates/ui-egui/tests/it/editing.rs+++ b/crates/ui-egui/tests/it/editing.rs@@ -6499,3 +6499,28 @@ fn a_paragraph_selected_by_its_frame_deletes_with_one_key() {         assert_eq!(blocks(&h).iter().map(|b| b.text.as_str()).collect::<Vec<_>>(), ["Page 1"], "undo restores it");     } }++/// #4915: In Edit PDF mode, selected items are deleted when pressing Delete or Backspace.+#[test]+fn delete_key_removes_selected_items_in_edit_pdf() {+    for key in [Key::Delete, Key::Backspace] {+        let mut h = harness(1, |_| {});+        assert!(h.state_mut().execute("edit.edit_text"));+        h.run_steps(2);+        let id = h.state().views[0].id;+        let blocks = |h: &Harness<'static, PdfCraftApp>| h.state().session.get(id).unwrap().text_blocks(0);+        let b = blocks(&h)[0].clone();+        let r = h.state().views[0].page_screen_rect(0).expect("on screen");+        let k = r.width() / 200.0;+        let screen = |x: f64, y: f64| egui::pos2(r.left() + x as f32 * k, r.top() + (300.0 - y as f32) * k);+        click_at(&mut h, screen((b.rect[0] + b.rect[2]) / 2.0, (b.rect[1] + b.rect[3]) / 2.0));+        assert!(h.state().views[0].line_editor.is_some(), "a click on the text opens it for typing");+        click_at(&mut h, screen((b.rect[0] + b.rect[2]) / 2.0, b.rect[3]) - egui::vec2(0.0, 4.0));+        assert!(h.state().views[0].line_editor.is_none(), "the frame selects the box");+        press(&mut h, Modifiers::NONE, key);+        assert!(blocks(&h).is_empty(), "{key:?} deletes the selected item");+        assert!(h.state_mut().execute("edit.undo"));+        h.run_steps(2);+        assert_eq!(blocks(&h).len(), 1, "undo restores the deleted item");+    }+}diff --git a/crates/ui-egui/tests/it/object_selection.rs b/crates/ui-egui/tests/it/object_selection.rs--- a/crates/ui-egui/tests/it/object_selection.rs+++ b/crates/ui-egui/tests/it/object_selection.rs@@ -385,3 +385,26 @@ fn modifier_selection_picks_foreground_text_and_added_items_over_background_artw         assert!(new.rect.iter().enumerate().all(|(i, value)| (value - old.rect[i] - shift[i % 2]).abs() < 0.01), "{old:?} -> {new:?}");     } }++/// #4915: Pressing Delete removes selected objects in Edit PDF mode.+#[test]+fn delete_key_removes_selected_objects_in_edit_pdf() {+    for key in [Key::Delete, Key::Backspace] {+        let mut h = harness();+        let total_objects = objects(&h).len();+        marquee(&mut h);+        h.get_by_label("3 objects selected");+        h.key_press(key);+        h.run_steps(4);+        assert!(+            h.query_all_by_label_contains("object selected").next().is_none() && h.query_all_by_label_contains("objects selected").next().is_none(),+            "selected objects deleted with {key:?}"+        );+        let app = h.state();+        assert_eq!(app.session.get(app.views[0].id).unwrap().can_undo(), Some("Delete content"));+        assert!(app.session.get(app.views[0].id).unwrap().dirty);+        assert!(h.state_mut().execute("edit.undo"));+        h.run_steps(4);+        assert_eq!(objects(&h).len(), total_objects);+    }+}