diff --git a/crates/ui-egui/src/panels/artboards.rs b/crates/ui-egui/src/panels/artboards.rs index 77023bacb..deff9d872 100644 --- a/crates/ui-egui/src/panels/artboards.rs +++ b/crates/ui-egui/src/panels/artboards.rs @@ -5,7 +5,8 @@ //! Artboard duplicates its artboard (as Duplicate Artboards does, with //! its art when the Artboard tool's Move/Copy Artwork with Artboard is on). The highlighted row is the active artboard, the one the status bar's navigator shows and //! Fit Artboard in Window fits: clicking a row makes it active, double-clicking its number also -//! fits it in the window. The options icon at a row's right end opens Artboard Options: a click on +//! fits it in the window. Shift-click selects a range of artboards and Ctrl/Cmd-click adds or +//! removes one, with any tool: another tool gives way to the Artboard tool first (#5698). The options icon at a row's right end opens Artboard Options: a click on //! the active artboard's icon, or a double-click on another row's icon. The lock column left of it //! shows a lock on a locked artboard, and a click there locks or unlocks the artboard //! (`artboard.setProps` with `locked`); Delete leaves locked artboards. @@ -488,6 +489,12 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { } } let m = ui.input(|inp| inp.modifiers); + // A Shift- or Ctrl/Cmd-click selects several artboards with any tool: it first + // switches to the Artboard tool, which holds the selection, so Properties and the + // Control bar then show the controls that change every selected artboard. + if resp.clicked() && (m.shift || m.command) && app.session.tool_id() != "artboard" { + app.select_tool("artboard"); + } let tool = app.session.tool_id() == "artboard"; row_clicked |= resp.clicked(); if resp.clicked() && tool && m.shift { diff --git a/crates/ui-egui/src/panels/artboards/tests.rs b/crates/ui-egui/src/panels/artboards/tests.rs index edae3a32e..bf2b47050 100644 --- a/crates/ui-egui/src/panels/artboards/tests.rs +++ b/crates/ui-egui/src/panels/artboards/tests.rs @@ -156,10 +156,20 @@ fn shift_clicking_rows_selects_several_artboards() { frame(&mut app, 9.0, click(4, egui::Modifiers::NONE)); assert_eq!(picked(&app, 4), [3]); assert_eq!(highlighted(frame(&mut app, 10.0, vec![])), 1); - // With another tool, a Shift-click makes the row's artboard active, as a plain click does. + // With another tool, a plain click makes the row's artboard active and keeps the tool. app.select_tool("selection"); - frame(&mut app, 11.0, click(2, egui::Modifiers::SHIFT)); - assert_eq!((picked(&app, 4), selected(&app, 4)), (vec![1], 1)); + frame(&mut app, 11.0, click(2, egui::Modifiers::NONE)); + assert_eq!((app.session.tool_id(), selected(&app, 4)), ("selection", 1)); + // A Shift-click switches to the Artboard tool and selects the range (#5698). + frame(&mut app, 12.0, click(4, egui::Modifiers::SHIFT)); + assert_eq!(app.session.tool_id(), "artboard"); + assert_eq!((picked(&app, 4), selected(&app, 4)), (vec![1, 2, 3], 3)); + // So does a Ctrl/Cmd-click, adding one artboard to the one active. + app.select_tool("selection"); + frame(&mut app, 13.0, click(1, egui::Modifiers::NONE)); + frame(&mut app, 14.0, click(3, egui::Modifiers::COMMAND)); + assert_eq!(app.session.tool_id(), "artboard"); + assert_eq!((picked(&app, 4), selected(&app, 4)), (vec![0, 2], 2)); } /// Double-clicking a row's number goes to its artboard and its name renames it; a click on diff --git a/crates/ui-egui/src/panels/properties.rs b/crates/ui-egui/src/panels/properties.rs index b8a42e928..79632f400 100644 --- a/crates/ui-egui/src/panels/properties.rs +++ b/crates/ui-egui/src/panels/properties.rs @@ -462,7 +462,7 @@ fn multi_color(app: &mut VectorcraftApp, ctx: &egui::Context) -> bool { /// Edit Artboards (the Artboard tool): the active artboard's name, which can be edited to rename /// it, and the Artboard Options icon; its position and size, its preset and /// orientation (#671) (with Scale Artwork with Artboard on, a new size scales its art, #602; a new -/// W or H, preset or orientation goes to every selected artboard, in one undo step), its Fill (background color), Move +/// W or H, preset or orientation goes to every selected artboard, in one undo step), its Fill (background color, also for every selected artboard), Move /// and Scale Artwork with Artboard, New Artboard and Delete Artboard, and Quick Actions: Rearrange All (#681) and /// Exit back to the Selection tool (#530). fn artboard_sections(app: &mut VectorcraftApp, ui: &mut Ui) { @@ -681,8 +681,11 @@ fn artboard_fill_row(app: &mut VectorcraftApp, ui: &mut Ui, i: usize, color: Opt None => {} } }); + // A Fill chosen from the list goes to every selected artboard, in one undo step (#5698). if let Some(c) = set { - app.run("artboard.setProps", json!({"index": i, "color": c.as_ref().map(super::color_json)})).ok(); + let color = c.as_ref().map(super::color_json); + let indices = super::artboards::renamed_with(app, i); + super::artboards::set_props(app, &indices, json!({}), |j, _| Some(json!({"index": j, "color": color}))).ok(); } if pick { app.run("ui.colorPicker", json!({"artboard": i})).ok(); diff --git a/crates/ui-egui/src/panels/properties/tests.rs b/crates/ui-egui/src/panels/properties/tests.rs index 30ac3cd45..7c5e69e11 100644 --- a/crates/ui-egui/src/panels/properties/tests.rs +++ b/crates/ui-egui/src/panels/properties/tests.rs @@ -665,6 +665,25 @@ fn edit_artboards_fill_sets_the_background_color() { assert_eq!(app.ui.dialog.as_ref().map(|d| d.fields.get("artboard")), Some(Some(&json!(1))), "the chip opens it too"); } +/// #5698: with Artboards 1 and 3 selected, a Fill chosen in Edit Artboards goes to both, in one +/// command and one undo step; Artboard 2 keeps none. +#[test] +fn edit_artboards_fill_sets_every_selected_artboard() { + let mut app = two_selected_artboards(); + let colors = |app: &VectorcraftApp| app.session.doc().unwrap().doc.artboards.iter().map(|a| a.color).collect::>(); + let undo = app.session.doc().unwrap().history.undo.len(); + let ctx = egui::Context::default(); + frame(&mut app, &ctx, vec![]); + let texts = frame(&mut app, &ctx, vec![]); + click(&mut app, &ctx, &texts, "None"); + let texts = frame(&mut app, &ctx, vec![]); + let commands = app.run_count; + click(&mut app, &ctx, &texts, "Black"); + assert_eq!(app.run_count.wrapping_sub(commands), 1, "one command"); + assert_eq!(colors(&app), [Some(Color::BLACK), None, Some(Color::BLACK)]); + assert_eq!(app.session.doc().unwrap().history.undo.len(), undo + 1, "one undo step"); +} + fn artboard_deletion_app(count: usize) -> VectorcraftApp { let mut app = VectorcraftApp::new(Session::new(), Default::default()); app.run("file.new", json!({"width": 200, "height": 100, "artboards": count})).unwrap(); diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index ae219584b..3042e2fd3 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -1,6 +1,6 @@ # Parity with Adobe Illustrator -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-05 · **Change:** minor (PDF import keeps DeviceN gradients of a spot ink over process plates, #3235; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-05 · **Change:** minor (Artboards panel multi-select with any tool, Fill for every selected artboard; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; public release notes through 30.7, August 2026) ## Feature submission evidence @@ -567,7 +567,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - **Contextual controls in Properties:** the [Properties panel overview](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/properties-panel-overview.html) lists controls that appear for particular selections and tools; Properties has them, each running the existing command. Quick Actions has Blend Options for one selected blend, with the Blend tool or any other, as the [blending page](https://helpx.adobe.com/illustrator/using/blending-objects.html) describes (#4817) (the Blend Options dialog, OK one undo step) and Merge Live Paint when a Live Paint group is selected with more paths and nothing Live Paint refuses (`livePaint.merge`). Appearance has the stroke's Variable Width Profile list, the Control bar's, with the Width tool or when the stroke has a variable width (`stroke.set {profile}`), and beside fx the Delete icon: with one effect on the one selected object (its own or a fill's or stroke's) its name and an icon that removes it (`effect.remove`), with several an icon that opens the Appearance panel, as the overview describes. With Direct Selection and corners of one path selected, Corner and Corner Radius set the kind and radius of those corners (`object.setLiveShape`); a live rectangle's and polygon's own rows already do. Each edit is one undo step. The overview's Variable Font icon was already in Character. Not checked against the reference app: whether Merge needs two Live Paint groups (the overview speaks of several selected groups; `livePaint.merge` takes a group and paths), and where exactly each control sits in its section. Evidence: `panels::properties::tests::{blend_options_is_a_quick_action_for_one_blend_with_the_blend_tool, merge_live_paint_is_a_quick_action_for_a_live_paint_group_and_more, the_width_profile_shows_for_a_variable_width_or_the_width_tool, direct_selected_corners_show_their_kind_and_radius, one_effect_has_a_delete_icon_in_appearance}`. - **Edit Artboards in Properties:** the active artboard's name is a field. Typing a new name and pressing Enter or clicking elsewhere renames that artboard in one undo step, as the Artboards panel's rename does (`artboard.setProps {index, name}`); pressing Escape or leaving the field empty keeps the old name. A click on the Artboard Options icon beside the field opens Artboard Options for the active artboard, as double-clicking the Artboard tool's button does (`tool.options {tool: "artboard"}`). Pointer and key tests in `panels/properties.rs` cover both. Public references: [Resize artboards](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/add-edit-artboards/resize-artboards.html) and [Create and add new artboards](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/add-edit-artboards/add-new-artboards.html). - **Artboard background colors:** each artboard can have a background color (`artboard.setProps {index, color}`, `color: null` removes it). With the Artboard tool, Properties has a Fill row: its list sets None, White or Black, and its chip and its Color Picker… item open the Color Picker for the artboard. Artboard Options has a Background Color row with a list that sets None, White or Black, and a color button. The canvas draws the artboard's paper in the color, multiplied with the paper color while Simulate Colored Paper is on, and the transparency grid still covers it. The native format saves the color, and a document without colors saves as before. Exports draw it behind each exported artboard's art, inside the artboard and in the color's own model: raster formats (on a transparent background too), PDF, SVG and EPS pages, `.ai` files' PDF pages, Export for Screens and print, whose preview shows it; files with editing data keep it as the artboard's color, not as art. Export for Screens has Include Artboard Fill beside Include Bleed (on by default and remembered; `includeArtboardFill: false`, which `document.export` and `file.print` take too, leaves it out) (#4937). Not done: `.ai` files the reference app reads keep it only in VectorCraft's editing data, and `.ai`/PDF import doesn't read a background color from the reference app's own data. Engine, canvas, Properties, Color Picker, Artboard Options, export (`fileio::tests_artboard_fill`) and Export for Screens dialog tests cover it. Public reference: [Apply colors to artboards](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/organize-manage-artboards/add-background-color-to-artboards.html). -- **Resizing several artboards:** with several artboards selected with the Artboard tool, a new W or H in Properties, the Transform panel or the Control bar, a preset or an orientation in Properties or the Control bar, and a new Width or Height in Artboard Options resize every selected artboard in one undo step (`artboard.setProps {artboards}`); with Scale Artwork with Artboard on, Properties, the Transform panel and the Control bar scale each object once, with the artboard it was inside before the change. The Transform panel, the Control bar and Artboard Options resize each one about its own reference point, a preset sizes each one in its own orientation, and X and Y still move the active artboard alone. Pointer and key tests in `panels/properties.rs`, dialog tests in `dialogs/tests.rs` and an engine test in `tests/xform.rs` cover them. Public references: [Artboard Enhancements In Illustrator CC](https://blog.adobe.com/en/publish/2017/11/10/artboard-enhancements-in-illustrator-cc) (a height and a width entered once resize every selected artboard) and [Using multiple artboards](https://helpx.adobe.com/illustrator/using/using-multiple-artboards.html) (2019). +- **Resizing several artboards:** with several artboards selected with the Artboard tool, a new W or H in Properties, the Transform panel or the Control bar, a preset or an orientation in Properties or the Control bar, and a new Width or Height in Artboard Options resize every selected artboard in one undo step (`artboard.setProps {artboards}`), and a Fill chosen in Properties colors each of them (#5698); a Shift- or Ctrl/Cmd-click on an Artboards panel row with another tool in use switches to the Artboard tool and selects as it does; with Scale Artwork with Artboard on, Properties, the Transform panel and the Control bar scale each object once, with the artboard it was inside before the change. The Transform panel, the Control bar and Artboard Options resize each one about its own reference point, a preset sizes each one in its own orientation, and X and Y still move the active artboard alone. Pointer and key tests in `panels/properties.rs`, dialog tests in `dialogs/tests.rs` and an engine test in `tests/xform.rs` cover them. Public references: [Artboard Enhancements In Illustrator CC](https://blog.adobe.com/en/publish/2017/11/10/artboard-enhancements-in-illustrator-cc) (a height and a width entered once resize every selected artboard) and [Using multiple artboards](https://helpx.adobe.com/illustrator/using/using-multiple-artboards.html) (2019). - **Artboard Escape routing:** Escape leaves Artboard editing for Selection; during a drag it first cancels the gesture. Headless egui key events cover idle Escape, active-drag cancellation and a subsequent Escape in `tests/distortkeys.rs`. - **Escape in the distort tools:** Escape during a Puppet Warp pin drag or turn, a Perspective Grid tool handle or plane widget drag, a Perspective Selection move, resize or plane widget drag, or a Liquify stroke cancels it: the art goes back to how the press found it, no undo step is added, and the tool stays chosen. Puppet Warp also selects again the pins selected before the press, and Escape during a Liquify Alt-drag puts the brush size back. Regression tests: `escape_cancels_*` in `crates/tools/src/distort/puppet.rs`, `perspective.rs` and `liquify.rs`, and `escape_cancels_a_puppet_warp_perspective_or_liquify_drag` in `tests/distortkeys.rs`. - **Shift with the Artboard tool:** a Shift-click adds an artboard to the selection or takes it out when the button comes up. A Shift-drag inside an artboard draws a new artboard there, and a Shift-drag on the pasteboard is a marquee that toggles the artboards it touches, as the [default keyboard shortcuts](https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) (a Shift-drag draws an artboard within an existing one) and [Using multiple artboards](https://web.archive.org/web/20210925094818/https://helpx.adobe.com/illustrator/using/using-multiple-artboards.html) (archived copy) describe. Shift no longer keeps an artboard move at 45° steps or a drawn artboard square. Escape during a marquee or while a new artboard is being drawn cancels it and keeps the Artboard tool. Pointer and key tests in `crates/tools/src/xform/artboard.rs` cover the four gestures and Escape. diff --git a/docs/ui-parity.md b/docs/ui-parity.md index 50cda9a08..b66aadac0 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -1,6 +1,6 @@ # UI and interaction parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-04 · **Change:** minor (isolation mode: a locked or hidden layer keeps the isolated art from clicks and marquees; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-04 · **Change:** minor (Artboards panel multi-select with any tool, Fill for every selected artboard; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged) ## Feature submission evidence @@ -30,6 +30,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard | Date | Change | Summary | |---|---|---| +| 2026-11-04 | minor | Artboards panel: a Shift- or Ctrl/Cmd-click on a row selects several artboards with any tool, switching to the Artboard tool first, so a preset, orientation, size or Fill set in Properties or the Control bar goes to every selected artboard; Fill used to set the active artboard only (#5698); scores and estimates unchanged | | 2026-11-04 | minor | Isolation mode: once the layer, or a group, around the isolated object is locked or hidden, a click or a marquee with the Selection tool no longer selects the isolated art (part of #5309); scores and estimates unchanged | | 2026-11-04 | minor | Transform Each's Scale has the documented Relative and Absolute radio buttons: percentages of each object's size, or the width and height it becomes (`object.transformEach` `relative`); the two scales have the link that keeps them in proportion (`__constrain`, as the shape dialogs'), and the panel lists Scale, Move, Rotate, the Options in two columns, the Reference Point and Preview (level with Copy, Cancel and OK) in the documented order; scores and estimates unchanged | | 2026-11-04 | minor | Cmd+Space pressed during an active drawing drag keeps that tool's cursor; clarify that Space can move an in-progress shape or anchor. Scores and estimates unchanged. | @@ -253,7 +254,7 @@ tools, never checked side by side) isn't captured row by row. | Escape leaves Artboard editing for Selection; during a drag it first cancels the gesture | done | Headless egui key events cover idle Escape, active-drag cancellation and a subsequent Escape in `tests/distortkeys.rs`. | | Escape while typing ends the edit, keeps the type selected and switches to the Selection tool | done | #1802 (#1686, #1656) | | Selection tool: selected area type and type on a path show an in port and an out port (empty, an arrow where threaded, the red "+" of overflow); a click on either loads the text cursor; a click on a closed path, on empty canvas or a drag threads the text there, after the clicked frame from its out port, before it from its in port; Escape or another tool drops it; a double-click on a threaded port breaks the thread there | partial | #2572 (`text.thread.add`, `before` for the in port); the out port sits on the frame's right side above the bottom-right corner handle and the in port on its left side below the top-left one, so the handles can still be grabbed; a double-click on a threaded port breaks the thread (`text.thread.break`, [archived help](https://web.archive.org/web/20220127090642/https://helpx.adobe.com/illustrator/using/creating-text.html)); the loaded cursor borrows the I-beam | -| Shift-click selects several artboards (Artboard tool, Artboards panel); they move, Alt-copy and delete together | done | `artboard.move`/`artboard.delete` `indices` (#1139); panel menu, trash and Properties share selected-set deletion; all-selected retains artboard 1 and a single board cannot be deleted, with pointer-event and Undo/Redo coverage | +| Shift-click selects several artboards (Artboard tool, Artboards panel); they move, Alt-copy and delete together | done | `artboard.move`/`artboard.delete` `indices` (#1139); in the panel, Shift- and Ctrl/Cmd-click work with any tool by switching to the Artboard tool (#5698); panel menu, trash and Properties share selected-set deletion; all-selected retains artboard 1 and a single board cannot be deleted, with pointer-event and Undo/Redo coverage | | Artboards panel: drag a row above or below another to reorder the artboards (as Move Up / Move Down do) | done | #4687; a line shows where the row lands, `artboard.reorder` in one undo step, the moved artboard becomes active; public forum answers describe the drag | | Artboards panel › Delete Empty Artboards | done | `artboard.deleteEmpty`; one undo step, guides go too, locked artboards stay, and artboard 1 when every artboard is empty and none is locked; an artboard is empty when no object (hidden, locked and template art included; guides not) has visual bounds that meet or touch it, a group counting by its members and a clip group or clipping layer by its members inside the clip (our reading of "no artwork"; the pages give no finer rule); [spec](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/add-edit-artboards/delete-artboards.html) | | Artboard Delete/Backspace delete selected boards while protecting artwork, the last board and active drags | done | Headless shortcut regressions in `tests/distortkeys.rs` cover retaining the original first board when all are selected, single-board protection, artwork, saved state and Undo/Redo; the navigator follows the tool’s surviving board through repeated deletion and history changes. |