Merge pull request #6605 from dotCooCoo/fix/gradient-stop-symbol-part

Gradients: picking a part of a symbol instance leaves no gradient stop selected
This commit is contained in:
BFlat
2026-11-11 23:25:06 +07:00
committed by GitHub
2 changed files with 35 additions and 3 deletions
+12 -3
View File
@@ -80,19 +80,28 @@ fn select_stop(s: &mut Session, p: &Value) -> Result<Value> {
}
/// Whose gradient a selected stop belongs to: the active document, its first selected object
/// (None: the default paint), the proxy in front and the Appearance panel's active item.
/// Selecting other art, toggling the proxy or picking another item leaves no stop selected.
/// (None: the default paint), whether a part of a symbol instance's art is picked, the proxy in
/// front and the Appearance panel's active item. Selecting other art, picking a part of the
/// instance, toggling the proxy or picking another item leaves no stop selected.
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct StopOwner {
doc: Option<usize>,
object: Option<NodeId>,
part: bool,
fill: bool,
item: Option<usize>,
}
impl StopOwner {
pub(crate) fn of(s: &Session) -> Self {
Self { doc: s.active, object: s.active().and_then(|d| d.selection.objects.first().copied()), fill: s.fill_active, item: s.appearance_item() }
let st = s.active();
Self {
doc: s.active,
object: st.and_then(|d| d.selection.objects.first().copied()),
part: st.is_some_and(|d| d.selection.symbol_part.is_some()),
fill: s.fill_active,
item: s.appearance_item(),
}
}
}
@@ -903,6 +903,29 @@ fn gradients_and_patterns_on_a_picked_object_are_taken() {
assert_eq!((undo_steps(&s), &s.paint.fill), (undo, &fill), "nothing changes");
}
/// A stop selected on the whole instance's gradient is not selected once a part of its art is
/// picked, so the Gradient tool does not take Delete for it, and is selected again when the whole
/// instance is.
#[test]
fn picking_a_part_leaves_no_gradient_stop_selected() {
let mut s = session();
let inst = pair(&mut s, "dynamic");
let g = json!({"kind": "linear", "stops": [{"offset": 0, "color": "#ff0000"}, {"offset": 1, "color": "#0000ff"}]});
s.execute("select.set", &json!({"ids": [inst.0]})).unwrap();
s.execute("paint.setFill", &json!({"gradient": g})).unwrap();
s.fill_active = true;
let view = ViewInfo::default();
s.select_tool("gradient", view).unwrap();
s.execute("gradient.selectStop", &json!({"index": 1})).unwrap();
assert_eq!(s.selected_stop(), Some(1));
assert!(s.tool_claims_key(vectorcraft_tools::ToolKey::Delete, view));
s.execute("symbol.instance.selectPart", &json!({"id": inst.0, "path": [1]})).unwrap();
assert_eq!(s.selected_stop(), None);
assert!(!s.tool_claims_key(vectorcraft_tools::ToolKey::Delete, view));
s.execute("select.set", &json!({"ids": [inst.0]})).unwrap();
assert_eq!(s.selected_stop(), Some(1));
}
#[test]
fn opacity_and_blend_on_a_picked_object_go_through_transparency_set() {
let mut s = session();