Commit Graph
4115 Commits
Author SHA1 Message Date
aiongg 8a6f9725b0 IDML: test a ruler guide in a column gutter without facing pages (#1096) (#1170) 2026-10-22 01:25:12 -04:00
macadminHU ec31f17a71 Merge branch 'main' into codex/hungarian-localization 2026-10-22 07:22:02 +02:00
aiongg 496b1899a2 macOS menu bar: menus keep working after a language change; key equivalents follow the shortcuts (#1540)
* macOS menu bar: keep working after a rebuild; key equivalents follow the shortcuts in effect

* macOS menu bar: the shortcut test sets its key with window.setShortcut
2026-10-22 01:18:41 -04:00
storybored379andClaude Opus 5.5 ecb2fc1676 MCP: complete tool hints and check nested argument keys
Extend the existing MCP tools instead of adding a second set (#259):

- every tool states destructiveHint and idempotentHint next to
  readOnlyHint/openWorldHint; input schemas are closed
- the #776 unknown-key check walks the schema, so a misspelt key in a
  batch step, a pointer event or mods is -32602 with its path instead
  of being ignored
- script::parse refuses JSON step keys other than command/params
- a panic outside a command (rendering, inspection, the app connection)
  is a tool error and the server keeps running

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 21:26:50 -07:00
Zuujis 438d7b6d79 Dedupe the 400-year-cycle UTC conversion and the EPUB package writer (#1537)
* Dedupe the 400-year-cycle UTC conversion and the EPUB package writer

SonarCloud flagged new-code duplication on main (17%): five copies of the
"move the instant into chrono's range by whole 400-year cycles" conversion
and two copies of the EPUB OPF/container/zip writer.

- designcraft-doc gains a `time` module: `date_parts(days)` and
  `utc_parts(secs, nanos)`. App logging, EPUB `iso8601`, PDF `civil`, PPTX
  `civil` and text-variable `civil` are now thin callers; each keeps its own
  format string and year clamp. The app reaches it through
  `designcraft_engine::doc`, so its direct chrono dependency is dropped.
- EPUB: `package_opf` + `write_package` shared by fixed-layout and
  reflowable export (same entry order and compression).
- Boundary tests on the helper: pre-1970, year 9999 -> 10000, i64 extremes,
  nanos past a second.

Output is unchanged: existing date tests pass, and fixed/reflowable EPUBs
(with/without cover, author, pre-1970 and i64::MAX dates) are byte-identical
to origin/main.

* time: drop the unreachable i128 clamp and match arms in utc_parts

Whole 400-year cycles times 400 stay under 2.6e16 for any i64 day count,
so the year can't overflow i64 and the i128 + saturate was dead code
(carried over from the copies this replaced). The date and time lookups
can't fail either; each keeps one unwrap_or_default instead of a match
with a fake 1970 fallback. Output and tests unchanged.
2026-10-21 21:46:38 -04:00
moppeeer c0d2156ea6 Merge remote-tracking branch 'origin/main' into anchored-wrap-as-placed
# Conflicts:
#	ROADMAP.md
#	crates/compose/src/tests.rs
2026-10-22 02:48:37 +02:00
moppeeer b2e16f3204 Merge remote-tracking branch 'origin/main' into snap-page-centre
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:42 +02:00
moppeeer 6b7db50e69 Merge remote-tracking branch 'origin/main' into properties-auto-fit
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:39 +02:00
moppeeer a11053d646 Merge remote-tracking branch 'origin/main' into loaded-cursor-thumbnail
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:37 +02:00
moppeeer d8a33e6c26 Merge remote-tracking branch 'origin/main' into properties-wrap-offsets
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:35 +02:00
moppeeer e3e87b0a70 Merge remote-tracking branch 'origin/main' into properties-opacity-slider
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:34 +02:00
moppeeer a4641fe022 Merge remote-tracking branch 'origin/main' into codex/toc-right-indent-separator
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:33 +02:00
moppeeer cc799c4f08 Merge remote-tracking branch 'origin/main' into direct-select-delete-image
# Conflicts:
#	ROADMAP.md
2026-10-22 02:46:32 +02:00
aiongg 2aa5da5950 Paragraph rules: Rule Above's offset is measured from the baseline (#1535)
* Paragraph rules: Rule Above's offset is measured from the first line's baseline

* ROADMAP: Rule Above offset progress line
2026-10-21 20:40:26 -04:00
moppeeerandClaude Opus 5.5 1a11284bc7 Properties tests: the corner shape list's doc comment back on its test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:39:01 +02:00
moppeeerandClaude Opus 5.5 8f9c9dd6cc Color panel: the spectrum's doc comment back above spectrum
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:38:43 +02:00
Dylan M. Taylor 3b985e3813 Use chrono instead of hand-rolled UTC conversion (#1479)
* Use chrono for UTC/calendar conversion instead of hand-rolled copies

Replaces the hand-rolled civil / civil_from_days / days_from_civil copies (the
146_097 / 719_468 magic numbers) across the logging timestamp, text-variable
dates, EPUB dcterms:modified, PDF metadata dates and PPTX core.xml dates with
chrono, added as a workspace dependency (default-features = false, std only, so
wasm is unaffected).

- apps/designcraft logging `timestamp` (private civil_from_days deleted).
- doc text variables: `civil` and `days_from_civil` use chrono::NaiveDate;
  `format_date` and `parse_iso_date` keep their own format/parse logic and
  still call these helpers.
- epub `iso8601`, pdf `civil`, pptx `civil`: UTC datetime via
  chrono::DateTime::from_timestamp.

Output is byte-identical and pinned by the existing date, ISO-date, EPUB,
image, EPS and logging tests. The OOXML/EPUB dcterms timestamps keep their
exact strings. Each converted helper keeps a proleptic-Gregorian fallback for
dates outside chrono's NaiveDate range (and for the serial/overflow dates
parse_iso_date can hand days_from_civil), so no input changes or panics.
AGENTS.md now says time goes through chrono.

Follow-up to storytold/cadcraft#1785

* Never panic on a clock outside chrono's range; keep 5-digit years unprefixed

logging.rs timestamp(): chrono's From<SystemTime> unwraps, so a clock past
year 262143 panicked inside the logger. Use the fallible DateTime::from_timestamp
and read such a clock, or a pre-epoch clock, as the epoch like the old saturating
code did. Years past 9999 are written with {:04} like before, because %Y adds a
'+'. Tests cover both cases.

epub iso8601(): write the year with {:04} instead of %Y, matching the old
{year:04} output, so years past 9999 are not prefixed with '+'. Test added.

AGENTS.md: the "Time goes through chrono" rule now notes the narrow fallback
for dates outside chrono::NaiveDate's range, which crates/doc/src/vars.rs
retains (Howard Hinnant's algorithm).

* Don't build an unrepresentable SystemTime in the far-future test

UNIX_EPOCH + Duration::from_secs(u64::MAX / 2) overflows Windows'
SystemTime and panicked before timestamp() ran, failing the Windows
test job. Build it with checked_add and only assert where it exists.

* Route out-of-range dates through chrono's 400-year cycle, not hand-rolled copies

doc/vars.rs kept hand-rolled Hinnant `civil_fallback`/`days_from_civil_fallback`
copies for dates outside chrono's ±262143-year range, and AGENTS.md carved a
"narrow fallback" exception for them, which left calendar arithmetic outside
chrono after all.

Replace both copies with the Gregorian 400-year cycle (146_097 days): chrono
converts the day/year within one cycle and whole cycles are added back via i128
(so i64::MIN/MAX can't overflow). `civil` is reached by the system clock through
`format_date(now(), ..)`, so it must stay exact; `days_from_civil` only ever
sees a 4-digit parsed year via `parse_iso_date`, but it uses the same cycle form
for consistency. Both reproduce the pre-chrono proleptic Gregorian result, so
outputs are unchanged (verified against the old formula over wide ranges and at
the i64 extremes).

New test pins dates past chrono's range on both sides of the epoch, through the
public `format_date` and round-tripping `days_from_civil`/`civil`, with values
from the old formula. Removed the AGENTS.md "narrow fallback" exception.

epub/pdf/pptx `civil`/`iso8601` are left as-is: the PR already dropped their
hand-rolled copies for pure chrono, and their remaining epoch (`unwrap_or_default`)
fallback only triggers for a metadata/clock timestamp past year 262143 -- the
live-clock/file-mtime case FredApps accepted, with outputs that clamp the year
anyway (pptx 0..9999, PDF DateTime). No hand-rolled copy remains there to replace.

Tested: cargo test -p designcraft-doc; fmt --check; clippy --all-targets -D warnings.

* Carry an overflowing day into the next month again in parse_iso_date

parse_iso_date accepts any day 1..=31, and the old days_from_civil
carried a day past the end of its month into the next one (2019-02-30 is
2019-03-02). from_ymd_opt rejects such a day, and unwrap_or(0) turned it
into 1970-01-01. chrono now places the 1st of the month and the day is
added on, which restores the old normalization. Tested through days_from_civil
and parse_iso_date.

* time: preserve old out-of-range date conversion (no epoch fallback)

`DateTime::from_timestamp(...).unwrap_or_default()` silently reset any
instant past chrono's year range to 1970-01-01, changing output the old
hand-rolled Howard-Hinnant code converted exactly (e.g. 10_000_000_000_000 s
was 318857-05-20 17:46:40, not the epoch). Restore the old conversion domain
with a cycle-based helper that routes the calendar through chrono (the
calendar repeats every 400 years = 146_097 days, so month/day/time come from
chrono and only the year is carried, keeping every i64 exact), then apply each
format's existing year clamp afterwards.

- apps/designcraft/src/logging.rs: `timestamp` via `utc_parts`; keep the
  pre-1970 epoch clamp; u64 secs past i64::MAX saturate, not epoch.
- crates/epub/src/lib.rs: `iso8601` via `utc_parts`.
- crates/pdf/src/export.rs: `civil` cycle-based; `date_time` keeps its
  0..=9999 year clamp.
- crates/pptx/src/package.rs: `civil` cycle-based, keeps its 0..=9999 year
  clamp on the year only (month/day/time keep the real instant).

Pinned old outputs in tests (through the public helpers):
  logging u64::MAX/2 s -> 292277026596-12-04T15:30:07.000Z (was epoch)
  epub 10_000_000_000_000 -> 318857-05-20T17:46:40Z
       -10_000_000_000_000 -> -314918-08-13T06:13:20Z
       i64::MAX -> 292277026596-12-04T15:30:07Z
       i64::MIN -> -292277022657-01-27T08:29:52Z
  pdf  civil(10_000_000_000_000) -> (318857,5,20,17,46,40)
  pptx civil(10_000_000_000_000) -> (9999,5,20,17,46,40) (year clamped)

* Don't build a year-318857 SystemTime unchecked in the logging test

Windows' SystemTime only reaches about year 30828, so
UNIX_EPOCH + Duration::from_secs(10_000_000_000_000) panicked before
timestamp() ran and failed the Windows test job. Build it with
checked_add and assert where the platform can hold it. The year-10000
case fits everywhere and stays unconditional.

* Name the 400-year range extension as the one exception to the time rule

The rule said never to hand-roll calendar math, but the range fix
(shifting by whole 400-year Gregorian cycles so dates past chrono's year
range keep their old output) is cycle arithmetic, so the rule and the code
disagreed. The rule now names that exception: the library still computes
month, day and time, and only whole cycles are carried in the year.

* Say the library computes month and day; time-of-day is plain arithmetic

Narrows the range-extension wording: the date library computes the
calendar fields, and splitting seconds into hours, minutes and seconds
is ordinary arithmetic, which is what the code does.
2026-10-21 19:36:27 -04:00
moppeeerandClaude Opus 5.5 9ab1122688 Package: check the PDF's view options before writing anything
`export::check_pdf_options` refuses what `pdf_report` would: the export
options, the flattener, and now `pageLayout` and `view`, which `pdf_report`
reads up front too. `file.package` checks with it before the output folder
is made, so an unknown page layout or view leaves no partial package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:28:37 +02:00
PiMinusMaxandClaude Opus 5.5 aa1a0a73f3 Gradient panel: drag the gradient onto the Swatches panel to keep it
A gradient made in the Gradient panel stayed unnamed: there was no way
to drag it into the Swatches panel for reuse. The panel's thumbnail now
drags the selection's gradient, and the Swatches list takes the drop as
a new gradient swatch (swatch.new, "New Gradient Swatch"). A gradient
that already is a swatch is left as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:28:23 +02:00
moppeeerandClaude Opus 5.5 c84ce7a545 Swatches: a click on another swatch keeps it picked and cancels a waiting rename
Ending a rename by clicking another swatch keeps that swatch picked (for
Delete Swatch) instead of the renamed one. A click on another swatch while
the rename's double-click wait runs cancels the rename.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:25:12 +02:00
moppeeerandClaude Opus 5.5 874d2be248 Control panel and Properties: a negative Last Line Right Indent; list buttons pressed by every paragraph
The Last Line Right Indent field takes negative values, as the First Line
Left Indent does. The Control panel's Bulleted and Numbered List buttons
show pressed through `Session::selection_has_list`, as Type › Apply Bullets
and Properties do. With #1483's fix merged, an explicit off no longer takes
the other list type away.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:20:59 +02:00
moppeeer a41ff9c609 Merge branch 'list-buttons-hanging-indent' into control-panel-lists-shading 2026-10-22 01:12:39 +02:00
moppeeerandClaude Opus 5.5 c71bf1a32c List buttons: pressed when every targeted paragraph has the list; off takes only its own
`Session::selection_has_list` checks every paragraph the list commands apply
to (selected text, cells or text frames). Type › Apply Bullets / Numbers and
Properties' Bulleted and Numbered List buttons both use it, so a selection
reaching an unbulleted paragraph isn't shown pressed. An explicit `on: false`
leaves paragraphs with the other list type, and their hanging indent, alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:12:32 +02:00
moppeeerandClaude Opus 5.5 4d968d8adc Paragraph border links: linking again makes the four the same
Clicking "Make all settings the same" back on gives the four weights or
offsets Top's value, and the four corners Top Left's size and shape, so OK
never saves sides that differ under a closed link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:06:12 +02:00
moppeeerandClaude Opus 5.5 63d3f5a19d Package the PDF as file.exportPdf makes it; refuse a bad pdf
file.package now writes its PDF through export's `pdf_report`, so a preset's
transparency flattening, the effects and hidden-layer rasterising, the blend
space, the view options and the transitions all reach the packaged PDF.
A `pdf` that is neither a switch nor export options is refused, as is a bad
flattener, before anything is written. Georgian: the printing term for spot
inks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:59:00 +02:00
moppeeer 2c43330c43 Merge branch 'package-dialog' into package-pdf-preset 2026-10-22 00:53:43 +02:00
moppeeerandClaude Opus 5.5 c04fa61d17 Package: a failed package keeps the dialog open; the ink table's Type column; no document is an error
- When `file.package` fails, the Package or Printing Instructions dialog
  comes back with its options and instructions, and the status line says
  why. Before, they were lost.
- The Colors and Inks table heads its kind column with the "Type:" key
  (without its colon). The "Type" key is the menu's and reads Text in
  most languages.
- `app.packageDialog` with no document open is an error rather than a
  silent success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:53:21 +02:00
moppeeerandClaude Opus 5.5 cb9d23dd52 Preferences test: the recent items count is 20
The test checked only that the count was whole, so another default would
pass. It asserts 20, InDesign's default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:51:01 +02:00
moppeeerandClaude Opus 5.5 ea5a2f790f Preferences › Interface: Single Column in Czech, Georgian, Polish and Russian
The Tools Panel menu's Single Column fell back to English in these
catalogs. Russian Double Column reads "Две колонки", the table's word for
layout columns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:49:45 +02:00
moppeeer 28bc79b69d Merge branch 'paragraph-style-general' into character-style-from-selection 2026-10-22 00:10:04 +02:00
moppeeerandClaude Opus 5.5 c5bca17a9b New Paragraph Style: apply to the selection once the dialog knows the style
The dialog notes that the created style exists (so a second OK edits it)
before Apply Style to Selection runs, so a failure there can't lead to a
duplicate style. The Justification check's doc comment is back above
its function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:02:56 +02:00
moppeeerandClaude Opus 5.5 e108408c31 Insert Pages: a placement given must be a page index; the dialog's page is clamped
`layout.pages.insert` refuses `after` and `before` given together (null
counts as given) and a placement that isn't a page index, instead of
inserting at the default position; the default applies only when
neither is given. The dialog sends the page its menu shows (a page past
the end is the last). The dialog title is in the shared table, and
Georgian "Before Page" reads "გვერდის წინ".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:58:07 +02:00
moppeeerandClaude Opus 5.5 8e980b1f87 Paragraph rules: Gap Tint shows 100% at its default
A full gap tint is left out of the rule's JSON, so the field read nothing
even after a Gap Color was chosen. It now reads a missing gap tint as
100%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:52:23 +02:00
paaspaas00andClaude Opus 5.5 3049301643 Paragraph Border and Shading: link the four sides, as InDesign's
The course's chapter 40 (Applying Borders to Styles). Paragraph Style
Options › Paragraph Border and Paragraph Shading get InDesign's "Make all
settings the same" link for the stroke weights, the offsets and the
corners. It starts on when the four are the same, so a side typed in sets
all four; with the link off a side is set alone, as the lesson gives a
border only a thick left side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:45:03 +02:00
Claude 6a56272b32 Merge remote-tracking branch 'upstream/main' into xref-edited-text 2026-10-21 21:43:20 +00:00
Claude 35eda11a18 Merge remote-tracking branch 'upstream/main' into parent-page-display 2026-10-21 21:43:13 +00:00
Claude c95880f75d Merge remote-tracking branch 'upstream/main' into running-header-order 2026-10-21 21:42:56 +00:00
Claude 899e48ce2e Merge remote-tracking branch 'upstream/main' into inline-objects-under-text 2026-10-21 21:42:48 +00:00
paaspaas00andClaude Opus 5.5 4c3f24e43d Package: the packaged PDF uses a chosen PDF preset
The Package dialog's Include PDF (Print) gets a PDF Preset, as InDesign's
Select PDF Preset: the Export PDF presets, the last one used first. The
packaged PDF always had the default settings.

`file.package` takes `pdf: {…file.exportPdf options}` besides true/false,
read with the same `export::options` before anything is written, so bad
options leave no partial package. The Export PDF dialog's field-to-params
code is shared (`pdf_export_params`, `pdf_preset_params`).

Found in the Learn Skills Daily course, chapter 27.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:39:43 +02:00
paaspaas00andClaude Opus 5.5 d21459ff3e File › Package: InDesign's Package dialog and Printing Instructions
Package… went straight to a folder picker and packaged with fixed options.
As in InDesign it now opens the Package dialog: Summary counts the fonts,
links and images and inks the package carries (a warning where some are
missing or modified), and Fonts, Links and Images and Colors and Inks list
them, with Show Problems Only. Create Printing Instructions leads to the
Printing Instructions dialog (contact, company, address, phone, fax,
email, instructions), whose text goes into the package's Instructions.txt;
Include IDML and Include PDF (Print) choose the copies the package carries.

Found in the Learn Skills Daily course, chapter 27.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:25:29 +02:00
paaspaas00andClaude Opus 5.5 e5e3f091d3 Preferences › File Handling: the recent items count is a whole number
Number of Recent Items to Display read "20.0": its field's drag speed of
0.2 gave it a decimal place. It now shows "20", as InDesign's does.

Found in the Learn Skills Daily course, chapter 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 21:02:24 +02:00
paaspaas00andClaude Opus 5.5 1d11e0a8c4 Preferences › Interface: Color Theme swatches and the Tools panel's columns
Preferences › Interface held only UI Size, and the interface theme could be
changed only from Window › Interface Color Theme. As in InDesign, Interface
now has Appearance, with a Color Theme swatch per theme (a click shows it at
once, Cancel goes back to the theme Preferences opened with), and Panels,
where Tools Panel sets a single or double column. UI Size moves to a UI
Scaling section of its own, as in InDesign's list.

Found in the Learn Skills Daily course, chapter 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:57:24 +02:00
paaspaas00andClaude Opus 5.5 c0e38160d6 Spelling: "we", "if", "email" and curly-apostrophe contractions are known
The spell checker uses the Moby Hyphenator II word list, which lacks some
very common short words (we, us, if, Mr, pm, vs) and most computer and web
vocabulary (email, online, website, database, desktop, download...).
Contractions typed with a typographer's apostrophe (don’t, we’re), which
Use Typographer's Quotes produces by default, were looked up with the
curly apostrophe and flagged too. Dynamic Spelling underlined most words
of an ordinary sentence.

`known` now reads U+2019 as a straight apostrophe (also in the user
dictionary) and accepts a short sorted list of such common words, with
the existing inflection rules applied to them.

Found in the Learn Skills Daily course, chapter 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:50:19 +02:00
paaspaas00andClaude Opus 5.5 e91f748350 Insert Pages dialog as InDesign's; pages can go before a page or first
Insert Pages… opened the generic command form (Count, a 0-based After
index, a parent id). It now opens InDesign's dialog: Pages; Insert After
Page, Before Page, At Start of Document or At End of Document, with the
page by name; and Parent ([None] or a parent). It is set to the page in
view (or the page right-clicked) and that page's parent.

`layout.pages.insert` takes `before` (0: at the start of the document);
`after` and `before` together are refused.

Found in the Learn Skills Daily course, chapter 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:17:21 +02:00
paaspaas00andClaude Opus 5.5 87675f5b0b Status bar page box names the parent in view and lists the parents
While a parent was shown, the status bar's page box and Properties › Page
still read page 1. As in InDesign, they now name the parent ("A-Parent"),
and their lists have the parents after the pages: choosing a parent shows
it, choosing a page leaves the parents for that page.

Found in the Learn Skills Daily course, chapter 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:49:49 +02:00
paaspaas00andClaude Opus 5.5 f0ae1c318a Color panel edits the gradient stop selected in the Gradient panel
With a gradient fill or stroke, the Color panel showed "[None] — choose a
colour on the ramp", and a spectrum click replaced the whole gradient with a
flat colour. As in InDesign, it now shows the stop selected in the Gradient
panel (the stop before a selected midpoint) with its values, and its
C/M/Y/K or R/G/B sliders and spectrum recolour that stop, keeping the others.

Found in the Learn Skills Daily course, chapter 24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:36:22 +02:00
paaspaas00andClaude Opus 5.5 d26750d947 Place cursor: a short drag places the frame it previews
The place cursor draws a frame from 3 points, but the canvas sent Drag
events only once egui started a drag (at max_click_dist, 6 points). A
release in between placed a frame the preview never showed. With the
place cursor, the canvas now follows the pointer from 3 points. (Review.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:22:55 +02:00
paaspaas00andClaude Opus 5.5 d0e90e71ca Place cursor: the crosshair throughout when no graphic is loaded
With nothing in the place cursor there's no thumbnail to show, so the
cursor is the crosshair before a press too, as it already was while
dragging. (Review.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:01:26 +02:00
paaspaas00andClaude Opus 5.5 114e3682fd Properties: the test checks a double-click leaves no swatches popup open
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:48:00 +02:00
aiongg 0e43a8c87a #1311: rustfmt 2026-10-21 16:32:29 +00:00