#1002: new art is refused when no layer is shown and unlocked

With every layer hidden or locked, the insertion layer fell back to the top layer anyway, so
drawing a shape, typing, pasting, making a graph, a flare, a grid, trim marks or a symbol put
the art on a hidden or locked layer: invisible, or unselectable by Select All. Illustrator
refuses to draw on a locked or hidden target layer (public forum answers, e.g.
https://community.adobe.com/t5/illustrator/can-t-draw-a-new-object-in-my-document/m-p/11107182).

DocState::target_parent is insertion_parent for new art, failing with "the target layer is
locked or hidden" when it would be a layer that isn't editable; those creation paths use it.
Another layer that is shown and unlocked still takes the art, as before. The message is in the
de, es, fr, it, ja, ru and uk catalogs. File > Place is left as it is (another branch reworks
it).

The test hides, then locks, the only layer: an ellipse, a polar grid, text and a paste each
fail with the message and leave the document unchanged; a new layer then takes a rectangle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
This commit is contained in:
bflatastic
2026-10-11 03:51:11 +07:00
parent e77d15c70d
commit eeb213e5a8
15 changed files with 55 additions and 9 deletions
+3 -2
View File
@@ -603,7 +603,7 @@ fn symbol_place(s: &mut Session, p: &Value) -> Result<Value> {
let centre = d.artboards.first().map(|a| a.rect.center()).unwrap_or(Point::ZERO);
let c = Point::new(f64_or(p, "x", centre.x), f64_or(p, "y", centre.y));
let size = natural_size(d, &name);
let parent = s.doc()?.insertion_parent();
let parent = s.doc()?.target_parent()?;
let id = s.edit("Place Symbol Instance", |d, sel| {
let id = d.alloc_id();
d.insert(parent, usize::MAX, Node::new(id, NodeKind::SymbolInstance { symbol: name.clone(), xf: place_xf(c, size) }))?;
@@ -843,7 +843,8 @@ fn symbol_spray(s: &mut Session, p: &Value) -> Result<Value> {
let alt = bool_or(p, "alt", false);
let size = natural_size(&st.doc, &name);
let set = st.selection.objects.first().copied().filter(|id| st.selection.len() == 1 && st.doc.node(*id).is_some_and(is_symbol_set));
let parent = st.insertion_parent();
// Only a new Symbol Set needs a layer that takes new art.
let parent = if alt || set.is_some() { st.insertion_parent() } else { st.target_parent()? };
if alt {
// Remove instances of this symbol under the brush (within the set, or anywhere).
let d = &st.doc;
+3 -3
View File
@@ -79,7 +79,7 @@ pub(crate) fn add_node(s: &mut Session, label: &str, kind: NodeKind, appearance:
/// Insert a new object looking like `look` (drawing modes apply); select it.
pub(crate) fn add_look(s: &mut Session, label: &str, kind: NodeKind, look: NewArt, name: Option<String>) -> Result<Value> {
let parent = s.doc()?.insertion_parent();
let parent = s.doc()?.target_parent()?;
let mode = s.draw_mode;
let inside = s.draw_inside;
let behind_of = s.doc()?.selection.in_paint_order(&s.doc()?.doc).first().copied();
@@ -298,7 +298,7 @@ fn flare(s: &mut Session, p: &Value) -> Result<Value> {
};
parts.push(("Ring", circle(at, rr), radial(at, rr, stops), 1.0));
}
let parent = s.doc()?.insertion_parent();
let parent = s.doc()?.target_parent()?;
let id = s.edit("Flare", |d, sel| {
let children = parts
.into_iter()
@@ -352,7 +352,7 @@ fn arc(s: &mut Session, p: &Value) -> Result<Value> {
}
fn grid_group(s: &mut Session, label: &str, paths: Vec<PathData>) -> Result<Value> {
let parent = s.doc()?.insertion_parent();
let parent = s.doc()?.target_parent()?;
let look = s.new_art_look(vectorcraft_color::Paint::None, s.paint.stroke.clone(), s.paint.stroke_width);
let id = s.edit(label, |d, sel| {
let children = paths
+1 -1
View File
@@ -346,7 +346,7 @@ fn paste_clip(s: &mut Session, p: &Value, mode: PasteMode, clip: &Clipboard, cho
let off = s.prefs.paste_offset;
let st = s.doc()?;
let same_doc = clip.source_doc == Some(st.uid);
let parent = st.insertion_parent();
let parent = st.target_parent()?;
// A copied artboard comes back with its art: right of the last artboard, or where it was
// (Paste in Place, in Front, in Back). Paste on All Artboards pastes only the art.
let board = clip
+1 -1
View File
@@ -831,7 +831,7 @@ fn create(s: &mut Session, p: &Value) -> Result<Value> {
spec.categories = vec!["A".into(), "B".into(), "C".into(), "D".into()];
spec.rows = vec![vec![3.0, 2.0], vec![5.0, 4.0], vec![4.0, 6.0], vec![7.0, 5.0]];
}
let parent = s.doc()?.insertion_parent();
let parent = s.doc()?.target_parent()?;
let id = s.edit("Graph", |d, sel| {
let gid = d.alloc_id();
let mut g = Node::group(gid, vec![]);
+1 -1
View File
@@ -702,7 +702,7 @@ fn trim_marks(s: &mut Session, p: &Value) -> Result<Value> {
if rects.is_empty() {
return Err(bad(C, "nothing to mark"));
}
let parent = s.doc()?.insertion_parent();
let parent = s.doc()?.target_parent()?;
let ids = s.edit("Create Trim Marks", |d, sel| {
let mut ids = vec![];
for r in &rects {