On Linux, ui.sampleScreenColor and the Color Picker's eyedropper button
now show the XDG desktop portal's color sampler (Screenshot.PickColor,
https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Screenshot.html).
A thread of its own makes the call and waits for the person, and the
picked sRGB color goes through the same conversion into the working RGB
space as on macOS and the web. A cancel leaves the colors as they were.
A session without a portal that has PickColor, a portal that does not
return from the call within 25 seconds (VectorCraft's own limit) or
leaves the bus before it answers, and a portal that ends the request in
another way each show a status message and end the wait. The two new
messages are translated in every catalog that has the sampler's other
messages. The request token is random, as the Request documentation
asks (https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Request.html).
The window is named for the portal on the UI thread, as for the save
dialog, and the sampler's thread keeps the window and its export until
the portal answers.
A save or export that writes a file per artboard, linked images or image
maps names them after the file picked in the save panel, which asked only
about that name. A file already there under one of the other names was
replaced without a question.
Save As, Save a Copy, Save as Template, Save and Export now check those
files before writing anything. When any is there, nothing is written and
a replaceFiles question names it (and lists all of them when there are
several). OK runs the save or export again on the document that asked and
replaces the named files; a file it would now write that the question did
not name is asked about again. Cancel writes nothing. A background save
or export checks from its worker and asks once it ends, after a dialog
open then. Files the document's last Save or Save As wrote are replaced
without asking.
Services::exists is now an Arc<dyn Fn(&str) -> bool + Send + Sync>.
An approval question that a control request, MCP, injected input, or a
file dialog one of them opened leads to now keeps OK disabled and
refuses every confirm, a person's click included. The dialog says to
choose Object › Plug-ins › Install Plug-in…, and ui.installPlugin answers
approval: "personMustStartInstall". The person's own Install Plug-in…,
File › Open or drop inspects the module again and asks a new question
with its half-second delay.
The origin is fixed when the request is made and goes with a native
file dialog's deferred answer and the web picker's answers, which now
arrive apart from drops and from window.vectorcraft.openFile (always
automation). A question about taking another module's place now opens
in the approval dialog, and automation's replace: true no longer skips
it. A module that needs no approval still installs at once.
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.
A save or an export with several notes named only the first of them in
the status bar, with the count, and the others could not be seen. The
status bar now keeps every note of a save or an export for the status
message's hover, as it does for an open's notes since #6752: resting
the pointer on the message lists them in the order the reply gives them
(a save's notes start with what the format loses), and screen readers
receive the list after the message. The status text is unchanged.
This covers Save, Save As, Save a Copy, Save as Template, Save a
Timestamped Copy, Save as PDF, Export As, Export Selection, Export for
Screens, Asset Export, Save for Web, Preview in Browser, Save for Office
Documents, Text Export Options, a print to a file and the CSS Properties
panel's export. The open, the saves and the exports read a reply's notes
through one helper.
Docs: docs/mcp.md and the css.exportFile params text,
docs/control-protocol.md, docs/target-app-parity.md.
VectorCraft could open and place HP-GL plot files but not write them,
so art for a pen plotter or a vinyl cutter had to go through another
program.
Export As, document.export and Export Selection now write HP-GL.
vectorcraft_cad::hpgl::export draws each visible path once along its
own line: a filled shape is its closed outline and a stroked path its
center line. Type is drawn as glyph outlines, a gradient mesh as its
outline, and a symbol instance as its art with its effects and the
instance's stain. Clipping masks cut the art they clip, and the art is
cut at the artboard's edges. Hidden and non-printing layers, hidden objects,
objects at 0% opacity, template layers, guides and placed images are
left out. Coordinates are plotter units (1016 to the inch, y up) from
the artboard's bottom-left corner or its center, and art more than
8,388,607 units from the origin is cut off.
Each color is a pen, in the order the plot first draws in it (up to
255), or a pen table maps each path to the pen of the nearest color.
With Use Artboards every file of the export uses the same numbering.
The pens draw in turn, each in paint order or, with sortPaths, nearest
path first. Curves are flattened to curveTolerance (0.1 pt by default).
hpglVersion "hpgl" writes IN, SP, PU and PD; "hpgl2" also writes the
palette (NP, PC) and each pen's paths as one encoded polyline (PE).
Options are checked, and Export As writes the file with the defaults.
Plots read back by the HP-GL reader give the same lines.
Docs: docs/mcp.md, docs/control-protocol.md, docs/file-format-parity.md,
docs/target-app-parity.md.
Document Setup gets a Color tab with the document color mode (RGB Color
or CMYK Color), a Convert to CMYK or Convert to RGB box for a mode
change (cleared, the colors keep their numbers), and the RGB and CMYK
profiles assigned to the document, with a working-space entry for none.
When the tab changes something, OK runs document.setup, then
edit.assignProfile, then file.documentColorMode in one command.batch,
and the document's changes are one undo step. Assign Profile runs first,
so a mode change converts through the profile picked with it. An
unchanged Color tab adds no color commands, and Cancel, or OK with
nothing changed, records no undo step. A Color tab field with a value of
the wrong kind is an error, and the dialog stays open with nothing
changed. File › Document Color Mode and Edit › Assign Profile… stay
where they are.
Catalogs: "Working RGB (don't tag)" and "Assign Profile" rows in every
complete catalog, and the "`{key}` must be a profile name or null"
message in every complete-message catalog. Docs: docs/mcp.md,
docs/control-protocol.md, docs/target-app-parity.md.
Save As to an EPS file showed Preview Format, Overprints and Flattener
Preset as text fields holding their ids (tiffColor, preserve, medium),
the PostScript level as a number field, and labeled every EPS option
except Use Artboards from its name ("Cmyk Post Script", "Thumbnails").
The dialog now shows the options Export's EPS Options shows. Preview,
Overprints, Flattener preset (the built-in presets, then saved ones) and
PostScript are menus of readable names. Transparent and Opaque apply to
the color TIFF preview only. Embed Fonts shows checked and disabled. The
PostScript level comes last. A pick writes the same values as before
(previewFormat "tiffColor", a built-in preset's id, a saved preset's
name, the level as a number). A value that the save would reject shows
as it is.
Every option the dialog shows has a written label. "Preview:" has a row
in every catalog, and the de, it, ja, ko, uk, vi and zh-hant catalogs
gain the menu names, which Export's EPS Options also showed in English.
Export As's Range field shows the "1-3, 5" example when emptied, as
Save As's does.
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.
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.
A plain Save that the location refuses (read-only filesystem or permission denied) now opens Save As with the name filled in, instead of ending in an error dialog. The refusal travels as a typed engine error (READ_ONLY_LOCATION), so the control protocol and MCP still return an error and never open a panel. Recovery failures, explicit destinations, a busy picker and Close/Quit keep their existing flow.
Closes#6146
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.
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.
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.
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.
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.
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.
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.