Commit Graph
293 Commits
Author SHA1 Message Date
.CooCooandDylan M. Taylor 5fb75aaefc Properties: Text Frame section shows inset spacing and vertical justification (#2661)
* Properties: Text Frame section shows inset spacing and vertical justification

Properties › Text Frame now shows the frame's inset spacing under the
columns: Top and Bottom, a link that makes all four the same, then Left
and Right. A non-rectangular frame shows one Inset, the distance its text
keeps from the outline. Four buttons set Vertical Justification to Top,
Center, Bottom or Justify. Type on a path shows neither.

The section also shows with the Type tool in a frame. There it changes
the frame that shows the insertion point, or every frame that holds part
of the selected text, as Object › Text Frame Options does.

* Properties: one Inset for a non-rectangular frame keeps the other sides

The single Inset sets only the top inset, the one kept from the
outline. A rectangular frame that holds part of the same selected text
keeps its own sides.

* Properties: the one Inset field and the composer share the frame outline test

FrameOutline::of_item builds an item's outline with its corner options
applied. The composer uses it to keep the top inset from the outline,
and the Properties panel uses it to decide whether a frame shows one
Inset, so the two give the same answer for every frame.

* Text Frame Options: frames taken while typing stay with their document

OK is refused when another document became active after the dialog opened, so the saved frame ids do not change frames in that document.

* Properties: the inset link starts linked again after Revert

The link's state is kept per document state instead of per document, so
a frame with equal insets in the reverted document starts linked.

* Text Frame Options: frames taken while typing are refused after Revert

Revert keeps the document's id but replaces its state, so a new frame
can reuse a saved frame id. The dialog now ties the frames to the
document state, and OK is refused after Revert as it is in another
document.

* Properties: the one Inset of a non-rectangular frame sets all four sides

The composer bounds a shaped frame's text by its rectangle less all four
insets as well as by the outline, so a single Inset that changed only the
top left hidden sides in place: lowering a uniform 96 pt inset to 0 kept
text overset. When every frame the field changes is shaped, it now sets
all four sides. With a rectangular frame among them, only the top inset
changes and each frame keeps its other sides.

* Fix text frame dialog merge resolution

* Keep text frame preview targets fixed

* Fix target field key inference

* Tests: Text Frame Options show four sides for text through an oval and a rectangle

With the Type tool and text selected through an oval and a threaded
rectangle, with the oval as the caret's stored frame, the dialog shows
the four inset sides, a changed Top leaves the rectangle's other sides
as they were, and the link stays off while the rectangle's sides are
uneven.

* Properties: the inset link starts off when another frame has uneven sides

With selected text that runs through several frames, the link of Text
Frame > Inset Spacing started linked when the frame the section shows had
four equal insets, and a changed Top then set all four sides of every
frame. The link now starts linked only when every frame the field changes
has four equal insets. Its state is kept for that set of frames, so a link
turned on for one frame does not carry over to selected text that also
runs through a frame with uneven sides.

---------

Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
2026-11-12 17:27:08 -05:00
.CooCoo 66b8c8ba3e Object styles: checks and fixes for corners, strokes and the style dialog (#2721)
- Corner options use path order for a path with more than one subpath, so
  a second rectangle no longer takes the first one's corner order.
- IDML export writes EnableStrokeAndCornerOptions="false" for a style
  without corners, so it does not take corners from its based-on style on
  import.
- style.object.create and style.object.edit refuse a stroke gap tint
  outside 0 to 1 and a stroke type field that its kind does not take, as
  object.stroke does. An edit that changes nothing returns restyled: 0.
- New Object Style and Object Style Options read a bare number in the
  document's ruler unit, keep a Text Frame General measurement that was
  not edited at its exact value, and New Object Style refuses a name
  another style has.
- Clear Overrides in the Object Styles panel is enabled when any selected
  object differs from its style.
2026-11-12 17:25:39 -05:00
Dylan M. Taylor e6ab0d263e Merge branch 'main' into feat/duplicate-layer 2026-11-12 16:43:33 -05:00
dotCooCoo 07d264fd23 Copy: bound the anchored-object walk through cells and notes
Copying a story gives the objects anchored in its table cells and
notes fresh ids down to 64 levels, as the table copy does. A copy whose
stories below that level hold anchored objects, tables or notes is
refused with the nested-too-deeply error instead of recursing without
limit.
2026-11-12 12:57:17 -08:00
dotCooCoo 963dc57d3b Merge main into feat/text-frame-options-type-tool 2026-11-12 12:23:08 -08:00
dotCooCoo b1ca9dd97d Merge main into feat/duplicate-layer 2026-11-12 12:23:07 -08:00
dotCooCoo 5662fefdaf Merge main into feat/duplicate-layer 2026-11-12 10:27:44 -08:00
autocraft-bot[bot] 99da9632b3 Merge main into feat/text-frame-options-type-tool 2026-11-12 18:05:59 +00:00
dotCooCoo 8d39765e93 Layers: use the anchored copies object copying now makes
Copying a frame now gives the objects anchored in its story copy ids of
their own and copies of the stories of anchored text frames. Duplicate
Layer renumbered them a second time, so live captions kept pointing at
the originals and shared stories were copied again. It now records the
ids of those copies instead.

Copying a frame also renumbers objects anchored in endnotes inside table
cells and footnotes, which kept their original ids before.
2026-11-12 09:15:31 -08:00
FredApps 2348380198 Merge main and preserve PR #2663 behavior 2026-11-12 18:14:28 +01:00
FredApps 9aa103b3a8 Merge pull request #1843 from dotCooCoo/fix/copied-story-anchor-table-ids
Copy: copied text gets text anchors and tables of its own
2026-11-12 18:04:28 +01:00
dotCooCoo 7604db695f Copy: point copied cross-references at copied anchors in one pass
Each copied story with text anchors walked every story copied before it
to retarget their cross-references, so copying many such frames took
time quadratic in their number. The copies' cross-references are now
pointed at the copied anchors once, after the last item is copied.
2026-11-12 07:57:27 -08:00
dotCooCoo c2a1543528 Copy: mark the renumber results as must-use
renumber and its helpers return false when a copy nests deeper than
MAX_COPY_DEPTH and must not be inserted. They now carry #[must_use], so
a caller that drops the result fails to build under -D warnings.
2026-11-12 07:40:29 -08:00
dotCooCoo 1fbb7e86b0 Merge #1084 (Alpha Channel text wrap) into main 2026-11-11 19:50:30 -08:00
dotCooCoo 3473b8d96e Text: Text Frame Options refuse an ids that is not a list of object ids
A call with an `ids` or `id` that is not an object id used to fall back
to the selected frame or the caret's frame. It now fails and leaves the
document unchanged.

The Properties panel's Text Frame section shows the frame Text Frame
Options change: with the Type tool, the frame the caret is drawn in.
2026-11-11 19:46:20 -08:00
dotCooCoo 18be5b76f5 Text: Text Frame Options in a footnote or table cell change the frame that shows it
With the insertion point in footnote text or a table cell and no stored
frame on the caret, Text Frame Options changed the last frame of the
thread. They now change the frame the caret is drawn in: the frame that
holds the placed footnote, or the cell's own occurrence (not a repeated
header or footer), else the frame that shows the footnote reference or
the table's anchor.
2026-11-11 19:06:29 -08:00
dotCooCoo 7809f5e9da Text: frame columns, gutter, switches and indents are checked too
object.textFrameOptions refuses a gutter outside 0 to 15552 pt, a column
count outside 1 to 40 (it was clamped) and an on/off option that is not
true or false (it was skipped). The Control bar's Columns field stops at
40, as the other column fields do. The params text gives the ranges and
lists flexibleWidth.

type.para and paragraph style create and edit refuse left and right
indents outside 0 to 15552 pt and first and last line indents outside
-15552 to 15552 pt. A style made from the selection is checked with the
values it takes from the selection.

style.paragraph.apply and style.paragraph.redefine check that Minimum,
Desired and Maximum stay in order in each justification row they change,
over the overrides paragraphs keep, and refuse the change otherwise.
2026-11-11 18:42:32 -08:00
dotCooCoo 510269744a Text: Text Frame Options open from the Type tool and change the frame holding the caret
Object > Text Frame Options and Cmd+B are enabled with a text caret or a
text selection. Without ids or selected objects, object.textFrameOptions
changes the frame that shows the insertion point, or every frame that
holds part of the selected text, instead of every frame of the story.
The dialog shows that frame's options and keeps the frames it opened
with while the preview reflows the text.

An empty ids list and an id that is not in the document are refused.
Options a frame already has leave the document unchanged and add no
undo step.

Fixes #2396
2026-11-11 18:40:25 -08:00
dotCooCoo e90517be45 Text: paragraph spacing and justification values are checked
type.para, style.paragraph.create and style.paragraph.edit accepted any
number for paragraph spacing and justification. They now refuse Space
Before, Space After and same-style spacing outside 0 to 15552 pt, word
spacing outside 0% to 1000%, letter spacing outside -100% to 500%, glyph
scaling outside 50% to 200%, Auto Leading outside 0% to 500%, and a
Single Word Justification other than left, center, right or
fullyJustified. Each justification row needs Minimum <= Desired <=
Maximum over the values the paragraph or style resolves to after the
change, including the styles based on an edited style and the
paragraphs, table cells and notes that use them.

object.textFrameOptions refuses an inset outside 0 to 15552 pt or a list
that is not four sides, and a verticalJustification, firstBaseline,
autoSize or columnsKind that is not one of its names. These were applied
or skipped without an error before. IDML import reads these values as
before.
2026-11-11 17:51:19 -08:00
aiongg e977f82558 Fix [Bug Report] [DesignCraft] Image content and frame don't move together (#2423)
Fixes #2422.

- crates/engine/src/cmd/object.rs
- crates/engine/tests/autocraft_regression_2422.rs
2026-11-06 18:21:30 -05:00
dotCooCoo 09832b12e8 Copy: skip cross-reference passes for stories without anchors or cross-references
Copying many text frames no longer walks every earlier copy for each new story: earlier copies are revisited only when the new story brings text anchors, and the new story's cross-references are mapped only when it holds any.
2026-11-04 12:02:45 -08:00
dotCooCoo 6052a504bf Copy: nested anchored stories keep cross-references to each other's copies
A story anchored in a copied story is copied before its host story enters
the document, so cross-references between the two kept the original
anchors. After a copied story is stored with the stories anchored in it,
the cross-references of every copy so far are pointed at the copied
anchors again.

A copy whose table cells nest tables or notes deeper than 64 levels is now
refused, as deeply nested groups are, instead of keeping the original's
table ids below that depth.
2026-11-04 11:50:50 -08:00
dotCooCoo 5e0a6aa6ea Merge main into fix/copied-story-anchor-table-ids 2026-11-04 10:07:39 -08:00
aiongg b1f67ee4e4 Merge pull request #2211 2026-11-04 04:14:12 +00:00
Dylan M. Taylor 4071bd40e6 address review: skip a graphic whose PDF crop is too large to trace 2026-11-04 00:39:05 +00:00
dotCooCoo c51f02ee67 Copy: tables inside copied table cells and notes get ids of their own
A copied story's tables got new ids, but tables in the stories of its
table cells and notes kept the original's, so a duplicate or paste left
two tables with one id. They now get new ids from the destination
document down to the same nesting limit, and the cell paragraphs follow.
2026-11-03 14:18:43 -08:00
aiongg 474ecd61d4 Merge main into fix/1522-anchored-copy-ids 2026-11-03 19:01:23 +00:00
dotCooCoo c61a72e28f Merge main into fix/copied-story-anchor-table-ids 2026-11-02 18:18:13 -08:00
aiongg 8ef2702660 Integration: cargo fmt 2026-10-31 00:37:39 +00:00
aiongg 22a8292db4 Integration: #1451 object.effects patches keep the default mode of a new inner shadow or glow 2026-10-31 00:33:45 +00:00
aiongg aae929eb97 Merge track 3 2026-10-30 23:56:48 +00:00
aiongg 9806f66fed Merge track 2 (Direct Selection stack)
Conflicts: panels/properties.rs imports (union); i18n/*.rs adjacent rows (both kept).
2026-10-30 23:56:47 +00:00
aiongg f2389b791c Merge PR #1461: Text Frame Options
crates/ui-egui/src/dialogs.rs: both dialog tests kept
crates/ui-egui/src/i18n/*.rs: union of keys
docs/target-app-parity.md: main's change line plus the Text Frame Options entry
2026-10-30 23:16:09 +00:00
aiongg 0e4cb1f294 Merge PR #1451: Effects blend modes for Drop Shadow, Inner Shadow and Outer Glow
crates/ui-egui/src/effects_dialog.rs: kept both the angle dial tests (main) and the blend mode test (PR); the stray 'The dialog's body.' doc line moved back onto show.
2026-10-30 23:16:03 +00:00
aiongg 8d55602ef1 Merge PR #1430: Properties: Anchor Point(s) with Convert Points and Delete Point(s), as in the reference app
crates/tools/src/select.rs: took the PR's later anchor_selection and moved_points use; kept main's content-mode-off corner pull
crates/ui-egui/src/canvas/frames.rs: kept the handle_shown filter from #1657
crates/ui-egui/src/panels/properties.rs: kept main's imports
crates/ui-egui/src/panels/properties/tests.rs: kept both sides' tests
crates/ui-egui/src/i18n/{ar,cs,de,it,ja,ka,pl,pt_br,ru,uk}.rs: union of both sides' keys
2026-10-30 23:15:49 +00:00
aiongg 3b79317e03 Merge PR #1416: Direct Selection: select anchor points with a marquee across paths and move them together
crates/engine/src/tests.rs: kept main's tests and the PR's new tests
crates/tools/src/tests.rs: kept main's tests and the PR's new tests
2026-10-30 23:14:41 +00:00
aiongg 2bf89ce370 Integration: #1394 turning Auto-Fit off alone keeps the picture where it is 2026-10-30 21:23:07 +00:00
aiongg 3fa5fbbbc7 Merge PR #1433: Fitting: Clear Frame Fitting Options, and the submenu grouped as the reference app's
Conflicts:
crates/ui-egui/src/menus/tables.rs: kept the Fitting separator from the Object menu order (#1413); #1433's own comment line dropped
crates/ui-egui/src/i18n/*.rs (ar, cs, de, it, ja, ka, pl, pt_br, ru, uk): kept both sides' keys, plus #1433's Clear Frame Fitting Options
2026-10-30 19:45:49 +00:00
aiongg 4a6be7eef5 Merge PR #1406: Object: Corner Options opens a dialog laid out as the reference app's, also from the Properties Corner link
Conflicts:
crates/ui-egui/src/i18n/*.rs (table, ar, cs, de, it, ja, ka, pl, pt_br, ru, uk): kept both sides' keys (#1414's Stroke Type/Corner Shape, #1406's Corner Size and Shape:), no duplicates
2026-10-30 19:45:16 +00:00
moppeeerandClaude Opus 5.5 963ac447fa Text Frame Options: the paragraph spacing limit set without another branch in text_frame_options
Keeps the function within clippy's cognitive complexity limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:26:34 +01:00
moppeeer 7c3dcd1d9f Merge remote-tracking branch 'origin/main' into codex/alpha-text-wrap
# Conflicts:
#	crates/compose/src/lib.rs
#	crates/doc/src/item.rs
#	crates/engine/src/lib.rs
#	crates/idml/src/export.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
2026-10-29 12:06:13 +01:00
moppeeer 271d20ba7f Merge remote-tracking branch 'origin/main' into properties-wrap-offsets
# Conflicts:
#	crates/ui-egui/src/panels/properties.rs
2026-10-29 11:43:59 +01:00
moppeeer b26ae037de Merge remote-tracking branch 'origin/main' into corner-options-dialog
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
2026-10-29 11:43:35 +01:00
moppeeer 00a64e5943 Merge remote-tracking branch 'origin/main' into direct-select-anchor-points
# Conflicts:
#	crates/tools/src/select.rs
#	crates/ui-egui/src/canvas.rs
2026-10-29 11:43:21 +01:00
moppeeer 5a4012bab8 Merge remote-tracking branch 'origin/main' into properties-anchor-points
# Conflicts:
#	crates/tools/src/select.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/panels/properties.rs
#	docs/target-app-parity.md
2026-10-29 11:42:56 +01:00
moppeeer e094562ef6 Merge remote-tracking branch 'origin/main' into clear-fitting-options
# Conflicts:
#	crates/ui-egui/src/i18n.rs
#	crates/ui-egui/src/menus.rs
2026-10-29 11:42:45 +01:00
moppeeer b6fec896f9 Merge remote-tracking branch 'origin/main' into effect-blend-modes
# Conflicts:
#	crates/doc/src/item.rs
#	crates/idml/src/export.rs
#	crates/idml/src/import.rs
#	crates/ui-egui/src/effects_dialog.rs
2026-10-29 11:42:14 +01:00
moppeeer 4145fcbc44 Merge remote-tracking branch 'origin/main' into text-frame-options-layout
# Conflicts:
#	crates/ui-egui/src/dialogs.rs
#	crates/ui-egui/src/i18n.rs
#	docs/target-app-parity.md
2026-10-29 11:41:36 +01:00
VoiceLessQ ba1ee2329b Give anchored objects fresh ids when copying text frames (fixes #1522)
Copying a text frame cloned its story but left the objects anchored in
it with the original's item ids. Save does not validate, load runs
Document::check and rejects duplicate ids, so a duplicated or pasted
frame with an inline graphic produced a file that failed to open with
"not a DesignCraft document: duplicate item id".

renumber (Duplicate, Alt-drag copy, Paste, Paste into text, parent item
overrides) and the data merge copy now give every anchored item in the
copied story, its table cells, footnotes and endnotes a fresh id.
Anchored text frames from IDML get their own story copy. Assets are not
adopted again: the story copy already remapped them.

The IDML export tests that relied on duplication to create shared ids
now set the shared id explicitly, so the export guard stays covered.
Files already saved with duplicate ids still do not open.
2026-10-28 21:10:50 -02:00
Dylan M. Taylor 5b21472180 Refactor engine for strict Clippy checks 2026-10-28 11:39:26 +00:00