Commit Graph
172 Commits
Author SHA1 Message Date
Brandon Thomas 742d46446f Merge PR #474 2026-10-15 00:35:27 -04:00
Brandon Thomas f79a507486 Merge PR #458 2026-10-15 00:35:27 -04:00
Brandon Thomas 84dbba029f Merge IDML/text cluster
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/uk.rs
2026-10-14 23:54:49 -04:00
Brandon Thomas afd8c0a0de Merge PR #789
# Conflicts:
#	crates/engine/src/cmd/style.rs
2026-10-14 23:42:34 -04:00
Brandon Thomas 450503f538 Merge EPUB/docx/datamerge cluster 2026-10-14 23:36:46 -04:00
Brandon Thomas 94d0c57236 Merge PR #937
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/uk.rs
2026-10-14 23:14:44 -04:00
Brandon Thomas 47e9e576d4 Merge PR #610 (linked text files read through crate::io, so the automation roots apply) 2026-10-14 23:07:27 -04:00
Brandon Thomas 528264a4a9 Merge PR #823 (with main's radial ellipse: linear gradients go through #823's linear_axis) 2026-10-14 23:07:06 -04:00
Brandon Thomas ee498ac68f Merge PR #973
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/uk.rs
#	crates/ui-egui/src/panels/properties.rs
2026-10-14 22:38:58 -04:00
Brandon Thomas ed3acb0f82 Merge PR #979 2026-10-14 22:05:13 -04:00
Brandon Thomas 2e5e3c4000 Merge PR #951 2026-10-14 22:05:13 -04:00
Brandon Thomas f4333338b3 Merge PR #889 2026-10-14 22:05:12 -04:00
Brandon Thomas 411ef4c454 Merge PR #881 2026-10-14 22:05:12 -04:00
Brandon Thomas 4bd1fbab37 Merge PR #765 2026-10-14 22:05:11 -04:00
Brandon Thomas 02dd8ade8d Merge PR #704 2026-10-14 22:05:11 -04:00
Brandon Thomas 3cdda36680 Merge PR #657 2026-10-14 22:05:11 -04:00
Brandon Thomas 3710dfa16f Merge PR #637 2026-10-14 22:05:11 -04:00
Brandon Thomas b379a5f0a5 Merge PR #577 2026-10-14 22:05:10 -04:00
Davit Matchakhelidze 9792aa025e Merge upstream main into ka-language 2026-10-15 03:38:25 +04:00
moppeeerandClaude Opus 5.5 6fe0770f47 Flex Layout: containers that lay out their objects, as InDesign 2026's
A Flex Layout container is a frame holding its objects as nested items
(as Edit › Paste Into makes), with a `flex` record: direction, wrap,
justification, cross-axis alignment, Fixed/Auto width and height, padding
and horizontal/vertical spacing. designcraft_doc::flex lays the objects
out (a Flexbox subset: lines, justification, alignment, Auto sizing), and
the engine runs it after every edit, so the container keeps its objects
in place whatever changes.

Commands: flex.add (Add to Flex Layout; detects aligned objects: their
direction, Auto size, Space Between at their own spacing, as InDesign
does), flex.convert (a group or rectangle frame), flex.remove (objects
stay, grouped), flex.set (every panel setting, plus the alignment grid
cell), flex.reorder. Resizing a container by its handles or W/H changes
its box and makes that side Fixed instead of scaling its objects;
dragging an object inside one drops it in the nearest place.

UI: Object › Flex Layout (Add to, Convert to, Remove, Show Flex Controls),
a Flex Layout panel (Window › Panels) laid out as InDesign's (Create Flex
Layout; alignment grid, W/H with Auto/Fixed; justification menu, four
directions, wrap; padding with the link button; spacing, greyed as
InDesign does when the justification works it out or nothing wraps), and
the same section in Properties. Icons are new drawings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:20:50 +02:00
NetterSilverandClaude Haiku 5.5 8b834d0533 Fix overflow in layout.pages.insert when after is u64::MAX
Found while testing crates/doc/src/build.rs:377 (Document::insert_pages), called from crates/engine/src/cmd/layout.rs:91

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 19:17:09 +00:00
moppeeer 9327a55100 Merge origin/main into #468 (layout-parent-guides-units)
Main restructured the dialog dispatch; #468's Create Guides and Margins and Columns arms moved into it unchanged.
2026-10-14 19:24:45 +02:00
Jeffrey Thayne 999d0583a3 Merge remote-tracking branch 'origin/main' into linked-docx
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/dialogs.rs
2026-10-14 11:21:54 -06:00
Brandon Thomas 0df9238c73 Merge PR #850 2026-10-14 12:56:09 -04:00
Davit MatchakhelidzeandClaude Opus 5.5 5d4ed2a663 text: Georgian document language; no initial capitals for Georgian
Georgian is a Properties text language (IDML "Georgian" maps to ka). Georgian has no initial capitals: Mtavruli is only for all-caps text, so Change Case title and sentence case and index section heads leave Mkhedruli as it is (doc::capitalizes); upper case still gives Mtavruli.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-14 20:55:04 +04:00
moppeeerandClaude Opus 5.5 188c4f7007 Facing pages take their side from their section's page numbers
Chris Nielsen's "Numbering Page Sections" (7:03): starting a section at
page 1 on a left page (the spread 8–9 selected) turns it into a lone
right-hand page 1 in InDesign, and the pages after it shuffle. DesignCraft
kept the page on the left, so odd page numbers sat on left pages.

