Commit Graph
332 Commits
Author SHA1 Message Date
dotCooCoo f1251af6e4 DXF: export options leave placed images and fill hatches out, and CNC / CAM turns both off
DXF Options gets Include Placed Images and Include Fill Hatches, and
document.exportDxf and document.export {format: dxf} take
includeImages and includeHatches. Both are VectorCraft's own options
and default to true, so Custom exports write what they wrote before.

- includeImages: false writes no IMAGE entity, IMAGEDEF, reactor or
  linked file for a placed image, and does not decode its pixels.
- includeHatches: false writes each filled area's outlines without the
  solid HATCH after them.
- Each adds one note to warnings when it left something out. R12,
  which has neither, keeps its own notes.
- The CNC / CAM preset sets both to false, so its drawing holds the
  cutting paths alone; the options given still override it, and
  changing either checkbox shows Custom.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-11 21:10:30 -08:00
BFlat 765bd30783 Merge pull request #6744 from dotCooCoo/feat/color-show-recent-colors
Color: the panel menu's Show Recent Colors shows or hides the Recent Colors row
2026-11-12 09:55:35 +07:00
BFlat 01efd56ee3 Merge pull request #6752 from dotCooCoo/fix/open-shows-every-import-note
Open: the status bar names what the file left out first, and its hover lists the notes
2026-11-12 09:40:03 +07:00
dotCooCoo 912610eb60 Open: the status bar names what the file left out first, and its hover lists the notes
After File > Open the status bar showed only the first of the import's
notes. A file whose layers weren't read could give another note first:
the EPS reader adds its note about brushes left out of the Brushes panel
before the note that the file came in as its page, so the status bar
named the brushes and not the page.

The status bar now names the first note that says reading the file left
something out (the notes that make Save ask before writing over the
file), else the first note, and still counts them all. When there are
several, hovering the message lists them in that order, translated where
the catalogs have them, as many as fit in the window and at most 30,
then how many more. Screen readers get the list after the message. The
status bar shows the list only while it shows the open's message. The
open's reply keeps its notes in the import's order.

Docs: docs/control-protocol.md (app.open), docs/target-app-parity.md.
2026-11-11 17:52:53 -08:00
dotCooCoo 62b6f53533 Color: the panel menu's Show Recent Colors shows or hides the Recent Colors row
The Color panel's menu gets a checked Show Recent Colors item under Show
Options / Hide Options. Unchecking it hides the panel's Recent Colors row;
checking it shows the row again. Applied colors still join the list while
the row is hidden, Hide Options hides the row either way, and the Swatches
panel keeps its own row.

The setting is on by default and is kept with the preferences
(ui.color_show_recent_colors); a saved value that is not true or false
reads as on. ui.colorPanel takes recentColors: bool and answers it.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-11 17:26:16 -08:00
dotCooCoo 3d7803289c Toolbars: a + button on a new toolbar adds and removes tools from a menu
A toolbar made with New Toolbar was filled only by dragging tools from
its All Tools drawer, which the ••• button opens. It now also has a +
button (Add Tool…) above the ••• button. Its menu lists every tool under
the drawer's headings; a click adds the tool at the end of that toolbar
(toolbar.addTool with toolbar), and the tools already in it are dimmed.
Under Remove Tool the menu lists the toolbar's tools, and a click takes
one out (toolbar.removeTool). The button takes the keyboard focus, and
the menu scrolls inside the window like the other long menus.

The drawer and its drags work as before. Add Tool… and Remove Tool have
rows in every catalog.
2026-11-11 11:57:53 -08:00
dotCooCoo 5d7e2fa8e1 MCP: ui.inspect leaves out paths outside the read roots
Under --automation-read-root, ui.inspect returned the paths of documents
still opening, the recent files, library panels' files and the folder
preferences even when they lay outside the read roots. The reply now
leaves them out, checked with file_access::check_read as ui.menu.list
checks recent files and listed scripts:

