Merge PR #3596: fix(print): restore previous paper size after leaving Label mode (#3564)

This commit is contained in:
aiongg
2026-10-22 01:44:50 +00:00
2 changed files with 139 additions and 6 deletions
+27 -6
View File
@@ -76,6 +76,8 @@ pub struct PrintDraft {
pub as_image: bool,
pub dpi: f64,
pub paper: usize,
/// The paper chosen before Label put label stock in, so leaving Label gives it back (#3564).
pub paper_before_label: Option<usize>,
/// The sheet shown in the preview (0-based).
pub sheet: usize,
pub current_page: usize,
@@ -129,6 +131,7 @@ impl Default for PrintDraft {
as_image: false,
dpi: 300.0,
paper: 0,
paper_before_label: None,
sheet: 0,
current_page: 0,
driver_options: None,
@@ -143,6 +146,26 @@ impl Default for PrintDraft {
}
impl PrintDraft {
/// Choose Page Sizing & Handling. Label loads label stock and remembers the paper it
/// replaced; leaving Label gives that paper back, unless another one was picked meanwhile.
pub fn set_handling(&mut self, handling: Handling) {
let leaving_label = self.handling == Handling::Label && handling != Handling::Label;
self.handling = handling;
self.sheet = 0;
if handling == Handling::Label {
// A label goes on label stock.
if self.paper != print::LABEL_PAPER {
self.paper_before_label = Some(self.paper);
self.paper = print::LABEL_PAPER;
}
} else if leaving_label
&& let Some(paper) = self.paper_before_label.take()
&& self.paper == print::LABEL_PAPER
{
self.paper = paper;
}
}
/// The engine settings for this draft (page count and labels from the document).
pub fn settings(&self, count: usize, labels: &[String]) -> Result<print::Settings, String> {
if self.handling == Handling::Multiple && self.order == PageOrder::CutStack && self.duplex != spool::Duplex::Off {
@@ -913,6 +936,7 @@ pub(crate) fn body(
});
// Label stock gets the label layout (cut, turned upright, fitted).
if d.paper != before && d.paper == print::LABEL_PAPER {
d.paper_before_label = Some(before);
d.handling = Handling::Label;
d.sheet = 0;
}
@@ -942,6 +966,8 @@ pub(crate) fn body(
&& let Some(paper) = matched
{
d.paper = paper;
// A paper picked outright: nothing for leaving Label to give back.
d.paper_before_label = None;
d.handling = Handling::Size;
d.size = SizeMode::Actual;
d.orientation = Orientation::Auto;
@@ -990,12 +1016,7 @@ pub(crate) fn body(
(Handling::Label, tl!("Label")),
] {
if widgets::mode_tab(ui, label, d.handling == h).clicked() {
d.handling = h;
d.sheet = 0;
// A label goes on label stock.
if h == Handling::Label {
d.paper = print::LABEL_PAPER;
}
d.set_handling(h);
}
}
});
+112
View File
@@ -426,3 +426,115 @@ fn an_empty_printer_list_says_none_were_found() {
h.get_by_label_contains("No printers were found");
assert!(!h.get_by_role_and_label(Role::Button, "Save as PDF").accesskit_node().is_disabled());
}
/// `PAPERS` index of the named sheet.
fn paper(name: &str) -> usize {
pdfcraft_engine::print::PAPERS.iter().position(|p| p.0 == name).unwrap()
}
/// Label loads label stock; leaving it gives the paper the person had back (#3564).
#[test]
fn leaving_label_gives_back_the_paper_it_replaced() {
use pdfcraft_engine::print::LABEL_PAPER;
use pdfcraft_ui_egui::PrintHandling;
let a4 = paper("A4");
let mut h = harness();
assert!(h.state_mut().execute("print.dialog"));
h.run_steps(3);
for (mode, tab) in
[(PrintHandling::Size, "Size"), (PrintHandling::Poster, "Poster"), (PrintHandling::Multiple, "Multiple"), (PrintHandling::Booklet, "Booklet")]
{
h.state_mut().print_draft.paper = a4;
h.state_mut().print_draft.handling = PrintHandling::Size;
h.run_steps(2);
h.get_by_role_and_label(Role::Button, "Label").click();
h.run_steps(2);
assert_eq!(h.state().print_draft.handling, PrintHandling::Label);
assert_eq!(h.state().print_draft.paper, LABEL_PAPER, "Label puts label stock in");
h.get_by_role_and_label(Role::Button, tab).click();
h.run_steps(2);
assert_eq!(h.state().print_draft.handling, mode);
assert_eq!(h.state().print_draft.paper, a4, "{tab} gives A4 back after Label");
h.get_by_value("A4");
}
}
/// A paper picked while in Label is the person's choice, and leaving Label keeps it.
#[test]
fn a_paper_picked_while_in_label_is_kept_when_leaving_it() {
use pdfcraft_engine::print::LABEL_PAPER;
use pdfcraft_ui_egui::{PrintDraft, PrintHandling};
let (a4, letter) = (paper("A4"), paper("US Letter"));
let mut d = PrintDraft { paper: a4, ..Default::default() };
d.set_handling(PrintHandling::Label);
assert_eq!(d.paper, LABEL_PAPER);
d.paper = letter;
d.set_handling(PrintHandling::Size);
assert_eq!(d.paper, letter);
// A second round trip from the kept paper gives that paper back.
d.set_handling(PrintHandling::Label);
d.set_handling(PrintHandling::Poster);
assert_eq!(d.paper, letter);
// Clicking Label again while in Label doesn't forget the paper it replaced.
d.set_handling(PrintHandling::Label);
d.set_handling(PrintHandling::Label);
d.set_handling(PrintHandling::Multiple);
assert_eq!(d.paper, letter);
}
/// Picking the label stock from the Paper menu switches to Label (the existing behaviour); leaving
/// Label afterwards gives back the paper picked before it.
#[test]
fn label_stock_picked_from_the_paper_menu_is_undone_by_leaving_label() {
use pdfcraft_engine::print::{LABEL_PAPER, PAPERS};
use pdfcraft_ui_egui::PrintHandling;
let a4 = paper("A4");
let mut h = harness();
assert!(h.state_mut().execute("print.dialog"));
h.run_steps(3);
h.state_mut().print_draft.paper = a4;
h.run_steps(2);
h.get_by_value("A4").click();
h.run_steps(2);
// The label stock is last in a menu that scrolls: bring it into view (it settles over a few
// frames) before clicking it.
h.get_by_label(PAPERS[LABEL_PAPER].0).scroll_to_me();
h.run_steps(4);
h.get_by_label(PAPERS[LABEL_PAPER].0).click();
h.run_steps(2);
assert_eq!(h.state().print_draft.paper, LABEL_PAPER);
assert_eq!(h.state().print_draft.handling, PrintHandling::Label);
h.get_by_role_and_label(Role::Button, "Size").click();
h.run_steps(2);
assert_eq!(h.state().print_draft.handling, PrintHandling::Size);
assert_eq!(h.state().print_draft.paper, a4);
}
/// The same through the Paper menu: US Letter picked while in Label stays when Size is chosen,
/// rather than the A4 Label replaced coming back.
#[test]
fn a_paper_picked_from_the_menu_while_in_label_is_kept() {
use pdfcraft_engine::print::{LABEL_PAPER, PAPERS};
use pdfcraft_ui_egui::PrintHandling;
let (a4, letter) = (paper("A4"), paper("US Letter"));
let mut h = harness();
assert!(h.state_mut().execute("print.dialog"));
h.run_steps(3);
h.state_mut().print_draft.paper = a4;
h.run_steps(2);
h.get_by_role_and_label(Role::Button, "Label").click();
h.run_steps(2);
assert_eq!(h.state().print_draft.paper, LABEL_PAPER);
h.get_by_value(PAPERS[LABEL_PAPER].0).click();
h.run_steps(2);
h.get_by_label("US Letter").scroll_to_me();
h.run_steps(4);
h.get_by_label("US Letter").click();
h.run_steps(2);
assert_eq!(h.state().print_draft.paper, letter);
h.get_by_role_and_label(Role::Button, "Size").click();
h.run_steps(2);
assert_eq!(h.state().print_draft.handling, PrintHandling::Size);
assert_eq!(h.state().print_draft.paper, letter, "the paper picked in Label is kept");
h.get_by_value("US Letter");
}