- Document::repaginate gives each facing page the side of its number in
  its section (odd: right, or left bound right to left). Document Setup's
  Start Page # is one case of it.
- layout.section repaginates when a section starts, changes or is removed;
  objects go with their pages, in one undo step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:03:58 +02:00
sanyamsingh001andCodex 17e280335a Merge tested main 0f4f382b0e into PR #458
Preserve the reviewed PR behavior and tested upstream base.

Co-Authored-By: Codex <codex@openai.com>
2026-10-14 19:08:24 +10:00
a2c0cb79ce A radial gradient on a box with no width or height is a circle across it
Review fix from aiongg (6db40bdb, the radial_ellipse part), ported to this
branch: a straight line's box has no ellipse, so its stroke's radial
gradient showed only the last stop once #823's gradient strokes land.

Co-authored-by: aiongg <aiongtaigi@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:39:03 +02:00
f69601b0ff A linear gradient across a straight line runs along its length, on screen and in PDF alike
Review fix from aiongg (72d7ea2e, with the line tests of 6db40bdb), ported
to this branch: Fill::linear_axis gives screen and PDF one gradient axis,
and a box with no extent along the gradient's angle takes its longer side.

Co-authored-by: aiongg <aiongtaigi@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:36:45 +02:00
moppeeer 5f00aa7bb3 Merge remote-tracking branch 'origin/main' into codex/gradient-strokes
# Conflicts:
#	crates/engine/src/cmd/style.rs
#	crates/idml/src/tests.rs
2026-10-14 10:33:30 +02:00
moppeeer 52e0aaa2d6 Merge remote-tracking branch 'origin/main' into codex/radial-gradient-ellipse
# Conflicts:
#	crates/engine/src/cmd/style.rs
2026-10-14 10:32:47 +02:00
Andres TorresiandClaude Haiku 5.5 be98657a22 feat(text): Typography panel lists and sets the OpenType features of the selection
A Typography panel (Window ▸ Show Panel, and the icon column) lists the
features of the selected text's fonts, merged over those fonts, grouped as
Ligatures, Alternates, Stylistic Sets (named by the font), Figure Style,
Figure Width, Figure Position and Capitals. A section or choice appears only
when a font offers it.

Each feature is a checkbox: checked when all of the selection has it, a dash
when only some of it does, empty when none does. A feature only some of the
selection's fonts offer is italic. Mutually exclusive choices are checkboxes
too, and choosing one turns the others off.

type.openTypeFeatures reports each feature's applied and available state over
the selection. type.feature turns features on or off across the selection,
keeping each run's other features. The fonts crate reads GSUB and GPOS
feature lists and stylistic set names.

The Character panel's OpenType menu is now a button that opens or focuses the
Typography panel.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-14 08:46:28 +01:00
moppeeer 3f1eb00bb3 Merge branch 'codex/page-tool' into codex/page-tool-control-panel
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 09:38:16 +02:00
moppeeer 65dbf3c3a2 Merge remote-tracking branch 'origin/main' into codex/page-tool
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 09:37:32 +02:00
Brandon Thomas 80663cccfd Merge PR #846 2026-10-14 01:54:43 -04:00
LabDennis ff5d866ff3 chore(sync): merge upstream main into PR #854 2026-10-14 06:51:45 +02:00
0f4f382b0e feat(text): improve editing, snapping, and threading
Add multi-click text selection, pending caret formatting and clipboard support, text-aware colour controls, guide/grid snapping, and frame threading with loaded-port interactions.