- opening and ui.recent_files keep only the readable paths, in order.
- A library panel keeps its row without its path; a library loaded from
  outside the roots shows as loaded/<file name> in its id and panel id,
  in ui.inspect and ui.docking.
- The folder preferences in ui.engine_prefs and in an open Preferences
  dialog are left out; an empty folder and the scratch disk choices
  Startup and None stay.

The app's own state is not changed. Without roots the replies are as
before.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-11 06:13:33 -08:00
dotCooCoo dfa6e6ea60 MCP: ui.menu.list leaves out recent files outside the read roots
Under --automation-read-root, a control client's ui.menu.list (and
ui.contextMenu.list, which shares the listing) left every File › Open
Recent Files row in, so the client saw the names of recent files it may
not read. file.recentFiles returned their full paths, and
file.openRecentN for such a file answered with a refusal naming the path.

Now the listing leaves out a recent file outside the read roots, as it
already leaves out listed scripts outside them. The other rows keep their
ids, so file.openRecent3 still opens the third file. file.recentFiles
returns only the files inside the roots, in order, and file.openRecentN
for a file outside them ends with "no such recent file", as an empty slot
does. The person's own menus and Home screen are unchanged.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-11 03:20:14 -08:00
dotCooCoo d9e9adbf45 MCP: answer_dialog sets the fields and answers the dialog in one request
answer_dialog sent ui.dialog.set and then ui.dialog.confirm or
ui.dialog.cancel as two requests. A dialog another control connection
opened between them was confirmed or canceled without the fields.

ui.dialog.set takes `action: confirm | cancel`, checked before any field
is set, and confirms or cancels the dialog the fields were set in within
the same request, replying {dialog, result}. answer_dialog sends set and
action together; an app whose reply has no `dialog` key did not answer
it, and the dialog is then confirmed or canceled with its own request.
2026-11-10 14:51:50 -08:00
dotCooCoo 860149a981 Merge main into feat/text-glyph-bounds 2026-11-09 22:03:17 -08:00
dotCooCoo 156613941a Type: glyph bounds take in underline and strikethrough bars
With Measure Type by Glyph Bounds on, point type is measured by its
glyph outlines and its underline and strikethrough bars, as the canvas
draws them. A typed W or H gives what is drawn that size, and underlined
or struck-through spaces are measured by their bars instead of the em
box.

The texts now say that each point type object selected as an object
(not inside a selected group) is measured this way, that moved type
snaps by its ink box, and which Arrange Tools commands follow the
option: Swap Objects, Replace with Top Object, Set Size of Each and
Sort Objects. Arrange in Grid and Group Overlapping Objects keep
measuring visual bounds.
2026-11-09 21:53:22 -08:00
dotCooCoo a1949095c6 Type: an option fits a text object's bounds to its glyph outlines
Measure Type by Glyph Bounds (`typeGlyphBounds`, off by default) is in
Preferences > Type > Glyph Bounds and the Transform panel menu. With it
on, the bounding box, the Transform, Control bar and Properties X, Y, W
and H, `object.setBounds`, the transform tools' reference point and the
Arrange commands measure point type selected on its own by the ink of
its glyphs instead of its em box. A typed W or H scales the live type
until its ink has that size.

- The engine caches each type object's ink in text space with its
  layout bounds; the cache is not saved.
- Use Preview Bounds adds the characters' strokes, and type with
  geometry effects is measured as drawn. Skewed type is measured by its
  outlines.
- Type that draws nothing, area type, type on a path and type inside a
  selected group are measured as before. Align and Distribute keep
  following Align to Glyph Bounds.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md,
object.setBounds params text.
2026-11-09 21:07:55 -08:00
dotCooCoo 86184868a5 New Document: More Settings is a pop-up, and Save Preset a mode of Preset Details
More Settings no longer replaces the dialog with a form that repeats Preset
Details. It opens a pop-up over New Document with only Number of Artboards,
the four layout buttons, Change to Right-to-Left Layout, Spacing and
Columns, editing the same fields live. Done, Escape and a click outside
close it and keep the values; the click outside does not reach the dialog
under it. Enter in a field applies it and closes the pop-up. The old form's
Templates… button is removed with it; File > New from Template opens
templates.

