diff --git a/ROADMAP.md b/ROADMAP.md index 804916fd..485f7fb7 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -123,7 +123,7 @@ Ranked; detail in [docs/roadmap.md](docs/roadmap.md) and [docs/gaps.md](docs/gap | Date | What landed | |---|---| -| 2026-10-11 | Effect › Brush Strokes: Accented Edges, Angled Strokes, Crosshatch, Dark Strokes, Ink Outlines, Spatter, Sprayed Strokes, Sumi-e (G2). Command parameters from agents and files checked before anything changes (paint, place, cuts, dashes, crop, asset ids, anchors, paths, distort; #984–#999); command dialogs keep whole numbers whole, so Create Object Mosaic takes the tiles typed (#1000); stepper arrows take Shift (×10) and Ctrl/Cmd (÷10) like the arrow keys (#991). Exports and Rasterize supersample Art Optimized edges, so shapes meeting edge to edge leave no seam (#983). Character and paragraph styles take leading, kerning, mojikumi and the other attributes left out at their defaults (#1001). Drawing, typing and pasting with no layer shown and unlocked is refused instead of adding art to a hidden or locked layer (#1002). MCP `add_text` gives type on or in a path the colour asked for (#1003). MCP `screenshot` of a connected app renders the artboard asked for (#1004). `vectorcraft-cli run` ends quietly when its reader closes early (#1005). | +| 2026-10-11 | Effect › Brush Strokes: Accented Edges, Angled Strokes, Crosshatch, Dark Strokes, Ink Outlines, Spatter, Sprayed Strokes, Sumi-e (G2). Command parameters from agents and files checked before anything changes (paint, place, cuts, dashes, crop, asset ids, anchors, paths, distort; #984–#999); command dialogs keep whole numbers whole, so Create Object Mosaic takes the tiles typed (#1000); stepper arrows take Shift (×10) and Ctrl/Cmd (÷10) like the arrow keys (#991). Exports and Rasterize supersample Art Optimized edges, so shapes meeting edge to edge leave no seam (#983). Character and paragraph styles take leading, kerning, mojikumi and the other attributes left out at their defaults (#1001). Drawing, typing and pasting with no layer shown and unlocked is refused instead of adding art to a hidden or locked layer (#1002). MCP `add_text` gives type on or in a path the colour asked for (#1003). MCP `screenshot` of a connected app renders the artboard asked for (#1004). `vectorcraft-cli run` ends quietly when its reader closes early (#1005). Select › All on Active Artboard selects on the artboard made active, not always the first (#1006). | | 2026-10-10 | Initial live Revolve (Effect › 3D and Materials, #846, #605), in its own `three-d` crate. Progress docs re-measured and restructured to the craftrules standard (this page, `docs/target-app-parity.md`, `gaps.md`, `ui-parity.md`, the format, hardware, localization, effects and type checklists). Same day: v0.8.0; Effect › Distort, Pixelate and Texture filters (13); German interface; Variables (data merge); Graph Type value axes and tick marks; restart when the first frame never reaches the screen (#964) | | 2026-10-09 | Radial Blur, Smart Blur, Unsharp Mask (gap 2 begins); 340 commits, the busiest day | | 2026-10-08 | v0.5.0–v0.7.0; community contributions: Pen and shape-tool modifiers, Layers, Artboards, Japanese composition, Hebrew/Arabic type, interface languages, saved selections | diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index d82fbbde..0077af03 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -579,6 +579,16 @@ impl VectorcraftApp { return r; } let mut params = params; + // Paste in place, in front, in back (#693) and Select › All on Active Artboard (#1006): onto + // or on the active artboard, the view's. + if matches!(id, "edit.pasteInPlace" | "edit.pasteInFront" | "edit.pasteInBack" | "select.allOnArtboard") + && params.get("artboard").is_none() + && self.view().is_some() + && let Some(n) = self.session.active().map(|d| d.doc.artboards.len()) + && let Some(p) = params.as_object_mut() + { + p.insert("artboard".into(), serde_json::json!(panels::artboards::selected(self, n))); + } if id.starts_with("edit.paste") { if let Err(e) = self.adopt_system_clipboard() { self.ui.status = e.clone(); @@ -592,14 +602,6 @@ impl VectorcraftApp { { p.insert("center".into(), serde_json::json!([c.x, c.y])); } - // In place, in front, in back: onto the active artboard (#693). - if matches!(id, "edit.pasteInPlace" | "edit.pasteInFront" | "edit.pasteInBack") - && params.get("artboard").is_none() - && let Some(i) = self.view().map(|v| v.artboard) - && let Some(p) = params.as_object_mut() - { - p.insert("artboard".into(), serde_json::json!(i)); - } if let Some(r) = dialogs::swatch_conflict::ask(self, id, ¶ms) { return r; } diff --git a/crates/ui-egui/src/panels/artboards.rs b/crates/ui-egui/src/panels/artboards.rs index db3be688..ab99fbaa 100644 --- a/crates/ui-egui/src/panels/artboards.rs +++ b/crates/ui-egui/src/panels/artboards.rs @@ -235,6 +235,26 @@ mod tests { crate::menus::invoke(&mut app, "view.goToArtboard", json!({"index": "previous"})); assert_eq!(selected(&app, 2), 0, "and the panel follows the navigator"); } + + /// #1006: Select › All on Active Artboard selects the art of the artboard made active here, + /// and an explicit artboard still wins. + #[test] + fn all_on_active_artboard_takes_the_active_artboard() { + let mut app = VectorcraftApp::new(Session::new(), Default::default()); + app.session.execute("file.new", &json!({"width": 100, "height": 100, "units": "Points", "artboards": 2})).unwrap(); + let mut rect = |x| app.session.execute("shape.rectangle", &json!({"x": x, "y": 10, "width": 20, "height": 20})).unwrap()["id"].clone(); + let (a, b) = (rect(10), rect(130)); + let picked = |app: &mut VectorcraftApp, params| { + crate::menus::invoke(app, "select.allOnArtboard", params); + let ids: Vec = app.session.active().unwrap().selection.objects.iter().map(|n| n.0).collect(); + json!(ids) + }; + select(&mut app, 1); + assert_eq!(picked(&mut app, json!({})), json!([b])); + select(&mut app, 0); + assert_eq!(picked(&mut app, json!({})), json!([a])); + assert_eq!(picked(&mut app, json!({"artboard": 1})), json!([b])); + } /// Double-clicking a row's number goes to its artboard and its name renames it; a row's /// Options button edits that artboard with the Artboard tool, and the tool's artboard is the /// active one.