Preserve a surviving opacity selection.

This commit is contained in:
FarmerGeorg
2026-11-02 14:36:10 +07:00
committed by bflatastic
parent ca71c169a2
commit a76c1ca50c
2 changed files with 36 additions and 2 deletions
+6 -2
View File
@@ -1475,8 +1475,12 @@ fn highlight_after_removal(app: &mut VectorcraftApp, ctx: &egui::Context, n: &No
let shift = |k: usize| (!gone.contains(&k)).then(|| k - gone.iter().filter(|g| **g < k).count());
let order = h.order.iter().filter_map(|k| shift(*k)).collect();
let anchor = h.anchor.and_then(shift);
let active = sel.rows().filter(|(r, _)| *r == rows).and_then(|(_, a)| shift(a));
set_active(app, ctx, active.map_or(Sel::None, |a| rows.sel(a)));
// A fill/stroke's Opacity row stays selected (renumbered) while its fill/stroke survives.
let active = match (sel, rows) {
(Sel::ItemOpacity(i), Rows::Items) => shift(i).map(Sel::ItemOpacity),
_ => sel.rows().filter(|(r, _)| *r == rows).and_then(|(_, a)| shift(a)).map(|a| rows.sel(a)),
};
set_active(app, ctx, active.unwrap_or(Sel::None));
set_pstate(ctx, "ap-multi", Highlight { owner: Some(n.id), rows, order, anchor });
}
@@ -55,6 +55,36 @@ fn a_duplicate_highlights_the_copies_above_the_originals() {
assert_eq!(pstate::<(Option<NodeId>, Sel)>(&ctx, "ap-sel").1, Sel::Effect(4));
}
/// Removing other fills/strokes keeps a fill/stroke's Opacity row selected, renumbered with its
/// item (so the Transparency panel keeps editing it); removing that item clears the selection.
#[test]
fn removing_items_keeps_a_surviving_item_opacity_row_selected() {
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
app.run("file.new", json!({"width": 100, "height": 100})).unwrap();
let id = app.run("shape.rectangle", json!({"x": 0, "y": 0, "width": 20, "height": 20})).unwrap()["id"].as_u64().unwrap();
app.run("select.set", json!({ "ids": [id] })).unwrap();
app.run("appearance.duplicateItem", json!({ "indices": [0] })).unwrap();
let owner = Some(NodeId(id));
let ctx = egui::Context::default();
let remove = |app: &mut VectorcraftApp, k: usize| {
let mut out = ctx.run_ui(egui::RawInput::default(), |ui| {
let n = first_subject(app).unwrap();
let sel = current_sel(app, ui.ctx(), Some(&n));
app.run("appearance.removeItem", json!({ "indices": [k] })).unwrap();
highlight_after_removal(app, ui.ctx(), &n, sel, Rows::Items, &[k]);
});
out.textures_delta.clear();
};
app.run("appearance.setActiveItem", json!({ "index": 2 })).unwrap();
set_pstate(&ctx, "ap-sel", (owner, Sel::ItemOpacity(2)));
remove(&mut app, 0);
assert_eq!(pstate::<(Option<NodeId>, Sel)>(&ctx, "ap-sel").1, Sel::ItemOpacity(1));
assert_eq!(app.session.appearance_item(), Some(1));
remove(&mut app, 1);
assert_eq!(pstate::<(Option<NodeId>, Sel)>(&ctx, "ap-sel").1, Sel::None);
assert_eq!(app.session.appearance_item(), None);
}
#[test]
fn opacity_labels() {
assert_eq!(opacity_text(1.0, BlendMode::Normal), "Default");