Layers: Merge Selected keeps to the highlighted layers, as documented (#2383)

Reverts the fallback that merged the layers of art selected on the canvas when no
layer row is highlighted: Illustrator's Merge Selected merges the highlighted rows
into the last one highlighted.
This commit is contained in:
bflatastic
2026-10-17 13:06:52 +07:00
parent fdc08e25d6
commit 424a49604c
3 changed files with 3 additions and 32 deletions
+2 -11
View File
@@ -263,22 +263,13 @@ fn merge_into(d: &mut Document, into: NodeId, others: &[NodeId]) -> Result<()> {
fn merge(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "layer.merge";
let mut ids = rows_param(s, p, C)?;
let ids = rows_param(s, p, C)?;
let st = s.doc()?;
let d = &st.doc;
// Nothing named or highlighted, but art selected on the canvas in several layers (Select All):
// merge those layers (#2383).
if p.get("ids").is_none() && p.get("id").is_none() && st.highlighted_rows().is_empty() {
let held: HashSet<NodeId> = st.selection.objects.iter().filter_map(|o| d.layer_of(*o)).collect();
let layers: Vec<NodeId> = d.layers.iter().map(|l| l.id).filter(|l| held.contains(l)).collect();
if layers.len() >= 2 {
ids = layers;
}
}
let mut seen = HashSet::new();
let ids: Vec<NodeId> = ids.into_iter().filter(|id| d.node(*id).is_some() && seen.insert(*id)).collect();
if ids.len() < 2 {
return Err(bad(C, "highlight two or more rows to merge, or select art in two or more layers"));
return Err(bad(C, "highlight two or more rows to merge"));
}
// The last highlighted layer that is not inside another highlighted row: with a layer and its
// sublayer both highlighted (Select All in the panel), the sublayer travels with its layer
-18
View File
@@ -625,24 +625,6 @@ fn merge_selected_with_all_layer_rows_highlighted_merges_into_the_last_top_level
}
}
/// Merge Selected with no highlighted rows but art selected in several layers (Select All on the
/// canvas) merges those layers; art in one layer still asks for rows (#2383).
#[test]
fn merge_selected_with_art_selected_in_several_layers_merges_those_layers() {
let mut s = session();
let a = rect(&mut s, 0.0);
run(&mut s, "layer.new", json!({"top": true}));
let b = rect(&mut s, 100.0);
run(&mut s, "select.set", json!({"ids": [b.0]}));
run(&mut s, "layer.highlight", json!({"ids": []}));
assert!(s.execute("layer.merge", &json!({})).is_err());
run(&mut s, "select.set", json!({"ids": [a.0, b.0]}));
let into = id(&run(&mut s, "layer.merge", json!({})));
let st = s.doc().unwrap();
assert_eq!(st.doc.layers.len(), 1);
assert!(st.doc.layer_of(a) == Some(into) && st.doc.layer_of(b) == Some(into));
}
/// Collect in New Layer puts the new layer beside the topmost row when that row is directly in a
/// layer, and on top of the layer holding its group when it is in a group. When that row is in a
/// hidden or locked layer, the selected art it collects from another layer is deselected, the key
+1 -3
View File
@@ -1461,8 +1461,6 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
let rows = st.highlighted_rows();
let current = st.current_layer();
let has_sel = !st.selection.is_empty();
// How many top-level layers hold the selected art: Merge Selected merges them.
let art_layers = st.selection.objects.iter().filter_map(|o| doc.layer_of(*o)).collect::<HashSet<_>>().len();
let isolated = st.isolation.is_some();
let targets: Vec<NodeId> = if rows.is_empty() { current.into_iter().collect() } else { rows.clone() };
let one_container = match targets.as_slice() {
@@ -1500,7 +1498,7 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
None,
Some(("Locate Object", "layer.locate", json!({}), has_sel, false)),
None,
Some(("Merge Selected", "layer.merge", json!({}), rows.len() >= 2 || (rows.is_empty() && art_layers >= 2), false)),
Some(("Merge Selected", "layer.merge", json!({}), rows.len() >= 2, false)),
Some(("Flatten Artwork", "layer.flatten", json!({}), true, false)),
Some(("Collect in New Layer", "layer.collectInNew", json!({}), !rows.is_empty() || has_sel, false)),
// Sentinel: rendered as Collect for Export › As Single / As Multiple (assets.add).