mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-24 10:27:44 -06:00
fix(engine): preserve existing table cell margins when side is omitted
In table.cellMargins, resolve existing margins from the table, its style, or defaults and only overwrite the sides explicitly provided in the command parameters. Closes #3490
This commit is contained in:
@@ -629,14 +629,19 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
.params(r#"{"header"?: pt, "footer"?: pt}"#),
|
||||
CommandSpec::new("table.cellMargins", "Cell Margins", "Table Layout › Alignment", |s, v| {
|
||||
let Some((tp, _, _)) = s.sel.focus.path.cell() else { return Err(CmdError::Disabled("not in a table".into())) };
|
||||
let story = s.sel.focus.story;
|
||||
let current = {
|
||||
let table = s.doc.table(story, &tp).ok_or_else(|| CmdError::Failed("no table".into()))?;
|
||||
let style = table.props.style.as_deref().and_then(|id| s.doc.styles.table_style(id));
|
||||
table.props.cell_margins.or(style.and_then(|st| st.parts.cell_margins)).unwrap_or([0.0, 5.4, 0.0, 5.4])
|
||||
};
|
||||
let m = [
|
||||
p::f32(v, "top").unwrap_or(0.0),
|
||||
p::f32(v, "left").unwrap_or(5.4),
|
||||
p::f32(v, "bottom").unwrap_or(0.0),
|
||||
p::f32(v, "right").unwrap_or(5.4),
|
||||
p::f32(v, "top").unwrap_or(current[0]),
|
||||
p::f32(v, "left").unwrap_or(current[1]),
|
||||
p::f32(v, "bottom").unwrap_or(current[2]),
|
||||
p::f32(v, "right").unwrap_or(current[3]),
|
||||
]
|
||||
.map(|x| x.clamp(0.0, 144.0));
|
||||
let story = s.sel.focus.story;
|
||||
s.doc.table_mut(story, &tp)?.props.cell_margins = Some(m);
|
||||
for path in s.doc.para_paths(story).into_iter().filter(|p| p.0.starts_with(&tp.0) && p.0.len() > tp.0.len()) {
|
||||
s.doc.para_mut(story, &path)?.touch();
|
||||
|
||||
@@ -8491,3 +8491,36 @@ fn rtf_list_round_trip_keeps_text() {
|
||||
assert_eq!(d.plain_text(StoryRef::Body), "first\nsecond", "{cmd}");
|
||||
}
|
||||
}
|
||||
|
||||
/// #3490: `table.cellMargins` preserves existing margins for any sides not passed.
|
||||
#[test]
|
||||
fn table_cell_margins_preserves_unpassed_sides() {
|
||||
let mut s = s();
|
||||
run(&mut s, "insert.table", json!({"rows": 1, "cols": 1}));
|
||||
let (tp, _, _) = s.sel.focus.path.cell().unwrap();
|
||||
|
||||
// 1. Updating 'top' only retains default left (5.4), bottom (0.0), and right (5.4).
|
||||
run(&mut s, "table.cellMargins", json!({"top": 20.0}));
|
||||
let margins = s.doc.table(StoryRef::Body, &tp).unwrap().props.cell_margins.unwrap();
|
||||
assert_eq!(margins, [20.0, 5.4, 0.0, 5.4]);
|
||||
|
||||
// 2. Updating 'left' subsequently retains previously set top (20.0), bottom (0.0), and right (5.4).
|
||||
run(&mut s, "table.cellMargins", json!({"left": 10.0}));
|
||||
let margins = s.doc.table(StoryRef::Body, &tp).unwrap().props.cell_margins.unwrap();
|
||||
assert_eq!(margins, [20.0, 10.0, 0.0, 5.4]);
|
||||
|
||||
// 3. Updating 'bottom' retains top (20.0), left (10.0), and right (5.4).
|
||||
run(&mut s, "table.cellMargins", json!({"bottom": 8.0}));
|
||||
let margins = s.doc.table(StoryRef::Body, &tp).unwrap().props.cell_margins.unwrap();
|
||||
assert_eq!(margins, [20.0, 10.0, 8.0, 5.4]);
|
||||
|
||||
// 4. Updating 'right' retains top (20.0), left (10.0), and bottom (8.0).
|
||||
run(&mut s, "table.cellMargins", json!({"right": 15.0}));
|
||||
let margins = s.doc.table(StoryRef::Body, &tp).unwrap().props.cell_margins.unwrap();
|
||||
assert_eq!(margins, [20.0, 10.0, 8.0, 15.0]);
|
||||
|
||||
// 5. Updating multiple sides at once retains unpassed sides.
|
||||
run(&mut s, "table.cellMargins", json!({"top": 0.0, "bottom": 0.0}));
|
||||
let margins = s.doc.table(StoryRef::Body, &tp).unwrap().props.cell_margins.unwrap();
|
||||
assert_eq!(margins, [0.0, 10.0, 0.0, 15.0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user