Commit Graph
294 Commits
Author SHA1 Message Date
BFlat a105e14aef Merge pull request #7220 from dotCooCoo/feat/image-indexed-color
Edit Colors: convert embedded images to indexed color
2026-11-14 02:40:36 +07:00
BFlat e718e975b6 Merge pull request #7104 from dotCooCoo/feat/actions-record-into-selected
Actions: Begin Recording adds steps to the selected action, and a drag moves a step
2026-11-14 01:54:47 +07:00
BFlat ca8e49e9e2 Merge pull request #7158 from dotCooCoo/fix/export-unused-option-warning
Export: warnings name an option the chosen format doesn't read
2026-11-14 01:54:29 +07:00
BFlat 2814e3e53d Merge pull request #7192 from dotCooCoo/feat/context-menu-smooth
Context menu: Smooth… on a selected path opens the Smooth slider
2026-11-14 00:51:29 +07:00
BFlat 211c673ee2 Merge pull request #7186 from dotCooCoo/fix/mcp-window-capture-private-temp
MCP: an old app's window capture goes through a private temporary folder
2026-11-14 00:50:17 +07:00
dotCooCoo 81d19f1718 Edit Colors: convert embedded images to indexed color
Edit > Edit Colors > Convert to Indexed Color... (edit.colors.toIndexed)
stores the embedded images in the selection as indexed-color PNGs: a
palette of at most 256 RGB colors, each pixel the index of one. The
dialog previews live and OK is one undo step.

- The palette is chosen as for a PNG-8 export (selective, perceptual,
  adaptive, web, gray, black and white), as evenly spaced levels of red,
  green and blue (uniform), or from the document's swatches. Dithering
  is diffusion, pattern, noise or none, with an amount.
- Pixels under half opacity become one transparent entry; the others
  become opaque in their own color. Linked images, colorized images and
  color glyph images keep their pixels.
- An image that is already an indexed PNG and would show the same pixels
  is left as it is, and no undo step is recorded when no image changes.
- An image of more than 134,217,728 pixels (33,554,432 in the web app)
  is refused, read from its header before decoding.
- With Select All, locked and hidden objects that hold an image that is
  not an indexed PNG yet are counted in notChanged, without converting
  them.
- The quantizer gains quantize_to, which maps pixels to a given palette.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 09:49:00 -08:00
dotCooCoo 6462060928 Merge main into fix/export-unused-option-warning 2026-11-13 09:15:25 -08:00
BFlat 60fd4bd644 Merge pull request #7090 from dotCooCoo/feat/pixel-snapping-options
View: Pixel Snapping Options choose whether Snap to Pixel snaps drawing, moving and scaling
2026-11-13 23:58:35 +07:00
BFlat 2aba3ccaff Merge pull request #7172 from dotCooCoo/fix/mcp-test-temp-folders
Tests: the vectorcraft-mcp tests remove the temp folders they create
2026-11-13 23:44:46 +07:00
dotCooCoo d1c8ff78de Context menu: Smooth… on a selected path opens the Smooth slider
A right-click on a selection that holds a path (a path, a group of
paths, a compound path, or anchors selected with Direct Selection) lists
Smooth…, after Join and Average… and the anchor entries when those are
listed. It opens the slider that Object › Path › Smooth opens, which
previews the result until OK keeps it as one undo step. With nothing,
only type or a group of type selected, Smooth… is not listed.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 08:35:40 -08:00
BFlat a2adbf61e6 Merge pull request #7106 from dotCooCoo/feat/custom-toolbar-dock
Toolbars: toolbars made with New Toolbar dock along the window's edges
2026-11-13 23:32:06 +07:00
dotCooCoo c9d85d61db Merge main into feat/actions-record-into-selected 2026-11-13 08:24:12 -08:00
dotCooCoo e11c21ce98 MCP: an old app's window capture goes through a private temporary folder
An app that does not send the image back wrote the window capture to
vectorcraft-window-<pid>.png directly in the system's temporary folder.
On a shared Unix temporary folder another user could put a link at
that name, and the app would then overwrite the file it points to. A
failed read also left the file behind.

