mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-12 05:42:52 +00:00
M5: Escape leaves a Fill & Sign tool, as it leaves a comment tool (#4539)
* Escape leaves a Fill & Sign tool, as it leaves a comment tool The first Escape closes the open type box, the next one goes back to Select; Fill & Sign's Text tool otherwise opened a box at every click with no way out by the keyboard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fill & Sign: a new text box deselects, so two presses of Escape close it and leave the tool 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:
1 parent
863af864a7
commit
8d569066b8
5 files changed
+64
-6
No files matched your search
@@ -606,9 +606,11 @@ pub(crate) fn keys(ctx: &egui::Context, view: &mut DocView, tool: &mut QuickTool
|
||||
}
|
||||
let cv = &mut view.comments;
|
||||
if ctx.input(|i| i.key_pressed(egui::Key::Escape)) {
|
||||
// One step back per press: cancel the gesture, then deselect, then drop the tool.
|
||||
// One step back per press: cancel the gesture, then deselect, then drop the tool (a
|
||||
// comment tool, or a Fill & Sign one: its Text tool would otherwise open a box at every
|
||||
// click with no way out by the keyboard).
|
||||
let cancelled = cv.gesture.take().is_some() || cv.selected.take().is_some();
|
||||
if !cancelled && matches!(tool, QuickTool::Comment(_)) {
|
||||
if !cancelled && matches!(tool, QuickTool::Comment(_) | QuickTool::Fill(_)) {
|
||||
*tool = QuickTool::Select;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,7 +491,10 @@ pub(crate) fn page_input(cx: PageToolContext<'_>, input: PageInput<'_>, free: bo
|
||||
match tool {
|
||||
FillTool::Text => {
|
||||
// Clicking away from an open box commits it: the page sees this click before the box
|
||||
// sees its lost focus, so replacing the box first would drop what was typed.
|
||||
// sees its lost focus, so replacing the box first would drop what was typed. A new box
|
||||
// deselects, as a comment tool's note or text box does: Escape then closes the box and
|
||||
// leaves the tool in two presses.
|
||||
view.comments.selected = None;
|
||||
let open = view.fill_text.replace(TypeBox { page, at: top, text: String::new(), size: text_size, color: text_color, focus: true });
|
||||
open.filter(|tb| !tb.text.trim().is_empty()).map(|tb| {
|
||||
FillAction::Edit(Box::new(typed_with_color(
|
||||
@@ -587,7 +590,8 @@ pub(crate) fn type_box(ctx: &egui::Context, view: &mut DocView, info: &DocInfo,
|
||||
r.request_focus();
|
||||
t.focus = false;
|
||||
}
|
||||
if ui.input(|i| i.key_pressed(egui::Key::Escape)) {
|
||||
// Taken here: the same press must not also leave the tool (one step back per press).
|
||||
if ui.input_mut(|i| i.consume_key(egui::Modifiers::NONE, egui::Key::Escape)) {
|
||||
cancel = true;
|
||||
} else if r.lost_focus() {
|
||||
commit = true;
|
||||
|
||||
@@ -159,6 +159,57 @@ fn clicking_elsewhere_with_add_text_keeps_the_typed_text() {
|
||||
assert!(h.state().views[0].fill_text.as_ref().is_some_and(|t| t.text.is_empty()), "a new, empty box is open");
|
||||
}
|
||||
|
||||
/// Escape steps back out of a Fill & Sign tool as out of a comment tool: the first press closes
|
||||
/// the open type box, the next one leaves the Text tool for Select, so a click opens no new box.
|
||||
#[test]
|
||||
fn escape_leaves_the_fill_and_sign_tools() {
|
||||
let mut h = harness();
|
||||
h.state_mut().execute("sign.fill.text");
|
||||
click(&mut h, 50.0, 250.0);
|
||||
assert!(h.state().views[0].fill_text.is_some(), "a box is open");
|
||||
h.key_press(egui::Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert!(h.state().views[0].fill_text.is_none(), "the first Escape closes the box");
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Fill(FillTool::Text), "the tool stays for the next box");
|
||||
h.key_press(egui::Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Select, "the next Escape leaves the tool");
|
||||
click(&mut h, 50.0, 150.0);
|
||||
assert!(h.state().views[0].fill_text.is_none(), "no new box");
|
||||
assert!(items(&h).is_empty(), "nothing was added: {:?}", items(&h));
|
||||
// A mark tool too.
|
||||
h.state_mut().execute("sign.fill.check");
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Fill(FillTool::Check));
|
||||
h.key_press(egui::Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Select);
|
||||
}
|
||||
|
||||
/// A box opened while a comment is selected deselects it: two presses of Escape still close the
|
||||
/// box and leave the tool.
|
||||
#[test]
|
||||
fn escape_leaves_the_text_tool_in_two_presses_after_a_selection() {
|
||||
let mut h = harness();
|
||||
h.state_mut().execute("sign.fill.text");
|
||||
click(&mut h, 50.0, 250.0);
|
||||
h.event(egui::Event::Text("Ada".into()));
|
||||
h.run_steps(1);
|
||||
commit_typed_text(&mut h);
|
||||
assert_eq!(items(&h).len(), 1, "{:?}", items(&h));
|
||||
h.state_mut().views[0].fill_text = None;
|
||||
h.state_mut().views[0].comments.selected = Some((0, 0));
|
||||
click(&mut h, 50.0, 150.0);
|
||||
assert!(h.state().views[0].fill_text.is_some(), "a box is open");
|
||||
assert_eq!(h.state().views[0].comments.selected, None, "the new box deselected the comment");
|
||||
h.key_press(egui::Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert!(h.state().views[0].fill_text.is_none(), "the first Escape closes the box");
|
||||
h.key_press(egui::Key::Escape);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Select, "the second Escape leaves the tool");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fill_text_size_controls_new_text_and_survives_settings_restore() {
|
||||
let mut h = harness();
|
||||
|
||||
Reference in new issue
Block a user