mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 14:22:39 +00:00
Merge pull request #2703 from dotCooCoo/fix/text-frame-inset-link-mixed
Text Frame Options: link the insets only when every selected frame has even sides
This commit is contained in:
2 files changed
+71
-1
No files matched your search
@@ -1005,6 +1005,24 @@ fn selected_frame_options(app: &DesignApp) -> Option<designcraft_doc::TextFrameO
|
||||
st.doc.item(fid)?.text_frame().map(|t| t.options.clone())
|
||||
}
|
||||
|
||||
/// True when every text frame the dialog changes has the same inset on all four sides: the
|
||||
/// selected items, else the caret's frame, else every frame of the caret's story.
|
||||
fn selected_frames_have_even_insets(app: &DesignApp) -> bool {
|
||||
let Some(st) = app.session.active() else {
|
||||
return true;
|
||||
};
|
||||
let mut ids = st.selection.items.clone();
|
||||
if ids.is_empty()
|
||||
&& let Some(t) = st.selection.text
|
||||
{
|
||||
ids = match t.frame {
|
||||
Some(f) => vec![f],
|
||||
None => st.doc.story(t.story).map(|s| s.frames.clone()).unwrap_or_default(),
|
||||
};
|
||||
}
|
||||
ids.iter().filter_map(|id| st.doc.item(*id)?.text_frame()).all(|t| t.options.inset.iter().all(|v| (v - t.options.inset[0]).abs() < 1e-9))
|
||||
}
|
||||
|
||||
/// Whether every selected text frame (the selected items, or the frame of the caret) has an
|
||||
/// outline that is not its own axis-aligned rectangle: an oval, a polygon, rounded or other corner
|
||||
/// options. Its text keeps one inset from the outline, as compose sets it; type on a path doesn't.
|
||||
@@ -1084,7 +1102,8 @@ fn seed_text_frame_options(app: &DesignApp, d: &mut Dialog) {
|
||||
d.fields.entry(k.clone()).or_insert_with(|| v.clone());
|
||||
}
|
||||
}
|
||||
d.fields.entry("insetLinked".to_string()).or_insert_with(|| json!(o.inset.iter().all(|v| (v - o.inset[0]).abs() < 1e-9)));
|
||||
// Linked only when no selected frame has uneven sides, so a typed side cannot overwrite them.
|
||||
d.fields.entry("insetLinked".to_string()).or_insert_with(|| json!(selected_frames_have_even_insets(app)));
|
||||
// The frame's width: Fixed Number shows each column's width from it as the fields change.
|
||||
if let Some(w) = selected_frame_width(app) {
|
||||
d.fields.insert("_frameWidth".into(), json!(w));
|
||||
|
||||
@@ -1738,6 +1738,57 @@ fn text_frame_options_change_only_what_was_edited() {
|
||||
assert_eq!(opts(&app), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_frame_options_link_the_insets_only_when_every_selected_frame_has_even_sides() {
|
||||
let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({})).unwrap();
|
||||
let frame = |app: &mut DesignApp, rect: [u32; 4], inset: Value| {
|
||||
let r = app.run("frame.create", json!({"rect": rect, "content": "text", "text": "Hello"})).unwrap();
|
||||
let id = r["id"].as_u64().unwrap();
|
||||
app.run("object.textFrameOptions", json!({"ids": [id], "inset": inset})).unwrap();
|
||||
(designcraft_doc::ItemId(id), r["story"].clone())
|
||||
};
|
||||
let (even, _) = frame(&mut app, [36, 36, 236, 236], json!(6));
|
||||
let (uneven, uneven_story) = frame(&mut app, [300, 36, 500, 236], json!([1, 2, 3, 4]));
|
||||
let (other_even, other_even_story) = frame(&mut app, [36, 300, 236, 500], json!(9));
|
||||
let inset = |app: &DesignApp, id| app.session.doc().unwrap().doc.item(id).unwrap().text_frame().unwrap().options.inset;
|
||||
let seeded = |app: &DesignApp| {
|
||||
let mut d = Dialog::new("textFrameOptions", json!({}));
|
||||
seed_text_frame_options(app, &mut d);
|
||||
d
|
||||
};
|
||||
// The frame with even sides is selected first: the uneven one still turns the link off.
|
||||
app.run("selection.set", json!({"ids": [even.0, uneven.0]})).unwrap();
|
||||
let mut d = seeded(&app);
|
||||
assert_eq!(d.s("insetTop"), "0p6");
|
||||
assert!(!d.b("insetLinked"), "a selected frame with uneven sides leaves the link off");
|
||||
// Top edited while unlinked: only Top changes, and each frame keeps its other sides.
|
||||
d.fields.insert("insetTop".into(), json!("1p0"));
|
||||
app.ui.dialog = Some(d);
|
||||
confirm(&mut app).unwrap();
|
||||
assert_eq!(inset(&app, even), [12.0, 6.0, 6.0, 6.0]);
|
||||
assert_eq!(inset(&app, uneven), [12.0, 2.0, 3.0, 4.0]);
|
||||
// A frame with even sides alone keeps the link on; selected with the uneven one, the link is off.
|
||||
app.run("selection.set", json!({"ids": [other_even.0]})).unwrap();
|
||||
assert!(seeded(&app).b("insetLinked"));
|
||||
app.run("selection.set", json!({"ids": [other_even.0, uneven.0]})).unwrap();
|
||||
assert!(!seeded(&app).b("insetLinked"));
|
||||
// A caret: the frames the dialog changes decide.
|
||||
app.run("text.select", json!({"story": uneven_story, "anchor": 0, "focus": 0})).unwrap();
|
||||
assert!(!seeded(&app).b("insetLinked"));
|
||||
app.run("text.select", json!({"story": other_even_story, "anchor": 0, "focus": 0})).unwrap();
|
||||
assert!(seeded(&app).b("insetLinked"));
|
||||
// A story threaded on into the uneven frame: a caret placed in the first frame changes only
|
||||
// that frame, and a caret with no frame changes every frame of the story.
|
||||
let (first, story) = frame(&mut app, [300, 300, 500, 500], json!(6));
|
||||
let (last, _) = frame(&mut app, [300, 520, 500, 700], json!([1, 2, 3, 4]));
|
||||
app.run("text.thread", json!({"from": first.0, "to": last.0})).unwrap();
|
||||
app.run("text.placeCaret", json!({"frame": first.0, "point": [310, 310]})).unwrap();
|
||||
assert!(seeded(&app).b("insetLinked"));
|
||||
app.run("text.select", json!({"story": story, "anchor": 0, "focus": 0})).unwrap();
|
||||
assert!(!seeded(&app).b("insetLinked"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn toc_dialog_adds_a_style_and_ok_makes_the_table_of_contents() {
|
||||
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||
|
||||
Reference in new issue
Block a user