diff --git a/crates/ui-egui/src/panels/comments_panel.rs b/crates/ui-egui/src/panels/comments_panel.rs index d54daf5717..591a667159 100644 --- a/crates/ui-egui/src/panels/comments_panel.rs +++ b/crates/ui-egui/src/panels/comments_panel.rs @@ -433,7 +433,7 @@ fn card(ui: &mut egui::Ui, view: &mut DocView, context: CardContext<'_>) -> Opti buttons_left = ui.min_rect().left(); }); }); - egui::Frame::NONE.inner_margin(egui::Margin { left: 34, right: 0, top: 4, bottom: 0 }).show(ui, |ui| { + let body = egui::Frame::NONE.inner_margin(egui::Margin { left: 34, right: 0, top: 4, bottom: 0 }).show(ui, |ui| { ui.set_width(ui.available_width()); if editing { if let Some(e) = inline_editor(ui, t, view, key, 2) { @@ -531,7 +531,7 @@ fn card(ui: &mut egui::Ui, view: &mut DocView, context: CardContext<'_>) -> Opti // The header selects the card, except where its buttons are. let mut r = head.response.rect; r.max.x = r.max.x.min(buttons_left - 2.0); - r + (r, body.response.rect) }); let rect = frame.response.rect; if selected { @@ -545,7 +545,8 @@ fn card(ui: &mut egui::Ui, view: &mut DocView, context: CardContext<'_>) -> Opti ui.add_space(5.0); // The header row selects the card (and shows the comment on the page); unselected cards are // clickable everywhere. - let hit = if selected { frame.inner } else { rect }; + let (head, body) = frame.inner; + let hit = if selected { head } else { rect }; let click = ui .interact(hit, ui.scope_id().with(("card", key)), Sense::click()) .on_hover_cursor(egui::CursorIcon::PointingHand) @@ -555,7 +556,10 @@ fn card(ui: &mut egui::Ui, view: &mut DocView, context: CardContext<'_>) -> Opti view.comments.reply.clear(); *nav = Some(Nav::Flash(a.page, a.shown_rect(rotation))); } - if click.double_clicked() && allowed { + // On the selected card a double-click on the text edits it too (dragging over it selects + // words of it, for copying). + let body = (selected && !editing).then(|| ui.interact(body, ui.scope_id().with(("card-body", key)), Sense::click())); + if (click.double_clicked() || body.is_some_and(|b| b.double_clicked())) && allowed { view.comments.open_editor(a.page, a.index, a.contents.clone().unwrap_or_default()); } let menu_id = ui.scope_id().with(("card-menu", key)); diff --git a/crates/ui-egui/tests/it/comments.rs b/crates/ui-egui/tests/it/comments.rs index 129bcbf3e4..29396830f7 100644 --- a/crates/ui-egui/tests/it/comments.rs +++ b/crates/ui-egui/tests/it/comments.rs @@ -143,6 +143,53 @@ fn sidebar_comment_centres_the_annotation_at_high_zoom() { } } +/// A double-click on the text of a card in the Comments panel edits it, as one on its header does +/// (a click there would select a word): on a selected card, and on one the first click selects. +#[test] +fn double_clicking_a_cards_text_edits_it() { + for selected in [true, false] { + double_click_a_cards_text(selected); + } +} + +fn double_click_a_cards_text(selected: bool) { + // Frames 1/60 s apart, so two clicks make a double-click. + let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).with_step_dt(1.0 / 60.0).build_eframe(move |_cc| { + let mut app = PdfCraftApp::new(); + app.set_option("language", "en").unwrap(); + app.open_bytes("text.pdf", None, TEXT_FIXTURE.to_vec()).expect("opens"); + app.set_option("left", "closed").unwrap(); + app.set_option("panel", "comments").unwrap(); + let shape = pdfcraft_engine::Shape::Note { at: [150.0, 90.0], icon: pdfcraft_engine::NoteIcon::Comment }; + assert!(app.apply_edit(pdfcraft_engine::Edit::AddAnnotation(pdfcraft_engine::NewAnnotation { + page: 0, + style: pdfcraft_engine::Style::default_for(&shape), + shape, + contents: "Edit this note".into(), + author: "Tester".into(), + }))); + app.views[0].comments.selected = selected.then_some((0, 0)); + app + }); + h.run_steps(4); + crate::support::settle(&mut h); + assert_eq!(h.state().views[0].comments.selected.is_some(), selected); + let p = h.query_all_by_label("Edit this note").next().expect("the card's text").rect().center(); + h.hover_at(p); + h.run_steps(1); + for _ in 0..2 { + for pressed in [true, false] { + h.event(egui::Event::PointerButton { pos: p, button: egui::PointerButton::Primary, pressed, modifiers: egui::Modifiers::NONE }); + } + h.run_steps(1); + } + h.run_steps(2); + assert_eq!(h.state().views[0].comments.selected, Some((0, 0)), "selected: {selected}"); + assert_eq!(h.state().views[0].comments.editing, Some((0, 0, "Edit this note".into())), "selected: {selected}"); + // And the editor is drawn. + note_editor(&h); +} + #[test] fn dragging_over_text_with_the_highlighter_highlights_it() { let mut h = harness(|app| app.set_option("quick", "highlight").unwrap()); diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml index 6ff5eca28e..f543284d54 100644 --- a/parity/acrobat-features.toml +++ b/parity/acrobat-features.toml @@ -4118,8 +4118,8 @@ milestone = "M5" status = "shipped" commands = ["comment.list"] tools = ["comment_edit"] -evidence = ["crates/annot/src/tests.rs::text_box_text_and_colour_changes_are_drawn", "crates/annot/src/tests.rs::editing_a_text_box_refits_its_rectangle", "crates/automation/tests/it/automation.rs::comments_through_tools", "crates/ui-egui/tests/it/comments.rs::ctrl_enter_posts_a_highlight_comment_and_shift_enter_adds_a_line", "crates/ui-egui/tests/it/comments.rs::one_reply_is_deleted_from_its_menu_and_the_thread_stays", "crates/ui-egui/tests/it/comments.rs::undo_and_redo_close_a_reply_editor_left_open"] -notes = "double-click a comment or card, or Edit in the menus (a reply from its own \"…\" menu); Ctrl+Enter (also Command+Enter) saves text in the focused comment editor, Shift+Enter adds a newline; a text box's rectangle follows the new text (wrap width and top edge stay, the height fits the wrapped lines). Undo or Redo closes the panel's editor without saving it, since either can move the comment it was open on" +evidence = ["crates/annot/src/tests.rs::text_box_text_and_colour_changes_are_drawn", "crates/annot/src/tests.rs::editing_a_text_box_refits_its_rectangle", "crates/automation/tests/it/automation.rs::comments_through_tools", "crates/ui-egui/tests/it/comments.rs::ctrl_enter_posts_a_highlight_comment_and_shift_enter_adds_a_line", "crates/ui-egui/tests/it/comments.rs::one_reply_is_deleted_from_its_menu_and_the_thread_stays", "crates/ui-egui/tests/it/comments.rs::undo_and_redo_close_a_reply_editor_left_open", "crates/ui-egui/tests/it/comments.rs::double_clicking_a_cards_text_edits_it"] +notes = "double-click a comment or card (its header or its text), or Edit in the menus; double-click a comment or card, or Edit in the menus (a reply from its own \"…\" menu); Ctrl+Enter (also Command+Enter) saves text in the focused comment editor, Shift+Enter adds a newline; a text box's rectangle follows the new text (wrap width and top edge stay, the height fits the wrapped lines). Undo or Redo closes the panel's editor without saving it, since either can move the comment it was open on" [[feature]] id = "comment.copy-comment-text"