The capture now goes to window.png in a new folder made for it inside
the temporary folder (owner-only on Unix; a name that is taken is
skipped). The folder is removed after the read, also when the app or
the read fails.
2026-11-13 08:19:07 -08:00
dotCooCoo 98ea3231fa Tests: the vectorcraft-mcp tests remove the temp folders they create
The MCP unit tests wrote their files into one folder per process under
the temp dir (vectorcraft-mcp-test-<pid>, vectorcraft-mcp-fileio-<pid>,
testkit's mcp-cancel folder) and nothing removed them. The export-as and
links tests removed their folder at the end, so a failing test left it.

Each test that writes files now holds a TempFolder, a folder of its own
that starts empty and is removed with everything in it when the test
ends, also when it panics, as the findfiles tests' Tree guard does
(crates/engine/src/cmd/findfiles/tests.rs:49). A new test checks that a
leftover folder is emptied and that the folder is removed on drop and
after a panic.
2026-11-13 07:44:41 -08:00
dotCooCoo d04a19ac53 Export: warnings name an option the chosen format doesn't read
`document.export`, `document.serialize` and `document.exportSelection`
accept a key that only another format takes. `{"format": "pdf",
"quality": 80}` wrote the PDF and gave no warning about `quality`.

The reply's `warnings` now name each such key, in the wording of a
save's note: "`quality` was not used: PDF files don't read it".

- The format's own options, the commands' own keys, null values and an
  exporter plug-in's format get no note.
- The note names the kind of file written. A legacy `.ai` file
  (`aiVersion: "7"`) reads `outlineText`, `hiddenObjects`,
  `transparentImages`, the artboard choice and `useArtboards`, and
  beside `aiVersion` no other option. The other `.ai` files don't read
  those three options or `preserveEditing`, which is always on for
  them.
- An export doesn't read `separateArtboards`, or `range` for a
  `vectorcraft` or `template` file. A save reads them to write each
  artboard to a file of its own.
- In the app, an export that automation asked for (`app.export` with a
  path, `file.exportAs` run as a command) gives the same notes in its
  reply and in the status bar. A Background Export replies before the
  file is written, and that reply has the notes. An export that a
  person starts from the File menu gets none.
- Export As gives a template export no `useArtboards` or `range`: a
  template doesn't read them.
- `vectorcraft-cli convert` sends `outlineText` only with
  `--outline-text`, and `hiddenLayers` only to the formats that read
  it. A conversion then warns only about an option the command line
  gave.

`document.save` gives its notes as before: it does not apply the `.ai`
rules above.

Docs: docs/mcp.md, docs/control-protocol.md,
docs/target-app-parity.md, the params text of the three commands.
2026-11-13 06:58:28 -08:00
dotCooCoo d747f5b365 Learn: Back to skills and the Quick skill guide card run learn.skills
learn.skills {} shows the Learn panel on its Skills tab with the list of
skills, with no skill and no tutorial open, and returns what learn.list
returns. Back to skills after a skill's last tutorial and the Quick skill
guide card on the For you tab now run it, so the control channel and MCP
can reach the same view.

- The command is listed in both UI command catalogs, and its label has a
  row in every catalog.
- Docs: docs/mcp.md, docs/target-app-parity.md, docs/ui-parity.md.
2026-11-13 04:34:35 -08:00
dotCooCoo 3990c748bd Toolbars: toolbars made with New Toolbar dock along the window's edges
A toolbar made with New Toolbar now docks in a lane along the window's
left or right edge (on the left, right of the Tools panel docked there).
Dropping its title bar on an edge docks it, with the target lit while
the title bar is dragged over it; dragging it out of its lane floats it
under the pointer, and Escape or losing the window's focus during the
drag puts it back. The title bar's context menu has Dock to Left, Dock
to Right and Float Toolbar.

- Toolbars docked at one edge stack from the top, each with an equal
  share of the lane's height, and the lane is as wide as its widest
  toolbar. A lane too short for its stack wraps it into more columns,
  up to half the width beside it; past that the toolbars show only
  their title bars, a lone toolbar included, and a column too short
  for those scrolls with the mouse wheel.
- With Keep Tools Beside the Canvas on and Tools docked on the left,
  the left lane is laid out inside the canvas panel right of Tools, and
  the canvas keeps room for one column of it and its 200 points.
- A release in the frame the pointer leaves the lane floats the toolbar
  with its corner where the drag put it.
- window.toolbar.dock {name, side?, order?} and window.toolbar.float
  {name, x?, y?} do the same from the control protocol; bad params are
  errors and change nothing. window.toolbar.list reports floating, side
  and order.
- CustomToolbar keeps dock (place in the edge's stack) and dock_right;
  both default, so toolbars saved before load floating. Workspaces and
  preferences keep the placement; New Toolbar still starts floating, a
  copy floats, and deleting a docked toolbar closes up its stack.
- Dock to Left, Dock to Right, Dock Toolbar and Float Toolbar have rows
  in every catalog.

Part of #1759
2026-11-13 04:29:55 -08:00
dotCooCoo cf10a77594 Actions: Begin Recording adds steps to the selected action, and a drag moves a step
With an action selected, Begin Recording records into it: Stop puts the
recorded commands after the selected step, or after the action's last
step, and the steps after them keep whether they are excluded. With no
action selected it still adds a new Action N.

- ui.action.record takes {set?, action?, after?}; action needs set.
  The place stays between the same steps while a step is inserted,
  deleted or moved in that action during the recording, and the selected
  step and an open Record Stop dialog follow their step when Stop adds
  the recorded steps before them.
- New ui.action.moveStep {set, action, step, toSet?, toAction?, before}
  moves a step within its action or into another action, also an empty
  one or one in another set. The step keeps its params and exclusion,
  the selected step and an open Record Stop dialog follow their step,
  and a move past 10,000 steps or 8 MiB is an error that changes
  nothing.
- In the Actions panel a step row drags: a line shows where the step
  goes, the release moves it once, and a release off the actions' rows
  leaves it where it was. The list scrolls near its edges.

Help page: https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/add-commands-to-actions.html

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 04:17:59 -08:00
dotCooCoo f81793d671 View: Pixel Snapping Options choose whether Snap to Pixel snaps drawing, moving and scaling
Control bar > Snapping > Pixel Snapping Options... opens a dialog with
three checkboxes: Snap to Pixel While Drawing, While Moving and While
Scaling. OK sets them; Cancel leaves them as they were. While View >
Snap to Pixel is off, the dialog notes that the options take effect once
it is on.

- view.snapToPixel.options {drawing?, moving?, scaling?} reads and sets
  them. They are kept in the preferences as the pixelSnap group, all on
  by default, so turning Snap to Pixel on behaves as before. An unknown
  key or a value that is not a boolean is refused and changes nothing.
  The command has a parameter schema, which raises the API level to 4.
- Drawing covers points the drawing tools place, the Knife's straight
  cut, the Measure tool and the rulers' origin. Moving covers Selection
  and Direct Selection moves, ruler guides, artboard moves and the
  Rotate, Reflect and Shear tools' drags. Scaling covers bounding-box,
  Free Transform, artboard and slice handles and the Scale tool's drag.
  An edit whose option is off snaps as it does with Snap to Pixel off.
- Align New Objects to Pixel Grid and the objects' pixel-aligned
  property do not depend on these options.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 01:38:58 -08:00
dotCooCoo 3792561e1a Learn: View more opens a tutorial's practice sample, and Next Up shows the next tutorial
Under a tutorial's steps, View more opens the tutorial's practice sample
as a new untitled document, which becomes the active one; open documents
stay as they are, and Save asks where to save the copy. Each of the 12
tutorials has its own small SVG drawing in panels/learn/samples.rs, read
only when View more is pressed.

Once the sample is open, Finish tutorial marks the tutorial finished.
A finished tutorial shows Next Up with the next tutorial's title in the
same skill, and Next Up shows that tutorial without opening its sample.
After a skill's last tutorial the panel says so and shows Back to
skills; Next Up never moves to another skill. Finished tutorials are
kept while the app runs; the skill rings and counts do not show them
yet. The help page's short video is not part of this change.

- learn.openSample, learn.finish and learn.next run the three controls
  and are listed in the UI command catalogs; a missing, non-string or
  unknown tutorial id, or a step out of order, is an error and changes
  nothing.
- New labels and messages have rows in every catalog.
- Docs: docs/mcp.md, docs/target-app-parity.md, docs/ui-parity.md and
  the ASSETS.md line for art generated in code.
2026-11-13 00:51:37 -08:00
BFlat 11a37082f7 Merge pull request #7058 from dotCooCoo/feat/touch-workspace
Touch: a two-finger tap switches between selection and drawing modes
2026-11-13 14:17:54 +07:00
BFlat 9b54280846 Merge pull request #7050 from dotCooCoo/feat/layers-delete-confirm
Layers: deleting layers that hold art asks first
2026-11-13 13:18:43 +07:00
BFlat 1b9aa07e65 Merge pull request #6995 from dotCooCoo/feat/actions-insert-select-path
Actions: Insert Select Path stores the selected path as a step
2026-11-13 12:27:58 +07:00
dotCooCoo cc19dc1db2 Touch: a two-finger tap switches between selection and drawing modes
In the Touch workspace, a two-finger tap on the canvas now switches
between the Selection tool and the drawing tool chosen last, as the
help page describes. It no longer undoes there; outside Touch a
two-finger tap still undoes, and a three-finger tap still redoes in
every workspace.

- New UI command tool.toggleTouchMode (Switch Selection and Drawing
  Modes, {} -> {tool}). From the Selection, Direct Selection, Group
  Selection, Magic Wand, Lasso or Perspective Selection tool it chooses
  the drawing tool chosen last in the window, or the Pencil tool when
  none has been chosen; from any other tool it chooses the Selection
  tool. The Hand, Rotate View, Zoom and Print Tiling tools never become
  the drawing tool. It adds no undo step.
- These tool lists and Pencil as the first drawing tool are
  VectorCraft's own rules.
- The label is in every catalog. Docs: docs/mcp.md, the touch row of
  docs/hardware-parity.md and docs/target-app-parity.md.
2026-11-12 21:21:52 -08:00
dotCooCoo 367c092fee Layers: deleting layers that hold art asks first
The Layers panel's trash button, rows dropped on it, the panel menu's
Delete Selection, and Delete or Backspace on highlighted rows now run
ui.layerDelete. When a layer or sublayer among the rows holds art
(hidden, locked and nested objects count; guides do not), a confirm
dialog asks first. OK deletes the rows it asked about, by id, in the
document it was asked in, as one undo step; Cancel keeps them. Empty
layers, guide-only layers and object or group rows alone are deleted at
once. layer.delete itself is unchanged and never asks.
2026-11-12 20:43:56 -08:00
BFlat 563850dca0 Merge pull request #6988 from dotCooCoo/feat/control-bar-float
Control bar: dragging the gripper away from both docked edges floats the bar
2026-11-13 10:26:54 +07:00
dotCooCoo b64b4802f8 Merge main into feat/actions-insert-select-path 2026-11-12 19:01:39 -08:00
BFlat c94577e3bf Merge pull request #6946 from dotCooCoo/feat/actions-select-object
Actions: Select Object selects objects by their Attributes note during playback
2026-11-13 09:30:34 +07:00
BFlat 39f7d33e22 Merge pull request #6943 from dotCooCoo/feat/color-rgb-percent
Color: a double-click right of an RGB field switches between percent and 0 to 255
2026-11-13 08:31:01 +07:00
BFlat 24af0c146a Merge pull request #6938 from dotCooCoo/fix/pdf-large-page-export
Export As: a PDF without artboards opens Save PDF and its options
2026-11-13 07:48:44 +07:00
dotCooCoo b1a3ec4a97 Merge main into feat/color-rgb-percent 2026-11-12 16:15:23 -08:00
dotCooCoo d3375c1656 Color: Toggle RGB Percent switches the RGB units from the keyboard
The double-click right of an RGB field was the only way to switch R, G and B
between percent and 0 to 255 from the UI. ui.colorRgbPercent (Toggle RGB
Percent) is listed in the command palette and in Keyboard Shortcuts without a
default key, and switches the same setting. A parameter answers an error and
changes nothing. The label has a row in every complete catalog.
2026-11-12 16:04:30 -08:00
dotCooCoo 2b975d620e Actions: Insert Select Path stores the selected path as a step
The Actions panel menu has Insert Select Path, after Insert Menu Item.
With one whole path or compound path selected, it inserts a Select
Path step into the action being recorded, or after the selected action
or step. Playing the step selects that path again.

- New engine command `select.storedPath {id, fingerprint}`. The step
  stores the path's object id and a fingerprint of its geometry and
  fill rule ("v1:" and 16 lowercase hex digits, FNV-1a 64). Playback
  selects the path only while it exists unchanged and can be selected;
  otherwise the step fails and the selection stays as it was. A path
  on a locked artboard is refused in isolation mode too.
- Capture refuses an empty selection, several objects, selected
  anchors or segments alone, groups, type, guides, a path selected
  together with ruler guides, a member of a compound path, and hidden,
  locked or template art.
- New UI command `ui.action.insertSelectPath {set?, action?, step?}`.
  Step rows show "Select Path".
- `.vcactions` files that hold a Select Path step are written as
  version 4. Reading accepts versions 1 to 4 and refuses a Select Path
  step with invalid params.
- Rows for the new labels and messages in every catalog.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-12 16:02:00 -08:00
dotCooCoo 6c280fa05a Control bar: dragging the gripper away from both docked edges floats the bar
Dragging the Control bar's gripper and releasing it within 24 points of
the top (under the menu bar) or the bottom of the window docks the bar
at that edge, as before. Released farther from both edges, the bar now
floats over the window under the pointer, 800 points wide or as wide as
the window, without taking room from the canvas. A floating bar's
gripper moves it or docks it again, and its panel menu keeps Dock to Top
and Dock to Bottom, neither checked while it floats.

- window.control.dock takes edge "float"; a floating bar floats where it
  last floated, first at 60, 80 in window points.
- Escape cancels a gripper drag, and a release outside the window leaves
  the bar where it was. In a window too short for a floating bar between
  the two zones, a release docks it at the nearer edge. A floating bar is
  kept inside a window that shrinks.
- Workspaces and preferences keep whether the bar floats and where;
  older ones dock it at the edge they name. Menus stop at the window's
  bottom while the bar floats.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-12 15:25:11 -08:00
dotCooCoo 68fe1dbaea Merge main into feat/actions-select-object 2026-11-12 15:11:08 -08:00
dotCooCoo 5494e1aaa7 Merge main into feat/color-rgb-percent 2026-11-12 15:11:03 -08:00
dotCooCoo cfff971d06 Merge main into fix/pdf-large-page-export 2026-11-12 14:40:47 -08:00
dotCooCoo 0956341034 MCP: the UI catalog lists useArtboards for the Save PDF dialog
crates/mcp/src/ui_catalog.rs is regenerated with `cargo xtask ui-commands`, so
the ui.savePdfDialog entry matches its description in
crates/ui-egui/src/menus/ui_commands.rs.
2026-11-12 13:55:12 -08:00
dotCooCoo 3e32e99a15 Merge main into feat/align-artboards 2026-11-12 13:47:00 -08:00
BFlat 71d717b1da Merge pull request #6940 from dotCooCoo/feat/learn-tool-locator
Learn: a tool's name in a tutorial step shows where the tool is
2026-11-13 04:26:05 +07:00
dotCooCoo 780d00671a MCP: the UI catalog lists learn.locateTool
crates/mcp/src/ui_catalog.rs is regenerated from crates/ui-egui/src/menus/ui_commands.rs, so `cargo xtask ui-commands --check` passes.
2026-11-12 11:59:18 -08:00
dotCooCoo ba20f468b3 Merge main into feat/align-artboards 2026-11-12 11:58:32 -08:00
dotCooCoo 74235d8959 Color: a double-click right of an RGB field switches between percent and 0 to 255
In RGB mode a double-click in the cell right of the R, G or B field
switches all three fields and sliders between 0 to 255 and percent (0 to
100 with a % suffix, as the CMYK fields show). The color does not change;
a typed percent converts back (50% is 127.5 of 255) and a slider click
picks a whole percent. Web Safe RGB, the hex field and the other modes
keep their units.

Only RGB rows have the cell. It is blank, is highlighted under the
pointer, and takes no keyboard focus, so Tab does not stop on it. The
RGB sliders are narrower by the cell's width and spacing, so an RGB row
is as wide as a row in the other modes and Tint, in a narrow panel too.
While a mixed selection disables the rows, a double-click on the cell
does nothing, as the fields beside it take no input.

The double-click runs ui.colorPanel {rgbPercent}, which takes a bool and
answers it. The setting is off by default and is kept with the
preferences (ui.color_rgb_percent); a saved value that is not true or
false reads as off. The color mixer in the Fill and Stroke chips'
popovers (Control bar and Properties panel) and the gradient stop dialog
show the same rows and follow the same setting.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-12 10:33:17 -08:00
dotCooCoo f78b943e9e Actions: Select Object selects objects by their Attributes note during playback
The Actions panel menu gets Select Object…, which opens Set Selection with a Note field and
Case Sensitive and Whole Word. The step it inserts runs the new select.byNote command, which
replaces the selection with every object that can be selected whose note matches. When none
matches, the selection, its Puppet Warp pins and the active Appearance item stay as they were,
and playback stops with an error. Action set files that hold the step are saved as version 4.
2026-11-12 10:32:27 -08:00
dotCooCoo 003bee8e70 Merge main into fix/window-menu-panel-toggle 2026-11-12 10:04:14 -08:00
BFlat c62d1d8713 Merge pull request #6908 from dotCooCoo/fix/actions-toggle-limits
Actions: recording, step exclusions and set edits keep sets that Load Actions reads
2026-11-13 00:50:37 +07:00
BFlat 3fed6e3380 Merge pull request #6911 from dotCooCoo/fix/canvas-zoom-ignores-ui-scaling
View: the art keeps its size at a zoom whatever the UI Scaling
2026-11-12 23:54:20 +07:00
dotCooCoo 1bf8bce083 Actions: Begin Recording params name the command that passes a limit only as it runs
ui.action.record's params text now says that a recorded command whose
step passes a limit only from the values it adds as it runs keeps its
edit and result, that later recorded commands are an error and do not
run, and that ui.action.stop leaves its step out.

crates/mcp/src/ui_catalog.rs now matches the desktop table again
(cargo xtask ui-commands --check), including the action-limit params
texts of the earlier commit.
2026-11-12 08:27:21 -08:00
BFlat 0cb73d0d66 Merge pull request #6845 from dotCooCoo/feat/linux-screen-color-portal
Color: Sample Color from Screen works on Linux through the desktop portal
2026-11-12 23:10:13 +07:00
dotCooCoo 2e968acc47 Align: the Align panel aligns and distributes the selected artboards
With the Artboard tool chosen, the Align panel's Align Objects,
Distribute Objects and Distribute Spacing buttons, their UI commands and
the Control bar's Align and Distribute buttons act on the artboards the
tool has selected, as the public page describes:
https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/organize-manage-artboards/align-and-distribute-artboards.html

- artboard.align, artboard.distribute and artboard.distributeSpacing
  move whole artboards with their guides, and with the art inside them
  when Move Artwork with Artboard is on, in one undo step. No undo step
  is recorded when no artboard moves.
- Align To offers Align to Selection and Align to Artboard. Align to
  Artboard keeps the active artboard in place, and the Distribute
  buttons then send the Distribute Spacing value. A locked artboard
  stays where it is. These rules are VectorCraft's own.
- The Control bar shows the Align buttons, the Align To menu and the
  Distribute buttons after the artboard controls while it has room.

Docs: docs/mcp.md, docs/ui-parity.md.
2026-11-12 07:28:16 -08:00