mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-27 03:06:57 -06:00
The issue asked for one-step symmetric shapes, splitting all selected art along a line and cropping art to a rectangle as real geometry. Only the freehand Knife and the Scissors existed, and neither works on compound paths as one shape. New commands path.mirrorCut, path.lineCut and path.rectCut cut the selected paths and compound paths (inside groups too) with pathops booleans against a half-plane or rectangle, and split open paths with the Knife/Path Eraser helpers. Mirror & Cut reflects the kept half and unites it with itself (open halves are joined on the axis). The draw2 piece helpers now rebuild compound paths too. Three tools (Eraser group, original icons) preview the cut live while dragging and commit it as one undo step; Mirror & Cut's axis and kept side are tool options shown in the Control bar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.7 KiB
Rust
39 lines
1.7 KiB
Rust
//! The cutting tools in the UI: toolbar entries, icons and Mirror & Cut's Control bar options.
|
|
|
|
use serde_json::json;
|
|
use vectorcraft_engine::Session;
|
|
|
|
use crate::{VectorcraftApp, chrome, icons, tests_labels::painted_text};
|
|
|
|
fn app() -> VectorcraftApp {
|
|
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
|
app.run("file.new", json!({"width": 300, "height": 300})).unwrap();
|
|
app
|
|
}
|
|
|
|
#[test]
|
|
fn the_cut_tools_have_their_own_icons_and_toolbar_slot() {
|
|
for (tool, icon) in [("mirrorCut", "dc-mirror-cut"), ("lineCut", "dc-line-cut"), ("rectCut", "dc-rect-cut")] {
|
|
let info = vectorcraft_tools::tool_info(tool).unwrap();
|
|
assert_eq!(icons::tool_icon(info.icon), icon);
|
|
assert!(icons::exists(icon), "{icon}");
|
|
assert!(crate::toolbar::BASIC.iter().flat_map(|(_, slots)| slots.iter()).any(|s| s.contains(&tool) && s.contains(&"knife")));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn the_control_bar_shows_mirror_and_cut_options() {
|
|
let mut app = app();
|
|
app.run("tool.select", json!({"tool": "lineCut"})).unwrap();
|
|
assert!(!painted_text(&mut app, chrome::control_bar).contains("Axis:"), "only Mirror & Cut has options");
|
|
app.run("tool.select", json!({"tool": "mirrorCut"})).unwrap();
|
|
let text = painted_text(&mut app, chrome::control_bar);
|
|
for s in ["Axis:", "Free", "Keep:", "Left"] {
|
|
assert!(text.lines().any(|l| l == s), "{s} in {text}");
|
|
}
|
|
app.run("tool.setOption", json!({"key": "axis", "value": "horizontal"})).unwrap();
|
|
app.run("tool.setOption", json!({"key": "keep", "value": "bottom"})).unwrap();
|
|
let text = painted_text(&mut app, chrome::control_bar);
|
|
assert!(text.lines().any(|l| l == "Horizontal") && text.lines().any(|l| l == "Bottom"), "{text}");
|
|
}
|