M3.25: appearance.setItem takes ids without a selection; undo/redo through mask editing tested
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4f685be57a
commit
745d50f76e
|
|
@ -22,8 +22,8 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
"Appearance Item",
|
||||
[],
|
||||
None,
|
||||
"{index, ids?, opacity?: 0..100, blend?, visible?, weight?, color?|none?|swatch?|gradient?} edit one fill/stroke of the appearance stack of the selection (or `ids`)",
|
||||
has_selection,
|
||||
"{index, ids?, opacity?: 0..100, blend?, visible?, weight?, color?|none?|swatch?|gradient?} edit one fill/stroke of the appearance stack of `ids` (default: the selection)",
|
||||
has_doc,
|
||||
set_item
|
||||
),
|
||||
cmd!("appearance.removeItem", "Remove Item", [], None, "{index}", has_selection, remove_item),
|
||||
|
|
@ -98,6 +98,9 @@ fn set_item(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
let idx = p.get("index").and_then(Value::as_u64).ok_or_else(|| bad("appearance.setItem", "missing index"))? as usize;
|
||||
let paint = paint_from(s, p)?;
|
||||
let ids = paint_targets(s, p)?;
|
||||
if ids.is_empty() {
|
||||
return Err(bad("appearance.setItem", "select objects or give ids"));
|
||||
}
|
||||
let blend = str_param(p, "blend").and_then(BlendMode::parse);
|
||||
s.edit("Appearance", |d, _| {
|
||||
for id in &ids {
|
||||
|
|
|
|||
|
|
@ -165,6 +165,11 @@ fn opacity_is_a_percentage_everywhere() {
|
|||
assert_eq!(doc(&s).node(a).unwrap().opacity, 1.0);
|
||||
s.execute("transparency.set", &json!({"opacity": 0.5})).unwrap();
|
||||
assert!((doc(&s).node(a).unwrap().opacity - 0.005).abs() < 1e-6);
|
||||
// Appearance items take ids without a selection too.
|
||||
s.execute("select.none", &json!({})).unwrap();
|
||||
assert!(s.execute("appearance.setItem", &json!({"index": 0, "opacity": 30})).is_err(), "no selection, no ids");
|
||||
s.execute("appearance.setItem", &json!({"index": 0, "ids": [a.0], "opacity": 30})).unwrap();
|
||||
assert!((fill_opacity(&s) - 0.3).abs() < 1e-6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -229,3 +234,35 @@ fn exports_while_editing_leave_the_editing_layer_out() {
|
|||
assert_eq!(pdf(&mut s).len(), pdf_editing.len());
|
||||
assert_eq!(png(&mut s), png_editing);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn undo_and_redo_walk_in_and_out_of_mask_editing() {
|
||||
let mut s = session();
|
||||
let obj = rect(&mut s, 0.0, 200.0);
|
||||
s.execute("transparency.makeOpacityMask", &json!({})).unwrap();
|
||||
let layer = doc(&s).mask_edit.unwrap().layer;
|
||||
s.execute("shape.rectangle", &json!({"x": 0, "y": 0, "width": 100, "height": 200})).unwrap();
|
||||
s.execute("transparency.stopEditingOpacityMask", &json!({})).unwrap();
|
||||
let state = |s: &Session| {
|
||||
let st = s.doc().unwrap();
|
||||
(st.doc.mask_edit.map(|m| m.layer), st.isolation, st.active_layer == Some(layer), has_edit_layer(&st.doc))
|
||||
};
|
||||
let editing = (Some(layer), Some(layer), true, true);
|
||||
assert_eq!(state(&s), (None, None, false, false));
|
||||
// Back into editing with the drawn art, then before it, then before the mask.
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(state(&s), editing);
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(state(&s), editing);
|
||||
assert!(doc(&s).node(layer).unwrap().children().unwrap().is_empty());
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(state(&s), (None, None, false, false));
|
||||
assert!(mask(&s, obj).is_none());
|
||||
// And forward again.
|
||||
s.execute("edit.redo", &json!({})).unwrap();
|
||||
s.execute("edit.redo", &json!({})).unwrap();
|
||||
assert_eq!(state(&s), editing);
|
||||
s.execute("edit.redo", &json!({})).unwrap();
|
||||
assert_eq!(state(&s), (None, None, false, false));
|
||||
assert_eq!(mask(&s, obj).unwrap().art.geometric_bounds().unwrap().x1, 100.0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue