From c99dbd7d6b57c10cc729e1ff91dc73340836743d Mon Sep 17 00:00:00 2001 From: aiongg Date: Sun, 11 Oct 2026 18:03:46 +0000 Subject: [PATCH] Integration: Document Setup margins let matching pages follow their parent page (#469) #469's Document Setup sets every page's and parent page's margins; next's parent-margins model (470aac7d) keeps pages marked local_margins out of later parent edits. After a Document Setup margin edit, pages that now match their parent page (margins and columns) lose the local mark, and parent margins are synced; pages with their own columns stay local. --- crates/doc/src/build.rs | 16 ++++++++++++++++ crates/engine/src/cmd/layout.rs | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/crates/doc/src/build.rs b/crates/doc/src/build.rs index 7e920e05a..3d47abc7e 100644 --- a/crates/doc/src/build.rs +++ b/crates/doc/src/build.rs @@ -628,6 +628,22 @@ impl Document { } } } + + /// Let document pages whose margins and columns match their parent page's follow it again, + /// after an edit that set every page and parent page alike (Document Setup's margins). + pub fn unmark_matching_local_margins(&mut self) { + for si in 0..self.spreads.len() { + for pi in 0..self.spreads[si].pages.len() { + let Some(page) = self.spreads[si].pages.get(pi) else { continue }; + if !page.local_margins || !self.parent_page(page).is_some_and(|q| q.same_margins(page)) { + continue; + } + if let Some(page) = Arc::make_mut(&mut self.spreads[si]).pages.get_mut(pi) { + page.local_margins = false; + } + } + } + } } #[cfg(test)] diff --git a/crates/engine/src/cmd/layout.rs b/crates/engine/src/cmd/layout.rs index d76ea7e4b..2af1babc7 100644 --- a/crates/engine/src/cmd/layout.rs +++ b/crates/engine/src/cmd/layout.rs @@ -369,6 +369,10 @@ pub fn specs() -> Vec { pg.margins = m; } } + // Pages that now match their parent page follow its later changes; local + // columns stay local. + d.unmark_matching_local_margins(); + d.sync_parent_margins(); } d.repaginate(); if let Some(b) = before { @@ -1321,6 +1325,22 @@ mod parent_margin_tests { (0..d.page_count()).filter_map(|i| d.page(i)).map(|p| (p.margins, p.columns.count, p.local_margins)).collect() } + #[test] + fn document_setup_margins_let_pages_follow_their_parent_page_again() { + let mut s = Session::new(); + s.execute("file.new", &json!({"pages": 3})).unwrap(); + s.execute("layout.marginsAndColumns", &json!({"pages": [1], "margins": 100})).unwrap(); + s.execute("layout.marginsAndColumns", &json!({"pages": [2], "margins": 100, "columns": 3})).unwrap(); + s.execute("layout.documentSetup", &json!({"margins": 20})).unwrap(); + let m = margins(&s.doc().unwrap().doc); + let twenty = Margins::uniform(20.0); + assert_eq!(m, vec![(twenty, 1, false), (twenty, 1, false), (twenty, 3, true)], "own columns stay local"); + s.execute("layout.marginsAndColumns", &json!({"parent": "A", "margins": 50})).unwrap(); + let m = margins(&s.doc().unwrap().doc); + assert_eq!(m[1], (Margins::uniform(50.0), 1, false), "page 2 follows the parent page again"); + assert_eq!(m[2], (twenty, 3, true)); + } + #[test] fn pages_follow_their_parent_pages_margins_unless_set_locally() { let mut s = Session::new();