Brushes: New Brush makes the brush from the art its options opened with

OK in a new scatter, art or pattern brush's Brush Options ran brush.new
without the art the dialog had captured for its preview, so brush.new
read the selection again. A selection changed while the dialog was open
gave the brush other art than the preview showed, and a cleared
selection made OK fail. OK now passes the captured art (the side tile
for a pattern brush) to brush.new.
This commit is contained in:
dotCooCoo
2026-10-27 14:36:12 +07:00
committed by bflatastic
parent 678cff6707
commit ca60c8e8a7
2 changed files with 40 additions and 3 deletions
+13 -3
View File
@@ -177,10 +177,20 @@ pub(super) fn open_new(app: &mut VectorcraftApp, ty: &str, ids: Option<Value>) -
Ok(Value::Null)
}
/// OK of a new brush's Brush Options: `brush.new` with the type, the name, the values set and the
/// dropped art's ids. The dialog closes once the brush is made.
/// OK of a new brush's Brush Options: `brush.new` with the type, the name, the values set, the art
/// the dialog opened with (`art` or `side` of `__def`, which the preview draws) and the dropped
/// art's ids. A selection changed or cleared while the dialog is open does not change the art. The
/// dialog closes once the brush is made.
fn create(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
let mut p = json!({ "type": d.str("__type"), "name": d.str("name").trim(), "params": params(d) });
let mut brush_params = params(d);
if let Some(def) = d.fields.get("__def") {
for key in ["art", "side"] {
if let Some(art) = def.get(key).filter(|v| !v.is_null()) {
brush_params[key] = art.clone();
}
}
}
let mut p = json!({ "type": d.str("__type"), "name": d.str("name").trim(), "params": brush_params });
if let Some(ids) = d.fields.get(IDS) {
p["ids"] = ids.clone();
}
+27
View File
@@ -166,6 +166,33 @@ mod tests {
assert_eq!((&def["type"], &def["size"]), (&json!("calligraphic"), &json!(9.0)));
}
/// The new brush takes the art its Brush Options opened with: changing or clearing the
/// selection while the dialog is open does not change the art, and OK still makes the brush.
#[test]
fn ok_makes_the_brush_from_the_art_the_dialog_opened_with() {
for (ty, key) in [("scatter", "art"), ("art", "art"), ("pattern", "side")] {
for change in ["select.set", "select.none"] {
let mut app = app();
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 50, "height": 20})).unwrap();
app.run("ui.newBrush", json!({})).unwrap();
set(&mut app, json!({"type": ty}));
super::super::confirm(&mut app).unwrap();
let captured = app.ui.dialog.as_ref().unwrap().fields["__def"][key].clone();
assert!(captured.is_object(), "{ty}");
if change == "select.set" {
app.run("shape.ellipse", json!({"x": 100, "y": 50, "width": 120, "height": 90})).unwrap();
} else {
app.run("select.none", json!({})).unwrap();
}
super::super::confirm(&mut app).unwrap_or_else(|e| panic!("{ty} after {change}: {e}"));
assert!(app.ui.dialog.is_none(), "{ty} after {change}");
let name = format!("New {}{} Brush", ty[..1].to_uppercase(), &ty[1..]);
let def = app.run("brush.get", json!({ "name": name })).unwrap();
assert_eq!(def[key], captured, "{ty} after {change}");
}
}
}
/// Cancel in New Brush, or in the Brush Options it opens, adds no brush and no undo step.
#[test]
fn cancel_adds_no_brush() {