mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-25 02:47:33 -06:00
With text selected, Layout > Columns used to change the whole section. As in Word (observed black-box), a continuous section break now goes where the selection starts and one where it ends, splitting a paragraph there, unless that end already meets a section boundary (the document's start or end, or an existing break); the columns go on the section between, in one undo step. `layout.columns` gains `apply: "selection"`, its default when text is selected in the main text. More Columns... offers "Selected text" and picks it then. Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
+3
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
**Stage: alpha** · next: beta, ~15 points (60% → 75% ready for real work) and ~150–230 h away
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** trivial (progress log: legacy outline, shadow, emboss and imprint text effects drawn, #2534; previously trivial: progress log: Indonesian proofing, #498; previously trivial: progress log: DOCX glossary documents (building blocks); previously trivial: progress log: Read Mode keeps the keyboard and shows whole, unobscured columns, #1772); previously trivial: progress log: font list entries of tall-ascent fonts no longer cut off, #2570); previously trivial: progress log: Split Cells and Convert Text to Table dialogs follow the Word check, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout fills the window width, #1876; previously trivial: progress log: Different First Page headers reachable from page 1, #2826; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717)); previously trivial (table style editor formats every part, #714); previously trivial: VML freeforms read and kept on save; previously trivial: progress log: consistent preferred cell widths; previously trivial: multi-paragraph field instructions no longer add blank lines; previously trivial: page-break-only list paragraphs hide their labels; previously trivial: progress log: grouped `flowChartOr` shapes draw their circle and crossing spokes; previously trivial: progress log: copies keep their formatting in other programs, #1523; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** trivial (progress log: Columns on selected text, #2024; previously trivial: progress log: legacy outline, shadow, emboss and imprint text effects drawn, #2534; previously trivial: progress log: Indonesian proofing, #498; previously trivial: progress log: DOCX glossary documents (building blocks); previously trivial: progress log: Read Mode keeps the keyboard and shows whole, unobscured columns, #1772); previously trivial: progress log: font list entries of tall-ascent fonts no longer cut off, #2570); previously trivial: progress log: Split Cells and Convert Text to Table dialogs follow the Word check, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout fills the window width, #1876; previously trivial: progress log: Different First Page headers reachable from page 1, #2826; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717)); previously trivial (table style editor formats every part, #714); previously trivial: VML freeforms read and kept on save; previously trivial: progress log: consistent preferred cell widths; previously trivial: multi-paragraph field instructions no longer add blank lines; previously trivial: page-break-only list paragraphs hide their labels; previously trivial: progress log: grouped `flowChartOr` shapes draw their circle and crossing spokes; previously trivial: progress log: copies keep their formatting in other programs, #1523; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-17 · **Change:** trivial (progress log: pasted blockquotes are indented paragraphs, #1270; previously trivial: progress log: print-area strings translated in every catalog; previously trivial: progress log: comments readable in the dark theme, #2045; previously trivial: progress log: ODT sections, #1379; previously trivial: progress log: table deletes, Change Case and Unlink Fields respect Track Changes and locked content controls, #1329; previously trivial: progress log: rounded rectangle corners, #1476; previously trivial: progress log: Save As type list, #1399; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Printing update:** 2026-10-12 · direct desktop printing through craft-print; details below.
|
||||
|
||||
@@ -149,6 +149,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
| 2026-10-16 | Indonesian proofing (#498): id-ID spelling reads the installed Hunspell `id_ID` dictionary (`hunspell-id` on Debian/Ubuntu, LibreOffice's `dict-id`, or the Dictionaries folder), suggestions use its MAP/REP/TRY/KEY tables, generic repeated-word (offering `anak-anak`) and spacing checks explain in Indonesian; Review › Language, Set Proofing Language and File › Options › Proofing offer Indonesian. No dictionary data bundled; hyphenation keeps the English fallback; parity estimates unchanged |
|
||||
| 2026-10-17 | A table inserted in a right-to-left paragraph is a right-to-left table, like Word, so Tab moves right to left through its cells (#2634) |
|
||||
| 2026-10-14 | DOCX row table border exceptions render and survive saving. Explicit cell borders win; a row exception does not change other rows. |
|
||||
| 2026-10-15 | Layout › Columns with text selected puts only that text in columns, as in Word (#2024): a continuous section break goes where the selection starts and one where it ends (splitting a paragraph there; none at the document's start or end, or where a section already begins or ends), and the columns go on the section between, one undo step; More Columns… offers "Selected text" and picks it. Before, the whole section took the columns |
|
||||
| 2026-10-14 | Tab stops edited on the ruler: the corner selector picks Left/Center/Right/Decimal/Bar, a click sets a stop (Alt skips the snap), dragging moves it with a guide line and position tooltip, dragging off the ruler clears it; markers draw per kind and mirror for RTL; one `para.tabs` call and one undo step per gesture |
|
||||
| 2026-10-12 | Table formulas: cell references and ranges (`=B2+B3`, `=SUM(B2:C3)`), arithmetic and comparisons, IF, AND, OR, NOT, TRUE, FALSE, DEFINED and the `\#` number format; ABOVE and LEFT sum the run of numbers next to the cell as Word does; an unknown function or a syntax error is an error instead of a sum; Update Field (F9) recalculates formula fields |
|
||||
| 2026-10-12 | Fields keep `w:dirty` through DOCX saves (#877): a begin marker flagged by a generator that couldn't compute a result (pandoc-style TOC placeholders) keeps the flag on open/save — as a buffered field or a range field — so Word still refreshes it on open; computing a result (Update Field, Update Table) clears it, like Word's F9 |
|
||||
@@ -432,6 +433,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
| 2026-10-16 | trivial | Progress log: comments readable in the dark theme (#2045) |
|
||||
| 2026-10-16 | trivial | Progress log: Indonesian proofing (#498) |
|
||||
| 2026-10-16 | trivial | Progress log: legacy outline, shadow, emboss and imprint text effects drawn (#2534) |
|
||||
| 2026-10-15 | trivial | Progress log: Columns on selected text (#2024) |
|
||||
| 2026-10-14 | trivial | Progress log: row table border exceptions |
|
||||
| 2026-10-12 | minor | Czech proofing review: short-word splits rank after deletion, NOSUGGEST excludes suggestions while accepting typed forms, affix comments apply only to headers, ratios keep spaces and repeated-word messages use Czech quotes; synthetic engine end-to-end and latency checks |
|
||||
| 2026-10-12 | minor | Czech spelling from the installed Hunspell dictionary, runtime-table suggestions and generic checks; Czech interface writes cs-CZ documents; no Czech hyphenation patterns bundled; estimates unchanged |
|
||||
|
||||
@@ -27,7 +27,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
CommandSpec::new("layout.size", "Size", "Layout › Page Setup", size).params(r#"{"name"?: "Letter|Legal|A4|…", "width"?: pt, "height"?: pt} (each side clamped to 7.2–1584 pt, 0.1–22 in; the section keeps its orientation)"#),
|
||||
CommandSpec::new("layout.columns", "Columns", "Layout › Page Setup", columns)
|
||||
.params(
|
||||
r#"{"count": 1-12, "space"?: pt, "separator"?: bool, "preset"?: "left|right", "widths"?: [[width pt, space after pt], …] (unequal columns; sets the count), "apply"?: "section|document|forward"}"#,
|
||||
r#"{"count": 1-12, "space"?: pt, "separator"?: bool, "preset"?: "left|right", "widths"?: [[width pt, space after pt], …] (unequal columns; sets the count), "apply"?: "section|document|forward|selection"} (default: selection when text is selected in the main text — section breaks around it — else section)"#,
|
||||
),
|
||||
CommandSpec::new("layout.break", "Breaks", "Layout › Page Setup", breaks)
|
||||
.params(r#"{"kind": "page|column|textWrapping|nextPage|continuous|evenPage|oddPage"}"#),
|
||||
@@ -569,7 +569,9 @@ fn columns(s: &mut Session, v: &Value) -> CmdResult {
|
||||
// Equal columns keep one spacing; unequal ones remember the first gap for a later switch back.
|
||||
let space = widths.first().map(|w| w.1).unwrap_or(space);
|
||||
let cols = Columns { count: count as u32, space, separator: sep, widths };
|
||||
match p::str(v, "apply").unwrap_or("section") {
|
||||
// With text selected the gallery works on that text, as in Word (#2024).
|
||||
let default = if selection_sectionable(s) { "selection" } else { "section" };
|
||||
match p::str(v, "apply").unwrap_or(default) {
|
||||
"section" => with_sect(s, |x| x.columns = cols.clone()),
|
||||
"document" => {
|
||||
let ends: Vec<usize> = s.doc.sections().iter().map(|(e, _)| *e).collect();
|
||||
@@ -585,10 +587,61 @@ fn columns(s: &mut Session, v: &Value) -> CmdResult {
|
||||
breaks(s, &json!({"kind": "continuous"}))?;
|
||||
with_sect(s, |x| x.columns = cols.clone())
|
||||
}
|
||||
x => Err(CmdError::Params(format!("unknown apply `{x}` (section, document or forward)"))),
|
||||
"selection" => {
|
||||
selection_to_sections(s)?;
|
||||
with_sect(s, |x| x.columns = cols.clone())
|
||||
}
|
||||
x => Err(CmdError::Params(format!("unknown apply `{x}` (section, document, forward or selection)"))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the selection can become sections of its own: text selected in the main text, outside
|
||||
/// tables.
|
||||
pub fn selection_sectionable(s: &Session) -> bool {
|
||||
let (a, b) = s.sel.ordered();
|
||||
!s.sel.is_collapsed() && [a, b].iter().all(|p| p.story == StoryRef::Body && p.path.depth() == 0)
|
||||
}
|
||||
|
||||
/// Columns for the selected text (#2024), as Word does it: a continuous section break where the
|
||||
/// selection starts and one where it ends, splitting paragraphs there, unless that end already
|
||||
/// meets a section boundary (the document's start or end, or a section break). The selection keeps
|
||||
/// its text, which is then the section(s) between.
|
||||
fn selection_to_sections(s: &mut Session) -> Result<(), CmdError> {
|
||||
if !selection_sectionable(s) {
|
||||
return Err(CmdError::Params("selected text in the main text, outside tables, is needed".into()));
|
||||
}
|
||||
let old = s.sel.clone();
|
||||
let (a, mut b) = old.ordered();
|
||||
let block = |p: &Pos| p.path.0.first().copied().unwrap_or(0) as usize;
|
||||
let len = |s: &Session, p: &Pos| s.doc.para_at(p).map(|q| q.len()).unwrap_or(0);
|
||||
let ends: Vec<usize> = s.doc.sections().iter().map(|(e, _)| *e).collect();
|
||||
let after_break = |i: usize| i.checked_sub(1).is_some_and(|j| ends.contains(&j));
|
||||
// A selection that took a section break with it ends before that break.
|
||||
if b.off == 0 && block(&b) > block(&a) && after_break(block(&b)) {
|
||||
let prev = Pos { path: wordcraft_doc::Path::top(block(&b) - 1), off: 0, ..b.clone() };
|
||||
b = Pos { off: len(s, &prev), ..prev };
|
||||
}
|
||||
let last_block = s.doc.body.len().saturating_sub(1);
|
||||
let end_break = !(b.off == len(s, &b) && (ends.contains(&block(&b)) || block(&b) == last_block));
|
||||
let start_break = !(a.off == 0 && (block(&a) == 0 || after_break(block(&a))));
|
||||
// The end first: the start's position doesn't move.
|
||||
if end_break {
|
||||
s.sel = Selection::caret(b.clone());
|
||||
breaks(s, &json!({"kind": "continuous"}))?;
|
||||
}
|
||||
let (first, last) = if start_break {
|
||||
s.sel = Selection::caret(a.clone());
|
||||
breaks(s, &json!({"kind": "continuous"}))?;
|
||||
let first = s.sel.focus.clone();
|
||||
let last = shifted_by_split(&b, &a, &first);
|
||||
(first, last)
|
||||
} else {
|
||||
(a, b)
|
||||
};
|
||||
s.sel = if old.anchor <= old.focus { Selection { anchor: first, focus: last } } else { Selection { anchor: last, focus: first } };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `[[width, space after], …]` in points: 1–12 columns, each at least 0.25", that fit the text
|
||||
/// width (`tw`).
|
||||
fn column_widths(v: &Value, tw: f32) -> Result<Vec<(f32, f32)>, CmdError> {
|
||||
@@ -956,6 +1009,84 @@ mod tests {
|
||||
assert!(s.run("layout.columns", &json!({"count": 2, "apply": "elsewhere"})).is_err());
|
||||
}
|
||||
|
||||
/// Each section's paragraphs (a section break's own paragraph shows as "") and column count.
|
||||
fn sections_of(s: &Session) -> Vec<(Vec<String>, u32)> {
|
||||
let mut from = 0;
|
||||
let mut out = Vec::new();
|
||||
for (end, x) in s.doc.sections() {
|
||||
let paras = (from..=end).map(|i| s.doc.para_at(&Pos::body(i, 0)).map(|p| p.text.clone()).unwrap_or_default()).collect();
|
||||
out.push((paras, x.columns.count));
|
||||
from = end + 1;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn select(s: &mut Session, from: (usize, usize), to: (usize, usize)) {
|
||||
s.sel = Selection { anchor: Pos::body(from.0, from.1), focus: Pos::body(to.0, to.1) };
|
||||
}
|
||||
|
||||
fn strs(v: &[&str]) -> Vec<String> {
|
||||
v.iter().map(|x| x.to_string()).collect()
|
||||
}
|
||||
|
||||
/// Columns on selected text (#2024), as observed in Word: a continuous section break before
|
||||
/// and after the selection, the columns on the section between, the rest left alone.
|
||||
#[test]
|
||||
fn columns_apply_to_the_selected_text() {
|
||||
let five = || Session::new(wordcraft_doc::Document::from_text("p1\np2\nalpha beta gamma\np4\np5"));
|
||||
// A whole paragraph (a triple-click takes its mark): each break gets a paragraph of its own.
|
||||
let mut s = five();
|
||||
select(&mut s, (2, 0), (3, 0));
|
||||
let whole = s.selected_text();
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s), vec![(strs(&["p1", "p2", ""]), 1), (strs(&["alpha beta gamma", ""]), 2), (strs(&["p4", "p5"]), 1)]);
|
||||
assert!(s.doc.sections().iter().skip(1).all(|(_, x)| x.start == SectionStart::Continuous));
|
||||
assert_eq!(s.selected_text(), whole, "the paragraph stays selected");
|
||||
// The same paragraph again: its section changes, no new breaks.
|
||||
select(&mut s, (3, 0), (4, 0));
|
||||
s.run("layout.columns", &json!({"count": 3})).unwrap();
|
||||
assert_eq!(sections_of(&s).iter().map(|(_, n)| *n).collect::<Vec<_>>(), vec![1, 3, 1]);
|
||||
// Taking the section break along changes nothing more.
|
||||
select(&mut s, (3, 0), (5, 0));
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s).iter().map(|(_, n)| *n).collect::<Vec<_>>(), vec![1, 2, 1]);
|
||||
// One undo step takes the breaks and the columns away.
|
||||
let mut s = five();
|
||||
select(&mut s, (2, 0), (3, 0));
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
s.run("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(sections_of(&s), vec![(strs(&["p1", "p2", "alpha beta gamma", "p4", "p5"]), 1)]);
|
||||
|
||||
// Words inside a paragraph: the breaks split it there.
|
||||
let mut s = five();
|
||||
select(&mut s, (2, 10), (2, 6));
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s), vec![(strs(&["p1", "p2", "alpha "]), 1), (strs(&["beta"]), 2), (strs(&[" gamma", "p4", "p5"]), 1)]);
|
||||
assert_eq!(s.selected_text(), "beta");
|
||||
assert!(s.sel.anchor > s.sel.focus, "a backward selection stays backward");
|
||||
|
||||
// At the document's start no break goes before it, at its end none after.
|
||||
let mut s = five();
|
||||
select(&mut s, (0, 0), (1, 0));
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s), vec![(strs(&["p1", ""]), 2), (strs(&["p2", "alpha beta gamma", "p4", "p5"]), 1)]);
|
||||
let mut s = five();
|
||||
select(&mut s, (4, 0), (4, 2));
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s), vec![(strs(&["p1", "p2", "alpha beta gamma", "p4", ""]), 1), (strs(&["p5"]), 2)]);
|
||||
// Select All: the whole document, no breaks.
|
||||
let mut s = five();
|
||||
s.run("select.all", &json!({})).unwrap();
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s), vec![(strs(&["p1", "p2", "alpha beta gamma", "p4", "p5"]), 2)]);
|
||||
|
||||
// Without a selection the caret's section changes; "selection" then needs one.
|
||||
let mut s = five();
|
||||
s.run("layout.columns", &json!({"count": 2})).unwrap();
|
||||
assert_eq!(sections_of(&s).len(), 1);
|
||||
assert!(s.run("layout.columns", &json!({"count": 2, "apply": "selection"})).is_err());
|
||||
}
|
||||
|
||||
/// #407 Line Numbers options: start, count by, distance and restart; options alone keep the
|
||||
/// restart mode, `none` turns numbering off.
|
||||
#[test]
|
||||
|
||||
@@ -112,12 +112,14 @@ pub struct ColumnsForm {
|
||||
pub cols: Vec<(f32, f32)>,
|
||||
/// Line between columns.
|
||||
pub separator: bool,
|
||||
/// `section`, `document` or `forward` (this point forward).
|
||||
/// `section`, `document`, `forward` (this point forward) or `selection` (selected text).
|
||||
pub apply: String,
|
||||
/// The section's text width, in the interface unit.
|
||||
pub text_width: f32,
|
||||
/// The document has more than one section (offer "This section").
|
||||
pub sections: bool,
|
||||
/// Text is selected that can take columns of its own (offer "Selected text", #2024).
|
||||
pub selection: bool,
|
||||
}
|
||||
|
||||
impl ColumnsForm {
|
||||
@@ -131,14 +133,21 @@ impl ColumnsForm {
|
||||
let c = &sp.columns;
|
||||
let count = c.count.clamp(1, 12);
|
||||
let sections = app.session.doc.sections().len() > 1;
|
||||
let selection = wordcraft_engine::cmd::page::selection_sectionable(&app.session);
|
||||
let apply = match (selection, sections) {
|
||||
(true, _) => "selection",
|
||||
(false, true) => "section",
|
||||
(false, false) => "document",
|
||||
};
|
||||
let mut f = ColumnsForm {
|
||||
count,
|
||||
equal: true,
|
||||
cols: Vec::new(),
|
||||
separator: c.separator,
|
||||
apply: if sections { "section" } else { "document" }.into(),
|
||||
apply: apply.into(),
|
||||
text_width: sp.text_width() / k,
|
||||
sections,
|
||||
selection,
|
||||
};
|
||||
if c.widths.len() == count as usize && count > 1 {
|
||||
f.equal = false;
|
||||
@@ -438,6 +447,9 @@ fn columns_ui(app: &mut WordApp, ui: &mut Ui, f: &mut ColumnsForm) -> bool {
|
||||
if f.sections {
|
||||
options.insert(0, ("section", "This section"));
|
||||
}
|
||||
if f.selection {
|
||||
options.push(("selection", "Selected text"));
|
||||
}
|
||||
let shown = options.iter().find(|(k, _)| *k == f.apply).map(|(_, l)| *l).unwrap_or("This section");
|
||||
egui::ComboBox::from_id_salt("columns_apply").selected_text(tl!(shown)).width(180.0).show_ui(ui, |ui| {
|
||||
for (k, l) in &options {
|
||||
@@ -1357,6 +1369,21 @@ mod tests {
|
||||
assert_eq!(wordcraft_engine::cmd::page::sect(&a.session).columns.count, 1);
|
||||
}
|
||||
|
||||
/// With text selected, More Columns applies to the selected text by default, as in Word
|
||||
/// (#2024): the other paragraphs keep one column.
|
||||
#[test]
|
||||
fn columns_dialog_applies_to_the_selected_text() {
|
||||
let mut a = app();
|
||||
assert!(!ColumnsForm::read(&a).selection, "no selection, no Selected text");
|
||||
a.run("select.paragraph", json!({})).unwrap();
|
||||
let mut f = ColumnsForm::read(&a);
|
||||
assert_eq!((f.selection, f.apply.as_str()), (true, "selection"));
|
||||
f.preset("two");
|
||||
a.run("layout.columns", f.params()).unwrap();
|
||||
let counts: Vec<u32> = a.session.doc.sections().iter().map(|(_, x)| x.columns.count).collect();
|
||||
assert_eq!(counts, vec![2, 1]);
|
||||
}
|
||||
|
||||
/// The Symbol dialog inserts in the chosen font and remembers the symbol.
|
||||
#[test]
|
||||
fn symbol_dialog_inserts_with_its_font() {
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
Apply to: Прилагане към:
|
||||
Whole document Целия документ
|
||||
This section Този раздел
|
||||
Selected text Избрания текст
|
||||
Fill Запълване
|
||||
Setting: Настройка:
|
||||
3-D 3-D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -1242,6 +1242,7 @@
|
||||
This font has no characters to show. Toto písmo neobsahuje žádné znaky k zobrazení.
|
||||
This point forward Od tohoto místa dále
|
||||
This section Tento oddíl
|
||||
Selected text Vybraný text
|
||||
Three Tři
|
||||
Tight Těsné
|
||||
Title from the document properties Název z vlastností dokumentu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -159,6 +159,7 @@
|
||||
Apply to: Übernehmen für:
|
||||
Whole document Gesamtes Dokument
|
||||
This section Dieser Abschnitt
|
||||
Selected text Markierter Text
|
||||
Fill Füllung
|
||||
Setting: Einstellung:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -198,6 +198,7 @@
|
||||
Use the Insert key to switch overtype on and off Usar la tecla Insert para activar y desactivar la sobrescritura
|
||||
Whole document Todo el documento
|
||||
This section Esta sección
|
||||
Selected text Texto seleccionado
|
||||
Fill Relleno de color
|
||||
Setting: Valor:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -1331,6 +1331,7 @@
|
||||
Apply to: Rakenda:
|
||||
Whole document Kogu dokument
|
||||
This section See jaotis
|
||||
Selected text Valitud tekst
|
||||
Fill Täide
|
||||
Setting: Säte:
|
||||
3-D Ruumiline
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 841 and column 23.
|
@@ -145,6 +145,7 @@
|
||||
Apply to: Appliquer à :
|
||||
Whole document Tout le document
|
||||
This section Cette section
|
||||
Selected text Texte sélectionné
|
||||
Fill Remplissage
|
||||
Setting: Type :
|
||||
3-D 3-D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -2257,6 +2257,7 @@ template Letter Pismo
|
||||
This password type isn't supported. Ova vrsta lozinke nije podržana.
|
||||
This point forward Od ove točke nadalje
|
||||
This section Ovaj odjeljak
|
||||
Selected text Odabrani tekst
|
||||
Three Tri
|
||||
Through Kroz
|
||||
Tight Usko
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -1642,6 +1642,7 @@
|
||||
Apply to: Alkalmazás erre:
|
||||
Whole document Teljes dokumentum
|
||||
This section Ez a szakasz
|
||||
Selected text Kijelölt szöveg
|
||||
Fill Kitöltés
|
||||
Setting: Beállítás:
|
||||
3-D Térhatású
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -144,6 +144,7 @@
|
||||
Apply to: Applica a:
|
||||
Whole document Tutto il documento
|
||||
This section Questa sezione
|
||||
Selected text Testo selezionato
|
||||
Fill Riempimento
|
||||
Setting: Impostazione:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -213,6 +213,7 @@
|
||||
Use the Insert key to switch overtype on and off Insert キーで上書きのオンとオフを切り替える
|
||||
Whole document 文書全体
|
||||
This section このセクション
|
||||
Selected text 選択したテキスト
|
||||
Fill 塗りつぶし
|
||||
Setting: 種類:
|
||||
3-D 立体
|
||||
|
||||
|
@@ -176,6 +176,7 @@
|
||||
Use the Insert key to switch overtype on and off Insert 키를 눌러 겹쳐쓰기 켜기/끄기
|
||||
Whole document 문서 전체
|
||||
This section 이 구역
|
||||
Selected text 선택한 텍스트
|
||||
Fill 채우기
|
||||
Setting: 설정:
|
||||
3-D 3차원
|
||||
|
||||
|
@@ -1329,6 +1329,7 @@
|
||||
This font has no characters to show. Ta czcionka nie zawiera znaków do pokazania.
|
||||
This point forward Od tego miejsca
|
||||
This section Ta sekcja
|
||||
Selected text Zaznaczony tekst
|
||||
Title from the document properties Tytuł z właściwości dokumentu
|
||||
Total Razem
|
||||
Track Changes Options Opcje śledzenia zmian
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -193,6 +193,7 @@
|
||||
Use the Insert key to switch overtype on and off Usar a tecla Insert para ativar e desativar a sobrescrita
|
||||
Whole document Documento inteiro
|
||||
This section Esta seção
|
||||
Selected text Texto selecionado
|
||||
Fill Cor de fundo
|
||||
Setting: Tipo:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -1620,6 +1620,7 @@ preview Title Пример
|
||||
Apply to: Применить к:
|
||||
Whole document Ко всему документу
|
||||
This section К этому разделу
|
||||
Selected text К выделенному тексту
|
||||
Fill Заливка
|
||||
Setting: Тип:
|
||||
3-D Объёмная
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -270,6 +270,7 @@
|
||||
Use the Insert key to switch overtype on and off Taster Insert uključuje i isključuje prepisivanje
|
||||
Whole document Ceo dokument
|
||||
This section Ovaj odeljak
|
||||
Selected text Izabrani tekst
|
||||
Fill Ispuna
|
||||
Setting: Vrsta:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 25.
|
@@ -274,6 +274,7 @@
|
||||
Use the Insert key to switch overtype on and off Тастер Insert укључује и искључује преписивање
|
||||
Whole document Цео документ
|
||||
This section Овај одељак
|
||||
Selected text Изабрани текст
|
||||
Fill Испуна
|
||||
Setting: Врста:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 11 and column 25.
|
@@ -191,6 +191,7 @@
|
||||
Use the Insert key to switch overtype on and off Använd Insert-tangenten för att slå på och av överskrivning
|
||||
Whole document Hela dokumentet
|
||||
This section Det här avsnittet
|
||||
Selected text Markerad text
|
||||
Fill Fyllning
|
||||
Setting: Inställning:
|
||||
3-D 3D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -1619,6 +1619,7 @@ preview Title Örnek
|
||||
Apply to: Uygula:
|
||||
Whole document Tüm belge
|
||||
This section Bu bölüm
|
||||
Selected text Seçili metin
|
||||
Fill Dolgu
|
||||
Setting: Ayar:
|
||||
3-D 3B
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 793 and column 23.
|
@@ -195,6 +195,7 @@
|
||||
Use the Insert key to switch overtype on and off Клавіша Insert вмикає та вимикає режим заміни
|
||||
Whole document Увесь документ
|
||||
This section Цей розділ
|
||||
Selected text До виділеного тексту
|
||||
Fill Колір заливки
|
||||
Setting: Тип:
|
||||
3-D Об'ємна
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 31.
|
@@ -141,6 +141,7 @@
|
||||
Apply to: Áp dụng cho:
|
||||
Whole document Toàn bộ tài liệu
|
||||
This section Phần này
|
||||
Selected text Văn bản đã chọn
|
||||
Fill Tô nền
|
||||
Setting: Thiết lập:
|
||||
3-D 3-D
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -225,6 +225,7 @@
|
||||
Use the Insert key to switch overtype on and off 用 Insert 键切换改写模式
|
||||
Whole document 整篇文档
|
||||
This section 本节
|
||||
Selected text 所选文字
|
||||
Fill 填充
|
||||
Setting: 设置:
|
||||
3-D 三维
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -214,6 +214,7 @@
|
||||
Use the Insert key to switch overtype on and off 使用 Insert 鍵切換取代模式
|
||||
Whole document 整份文件
|
||||
This section 本節
|
||||
Selected text 選取的文字
|
||||
Fill 填滿
|
||||
Setting: 設定:
|
||||
3-D 立體
|
||||
|
||||
|
+2
-1
@@ -1,6 +1,6 @@
|
||||
# UI parity with Microsoft Word
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** trivial (Different First Page headers reachable from page 1, #2826; previously trivial: a copied equation also goes in the clipboard's MathML formats, #1297; previously trivial: Read Mode keeps the keyboard, shows whole columns and keeps text clear of the page-turn bar, #1772); previously trivial: font list entries of tall-ascent fonts sit in their row, not cut off, #2570); previously trivial: Split Cells and Convert Text to Table dialogs follow Word's merged-cell limits and Initial column width, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout text fills the window width, #1876; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717)); previously trivial: comment balloons readable in the dark theme, #2045; previously trivial (Modify Table Style formats every table style part, #714); previously trivial: a click on the ribbon chrome hands the keyboard to the page in the same frame, #1093 follow-up; previously trivial: Page Setup vertical alignment, #1320; previously trivial: the app opens on the Home tab every launch, as in Word; previously trivial: no document behind the Start screen, #1129; previously trivial: equation pictures share a few textures, #1002; previously trivial: selection bar in the left margin, #856; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously major: first version; ribbon, dialogs, shortcuts and on-canvas interaction measured from `crates/ui-egui` and the command registry) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** trivial (Columns on selected text, #2024; previously trivial: Different First Page headers reachable from page 1, #2826; previously trivial: a copied equation also goes in the clipboard's MathML formats, #1297; previously trivial: Read Mode keeps the keyboard, shows whole columns and keeps text clear of the page-turn bar, #1772); previously trivial: font list entries of tall-ascent fonts sit in their row, not cut off, #2570); previously trivial: Split Cells and Convert Text to Table dialogs follow Word's merged-cell limits and Initial column width, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout text fills the window width, #1876; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717)); previously trivial: comment balloons readable in the dark theme, #2045; previously trivial (Modify Table Style formats every table style part, #714); previously trivial: a click on the ribbon chrome hands the keyboard to the page in the same frame, #1093 follow-up; previously trivial: Page Setup vertical alignment, #1320; previously trivial: the app opens on the Home tab every launch, as in Word; previously trivial: no document behind the Start screen, #1129; previously trivial: equation pictures share a few textures, #1002; previously trivial: selection bar in the left margin, #856; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously major: first version; ribbon, dialogs, shortcuts and on-canvas interaction measured from `crates/ui-egui` and the command registry) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
|
||||
How WordCraft looks and feels next to Word: ribbon, dialogs, panes, keyboard, mouse and touch.
|
||||
Typing behaviour has its own checklist ([`typing-parity.md`](typing-parity.md)). All assets are our
|
||||
@@ -71,6 +71,7 @@ The Language dialog reads effective character formatting, including document def
|
||||
| 2026-10-16 | trivial | Font list: each entry's capitals are centred in its row, so a font with a very tall ascent (Amiri, Amiri Quran) no longer sits low or is cut in half, and the list reads as one even list (#2570) |
|
||||
| 2026-10-16 | trivial | Read Mode keeps the keyboard on entering, shows only whole columns, centred, and ends them above the page-turn bar (#1772) |
|
||||
| 2026-10-16 | trivial | Comment and revision balloons are readable in the dark theme: the card, the markup area, the author stripes and the leader lines come from theme tokens, and the text reaches 4.5:1 (#2045) |
|
||||
| 2026-10-15 | trivial | Layout › Columns works on the selected text, as in Word: section breaks around it, the rest of the document unchanged; More Columns… adds "Selected text" to Apply to and picks it when text is selected (#2024) |
|
||||
| 2026-10-13 | trivial | New/Modify Table Style: No Border on a part that inherits its lines hides them; emptying the font box makes the part's font inherited again (#1288) |
|
||||
| 2026-10-14 | trivial | Tab stops edited on the ruler: corner kind selector, click to set, drag to move or off to clear, per-kind markers mirrored for RTL; each gesture one `para.tabs` call and one undo step; Rulers 85% → 90% |
|
||||
| 2026-10-12 | trivial | Tables on the page: one selected cell (Select Cell, or a click along its left edge) is a cell selection when its border is dragged: the border moves in its row only (#962) |
|
||||
|
||||
Reference in New Issue
Block a user