mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
G1: Grid tool dialogs add reference point locator (#1377)
Rectangular and Polar Grid click dialogs show the nine-point locator and resize width/height about it using the same artboard_rect logic as Artboard Options. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Cursor
parent
059b6d083c
commit
699e6e9af4
@@ -2,8 +2,11 @@
|
||||
//! Star, Line Segment Tool Options and the two grids (size, divider counts and skews, switches).
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_geom::Rect;
|
||||
|
||||
use super::{DialogSpec, form, run_and_close};
|
||||
use crate::panels::transform::artboard_rect;
|
||||
use crate::widgets;
|
||||
use crate::VectorcraftApp;
|
||||
use crate::state::Dialog;
|
||||
|
||||
@@ -27,9 +30,46 @@ fn grid_keys(kind: &str) -> ([&'static str; 2], [&'static str; 2]) {
|
||||
if kind == "polarGrid" { (["concentric", "radial"], ["concentricSkew", "radialSkew"]) } else { (["rows", "columns"], ["rowSkew", "columnSkew"]) }
|
||||
}
|
||||
|
||||
/// The 9-point locator index for a grid dialog (`reference`, default top-left).
|
||||
fn grid_reference(d: &Dialog) -> usize {
|
||||
d.fields.get("reference").and_then(|v| v.as_u64()).map(|n| (n as usize).min(8)).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// A grid dialog's bounding box from its top-left `x`/`y` and size fields.
|
||||
fn grid_placed(d: &Dialog) -> Rect {
|
||||
let (x, y) = (d.f64("x", 0.0), d.f64("y", 0.0));
|
||||
Rect::new(x, y, x + d.f64("width", 100.0), y + d.f64("height", 100.0))
|
||||
}
|
||||
|
||||
fn set_grid_placed(d: &mut Dialog, r: Rect) {
|
||||
d.fields.insert("x".into(), json!(r.x0));
|
||||
d.fields.insert("y".into(), json!(r.y0));
|
||||
d.fields.insert("width".into(), json!(r.width()));
|
||||
d.fields.insert("height".into(), json!(r.height()));
|
||||
}
|
||||
|
||||
/// The form's fields, then a grid's switches.
|
||||
fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
form::grid(ui, d, app.session.general_unit());
|
||||
let unit = app.session.general_unit();
|
||||
if matches!(d.kind.as_str(), "rectangularGrid" | "polarGrid") {
|
||||
ui.horizontal(|ui| {
|
||||
let refi = grid_reference(d);
|
||||
if let Some(i) = widgets::reference_point(ui, refi) {
|
||||
d.fields.insert("reference".into(), json!(i));
|
||||
}
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
let refi = grid_reference(d);
|
||||
let (was, w0, h0) = (grid_placed(d), d.f64("width", 100.0), d.f64("height", 100.0));
|
||||
form::grid_then(ui, d, unit, |_, d| {
|
||||
let (w, h) = (d.f64("width", 100.0), d.f64("height", 100.0));
|
||||
if (w - w0).abs() > 1e-9 || (h - h0).abs() > 1e-9 {
|
||||
set_grid_placed(d, artboard_rect(was, refi, None, None, Some(w), Some(h), false));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
form::grid(ui, d, unit);
|
||||
}
|
||||
let own = match d.kind.as_str() {
|
||||
"rectangularGrid" => ("frame", tl!("Use Outside Rectangle As Frame")),
|
||||
"polarGrid" => ("compound", tl!("Create Compound Path From Ellipses")),
|
||||
@@ -54,8 +94,9 @@ fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
|
||||
kind @ ("rectangularGrid" | "polarGrid") => {
|
||||
// The switches as they are; the typed fields as numbers.
|
||||
let (mut p, (counts, skews)) = (form::params(d), grid_keys(kind));
|
||||
for (k, default) in [("width", 100.0), ("height", 100.0)] {
|
||||
p[k] = json!(d.f64(k, default));
|
||||
let r = grid_placed(d);
|
||||
for (k, v) in [("x", r.x0), ("y", r.y0), ("width", r.width()), ("height", r.height())] {
|
||||
p[k] = json!(v);
|
||||
}
|
||||
for (count, skew) in counts.into_iter().zip(skews) {
|
||||
p[count] = json!((d.f64(count, 5.0) as u64).min(999));
|
||||
|
||||
@@ -159,6 +159,20 @@ fn key_frame(app: &mut VectorcraftApp, key: egui::Key) {
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
|
||||
/// #1377: OK uses the bounding box after a reference-point resize (`artboard_rect` keeps the
|
||||
/// center pinned when width doubles).
|
||||
#[test]
|
||||
fn rectangular_grid_reference_point_pins_center_when_width_changes() {
|
||||
let mut app = app();
|
||||
click(&mut app, Point::new(100.0, 100.0));
|
||||
assert_eq!(field(&app, "reference"), json!(0));
|
||||
for (key, value) in [("reference", json!(4)), ("x", json!(50.0)), ("y", json!(50.0)), ("width", json!(200)), ("height", json!(100))] {
|
||||
set(&mut app, key, value);
|
||||
}
|
||||
let id = confirm(&mut app);
|
||||
assert_grid(&app, id, Rect::new(50.0, 50.0, 250.0, 150.0), 5, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangular_grid_canvas_click_opens_registered_dialog_with_saved_counts_and_point_defaults() {
|
||||
let mut app = app();
|
||||
|
||||
@@ -19,7 +19,13 @@ pub fn open_tool_dialog(app: &mut VectorcraftApp, kind: &str, p: Value) {
|
||||
// The grids: the tool's stored options (divider counts and skews, switches) at the default size.
|
||||
"rectangularGrid" | "polarGrid" => {
|
||||
let mut fields = app.session.tool_options_of(kind);
|
||||
for (key, value) in [("x", json!(x)), ("y", json!(y)), ("width", json!("100 pt")), ("height", json!("100 pt"))] {
|
||||
for (key, value) in [
|
||||
("x", json!(x)),
|
||||
("y", json!(y)),
|
||||
("width", json!("100 pt")),
|
||||
("height", json!("100 pt")),
|
||||
("reference", json!(0)),
|
||||
] {
|
||||
fields[key] = value;
|
||||
}
|
||||
Dialog::new(kind, fields)
|
||||
|
||||
Reference in New Issue
Block a user