Object styles: edits reach text frames anchored in stories, cells and notes

style.object.edit updates the attributes and paragraph styles of text
frames anchored in stories, table cells and notes, as IDML import
places them, as it does for frames on spreads.
This commit is contained in:
dotCooCoo committed 2026-11-11 21:33:24 -08:00
1 parent 4282f30cf9
commit 658a6e42dc
2 files changed
+30 -13

No files matched your search

+5 -13
View File
@@ -422,7 +422,7 @@ pub(super) fn edit_object(s: &mut Session, p: &Value) -> Result<Value> {
|| corners.as_ref().is_some_and(|(o, _)| it.corners == o.named_to_path(&it.path))
|| frame.as_ref().is_some_and(|(o, n)| it.text_frame().is_some_and(|t| t.options.clone().follow_general(o, n)))
};
let updated = d.update_items(
let updated = d.update_placed_items(
|it| it.object_style == new.name && follows(it),
|it| {
if let Some((o, n)) = &effects
@@ -458,18 +458,10 @@ pub(super) fn edit_object(s: &mut Session, p: &Value) -> Result<Value> {
// is in the old one's; when the style set none before, all of it does.
let mut restyled = 0;
if new.paragraph_style.is_some() && (new.paragraph_style != old.paragraph_style || new.apply_next_style != old.apply_next_style) {
let mut stories = Vec::new();
for sp in d.spreads.iter().chain(d.parents.iter()) {
for it in &sp.items {
it.walk(&mut |i| {
if i.object_style == new.name
&& let Some(tf) = i.text_frame()
{
stories.push(tf.story);
}
});
}
}
// Frames on spreads and parents, in groups, and anchored in stories, table cells and
// notes (as IDML import places them).
let mut stories: Vec<_> =
d.placed_items().into_iter().filter(|i| i.object_style == new.name).filter_map(|i| i.text_frame().map(|tf| tf.story)).collect();
stories.sort_unstable();
stories.dedup();
let styles = d.styles.clone();
+25
View File
@@ -1002,6 +1002,31 @@ fn a_stroke_added_to_an_object_style_reaches_default_strokes() {
assert_eq!(weight(&s, stroked_text), 1.0, "a text frame's own 1 pt stroke stays");
}
/// A text frame anchored in a story (as IDML import places one) takes a new paragraph style of
/// its object style like a frame on the page.
#[test]
fn an_object_style_edit_restyles_an_anchored_text_frame() {
use designcraft_doc::ItemId;
let mut s = session();
s.execute("style.paragraph.create", &json!({"name": "Body"})).unwrap();
s.execute("style.paragraph.create", &json!({"name": "Lead"})).unwrap();
s.execute("style.object.create", &json!({"name": "Sidebar", "fromSelection": false, "paragraphStyle": "Body"})).unwrap();
let r = s.execute("frame.create", &json!({"rect": [36, 36, 136, 86], "content": "text", "text": "Inner", "caret": false})).unwrap();
let (inner, inner_story) = (ItemId(r["id"].as_u64().unwrap()), designcraft_doc::StoryId(r["story"].as_u64().unwrap()));
s.execute("style.object.apply", &json!({"name": "Sidebar", "ids": [inner.0]})).unwrap();
let r = s.execute("frame.create", &json!({"rect": [36, 200, 400, 400], "content": "text", "text": "Before after.", "caret": false})).unwrap();
let host = designcraft_doc::StoryId(r["story"].as_u64().unwrap());
{
let d = std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc);
let it = d.item(inner).unwrap().clone();
std::sync::Arc::make_mut(&mut d.spreads[0]).items.retain(|i| i.id != inner);
d.story_mut(host).unwrap().insert_object(7, designcraft_doc::AnchoredObject::new(it, Default::default()));
}
let r = s.execute("style.object.edit", &json!({"name": "Sidebar", "paragraphStyle": "Lead"})).unwrap();
assert_eq!(r["restyled"], 1, "{r}");
assert_eq!(s.doc().unwrap().doc.story(inner_story).unwrap().paras[0].style, "Lead");
}
#[test]
fn object_style_effects_reach_grouped_and_anchored_items() {
use designcraft_doc::ItemId;