Commit Graph
1459 Commits
Author SHA1 Message Date
Cursor Agentandnrq6993-a11y fe9ceb3dfa G11: copy fill/stroke by dragging between proxies (#3467)
## Summary
Dragging the Fill or Stroke proxy onto the other square applies that paint
there, like dropping a swatch on art. Matches Illustrator's fill/stroke
chips accepting a dragged color from the other.

## Tests
- panels::tests::dropping_a_proxy_paint_on_the_other_proxy_applies_it

Closes storytold/vectorcraft#3467

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 07:21:52 +07:00
Murat Vural e33094e11d i18n: add Turkish (tr) localization
- Add crates/ui-egui/src/i18n/tr.tsv covering all menu strings, commands, UI labels, and status/error messages with standard Turkish vector software vocabulary.
- Register Turkish in LANGUAGES with plural_none and complete_menus: true.
- Support tr, tr-TR, tr_TR.UTF-8, tr-CY locale mapping in lang_from_tag.
- Add Turkish typographic quotation marks in crates/doc/src/setup.rs.
- Add turkish_reads_as_turkish unit test and register tr in KEEPS_MENU_NAMES and COMPLETE_MESSAGES.
- Include RTF diagnostic message with exact TSV escaping.
2026-10-22 07:21:51 +07:00
Murat Vural 9bd9f570ae i18n: size Document Setup Edit Artboards button to fit localized labels 2026-10-22 07:04:00 +07:00
dotCooCoo 17fbf6ad6a Library panels: Locate Library… refuses a panel whose library is there
ui.libraryPanel.locate checked only that the panel was open. Run on an
open panel whose library was there, such as the built-in Pastels, it
loaded the file given or picked and showed that library in the panel
in place of Pastels.

It now answers "library panel `{given}` isn't missing its library" for
such a panel, before it asks for a file or loads one, and the panel
keeps its library. A persistent panel whose library's file is gone
locates as before.

Docs: docs/mcp.md (ui.libraryPanel.locate).
2026-10-22 07:03:20 +07:00
Cursor Agentandnrq6993-a11y 757eaf9afa Effect Gallery: plain filter list and live stack preview
Remove hash-coloured thumbnails; preview the selection with the applied
filter stack on the canvas (Cancel rolls back). OK commits via batch.

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 07:03:19 +07:00
nrq6993-a11yandCursor d275fbf725 G2: catalog Effect Gallery dialog tl! strings for all locales.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 06:52:12 +07:00
nrq6993-a11yandCursor e72735bcf9 G2: satisfy clippy and rustfmt on Effect Gallery dialog.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 06:52:07 +07:00
nrq6993-a11yandCursor dd9c285252 G2: Effect Gallery six categories and per-filter settings
Limit gallery folders to the six Photoshop-style sets and edit stack params via the existing effect dialog body before apply.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 06:52:07 +07:00
nrq6993-a11yandCursor ae3a8fe4c3 G2: Effect Gallery dialog to browse and apply raster filter stacks
Adds Effect → Effect Gallery with category browsing, procedural thumbnails, and a reorderable stack applied via command.batch as separate appearance effects.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 06:52:07 +07:00
Louise FoxandClaude Opus 5.5 2f893566ee Export As: a held Enter doesn't confirm the options; exporters get their file
Follow-ups to the review of the exporter plug-ins PR (#3171):

- Export As opens its format's options once the save panel has picked
  the file. The Enter that closed the panel, still held, confirmed
  them at once: Save As marks such a dialog (dialogs::AFTER_PANEL) so
  it waits for Enter to be let go, Export As didn't. Every options
  dialog it opens after the panel is marked now, an exporter plug-in's
  included, through one helper (dialogs::opened_by_panel) that Save As
  uses too.
- io::export with options that aren't a JSON object dropped the path
  and format it adds for the encoder: an exporter plug-in was told the
  document's name and its first extension instead of the file it
  writes. Such options now count as none.
- The exporter UI tests remove the plug-ins they install, so no other
  test's Export As lists them.

tests_export.rs reproduces the held Enter for every options dialog
(PNG, SVG, Save PDF, Text, DXF, EPS and an exporter's), and
tests_plugin_export.rs the options that aren't an object; both failed
before the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhvnnnD5fTFupK8WWq35un
2026-10-22 06:40:28 +07:00
Cursor Agentandnrq6993-a11y 6066b4b8c7 Properties: regression test for ellipse pie in Transform section (#3451)
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 06:29:30 +07:00
Cursor Agentandnrq6993-a11y 718c65c855 Ellipse pie angles in Transform and Properties (#3451)
## Summary

Live ellipses already support pie start/end angles, canvas widgets and Invert Pie
like Illustrator. Label the Properties panel Transform section with Ellipse
Properties so the pie fields match the Transform panel and are easier to find.

## Tests

- `an_ellipse_shows_its_pie_properties` in `panels/transform` tests.

Closes storytold/vectorcraft#3451

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 06:29:30 +07:00
dotCooCoo 4e4723699d Export: EPS, legacy .ai, EMF/WMF and DXF give one note for images that can't be decoded
EPS, EMF, WMF and DXF exports gave each image they left out because it
couldn't be decoded its own warning, "image '<key>' could not be
decoded and was left out", which names the internal key the document
stores the image under. A version 7 .ai said "an image that can't be
decoded or is too large was left out".

The four writers now give the note raster exports, PDF and the legacy
.ai flattening give, "an image couldn't be decoded and is missing from
the picture", once per export. In a version 7 .ai it is one line with
the note for flattened art. The other image notes in the same
functions no longer name the key: EPS's note for an image too large to
write, and DXF's notes for an image with no pixels (its rows in 23
catalogs are reworded) and one that could not be written. Legacy .ai
gives a separate note for an image that is empty or too large.

Docs: docs/mcp.md (EPS, DXF export, EMF and WMF, aiVersion "7").
2026-10-22 06:13:32 +07:00
dotCooCoo 3bb0f07a4b Tests: the data set export test fails when its folder cannot be emptied (#3389)
variables_panel_data_sets_ask_off_the_ui_thread empties its folder
before Export Data Sets… writes out.csv, then checks that the file is
exactly the header and the row for data set B. It ignored the result
of remove_dir_all, and create_dir_all succeeds on a folder that is
still there. When the folder could not be emptied, an out.csv left by
an earlier run passed the check even when the export wrote nothing.

The test now fails when emptying the folder fails with an error other
than NotFound.
2026-10-22 06:07:55 +07:00
Cursor Agentandnrq6993-a11y c8082facb1 G11: Align panel moves ruler guides to artboard (#3463)
## Summary
object.align now moves selected ruler guides when aligning to the artboard,
matching Illustrator and the existing Distribute behaviour. Guide-only
selection can run align; the Align panel enables its buttons when only
guides are selected. Guides still stay put when objects are in the selection
and Align To is Selection; key-guide behaviour is unchanged.

## Tests
- engine tests_keyguide: guides_selected_alone_align_to_artboard; updated
  selected_guides_align_to_a_clicked_key_object for artboard align
- ui-egui align panel: the_align_buttons_align_guides_selected_alone_to_artboard

Closes storytold/vectorcraft#3463

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 05:20:10 +07:00
dotCooCoo bd9a508d49 Save As: the suggested extension typed in another case gets the picked type's
On Linux and the BSDs, where the save dialog reports the file type
picked in it, a name that still ends in the suggested name's extension
gets the picked type's extension. The comparison was case-sensitive,
so Untitled-1.VECTORCRAFT with "PDF-compatible .ai" picked was saved
as a native file named Untitled-1.VECTORCRAFT instead of Untitled-1.ai.

with_picked_type now compares the lower-case extensions that
fileio::extension gives. A name typed with the picked type's own
extension in another case (a.AI with .ai picked) stays as typed.

This follows up #3372.

Docs: docs/target-app-parity.md.
2026-10-22 05:09:55 +07:00
BFlat b15230bfb5 Merge pull request #3461 from lehni/update/canvas-partial-redraw
Canvas: an edit redraws only the area it changed
2026-10-22 05:09:38 +07:00
Jürg Lehni ede08590a0 Canvas: an edit redraws only the area it changed
Wide effect rasters cropped to the frame also serve parts of it.
2026-10-22 04:45:43 +07:00
bflatastic 92f295d2a2 Blend: Ease In / Ease Out and separate Color Ease in Blend Options (#1124)
Squashed from #2539 onto main.
2026-10-22 04:40:10 +07:00
bflatastic 34cde7c3db Character: Character Direction sets the selected characters left to right or right to left
Squashed from #3436 onto main.
2026-10-22 04:18:35 +07:00
bflatastic b3268a829d UI.8: collapse dock groups to their tabs
Squashed from #3281 onto main.
2026-10-22 04:07:25 +07:00
bflatastic 9cda8452ab UI.6: dock panels into any dock group
Squashed from #3280 onto main.
2026-10-22 03:40:36 +07:00
gorkematlynandClaude Opus 5.5 d6d91c0954 UI.7: match workspace names whatever their case
find_saved matched names case-insensitively but save_as, remember and
switch compared them exactly: "Mine" saved over "mine" made a second
workspace, and changes kept as "Mine" didn't come back when switching
to "mine". save_as now replaces a user workspace of the name in any
case, remembered layouts are kept under the saved spelling and looked
up whatever the case, and sanitized maps remembered layouts to the
saved spelling and keeps one per workspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
gorkematlynandClaude Opus 5.5 e3e761fe32 UI.7: doc comments on the workspace tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
gorkematlynandClaude Opus 5.5 81de0f6fbf UI.7: keep the newest remembered layout when the list is full
remember() pushed the layout being left and then truncated the list to
64, so with 64 workspaces already remembered it dropped the entry it
had just pushed and the changes were lost. Drop the oldest entries
instead; a test fills the list and checks the last one left survives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
gorkematlynandClaude Opus 5.5 4308821285 UI.7: workspaces keep their layout changes
A workspace remembers the changes made in it: switching away keeps them
(UiState::workspace_changes, kept with the preferences), switching back
restores them, and Reset <name> returns to the saved layout. Saving a
workspace starts it with no changes; renaming keeps them, deleting drops
them, and deleting the current workspace shows Essentials as it was
left. Saved preferences recover a damaged remembered layout instead of
losing the whole file.

Split from #2965 as a reviewer asked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
Don Omondi a3b2b18cb0 M3: preserve highlighted Eyedropper ranges and reject incompatible transparency 2026-10-22 02:58:48 +07:00
bflatastic 10a178f64a Shape Builder: Gap Detection and Tool Options (#2523)
Squashed from #2526 onto main.
2026-10-22 02:53:17 +07:00
bflatastic 62776d5f46 Recolor: recolor.apply takes a model option for the new colour's model (#2170)
Squashed from #2520 onto main.
2026-10-22 02:01:57 +07:00
Cursor Agentandnrq6993-a11y 59f4b753dd G4: mark Snap to Glyph done in parity docs and test the menu toggle
## Summary
Aligns parity checklists with shipped View › Snap to Glyph behaviour (#3124):
when Smart Guides are on, drawing tools snap to live-text baselines and glyph
bounds via `view.snapToGlyph`. Adds a headless test that `view.snapToGlyph`
toggles the UI view flag like Illustrator’s menu item.

## Tests
- `vectorcraft-ui-egui`: `snap_to_glyph_menu_command_toggles_the_view_flag`
- Existing `tools::text_tests::snap_to_glyph_lines_up_new_point_type_with_a_baseline`

Part of gap G4

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 01:25:51 +07:00
bflatastic eb9e064254 G2: Effect › Artistic › Fresco raster filter
Squashed from #3096 onto main.
2026-10-22 01:15:09 +07:00
bflatastic 5925e6339a G2: Effect › Sketch › Torn Edges raster filter
Squashed from #3010 onto main.
2026-10-22 01:06:25 +07:00
bflatastic b45bb3dd54 Character panel Tate-chu-yoko marks vertical type as a horizontal block
Squashed from #3399 onto main.
2026-10-22 01:06:24 +07:00
Jürg Lehni a92f0264c2 Canvas: each update copies the rendered frame whole instead of pixel by pixel
The renderer's pixels and egui's are both premultiplied RGBA8, so color_image copies the bytes in one go. At 3456×2234 that takes 0.9 ms instead of 3.4 ms per update, at 5120×2880 1.6 ms instead of 6.8 ms. Every rendered image the UI shows (canvas, thumbnails, previews) goes through it.
2026-10-22 00:54:44 +07:00
bflatastic a5c0c29b25 G2: Effect › Pathfinder › Soft Mix blends overlapping CMYK fills
Squashed from #3063 onto main.
2026-10-22 00:54:43 +07:00
bflatastic adbe0566a6 G4: System Layout spaces every text object in whole points
Squashed from #3412 onto main.
2026-10-22 00:54:43 +07:00
dotCooCoo a3e7dc9e41 i18n: the message scan reads errors made with bad() and error variants, and new ones need rows
complete_languages_translate_every_message read a message literal only
right after a marker such as Err( or Other(. It did not read the
message given to the engine's bad(cmd, ...), so this test did not
require a row for a parameter error. It also did not read the messages
given to the engine's err() and error(), to the PDF writer's bad() and
failed(), or to an error enum's variant such as PsError::Limit(...).
1,122 of these messages have no row in any complete catalog.

The scan now reads those messages, a literal or a format! string, in
the same template form as the catalogs' rows. It skips PsError::Ps and
EngineError::UnknownCommand, whose first argument is a PostScript error
name or a command id. The 1,122 messages are listed in
untranslated_messages.txt next to the tests, together with the 71 that
pull requests open at 009384b add without rows, and the test lets a
listed message through whether or not it has rows. Every other message
needs a row in each complete catalog, so a new message made this way
fails the test until it has its rows.
VECTORCRAFT_I18N_DUMP_UNTRANSLATED=<file> writes the messages in the
sources that lack a row. No catalog rows change.

Docs: docs/development.md, docs/localization-parity.md.
2026-10-22 00:40:10 +07:00
bflatastic 03a2da13ba G2: Effect › Artistic › Colored Pencil raster filter
Squashed from #3028 onto main.
2026-10-22 00:30:39 +07:00
bflatastic 755f2b9158 G2: Effect › Artistic › Rough Pastels raster filter
Squashed from #3044 onto main.
2026-10-22 00:23:50 +07:00
bflatastic 695f7c0d4b G2: Effect › Artistic › Underpainting raster filter
Squashed from #3035 onto main.
2026-10-22 00:23:50 +07:00
bflatastic 03bd5e5a53 G2: Effect › Artistic › Paint Daubs raster filter
Squashed from #3032 onto main.
2026-10-22 00:23:49 +07:00
bflatastic f329f6271d G2: Effect › Artistic › Palette Knife raster filter
Squashed from #3038 onto main.
2026-10-22 00:23:48 +07:00
bflatastic bbe026607f Variables: Load Variable Library… reads a variable library's text variables and data sets
Squashed from #2853 onto main.
2026-10-22 00:12:39 +07:00
bflatastic 14f804cdee Type: ruby (ふりがな) for live text
Squashed from #3448 onto main.
2026-10-22 00:10:56 +07:00
bflatastic 2cd7f156fb Add lighting presets to 3D effects
Squashed from #3442 onto main.
2026-10-22 00:01:37 +07:00
dotCooCoo 4d1581f3da Document Info: a Repeat Objects category lists the document's repeats
Document Info had no Repeat Objects category, and document.info
refused category "repeats". The reference app's Document Info panel
menu lists Repeat Objects after Font Details.

Document Info now has a Repeat Objects category after Embedded Images.
It lists each radial, grid and mirror Repeat object by name with its
kind and the number of instances it makes. For a grid it gives the
rows and columns instead, followed by the number of instances it
draws when that is fewer. The count comes from the new
RepeatSpec::instances, which gives the number of instances a repeat
draws. That number is smaller than its options give when repeats
nested in its source would pass the instance budget. With Selection
Only the category lists the Repeat objects in the selection.
document.info gives them as repeatObjects, the panel's flyout offers
the category, and the text report that Document Info › Save… and
File › Package write has a REPEAT OBJECTS section. The title has a row
in every catalog.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-22 00:01:36 +07:00
Drew DibbleandClaude Opus 5.5 4f5f573ded Properties: doc comments for the panel's entry point and its test helpers
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 00:01:36 +07:00
Drew DibbleandClaude Opus 5.5 f19b33c219 G1: Properties: Edit Clipping Path and Edit Contents for one clip group
With one clip group selected, the Properties panel has Edit Clipping
Path and Edit Contents at its top, under the Clip Group heading, as the
reference app does: "With the clip group selected, click the Edit
Clipping Path button at the top of the Properties panel to select and
edit the mask, or click the Edit Contents button to select and edit the
masked content"
(https://www.adobe.com/learn/illustrator/web/crop-using-masks). They
run the existing object.clippingMask.editMask and editContents, which
select the clipping path or the clipped art for the selection tools, as
Object > Clipping Mask does. Edit Contents shows only when the group
clips something. With several objects selected they don't show (the
tutorial describes one selected clip group); the Contextual Task Bar
does the same. Both labels are already in every catalog.

Test: panels::properties::tests::one_clip_group_has_edit_clipping_path_and_edit_contents_at_the_top
(first under the heading, each selecting its part; Edit Clipping Path
alone once the clipped art is deleted; neither for a clip group
selected with another object in either order, or for a plain group).
Documented in docs/target-app-parity.md, docs/ui-parity.md and
docs/gaps.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 00:01:36 +07:00
bflatastic c895f64063 Format: rustfmt after the batch 2026-10-21 23:38:03 +07:00
nrq6993-a11yandCursor 4e5f5e608b G12: translate Touch workspace for complete i18n catalogs
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-21 23:38:03 +07:00