UI.P1: Persist Polygon and Star counts after exact-size placement

This commit is contained in:
FractalEncrypt
2026-10-21 15:42:37 +07:00
committed by bflatastic
parent a5a9371979
commit b9fa08f9e6
7 changed files with 76 additions and 10 deletions
+11 -1
View File
@@ -94,6 +94,16 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
}
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
let count = match d.kind.as_str() {
"polygon" => Some(("sides", 6.0, 3.0)),
"star" => Some(("points", 5.0, 2.0)),
_ => None,
};
let options = count.map(|(key, default, min)| {
let mut values = json!({});
values[key] = json!(d.f64(key, default).clamp(min, 1000.0) as u64);
values
});
let (x, y) = (d.f64("x", 0.0), d.f64("y", 0.0));
let (id, params) = match d.kind.as_str() {
"ellipse" => ("shape.ellipse", json!({"x": x, "y": y, "width": d.f64("width", 100.0), "height": d.f64("height", 100.0)})),
@@ -125,7 +135,7 @@ fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
),
};
// On the active plane while the perspective grid shows, sized in plane units from the click.
let options = matches!(d.kind.as_str(), "rectangularGrid" | "polarGrid").then(|| params.clone());
let options = options.or_else(|| matches!(d.kind.as_str(), "rectangularGrid" | "polarGrid").then(|| params.clone()));
let result = match vectorcraft_engine::perspective_click(&app.session, id, &params, vectorcraft_geom::Point::new(x, y)) {
Some((id, params)) => run_and_close(app, &id, params),
None => run_and_close(app, id, params),
+4 -2
View File
@@ -14,8 +14,10 @@ pub fn open_tool_dialog(app: &mut VectorcraftApp, kind: &str, p: Value) {
let d = match kind {
"rectangle" | "ellipse" => Dialog::new(kind, json!({"x": x, "y": y, "width": "100 pt", "height": "100 pt"})),
"roundedRectangle" => Dialog::new(kind, json!({"x": x, "y": y, "width": "100 pt", "height": "100 pt", "radius": "12 pt"})),
"polygon" => Dialog::new(kind, json!({"x": x, "y": y, "radius": "50 pt", "sides": 6})),
"star" => Dialog::new(kind, json!({"x": x, "y": y, "radius1": "50 pt", "radius2": "25 pt", "points": 5})),
"polygon" => Dialog::new(kind, json!({"x": x, "y": y, "radius": "50 pt", "sides": app.session.tool_options_of(kind)["sides"]})),
"star" => {
Dialog::new(kind, json!({"x": x, "y": y, "radius1": "50 pt", "radius2": "25 pt", "points": app.session.tool_options_of(kind)["points"]}))
}
"lineSegment" => Dialog::new(kind, json!({"x": x, "y": y, "length": "100 pt", "angle": 0})),
// The grids: the tool's stored options (divider counts and skews, switches) at the default size.
"rectangularGrid" | "polarGrid" => {
+45
View File
@@ -1015,6 +1015,51 @@ pub(crate) mod tests {
assert!(app.run("tool.options", json!({"tool": "lasso"})).is_err());
}
#[test]
fn polygon_and_star_canvas_counts_persist_without_new_toolbar_dialogs() {
for (tool, key, count) in [("polygon", "sides", 3), ("star", "points", 7)] {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.run("file.new", json!({"width":300,"height":300})).unwrap();
app.select_tool(tool);
assert!(open_options(&mut app, tool).is_err(), "upstream toolbar opening behavior stays unchanged");
assert!(app.ui.dialog.is_none());
let objects =
|app: &VectorcraftApp| app.session.active().unwrap().doc.layers.iter().map(|l| l.children().map_or(0, |c| c.len())).sum::<usize>();
crate::dialogs::open_tool_dialog(&mut app, tool, json!({"x":120,"y":130}));
let d = app.ui.dialog.as_mut().unwrap();
assert!(d.fields.contains_key(if tool == "polygon" { "radius" } else { "radius1" }));
d.fields.insert(key.into(), json!(count));
crate::dialogs::confirm(&mut app).unwrap();
assert_eq!(objects(&app), 1, "deliberate exact-size placement");
assert_eq!(app.session.tool_options()[key], count);
for round in 0..3 {
if round == 2 {
app.select_tool("ellipse");
app.select_tool(tool);
}
let view = app.view_info();
for (kind, x, y) in [
(vectorcraft_tools::PointerKind::Down, 50.0, 50.0),
(vectorcraft_tools::PointerKind::Drag, 90.0, 90.0),
(vectorcraft_tools::PointerKind::Up, 90.0, 90.0),
] {
app.session.pointer(&vectorcraft_tools::PointerEvent::new(kind, x, y), view).unwrap();
}
assert_eq!(objects(&app), round + 2);
let st = app.session.active().unwrap();
let node = st.doc.node(*st.selection.objects.first().unwrap()).unwrap();
assert_eq!(node.path_data().unwrap().anchor_count(), if tool == "polygon" { 3 } else { 14 });
}
crate::dialogs::open_tool_dialog(&mut app, tool, json!({"x":140,"y":150}));
let d = app.ui.dialog.as_mut().unwrap();
assert_eq!(d.fields[key], count, "reopening uses the chosen count");
d.fields.insert(key.into(), json!(9));
crate::dialogs::cancel(&mut app);
assert_eq!(objects(&app), 4);
assert_eq!(app.session.tool_options()[key], count, "Cancel keeps the count");
}
}
#[test]
fn double_clicking_the_hand_zoom_and_transform_tools() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
+4 -1
View File
File diff suppressed because one or more lines are too long
+4 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -1
View File
File diff suppressed because one or more lines are too long