Include the layout, drop-cap and IDML updates carried from #83, with safeguards for generated and linked stories, external text references, local IDs, locked frames and atomic colour edits.

Fixes #23.

Co-authored-by: Sean Hammond <sean.hammond@und.edu>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:41:46 -06:00
moppeeerandClaude Opus 5.5 59b6125af1 feat(ui): Control panel for the Page tool; Controlled by Parent; Show Parent Page Overlay
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (1:02–
2:06, 13:47) sizes pages from the Control panel with the Page tool
selected: X/Y, W/H, the page-size preset ("US Business Card"),
orientation, Liquid Page Rule ("Controlled by Parent"), Objects Move with
Page and Show Parent Page Overlay. DesignCraft's Control panel showed the
(empty) object controls.

- ui: with the Page tool, the Control panel shows the selected page (or
  the page in view): the reference point (W/H, preset and orientation
  keep it in place via layout.pageSize's anchor), X/Y (read-only),
  W/H, the preset dropdown, portrait/landscape, Liquid Page Rule, Objects
  Move with Page (always on: pages don't move within spreads yet) and
  Show Parent Page Overlay.
- doc: LiquidRule::ControlledByParent (the parent page's rule, Off
  without one; resolved by liquid::effective_rule); Page.show_parent_overlay.
- engine: layout.pageOptions {pages, showParentOverlay}; liquid.pageRule
  takes controlledByParent.
- canvas: the parent page's size over a page with the overlay on.
- Liquid Layout panel and Control panel share InDesign's rule list
  (Off, Scale, Re-center, Object-based, Guide-based, Controlled by
  Parent); "US Business Card" preset; translations.

Builds on the Page tool PR (#862) for the selected page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:51:47 +02:00
moppeeerandClaude Opus 5.5 cc13e80c9d feat(tools): Page tool selects pages; handles preview the liquid rule, Alt-drag resizes
Chris Cicchino's "Adobe InDesign – Page Tool and Liquid Layout" (0:42–
2:06) selects a page with the Page tool, gets its bounding box with
handles, drags a handle (the page springs back: a liquid-rule preview),
holds Option to really resize it, Shift for proportions, and reads the
size in a tooltip by the cursor. DesignCraft's Page tool only opened a
generic Page Size dialog on click.

- tools: the Page tool selects the page under a click (none on the
  pasteboard); the selected page shows its outline, eight handles and
  its liquid page rule ("Scale", "Object-Based"…) above it. Dragging a
  handle previews layout.pageSize (the liquid rule re-flows the
  objects) and springs back on release; Alt resizes, Shift keeps the
  proportions; a W/H readout follows the pointer; resize cursors on the
  handles. Double-click a page for the Page Size dialog.
- doc: Selection.page (the Page tool's page); engine: layout.selectPage
  (no undo step).
- layout.pageSize `anchor` (0-8): the page grows away from the
  reference point and its objects and guides keep their place relative
  to it (a handle drag anchors the opposite edge); liquid rules work
  from that.
- canvas: PageHandles and Tag overlays; translations for the tags and
  the Resize Page undo label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 00:29:55 +02:00
LabDennis 0fd627aa44 perf(assets): index duplicate candidates by content (#727) 2026-10-13 23:12:09 +02:00
aiongg 129adfa429 Layout: Table of Contents dialog with entry styles, page number position and IDML TOC styles (#755) 2026-10-13 20:41:56 +00:00
sanyamsingh001andCodex f4f2f0bb08 FIX-TABLE-SELECTION: resolve selected merged-cell owners
Co-Authored-By: Codex <codex@openai.com>
2026-10-14 06:20:41 +10:00
moppeeerandClaude Opus 5.5 370dca2ca2 feat(render): gradient strokes, on screen, in PDF and in the Gradient panel
A gradient swatch on a stroke drew nothing: strokes were painted with a
single resolved colour. LYH Studio episode 6 gives the loop on the right
page (9:13) and, at first by accident, the circle (1:19, "right now it
is on the stroke") a gradient stroke.

- doc: Stroke::gradient_angle / gradient_vector (as Fill's) and
  Stroke::as_fill(), the stroke's paint as a fill.
- render and PDF: a gradient stroke is painted like a gradient fill,
  across the path's box (dash gaps and arrowheads keep their paints).
- engine: object.gradient {target: stroke} edits the stroke's
  gradient (kind, stops, angle, the Gradient Swatch tool's from/to);
  scaling moves the stroke's vector with the shape.
- IDML: GradientStrokeStart/Length/Angle round-trip.
- Gradient panel: acts on the stroke when the toolbox's Stroke box is
  in front, as InDesign's follows the Fill/Stroke proxy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:11:58 +02:00
Jeffrey ThayneandClaude Opus 5.5 7b33c981dc Links: only read a linked text file when its size or time changed
The Links panel lists links about twice a second, and each listing
hashed every linked text file. A linked text file now also remembers
its modification time (as Data Merge does for its source, through the
same size-and-time fingerprint): while size and time match, it isn't
read. A different size is Modified without reading. When only the time
changed, the content hash still decides (a file saved or synced again
without changes stays OK), and the session remembers that check by
size and time, so the next poll doesn't read the file again. Update and
Relink record the size and time from before their read. Test: polls of
an unchanged file don't read it (it is made unreadable), a touched but
unchanged file is read once and stays OK, a changed file is Modified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 09:30:40 -06:00
Jeffrey Thayne 38bf116604 Merge remote-tracking branch 'origin/main' into linked-docx 2026-10-13 09:25:53 -06:00
Gert Pellin 2a3d1dc183 Styles: name the attributes in the params docs, and a wrong one in the command's error (#777)
- describe style.paragraph.create (and .edit, style.character.create,
  .edit) gave chars?: {…} and para?: {…}. The descriptions now say they
  take type.char's and type.para's attributes and name the common ones.
- A wrong attribute gave "invalid parameters for `style`: unknown
  attribute `font`". The error now names the command and the group,
  and the attribute meant (nearest name, or one the key starts or ends)
  or else lists them all: "invalid parameters for
  `style.paragraph.create`: chars: unknown attribute `font`; did you
  mean `fontFamily`?". The suggestion comes from set_json, so
  type.char, type.para and find.change get it too.
- chars or para that isn't an object is an error instead of ignored.

Fixes #777
2026-10-13 16:48:27 +02:00
moppeeerandClaude Opus 5.5 7a30e5427e fix(render): radial gradients stretch with the object's box, as in InDesign
InDesign draws a radial gradient in the object's bounding box: on a
non-square frame it's an ellipse reaching the frame's sides, and a
Gradient Swatch tool drag keeps those proportions. LYH Studio episode 6
(3:16) gives the left page's background a radial gradient: magenta in
the middle, cyan out to every edge. DesignCraft drew a circle reaching
only the longer side, so a portrait page stayed purple at its sides.

- doc: `Fill::radial_ellipse(bounds)`: centre and radii (default: the
  box's centre and half its width and height; with a tool vector, its
  start, and its length measured with the box made square).
- render: the radial paint is that circle, stretched by the paint
  transform; PDF: the shading's transform does the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:58:05 +02:00
sanyamsingh001andCodex 3ac4d2e913 Preserve endnote and editorial payloads in text slices
Co-Authored-By: Codex <codex@openai.com>
2026-10-13 22:59:29 +10:00
Noah Scholz 65bb4e3f66 fix(tables): keep each table anchor in its own paragraph
Backspace at the start of the second of two consecutive tables merged their
anchor paragraphs: Story::delete kept one table id, the other table was
dropped and the paragraph held two anchors. Pasting a table next to an anchor
replaced the existing table the same way, and pasting several paragraphs
right before an anchor left its table unreferenced. Saving succeeded;
reopening failed with "paragraph must hold exactly one anchor".

fix_tables now splits a table paragraph that holds further anchors, so every
anchor gets its own paragraph again. delete and insert_story tell it which
table each surviving anchor belongs to (fix_tables_with), and insert_story
fixes tables up once after the whole paste instead of after every run.

Regression tests in doc (Backspace between tables, deleting the middle of
three, paste before/after an anchor, paragraphs pasted before an anchor) and
engine (text.delete and edit.paste through commands, then a file round-trip);
all failed before the fix.

Claude-Session: https://claude.ai/code/session_01La6SDgsmdZfgfDDmx3wiGU
2026-10-13 08:17:51 +00:00
moppeeerandClaude Opus 5.5 5b74bd71e4 fix(render): A group's gradient feather masks everything the group draws
The DestIn mask now covers the whole render target (and the PDF's
exported area), with the gradient kept in item space through the paint
transform, since past the gradient's ends the end opacity carries on: a
child's long drop shadow or thick stroke is faded, not cut off at a box.
feather_bounds counts only shown children and active states, walking
nested groups without recursion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 09:33:12 +02:00