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.
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.
#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.
#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.
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
#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.
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
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
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
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.
After a panic the guard said that no undoable command is running. A
command that ran the one that panicked and carried on then had each
later command it ran record an undo step of its own. The guard now
puts that back to what it was when the command started.
Rotate Spread, Proof Setup, Proof Colors, Flattener Preview, Show Tag
Markers, Separations Preview and Show/Hide Tagged Frames were at the end
of the Type menu. They are in View now, which follows InDesign's order:
Overprint Preview and proofing, zoom, Rotate Spread, Screen Mode,
Display Performance, rulers, Extras (frame edges, text threads), Grids &
Guides and Structure (tagged frames, tag markers). Show Hidden
Characters stays in Type, as in InDesign; W still toggles Preview.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Fill and Stroke menus in Properties › Appearance have a Tint
field and, for a text frame, Apply To: Frame or Text. DesignCraft's
listed only the swatches, so a tint needed the Swatches panel and a
text frame's text colour needed a text selection.
The menus now have both: the tint applies to the fill or stroke of the
frame (object.fill / object.stroke) or of its text (type.char fillTint /
strokeTint); Apply To: Text colours the whole story. With text selected
the menu applies to the selected text, with its tint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
frame.create and text.insert turned \r and \r\n into paragraph returns,
but story.replaceRange, story.setText, note.new, footnote and endnote
text, type on a path and table cells kept the CR in the text, where it
drew as a missing glyph and joined the paragraphs. They all use
text_param now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
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.
Only these two dialogs read bare numbers in the ruler unit; other dialogs keep their meaning.
Apply to: this page, both pages of the spread, or all pages. Parent edits default to the whole parent spread.
Replace unchecked indexing in inherited_guides and marginsAndColumns with get().
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRYQ5eieuUrtxhdbh6goq
#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.
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)
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
Corners were applied only where two straight segments meet, and every
other segment was redrawn as a straight line: a Pathfinder quarter
circle with rounded corners rendered as a triangle with one round
corner. Corner points are now where the path turns; the sides next to a
corner are trimmed along their length, curves included, and stay
curves. Smooth points are left alone; rectangles are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
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>
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>
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>
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>
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>
A running header (or any text variable) in a parent-page frame was empty or
wrong on pages whose page number repeats an earlier one: with two sections
that both number from 1 (front matter 1-10, body 1-...), body pages 1-10
showed nothing. The renderer and PDF export passed only the page's name to
the composition cache, which looked the page up as the first page with
that name - in the front matter, before any heading.
CompositionCache::get now takes the absolute page index (None for a story's
own frames) and derives the name for page-number markers from it; the cache
is keyed by index, so two pages with the same name no longer share a
composed header. The renderer and PDF export pass first_page_of_spread + i.
Test: running_header_on_parent_page_with_repeated_page_numbers (pages named
1, 2, 1, 2; the only heading on the third page). Before the fix the third
page's header was empty (0 glyphs); with it, "Epsilon" (7).
Found with an InDesign IDML (a dictionary with two sections and Match
Character Style running headers on its parent page), together with #301.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CgGsJkVe5GYG9qK6VFdECa
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>
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>
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>
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>
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>