Save Preset no longer adds a Preset Name row under the document's name. It
replaces the top of Preset Details with a Save Document Preset heading, the
preset's name (focused, text selected), Cancel and Save, and hides the
document's name, Close and Create. The rows under it stay where they are
and editable, and Save stores them. Enter in the name saves; Escape is
Cancel and keeps the edits. Nothing creates a document in this mode: a
double-clicked preset card, Enter elsewhere and ui.dialog.confirm (which
saves). A single click on a card fills the fields, as outside the mode.

Save Preset's default name is now the first "Preset N" that no saved
preset has, and it is offered again after each save. Before, it was
"Preset <count + 1>", and after a save the field kept the saved name, so
pressing Save could replace an existing preset. A name typed by hand still
replaces a preset of the same name, as before.

Enter creates the document on a new press only, so a held Enter's repeats
after a save do not create one.

The newDocumentMore dialog kind, presetName and __saving keep working for
the control protocol (ui.click on More Settings opens the pop-up);
docs/control-protocol.md describes them. The catalog rows of the removed
form's strings are removed.
2026-11-09 17:55:38 -08:00
dotCooCoo c2753c1169 Merge main into fix/plugin-grant-app-approval 2026-11-08 22:17:36 -08:00
BFlat cc02f7b35e Merge pull request #4379 from dotCooCoo/fix/shape-builder-merge-off-ui-thread
Shape Builder: a large selection merges on another thread
2026-11-09 13:10:54 +08:00
dotCooCoo 391705af50 Merge main into fix/plugin-grant-app-approval 2026-11-08 21:10:29 -08:00
BFlat 1b8f273255 Merge pull request #6277 from dotCooCoo/fix/titlebar-variable-doc
Linux: docs say which VECTORCRAFT_TITLEBAR values take precedence
2026-11-09 13:06:49 +08:00
dotCooCoo e7c3307f07 Merge main into fix/plugin-grant-app-approval 2026-11-08 20:58:47 -08:00
dotCooCoo fc728b909e Merge main into fix/shape-builder-merge-off-ui-thread 2026-11-08 20:23:21 -08:00
dotCooCoo edaf6cbc07 Linux: docs say which VECTORCRAFT_TITLEBAR values take precedence
Only app, system and desktop override the frame choice. Any other value, such as unknown, is ignored, so System Title Bar still applies.
2026-11-08 20:20:27 -08:00
dotCooCoo 0b19003214 Merge main into fix/save-screens-unknown-options 2026-11-08 20:13:09 -08:00
dotCooCoo 71c3a7c8e2 Merge main into fix/plugin-grant-app-approval 2026-11-08 19:36:52 -08:00
BFlat c040fa7a55 Merge pull request #2279 from dotCooCoo/feat/color-wheel-panel
Part of #978: Window › Color Wheel picks colors on a hue ring and a saturation and brightness square
2026-11-09 11:30:27 +08:00
dotCooCoo 36755be821 Merge main into fix/plugin-grant-app-approval 2026-11-08 19:30:19 -08:00
dotCooCoo 67e3d6f13f Merge main into fix/save-screens-unknown-options 2026-11-08 19:13:11 -08:00
BFlat 4d8d2fb8ef Merge pull request #5036 from dotCooCoo/fix/linux-title-bar-r
Linux: VECTORCRAFT_TITLEBAR takes precedence over System Title Bar for the run it is set in
2026-11-09 11:08:44 +08:00
dotCooCoo 4941b377f9 Merge main into fix/plugin-grant-app-approval 2026-11-08 19:01:49 -08:00
dotCooCoo 31769bd8ad Part of #978: Window › Color Wheel picks colors on a hue ring and a saturation and brightness square
Window › Color Wheel opens a new panel: the Fill and Stroke proxy
beside a hue ring around a square with saturation across and
brightness up at the ring's hue. It edits what the Color panel's
sliders edit (the active proxy's color, the selected gradient stop or
freeform point) through the same paint commands, and a drag is one
undo step. Alt paints the other proxy, and Shift steps the ring by
45°. The Color panel does not change.

