mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-07 12:12:47 +00:00
M5: a double-click on a comment card's text edits it (#4544)
* A double-click on a comment card's text edits it On the selected card in the Comments panel only the header took the double-click: the text is a selectable label, so a double-click there selected a word and the editor stayed closed (a tester's report). It now opens the editor too; dragging over the text still selects it for copying. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tests: the double-clicked card's editor is drawn too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Review: the double-click test also starts from a card that isn't selected It selected the card before any input, so it never covered what the change is for in the Comments panel as one uses it: a first click on the text of an unselected card selects it, the second edits it. The test now runs both ways. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8d569066b8
commit
04cee34bfe
@@ -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));
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user