mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-01 21:57:12 -06:00
Fix #4978: Area Type Options › Text Flow by rows or by columns
This commit is contained in:
@@ -87,7 +87,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Area Type Options…",
|
||||
["Type"],
|
||||
None,
|
||||
"{ids?|id?, width?: pt, height?: pt, rows?, columns?, gutter?: pt, inset?: pt, firstBaseline?: ascent|capHeight|xHeight|leading|fixed, firstBaselineMin?: pt, verticalAlign?: top|center|bottom|justify, fit?: none|autoHeight|shrinkText, fitMinPercent?: 10..100, …the keys of its own reply (it can be passed back; the values it only reports are ignored)} set the selected area type's options; width and height size the type area from its top-left corner, along the type's own axes, and the text reflows at its size (with fit autoHeight, Auto Size, the frame's height follows the text after every edit and height is ignored; setting the height by hand turns it off); fit shrinkText scales overflowing text down (size, leading, baseline shift) by the largest factor down to fitMinPercent % (default 50) that makes it fit (none given: query) → the first object's options, plus overflow (the text doesn't fit its frame) and fitScale (Shrink Text's factor, 1 unshrunk)",
|
||||
"{ids?|id?, width?: pt, height?: pt, rows?, columns?, gutter?: pt, inset?: pt, firstBaseline?: ascent|capHeight|xHeight|leading|fixed, firstBaselineMin?: pt, verticalAlign?: top|center|bottom|justify, flow?: columns|rows (Text Flow: down each column's rows, then across, the default; or across each row's columns, then down), fit?: none|autoHeight|shrinkText, fitMinPercent?: 10..100, …the keys of its own reply (it can be passed back; the values it only reports are ignored)} set the selected area type's options; width and height size the type area from its top-left corner, along the type's own axes, and the text reflows at its size (with fit autoHeight, Auto Size, the frame's height follows the text after every edit and height is ignored; setting the height by hand turns it off); fit shrinkText scales overflowing text down (size, leading, baseline shift) by the largest factor down to fitMinPercent % (default 50) that makes it fit (none given: query) → the first object's options, plus overflow (the text doesn't fit its frame) and fitScale (Shrink Text's factor, 1 unshrunk)",
|
||||
has_selection,
|
||||
area_options
|
||||
),
|
||||
@@ -1006,6 +1006,7 @@ pub(crate) fn area_options_json(t: &TextObject) -> Result<Value> {
|
||||
let lay = vectorcraft_text::layout(vectorcraft_text::FontDb::global(), t);
|
||||
if let Some(o) = v.as_object_mut() {
|
||||
o.insert("fit".into(), json!(t.area.fit.id()));
|
||||
o.insert("flow".into(), json!(t.area.flow));
|
||||
let min = match t.area.fit {
|
||||
AreaFit::ShrinkText { min_percent } => min_percent,
|
||||
_ => AreaFit::DEFAULT_MIN_PERCENT,
|
||||
@@ -1022,7 +1023,7 @@ pub(crate) fn area_options_json(t: &TextObject) -> Result<Value> {
|
||||
}
|
||||
|
||||
/// The [`vectorcraft_doc::AreaOptions`] keys `text.areaOptions` merges as they are.
|
||||
const AREA_KEYS: [&str; 7] = ["rows", "columns", "gutter", "inset", "firstBaseline", "firstBaselineMin", "verticalAlign"];
|
||||
const AREA_KEYS: [&str; 8] = ["rows", "columns", "gutter", "inset", "firstBaseline", "firstBaselineMin", "verticalAlign", "flow"];
|
||||
|
||||
fn area_options(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "text.areaOptions";
|
||||
|
||||
@@ -476,3 +476,35 @@ fn area_type_options_align_the_lines_vertically() {
|
||||
assert_eq!(text(&s, id).cached_bounds, before);
|
||||
assert!(cmd::find_command("text.areaOptions").unwrap().params.contains("verticalAlign?: top|center|bottom|justify"));
|
||||
}
|
||||
|
||||
/// Area Type Options › Text Flow (#4978): `flow` fills the cells by columns (the default) or by
|
||||
/// rows, is reported back, refuses other values and undoes.
|
||||
#[test]
|
||||
fn area_type_options_set_the_text_flow() {
|
||||
use vectorcraft_doc::TextFlow;
|
||||
let mut s = session();
|
||||
let id = area(&mut s, 0.0, 0.0, 420.0, 300.0, &"Words flow from cell to cell in order. ".repeat(40));
|
||||
sel(&mut s, &[id]);
|
||||
let r = s.execute("text.areaOptions", &json!({"rows": 2, "columns": 2, "gutter": 20})).unwrap();
|
||||
assert_eq!(r["flow"], "columns");
|
||||
// Where the second cell sits from the first.
|
||||
let second = |s: &Session| {
|
||||
let f = layout(s, id).frames;
|
||||
(f[1].x0 - f[0].x0, f[1].y0 - f[0].y0)
|
||||
};
|
||||
assert_eq!(second(&s), (0.0, 160.0), "by columns the second cell is below the first");
|
||||
let n = undo_len(&s);
|
||||
assert_eq!(s.execute("text.areaOptions", &json!({"flow": "rows"})).unwrap()["flow"], "rows");
|
||||
assert_eq!(text(&s, id).area.flow, TextFlow::Rows);
|
||||
assert_eq!(second(&s), (220.0, 0.0), "by rows the second cell is beside the first");
|
||||
let l = layout(&s, id);
|
||||
assert!(l.lines.iter().any(|li| li.region == 1 && li.x0 >= l.frames[1].x0 - 1e-6), "text reaches it");
|
||||
assert_eq!((undo_len(&s), last_step(&s).as_str()), (n + 1, "Area Type Options"));
|
||||
for bad in [json!({"flow": "diagonal"}), json!({"flow": "Rows"}), json!({"flow": 1}), json!({"flow": null})] {
|
||||
assert!(s.execute("text.areaOptions", &bad).is_err(), "{bad}");
|
||||
}
|
||||
assert_eq!((undo_len(&s), text(&s, id).area.flow), (n + 1, TextFlow::Rows));
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!((text(&s, id).area.flow, second(&s)), (TextFlow::Columns, (0.0, 160.0)));
|
||||
assert!(cmd::find_command("text.areaOptions").unwrap().params.contains("flow?: columns|rows"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user