Paste: in front or back of a compound path's member, other art goes beside the compound path

With a member of a compound path selected, Paste in Front and Paste in Back
put the clipboard's objects next to that member, inside the compound path,
whatever they were. A pasted group, compound path or type object then sat
inside a compound path, which holds only paths. The model-based test
`random_command_sequences` stops on this with "compound #N has a non-path
child".

When the clipboard holds anything other than paths, the objects now go
right above or below the compound path. Paths still go next to the member,
inside the compound path.
This commit is contained in:
dotCooCoo
2026-11-01 06:42:33 -08:00
parent 05d5f99fd7
commit 827e137b5c
2 changed files with 49 additions and 2 deletions
+13 -2
View File
@@ -813,11 +813,13 @@ fn paste_clip(s: &mut Session, p: &Value, mode: PasteMode, clip: &Clipboard, cho
&& (st.doc.paste_remembers_layers || boards.is_some())
&& parent.is_some_and(|p| st.doc.node(p).is_some_and(Node::is_layer));
// Front/back: relative to the selection (top-most / bottom-most selected object); with
// nothing selected, the top / bottom of the current layer.
// nothing selected, the top / bottom of the current layer. Art other than paths goes beside
// the compound path that holds the selected object, not into it.
let anchor = if front || back {
let order = st.selection.in_paint_order(&st.doc);
let a = if front { order.last() } else { order.first() };
a.and_then(|id| st.doc.position(*id))
let paths_only = clip.nodes.iter().all(|n| matches!(n.kind, vectorcraft_doc::NodeKind::Path { .. }));
a.map(|id| paste_anchor(&st.doc, *id, paths_only)).and_then(|id| st.doc.position(id))
} else {
None
};
@@ -900,6 +902,15 @@ fn paste_clip(s: &mut Session, p: &Value, mode: PasteMode, clip: &Clipboard, cho
}))
}
/// What pasted art goes beside: `id`, or the compound path holding it when the art isn't only
/// paths (a compound path holds paths only).
fn paste_anchor(doc: &Document, id: NodeId, paths_only: bool) -> NodeId {
match doc.parent_of(id) {
Some(p) if !paths_only && doc.node(p).is_some_and(|n| matches!(n.kind, vectorcraft_doc::NodeKind::Compound { .. })) => p,
_ => id,
}
}
/// The first unlocked layer or sublayer called `name` (topmost first), or a new top layer.
fn layer_named(d: &mut Document, name: &str) -> NodeId {
let mut found = None;