mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-31 07:39:08 +00:00
fix(ui): Redo from the menu with typing in a page box stays in the box
Redo from the menu or toolbar closed the box first, which applied its
typing: a new edit that dropped the document's waiting Redo, and the
Redo itself then failed. The step was gone. Redo now goes to the box as
the key does: what Undo took back there comes back, and typing the page
doesn't have yet stays as it is, with the document's Redo waiting.
A new text box the document refused was put back without the request
to select the item once it exists, which stayed behind. It is put back
with the box.
Carried from #4179 (632ba10e). This branch already routed the menu's
Redo to the box; the test from #4179 covers what its own
redo_from_the_menu_puts_the_typing_back_in_the_box did, so that one
goes.
This commit is contained in:
1 parent
caf7bdd8e1
commit
dce32fb2ab
3 files changed
+93
-11
No files matched your search
@@ -296,12 +296,13 @@ impl PdfCraftApp {
|
||||
}
|
||||
let added = self.session.get(id).map(|d| d.added().to_vec()).unwrap_or_default();
|
||||
let Some(view) = self.views.get_mut(i) else { return true };
|
||||
let draft = view.content.draft.clone();
|
||||
// Finishing new text also asks for it to be selected once it exists: put that back too.
|
||||
let (draft, select_added) = (view.content.draft.clone(), view.content.select_added);
|
||||
if let Some(edit) = view.content.finish_draft(&added)
|
||||
&& !self.apply_edit(edit)
|
||||
{
|
||||
if let Some(view) = self.views.get_mut(i) {
|
||||
view.content.draft = draft;
|
||||
(view.content.draft, view.content.select_added) = (draft, select_added);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1583,6 +1584,46 @@ mod tests {
|
||||
out
|
||||
}
|
||||
|
||||
/// `one_page_pdf`, opening without a password, whose permissions refuse changes.
|
||||
fn no_changes_pdf() -> Vec<u8> {
|
||||
let mut doc = pdfcraft_cos::Document::open(std::sync::Arc::new(one_page_pdf())).unwrap();
|
||||
let encryption = pdfcraft_cos::NewEncryption {
|
||||
algorithm: pdfcraft_cos::Algorithm::Aes256,
|
||||
user_password: "",
|
||||
owner_password: "owner",
|
||||
permissions: -1 ^ 8,
|
||||
encrypt_metadata: true,
|
||||
seed: [4; 32],
|
||||
};
|
||||
doc.set_encryption(&encryption).unwrap();
|
||||
pdfcraft_cos::write_full(&doc, &Default::default()).unwrap()
|
||||
}
|
||||
|
||||
/// Undo with a new text box open on a document that refuses changes: the box is put back as
|
||||
/// it was. Finishing it had asked for the new item to be selected, and that request stayed
|
||||
/// behind once the add was refused.
|
||||
#[test]
|
||||
fn a_refused_text_box_is_put_back_whole() {
|
||||
let mut app = crate::PdfCraftApp::new();
|
||||
app.set_option("language", "en").unwrap();
|
||||
app.open_bytes("a.pdf", None, no_changes_pdf()).unwrap();
|
||||
let style = crate::content_ui::default_style();
|
||||
app.views[0].content.draft = Some(crate::content_ui::TextDraft {
|
||||
page: 0,
|
||||
index: None,
|
||||
rect: [20.0, 20.0, 120.0, 40.0],
|
||||
text: "Typed".into(),
|
||||
style,
|
||||
focus: false,
|
||||
selection: None,
|
||||
typing_from: None,
|
||||
});
|
||||
app.undo();
|
||||
let content = &app.views[0].content;
|
||||
assert_eq!(content.draft.as_ref().map(|d| d.text.as_str()), Some("Typed"), "the refused box stays open");
|
||||
assert_eq!(content.select_added, None, "nothing was added to select");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn save_asks_where_to_keep_an_email_attachment_and_leaves_the_temporary_copy_alone() {
|
||||
let dir = staging_dir("mail-temp");
|
||||
|
||||
@@ -1008,6 +1008,39 @@ fn redo_after_undoing_typing_in_added_text_puts_it_back() {
|
||||
assert_eq!(doc.can_redo(), Some("Edit content"), "the document's Redo still waits");
|
||||
}
|
||||
|
||||
/// Redo from the menu with retyping the page doesn't have yet in an added text box: the typing
|
||||
/// stays in the box and the document's Redo waits (closing the box first wrote the typing, which
|
||||
/// dropped that Redo). After Undo in the box, Redo from the menu puts the typing back there.
|
||||
#[test]
|
||||
fn redo_from_the_menu_with_retyping_in_the_box_keeps_the_documents_redo() {
|
||||
let mut h = harness();
|
||||
let rect = [40.0, 195.0, 240.0, 210.0];
|
||||
let text = pdfcraft_engine::AddedText { rect, text: "Reviewed".into(), ..Default::default() };
|
||||
assert!(h.state_mut().apply_edit(pdfcraft_engine::Edit::AddText { page: 0, text: text.clone() }));
|
||||
let bold = pdfcraft_engine::AddedText { bold: true, ..text };
|
||||
assert!(h.state_mut().apply_edit(pdfcraft_engine::Edit::UpdateContent { page: 0, index: 0, content: pdfcraft_engine::AddedContent::Text(bold) }));
|
||||
assert!(h.state_mut().execute("edit.undo"));
|
||||
assert!(h.state_mut().execute("edit.text"));
|
||||
h.run_steps(3);
|
||||
let point = at(&h, 45.0, 195.0);
|
||||
click(&mut h, point);
|
||||
assert_eq!(h.state().views[0].content.draft.as_ref().and_then(|d| d.index), Some(0), "the editor opened on the text");
|
||||
h.key_press_modifiers(egui::Modifiers::COMMAND, egui::Key::End);
|
||||
h.event(egui::Event::Text(" twice".into()));
|
||||
h.run_steps(2);
|
||||
assert!(h.state_mut().execute("edit.redo"));
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().views[0].content.draft.as_ref().map(|d| d.text.as_str()), Some("Reviewed twice"), "the typing stays in the box");
|
||||
h.key_press_modifiers(egui::Modifiers::COMMAND, egui::Key::Z);
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().views[0].content.draft.as_ref().map(|d| d.text.as_str()), Some("Reviewed"), "Undo takes it back in the box");
|
||||
assert!(h.state_mut().execute("edit.redo"));
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().views[0].content.draft.as_ref().map(|d| d.text.as_str()), Some("Reviewed twice"), "Redo from the menu puts it back");
|
||||
let s = h.state();
|
||||
assert_eq!(s.session.get(s.views[0].id).unwrap().can_redo(), Some("Edit content"), "the document's Redo still waits");
|
||||
}
|
||||
|
||||
/// Redo with an added text box open and unchanged reaches the document's waiting Redo, even when
|
||||
/// the box's text ends in a space: closing the unchanged box writes nothing, so it can't clear
|
||||
/// that Redo first.
|
||||
|
||||
@@ -6202,11 +6202,12 @@ fn a_second_alignment_for_a_selected_row_stays_on_that_row() {
|
||||
assert!((mid - centre).abs() < 1.0, "the last row is centred: {last:?} in {wide:?}");
|
||||
}
|
||||
|
||||
/// Redo from the menu (not the key) after Undo in the box took the typing back: the typing comes
|
||||
/// back in the box, and the document's own Redo (a formatting change) still waits. The menu went
|
||||
/// to the document, which applied the box first: a new edit, which dropped that Redo.
|
||||
/// Redo from the menu or toolbar with typing in the box the page doesn't have yet. Closing the
|
||||
/// box first applied the typing, a new edit that dropped the document's waiting Redo, and the
|
||||
/// Redo itself then failed: the step was gone. The typing now stays in the box and the Redo
|
||||
/// waits; once Undo in the box takes the typing back, Redo from the menu puts it back there.
|
||||
#[test]
|
||||
fn redo_from_the_menu_puts_the_typing_back_in_the_box() {
|
||||
fn redo_from_the_menu_with_typing_in_the_box_keeps_the_documents_redo() {
|
||||
let mut h = harness(1, |_| {});
|
||||
assert!(h.state_mut().execute("edit.edit_text"));
|
||||
h.run_steps(2);
|
||||
@@ -6222,16 +6223,23 @@ fn redo_from_the_menu_puts_the_typing_back_in_the_box() {
|
||||
h.event(egui::Event::Text(" more".into()));
|
||||
h.run_steps(2);
|
||||
let typed = h.state().views[0].line_editor.as_ref().unwrap().text.clone();
|
||||
assert!(h.state_mut().execute("edit.redo"));
|
||||
h.run_steps(3);
|
||||
{
|
||||
let s = h.state();
|
||||
let ed = s.views[0].line_editor.as_ref().expect("the box stays open");
|
||||
assert_eq!(ed.text, typed, "the typing stays in the box, unapplied");
|
||||
let doc = s.session.get(s.views[0].id).unwrap();
|
||||
assert_eq!((doc.can_redo(), doc.text_blocks(0)[0].base_font.as_str()), (Some("Edit text"), "Helvetica"), "the document's Redo still waits");
|
||||
}
|
||||
h.key_press_modifiers(Modifiers::COMMAND, Key::Z);
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().views[0].line_editor.as_ref().unwrap().text, original, "the typing is taken back");
|
||||
assert_eq!(h.state().views[0].line_editor.as_ref().unwrap().text, original, "Undo takes the typing back in the box");
|
||||
assert!(h.state_mut().execute("edit.redo"));
|
||||
h.run_steps(3);
|
||||
let s = h.state();
|
||||
let ed = s.views[0].line_editor.as_ref().expect("still typing");
|
||||
assert_eq!(ed.text, typed, "Redo puts the typing back");
|
||||
let doc = s.session.get(s.views[0].id).unwrap();
|
||||
assert_eq!((doc.can_redo(), doc.text_blocks(0)[0].base_font.as_str()), (Some("Edit text"), "Helvetica"), "the document's Redo still waits");
|
||||
assert_eq!(s.views[0].line_editor.as_ref().expect("still open").text, typed, "Redo from the menu puts the typing back");
|
||||
assert_eq!(s.session.get(s.views[0].id).unwrap().can_redo(), Some("Edit text"), "the document's Redo still waits");
|
||||
}
|
||||
|
||||
/// Two copies of a document, the same paragraph open in each. The paragraph boxes share one text
|
||||
|
||||
Reference in new issue
Block a user