Commit Graph
1155 Commits
Author SHA1 Message Date
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
aiongg 5dc90d3228 Merge #495: pt-BR: complete the interface translation
# Conflicts:
#	crates/ui-egui/src/i18n/pt_br.rs
2026-10-11 16:36:20 +00:00
aiongg ee2f4dffd6 Merge #506: Recovery: each running app keeps its own recovery data 2026-10-11 16:36:07 +00:00
aiongg 3fbaf6f2dc Merge #491: UI: Alt + wheel zooms the view at the pointer 2026-10-11 16:36:07 +00:00
Dylan M. Taylor ca343e8985 ci: refactor workflows to use storytold/craft-common-actions (#489)
* ci: refactor workflows to use reusable artcraft-common-actions

* ci: point reusable workflows to storytold/craft-common-actions

* ci: pin storytold/craft-common-actions to commit 27a978f and pass secrets explicitly

* ci: use @main (unpinned) for craft-common-actions with explanation comment
2026-10-11 11:52:22 -04:00
noah1400 257fb08dbd Recovery: each running app keeps its own recovery data (#496)
Document uids start at 1 in every process, and every running app wrote
its recovery entries into the one recovery folder. Two apps wrote over
each other's `1.designcraft`, and an app that started reopened and
removed the entries of one still running.

A run now has a folder of its own in the recovery folder and holds a
lock in it for as long as it runs. An app that starts moves the entries
of runs that have ended, and those an earlier version wrote, into its
folder and reopens them. A locked folder is left alone.
2026-10-11 16:55:39 +02:00
aiongg 3699b9c4d0 Merge ui-script-fallback: UI: show Tamil, Indic, Southeast Asian and other scripts from installed fonts 2026-10-11 14:14:40 +00:00