Commit Graph
1161 Commits
Author SHA1 Message Date
aiongg f5ee268962 Merge justification-dialog: a Justification dialog for the selected paragraphs (#531)
Conflict: ROADMAP.md: both progress-log entries, #531's above next's 2026-10-11 lines.
Conflict: docs/typography-parity.md: status line lists next's changes and the Justification dialog.
Conflict: crates/engine/src/cmd/text.rs: selection_attrs keeps next's typing-format chars and adds paraMixed for {mixed: true}; mixed_para_attrs sits beside next's apply_typing_format and link_style.
Conflict: crates/ui-egui/src/dialogs.rs: titles, draw and confirm arms for both paragraphLocal and justification; the style dialog's justify arm calls the shared justification(), which uses next's composer_choice (Japanese composers) and selects neither composer when mixed; the style dialog's justification check moved into next's confirm_paragraph_style_options (section set to justify, reason in next's status line); tests from both sides.
Conflict: crates/ui-egui/src/i18n/ja.rs: union of rows.
Conflict: crates/ui-egui/src/i18n/uk.rs: union of rows.
Conflict: crates/ui-egui/src/menus.rs: UI_COMMANDS, run_ui arms and Type menu keep next's Paragraph Borders and Shading, Span Columns and Bullets and Numbering plus Justification… (Cmd+Alt+Shift+J, free on next) right after Paragraph Rules…; menu_enabled keeps next's IME check before the type.para check.
Auto-merged crates/ui-egui/src/panels/properties.rs: Justification… joins the Paragraph panel menu list after Paragraph Rules….
2026-10-11 20:49:57 +00:00
aiongg 1a9499b465 Merge document-grid: View draws the document grid (#530)
ROADMAP.md: both progress-log lines
docs/target-app-parity.md: next's lines plus the document grid
2026-10-11 20:47:12 +00:00
aiongg 3f752312d6 Type: Justification dialog for the selected paragraphs (#531)
Type > Justification... and the Paragraph panel menu (Cmd+Alt+Shift+J) open
the Justification controls of Paragraph Style Options for the selected
paragraphs: word and letter spacing, glyph scaling, composer, kashidas and
Korean line breaks. Values that differ across the selection show empty, and
OK applies only the edited fields through type.para as one undo step.
Spacing values outside their range or out of minimum/desired/maximum order
keep the dialog open with the reason, in both dialogs.

type.selectionAttrs takes {mixed: true} and lists the paragraph attributes
that differ across the selected paragraphs as paraMixed.
2026-10-11 20:46:38 +00:00
aiongg 61504dae48 View: draw the document grid (#530)
Show/Hide Document Grid (View > Grids & Guides, Cmd+') draws the grid
on the positions Snap to Document Grid uses: subdivision and major
lines from each page's top-left corner, across the spread's band of the
pasteboard, behind or in front of page items as the grid settings say.
Dense lines are left out at low zoom. The Properties toggle runs the
command.
2026-10-11 20:46:38 +00:00
aiongg d240ecb0b9 Merge idml-spread-rotation: IDML keeps a spread's view rotation
ROADMAP.md: both progress-log lines
crates/idml/src/tests.rs: next's test modules plus spread_rotation
docs/target-app-parity.md: next's lines; Rotate Spread names IDML's spread transform
2026-10-11 20:11:34 +00:00
aiongg a8fc6a5219 IDML: read and write a spread's view rotation (#484)
Rotate Spread is the rotation part of the Spread element's ItemTransform.
Import maps the three quarter-turn matrices to view_rotation on the spread's
first page and treats anything else as no rotation; pages and items keep
their unrotated spread coordinates. Export writes the rotation part for
document spreads; parent spreads stay identity.
2026-10-11 20:11:05 +00:00
aiongg 5a7a3ebefd Integration: Control bar tests find the bar's own button when Properties has one with the same name (#524 × object controls) 2026-10-11 19:19:07 +00:00
aiongg 1ff299adf2 Merge place-no-autofit update: the fitting test names its fitting 2026-10-11 19:18:07 +00:00
aiongg 54b607525e Place: the fitting test names its fitting, since a placed image no longer auto-fits 2026-10-11 19:18:07 +00:00
aiongg 3725b90a2a Integration: context menu test expects Paste available with nothing copied (#84 update)
The #84 update enables edit.paste whenever a document is open, since the system clipboard may hold another app's text. next's right_clicking_an_object_selects_it_and_its_menu_arranges_it (from the context-menu work) asserted Paste greyed before any copy; it asserts Paste is available.
2026-10-11 19:14:30 +00:00
aiongg 83893ba3f0 Integration: menu_row matches only buttons that aren't toggles (#524)
#524 gives icon buttons their tooltip as accessible name, so the Task Bar's icon toggles share names with menu rows. right_clicking_an_object_selects_it_and_its_menu_arranges_it and rows_hidden_in_the_menu_bar_are_hidden_in_context_menus found two nodes; the canvas tests' menu_row helper skips toggle buttons.
2026-10-11 19:12:15 +00:00
aiongg f1459e6e64 Merge #524: Pathfinder section in Properties
Conflict: ROADMAP.md: both progress lines kept, the PR's first
2026-10-11 19:12:01 +00:00
aiongg 13fb00fd08 Integration: transform.move on content reports the ids it moved (#521)
#521 makes transform.move return {moved, ids}; next's move_content (the content-selection path, content?) returned only {moved}. It returns the ids of the items whose content or frame moved, and copies_report_their_ids checks it.
2026-10-11 19:11:53 +00:00
aiongg 3af8c6275d Merge #521: Copies report their ids
Conflict: ROADMAP.md: both progress lines kept, the PR's first
Conflict: crates/engine/src/cmd/object.rs: transform.move params doc is next's (with content?) plus the PR's return text; next's test modules and the PR's copy_ids_tests both kept
2026-10-11 19:11:43 +00:00
aiongg 12647790c8 Integration: formatting_affects_text test fills with default swatch names (#520)
#520 makes object.fill refuse a name that isn't a swatch; next's Formatting Affects Text test filled the frame with "Cyan" and the text with "Magenta". It uses the default swatches C=100 M=0 Y=0 K=0 and C=0 M=100 Y=0 K=0. No other caller passes a bare name.
2026-10-11 19:11:24 +00:00
aiongg fc05e814df Merge #520: Object fills and strokes must name a swatch
Conflict: ROADMAP.md: both progress lines kept, the PR's first
Conflict: crates/engine/src/cmd/object.rs: next's reorder/group test modules and the PR's swatch_name_tests both kept
2026-10-11 19:10:39 +00:00
aiongg d8f1e69882 Merge place-no-autofit: an image placed into a frame leaves Auto-Fit off
Conflict: crates/engine/src/cmd/file.rs: next's natural-size (bw, bh) fill with the branch's comment; both place-into-frame paths set auto_fit to the default
2026-10-11 19:10:20 +00:00
aiongg 53d57e7e17 Merge #84 update: paste text with no insertion point makes a text frame
Conflict: crates/engine/src/cmd/edit.rs: edit.paste params doc joins next's `spread?: index (0)` with the branch's text-frame and `at?` text; enablement is the branch's has_doc
Conflict: crates/ui-egui/src/canvas.rs: next's current_spread and the branch's view_centre both kept
2026-10-11 19:10:07 +00:00
aiongg 1da2bb9082 Place: an image placed into a frame fills it once and leaves Auto-Fit off 2026-10-11 18:59:08 +00:00
aiongg 162a7f14bb Paste: text from another app with no insertion point becomes a new text frame (#518)
Paste with no text insertion point and text on the system clipboard that
does not stand for copied objects creates a text frame holding it,
selected as an object: as wide as the first column of the page's margin
area, as tall as the text (at most the margin area) and centred in the
view. One undo removes it.

edit.paste takes optional spread and at params and is available whenever
a document is open, since the engine cannot see the system clipboard.
The paste keys without a native menu pass the paste event's text; menu
Paste reads the system clipboard. With a native menu, an object copy
records the system clipboard's text at that moment, so older text from
another app still pastes the copied objects.
2026-10-11 18:55:50 +00:00
moppeeerandClaude Opus 5.5 191594897b feat(ui): Pathfinder section in Properties
With several objects selected, InDesign's Properties panel shows
Pathfinder: Add, Subtract, Intersect, Exclude Overlap and Minus Back.
DesignCraft had them only in Object › Pathfinder and the Pathfinder
panel. The section sits after Align, with code-drawn icons.

Section titles and icon buttons in Properties now have accessible names
(the title; the button's tooltip), so screen readers can tell them apart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:16:44 +02:00
moppeeerandClaude Opus 5.5 b837371f50 feat(engine): Copies report their ids
transform.move with copy, edit.duplicate and edit.stepAndRepeat
returned only a count, so a script (or an agent) couldn't act on the
copies it had just made. They now return `ids`: the objects moved, or
the copies. The counts are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:09:00 +02:00
moppeeerandClaude Opus 5.5 6f053fc7b3 fix(engine): Object fills and strokes must name a swatch
object.fill and object.stroke stored any string as the swatch, so a
name like `Paper` or `Black` (the swatches are `[Paper]`, `[Black]`)
painted nothing without an error. They now refuse an unknown name,
change nothing, and suggest the swatch it was probably meant to be.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:06:43 +02:00
aiongg 0b0a0c717f Integration: German rows for Optical Margin Alignment and Document Setup (#509, #469)
de.rs has a row for every key of the shared table; #509 and #469 added these keys to the shared table only. Translations follow the shared table's German column.
2026-10-11 18:04:45 +00:00
aiongg a5326169f5 Integration: indd-utils 867c967a 2026-10-11 18:03:53 +00:00
aiongg c99dbd7d6b Integration: Document Setup margins let matching pages follow their parent page (#469)
#469's Document Setup sets every page's and parent page's margins; next's parent-margins model (470aac7d) keeps pages marked local_margins out of later parent edits. After a Document Setup margin edit, pages that now match their parent page (margins and columns) lose the local mark, and parent margins are synced; pages with their own columns stay local.
2026-10-11 18:03:46 +00:00
aiongg 76450c630a Merge #469: feat(ui): Lay out Document Setup like InDesign's
Conflict: ROADMAP.md: progress log keeps both
Conflict: docs/target-app-parity.md: next's New Document line, the PR's Document Setup line
Conflict: crates/engine/src/cmd/layout.rs: setup_tests keep both tests
Conflict: crates/ui-egui/src/dialogs.rs: dispatch takes the PR's documentSetup block and keeps next's numberingSection; tests drop the PR's copies of dialog_context, dialog_frame, visible_label, click_dialog and scroll_dialog (next has them)
Conflict: crates/ui-egui/src/i18n.rs: TABLE keeps both; the PR's Top:/Bottom:/Left:/Right: rows dropped (next has them)
Conflict: crates/ui-egui/src/i18n/it.rs: keeps both; the PR's Top:/Bottom:/Left:/Right: rows dropped (next has them)
2026-10-11 18:03:16 +00:00
aiongg 43019733a8 Merge #512: Hyphenation: Portuguese text is hyphenated with hyph-utf8's Portuguese patterns 2026-10-11 18:01:34 +00:00
aiongg 5bc9594679 Merge #511: Place: PDF pages and SVGs keep their exact size
Conflict: crates/engine/src/cmd/file.rs: file_place keeps next's PdfCrop block (pdf_crop, Asset, crop_pdf, (nw, nh) fallback) with the PR's exact natural size for (nw, nh); the PR's crop_box match dropped; pdf_crop_tests keep both tests
2026-10-11 18:01:34 +00:00
aiongg 3fedc862f6 Merge #510: Color parsing: one scale per colour, not per component
Conflict: crates/engine/src/cmd/style.rs: parse_color object arm keeps next's early gray branch (per-value scale), then the PR's shared-scale CMYK
2026-10-11 18:01:14 +00:00
aiongg 7be1375aab Merge #509: feat: Add UI checkbox for Optical Margin Alignment (#494) 2026-10-11 18:01:03 +00:00
aiongg f3f8162996 Merge #490: i18n: Czech interface language
Conflict: crates/ui-egui/src/lib.rs: next's take_ime_discard/canvas_ime, then the PR's status_error
Conflict: crates/ui-egui/src/panels/glyphs.rs: next's grid test assertions kept, the PR's misplaced status line dropped; the insert error goes through status_error
2026-10-11 18:01:03 +00:00
aiongg 1f6004505e Merge #506: Recovery: each running app keeps its own recovery data
Conflict: crates/engine/src/recovery.rs: run_dir takes the PR's DirBuilder (0o700 on Unix, create_dir elsewhere); rest is next's
2026-10-11 18:00:49 +00:00
aiongg 2f660106b5 Merge upstream main (ca343e89) 2026-10-11 18:00:41 +00:00
noah1400 8119eece43 Recovery: run_dir passes clippy on Windows (#496)
The builder for a run's folder was `mut` only for the mode that Unix
sets, so `-D warnings` rejected it everywhere else. The folder is now
made the way `secure_recovery_dir` makes the recovery folder: with its
mode on Unix, and with `create_dir` elsewhere.
2026-10-11 19:39:09 +02:00
LosminekandClaude Opus 5.5 59f358f709 i18n (cs): translate remaining dialog, panel, menu and About strings
Wrap the English captions that still bypassed `tr`: print range radios,
shortcut recording prompt, Preferences snapping labels, Find/Change results,
import style-conflict options, Insert Cross-Reference "Link To", Layers
status line (via count_label), Properties/Table/Swatches/Task Bar tooltips,
Quick Apply style categories, hyperlink/bookmark page text, Story Editor
title, the About window (tabs, links, app descriptions) and the credits
tables. Composed strings use named-placeholder templates; Czech counts use
the existing plural helper. Adds the Czech strings, a "contributors" context
for the Name column, and the matching stale-key allow-list entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:34:17 +02:00
LosminekandClaude Opus 5.5 314f82eba0 i18n (cs): translate status-bar messages
The status line showed English for the messages the UI composes itself.
Literal messages and templates now go through `tr` at their call sites
("Packaged {count} files into {dir}" and similar), the "<feature>: <error>"
messages share a small `DesignApp::status_error` helper that translates the
feature name, and "Home" is translated too. Engine error texts stay as the
engine wrote them. Adds the Czech strings, the stale-key allow-list entries
and a test for the helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:29:24 +02:00
LosminekandClaude Opus 5.5 63b0425464 i18n (cs): translate the tool names in the Tools panel
Toolbar tooltips and flyouts showed the English labels from the tool
catalogue. Look the labels up with `tr` and add the 37 Czech tool names
(InDesign-style "Nástroj ..." naming). The stale-key test now also accepts
keys that are tool labels, and a new test checks every tool has a Czech name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:26:40 +02:00
LosminekandClaude Opus 5.5 e24c0190f8 i18n (cs): translate labels that were looked up but missing from the catalog
Find/Change > Object fill labels, the QR code field labels and the
Chinese/[No Language] entries of the text-language list already go through
`tr`; add their Czech strings and list them in the stale-key test's
allow-list so the catalog test accepts them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:25:27 +02:00
LosminekandClaude Opus 5.5 fb9da639e7 i18n (cs): translate the Activate Panel, Move Panel and Change Panel Layout commands
They appear in Keyboard Shortcuts and command search but had no Czech entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:04:24 +02:00
moppeeerandClaude Opus 5.5 90407a892a fix(ui): Document Setup keeps each page's margins unless they're edited
OK sent the first page's margins every time, and the engine writes them to
every page and parent page, so changing only the page count overwrote
each page's own margins. The margins now go only when they were edited.

Measures are read as every dialog reads them again, leaving bare-number
units to the shared change in #468.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:01:28 +02:00
moppeeerandClaude Opus 5.5 2d1cad4c45 feat(ui): Lay out Document Setup like InDesign's
File > Document Setup now follows InDesign's layout: Intent, Number of
Pages and Start Page # with Facing Pages and Primary Text Frame (shown,
set when the document is made) beside them, Binding; a Page Size group
(preset menu keeping the orientation, width and height with arrows,
orientation icons); a Margins group (top, bottom, inside, outside, or
left and right without facing pages, with a link that keeps them equal);
Bleed and Slug (collapsible, a column per edge, a link per row); and an
Adjust Layout box whose button applies the changes with objects
following the new page size and margins.

Measures are read in the document's units (a plain 12 is 12 mm in a
metric document, not 12 picas). OK sends one layout.documentSetup (one
undo step); a value that can't be read keeps the dialog open with the
reason in the status bar. New strings are translated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:53:40 +02:00
moppeeerandClaude Opus 5.5 7234fd9080 feat(engine): Document Setup sets every page's margins; refuses impossible sizes
layout.documentSetup takes `margins` (a number or {top, bottom, inside,
outside}) for every page and parent page, in the same undo step as the
rest of the setup; with adjustLayout objects follow the new margins too.
It reports the first page's margins and whether the document has a
primary text frame. Widths and heights outside 0-216 in, and margins it
can't read or outside 0-216 in, are refused before anything changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:53:40 +02:00
japbcoelhoandClaude Opus 5.5 db55cb7e49 Hyphenation: Portuguese text is hyphenated with hyph-utf8's Portuguese patterns
Text set in Portuguese ("Portuguese: Brazilian", "Portuguese", pt_BR) got
no hyphenation, so justified Portuguese columns could only stretch their
word spaces (up to 335 % of the normal space in a 56 mm column of 10 pt
Times).

Turn on hypher's "portuguese" feature, beside Spanish: hyph-pt.tex 1.4
(2024-07-13) from hyph-utf8, BSD-3-Clause, credited in NOTICE.
Lang::for_language already maps the Portuguese names and locale codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:52:46 -03:00
japbcoelhoandClaude Opus 5.5 72bdc0a919 Place: PDF pages and SVGs keep their exact size
file.place sized a placed PDF page (and SVG) from its size rounded to
whole points, while the export draws the page into that size: a page of
91.774 x 613.276 pt became 92 x 613 and was drawn 0.25 % wider and
0.3 % shorter, so pieces laid edge to edge left gaps of up to 1.9 pt.
A 100.4 x 50.4 pt page placed 100.4 pt wide came out 50.2 pt tall:
`Rect { x0: 0.0, y0: 0.0, x1: 100.4, y1: 50.2 }`.

The graphic's natural size is now the exact page (crop box) or SVG size;
the rounded pixel size stays for display and preflight. place.load (the
place cursor) gets the same exact size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:52:46 -03:00
japbcoelhoandClaude Opus 5.5 5a1e9de92e Color parsing: one scale per colour, not per component
A CMYK component of 1 or less was read as a fraction even when the other
components were percentages, so {"c": 0.7, "m": 0, "y": 12.2, "k": 0}
(a pale cream) became C 70 % Y 12.2 % and exported as
`0.7019608 0 0.12156863 0 k`. The same applied to RGB arrays.

Now a colour is read as percentages (0..100, or 0..255 for RGB) when any
component is above 1, and as fractions only when every component is
within 0..1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:52:46 -03:00
Mara Johnson a02fc011bf Paragraph panel: Optical Margin Alignment checkbox (#494)
The composer already hangs punctuation when a paragraph's opticalMargin is on, but nothing in the UI could turn it on.

Reported by @mjohnson7cd
2026-10-11 12:41:33 -04:00
aiongg 933cfb11e6 Integration: recovery folders build on Windows without an unused mut (#506) 2026-10-11 16:40:05 +00:00
aiongg 68974c0d7d Integration: indd-utils bff0fd4d 2026-10-11 16:37:23 +00:00
aiongg 52c28c625e Merge #490: i18n: Czech interface language
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
2026-10-11 16:37:15 +00:00