A pick is display sRGB and goes into the working RGB space through the
color settings. An RGB, CMYK or Lab color keeps its model, and a Gray
color or a tint of a global swatch becomes a process color in the
document's color mode. The wheel keeps the hue of the last pick while
the objects, the proxy and the color are unchanged, so a drag through
a gray and back keeps the hue.

A press gives the ring or the square the keyboard focus. The arrow
keys then step the hue by 1° or the saturation and brightness by 1%.
With Shift a press steps ten times as far, and with Cmd/Ctrl it steps
a tenth as far. Each press makes one undo step, and Escape or a click
elsewhere gives the keys back to the tools. Screen readers
read the ring as a slider from 0 to 360 with increment, decrement and
set-value actions, and the square as its name and both values. The
Color Picker's color field is the same widget, so it takes the same
keys and reports its name and values.

Color::to_hsb and Color::from_hsb now call the new rgb_to_hsb and
hsb_to_rgb, which the panel uses on display sRGB numbers.
2026-11-08 18:43:48 -08:00
dotCooCoo 81149bb945 Linux: VECTORCRAFT_TITLEBAR takes precedence over System Title Bar for one run
On Linux and the BSDs, VECTORCRAFT_TITLEBAR=app now uses the app bar as the title bar with System Title Bar on. Before, System Title Bar kept the desktop's frame while the Preferences note said the variable chooses the title bar.

While the variable is set, Preferences dims System Title Bar, and the note that System Title Bar takes precedence over VectorCraft Title Bar on Every Desktop does not show. macOS and Windows do not read the variable.
2026-11-08 18:31:31 -08:00
dotCooCoo bf4ec4253d Merge main into fix/save-screens-unknown-options 2026-11-08 18:13:32 -08:00
dotCooCoo 918ef940cb Merge main into feat/plugin-importers 2026-11-08 16:45:20 -08:00
dotCooCoo 727a611ef7 Merge fix/plugin-grant-module-hash into fix/plugin-grant-app-approval 2026-11-08 16:35:45 -08:00
dotCooCoo 4c3f0b4c33 Merge main into fix/save-screens-unknown-options 2026-11-08 15:32:45 -08:00
dotCooCoo 4fff063dcc Merge main into fix/export-unknown-options 2026-11-08 14:25:57 -08:00
dotCooCoo 36bca85879 Plug-ins: app.open passes params to the importer File › Open picks
app.open with params and no importer ran file.open with the path alone, so the desktop app ran the importer on its defaults while headless app.open passed the params to document.open. file.open now carries params to the importer that opens the file.

The importer parameters test installs its module with replace from the second pass on, as plugin.install requires. The permission table in docs/plugins.md lists doc.read for filter, effect and exporter.
2026-11-08 12:59:17 -08:00
dotCooCoo d5fc96327e Merge main into fix/shape-builder-merge-off-ui-thread
# Conflicts:
#	crates/engine/src/lib.rs
#	crates/engine/src/session/documents.rs
2026-11-08 11:33:51 -08:00
dotCooCoo 19f7fb774b Merge main into feat/plugin-importers 2026-11-08 11:30:49 -08:00
dotCooCoo 33489f9c1a Merge main into fix/plugin-grant-app-approval 2026-11-08 11:28:38 -08:00
dotCooCoo fd3482c272 Merge main into fix/shape-builder-merge-off-ui-thread 2026-11-08 11:28:00 -08:00
dotCooCoo 1b30f960e6 Merge main into fix/plugin-grant-app-approval 2026-11-08 11:27:11 -08:00
dotCooCoo a4a516e82f Plug-ins: only a person can approve a plug-in's permissions and heavy budget
`plugin.install` accepted `grant` and `allowHeavy` from any client, so
the program installing a plug-in could answer its own permission
prompt.

