fix(paint): preserve new-art defaults when paint edits are rejected
This commit is contained in:
parent
6f7f32c64d
commit
4c011cf42e
|
|
@ -375,15 +375,7 @@ fn apply_to_proxy(s: &mut Session, p: &Value, paint: Paint) -> Result<Value> {
|
|||
/// remember the paint.
|
||||
fn apply_paint(s: &mut Session, p: &Value, paint: Paint, fill: bool) -> Result<Value> {
|
||||
let cmd = if fill { "paint.setFill" } else { "paint.setStroke" };
|
||||
// New art gets the paint fitted to itself, not placed where this one is.
|
||||
if fill {
|
||||
s.paint.fill = unplaced(&paint);
|
||||
} else {
|
||||
s.paint.stroke = unplaced(&paint);
|
||||
}
|
||||
if bool_or(p, "focus", true) {
|
||||
s.fill_active = fill;
|
||||
}
|
||||
// Resolve the requested targets before mutating defaults or the active proxy.
|
||||
let item = item_target(s, p, cmd)?.of_kind(s, fill);
|
||||
let selected = item.targets(s, p)?;
|
||||
let ids = super::graph::paint_targets(&s.doc()?.doc, &selected);
|
||||
|
|
@ -423,6 +415,16 @@ fn apply_paint(s: &mut Session, p: &Value, paint: Paint, fill: bool) -> Result<V
|
|||
Ok(())
|
||||
},
|
||||
)?;
|
||||
// Rejected edits leave the next shape's appearance and active proxy untouched.
|
||||
// New art takes an unplaced gradient so that it fits the new object's own bounds.
|
||||
if fill {
|
||||
s.paint.fill = unplaced(&paint);
|
||||
} else {
|
||||
s.paint.stroke = unplaced(&paint);
|
||||
}
|
||||
if bool_or(p, "focus", true) {
|
||||
s.fill_active = fill;
|
||||
}
|
||||
s.remember_paint(&paint);
|
||||
ok()
|
||||
}
|
||||
|
|
@ -436,7 +438,6 @@ fn set_run_stroke(style: &mut CharStyle, paint: Paint) {
|
|||
}
|
||||
|
||||
fn swap(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
std::mem::swap(&mut s.paint.fill, &mut s.paint.stroke);
|
||||
let ids = paint_targets(s, p)?;
|
||||
if !ids.is_empty() {
|
||||
s.edit("Swap Fill and Stroke", |d, _| {
|
||||
|
|
@ -458,11 +459,11 @@ fn swap(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
Ok(())
|
||||
})?;
|
||||
}
|
||||
std::mem::swap(&mut s.paint.fill, &mut s.paint.stroke);
|
||||
ok()
|
||||
}
|
||||
|
||||
fn default_paint(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
super::newart::reset(s);
|
||||
let ids = paint_targets(s, p)?;
|
||||
if !ids.is_empty() {
|
||||
s.edit("Default Fill and Stroke", |d, _| {
|
||||
|
|
@ -481,6 +482,7 @@ fn default_paint(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
Ok(())
|
||||
})?;
|
||||
}
|
||||
super::newart::reset(s);
|
||||
ok()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,40 @@ fn fill_and_stroke_commands() {
|
|||
s.execute("paint.setFill", &json!({"gradient": {"kind": "radial"}})).unwrap();
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn rejected_paint_edits_leave_new_art_defaults_and_focus_unchanged() {
|
||||
let mut s = session();
|
||||
let id = rect(&mut s, 0.0, 0.0, 10.0, 10.0);
|
||||
s.execute("paint.setFill", &json!({"color": "#00ff00"})).unwrap();
|
||||
s.execute("paint.setStroke", &json!({"color": "#ff0000"})).unwrap();
|
||||
let defaults = s.paint.clone();
|
||||
let focused = s.fill_active;
|
||||
let original_fill = s.doc().unwrap().doc.node(id).unwrap().appearance.fill_paint();
|
||||
let original_stroke = s.doc().unwrap().doc.node(id).unwrap().appearance.stroke_paint();
|
||||
|
||||
// Both shortcut commands used to change defaults before checking invalid ids.
|
||||
for (command, params) in [
|
||||
("paint.swap", json!({"ids": "not an array"})),
|
||||
("paint.default", json!({"ids": ["not an object id"]})),
|
||||
("paint.setFill", json!({"color": "#123456", "ids": [false]})),
|
||||
("paint.setStroke", json!({"color": "#123456", "ids": "not an array"})),
|
||||
("paint.setFill", json!({"color": "#123456", "item": "invalid"})),
|
||||
] {
|
||||
assert!(s.execute(command, ¶ms).is_err(), "{command} should reject {params}");
|
||||
assert_eq!(s.paint, defaults, "{command} changed new-art defaults on failure");
|
||||
assert_eq!(s.fill_active, focused, "{command} changed the active proxy on failure");
|
||||
let appearance = &s.doc().unwrap().doc.node(id).unwrap().appearance;
|
||||
assert_eq!(appearance.fill_paint(), original_fill);
|
||||
assert_eq!(appearance.stroke_paint(), original_stroke);
|
||||
}
|
||||
|
||||
// Successful operations still update both the selected object and new-art defaults.
|
||||
s.execute("paint.swap", &json!({})).unwrap();
|
||||
assert_eq!(s.paint.fill, defaults.stroke);
|
||||
assert_eq!(s.paint.stroke, defaults.fill);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn select_same_fill() {
|
||||
let mut s = session();
|
||||
|
|
|
|||
Loading…
Reference in New Issue