The desktop app now shows an approval dialog that names the module,
its hash and what it asks for. Confirming it gives the engine a
one-use approval tied to that module id, hash and permission list. A
control or MCP request and a frame of synthetic input cannot confirm
the dialog, and Enter does not confirm it.

Without such an approval, `grant` and `allowHeavy` are refused. The
new `--allow-plugin-grants` flag on `mcp` and `run` lets a person who
starts a headless session accept them from requests. The flag cannot
be combined with `--connect`. A module already approved in the desktop
app still installs through its stored grant.
2026-11-08 11:03:38 -08:00
Sven Lafebre 057978f61a Fix #6135: the importPdf row states when the dialog opens 2026-11-09 02:03:10 +07:00
Sven Lafebre 1e7e1d33e9 Fix #6135: opening a .ai with editing data skips the Import PDF dialog
The editing data of a .ai or .ait holds every artboard, so a multi-page
file has no pages to pick. Opening one now goes straight to it, as a
file carrying its VectorCraft document already does. The dialog stays
for PDFs, a .ai that is only a PDF, a password, and Place.
2026-11-09 02:03:10 +07:00
dotCooCoo 79351d7063 Merge main into feat/plugin-importers 2026-11-08 10:25:28 -08:00
dotCooCoo 01ff8464c4 Merge main into fix/save-screens-unknown-options 2026-11-08 10:08:30 -08:00
dotCooCoo 1ce9e9e9eb Merge main into feat/plugin-importers 2026-11-08 09:41:06 -08:00
dotCooCoo fb413b39f3 Title bar: a Linux and BSD preference uses the app bar where the desktop draws the frame
Squashed from #6101 onto main.
2026-11-09 00:27:21 +07:00
dotCooCoo cd8e98c6cd DXF: a CNC / CAM preset sets the export options for cutting software
Squashed from #5500 onto main.
2026-11-09 00:25:53 +07:00
dotCooCoo 315ff52ffd Workspace: make keeping Tools beside the canvas an option, off by default
Docked Tools stays at the window's left edge again, outside any panels
docked on the left. Window › Toolbars › Keep Tools Beside the Canvas
(`window.toolsBesideCanvas {on?}`) docks it between those panels and the
canvas instead.

- The setting is its own field in the UI state and in workspaces, and a
  missing field reads as off, so saved state and workspaces keep Tools at
  the window's edge. Built-in workspaces have it off.
- Off, app.rs draws docked Tools before the docking layout, the canvas
  reserves no width for it, and only the full-height window-edge strip
  docks a floating Tools panel. On, the canvas panel draws it, the canvas
  keeps room for it, and both the window edge and the canvas edge dock it
  beside the canvas.
- Turning the setting off forgets the canvas-edge strip, so a strip laid
  out while it was on does not dock Tools. A floating Tools panel stays
  floating when the setting changes.
- `window.panel.dock {panel: "tools"}` docks Tools where the setting says.
- The menu label has a row in every catalog.

Docs: docs/mcp.md, docs/control-protocol.md, the ROADMAP progress log and
docs/target-app-parity.md. The headline-numbers row and the paragraphs
under the status lines are gone, and scores are unchanged.
2026-11-08 23:51:40 +07:00
dotCooCoo 8c7e7041fd Title bar: the app bar shows no brand mark under the desktop's own frame
On Linux, when the desktop draws the window's frame (KDE, Sway,
Hyprland, COSMIC and X11 sessions), the app bar painted the brand mark
under the desktop's title bar unless System Title Bar was on. The mark
followed the live preference instead of the frame the window has.

The desktop app now records the frame it opened the window with
(VectorcraftApp::desktop_frame), and system_title_bar reads it. A
change to System Title Bar during a session no longer shows or hides
the mark; it changes with the frame at the next start. Embedders
without a window of their own keep the mark.
2026-11-08 23:50:37 +07:00