Isolation mode: Lock, Unlock All, Hide and Show All work on the isolated art

Squashed from #4849 onto main.
This commit is contained in:
dotCooCoo
2026-11-01 01:21:53 +07:00
committed by bflatastic
parent f1a6a9ff67
commit b46cdc4e4d
12 changed files with 511 additions and 226 deletions
+15 -13
View File
@@ -182,20 +182,22 @@ pub fn has_multi(s: &Session) -> std::result::Result<(), String> {
let st = s.active().ok_or("no document open")?;
if st.selection.len() < 2 { Err("select at least two objects".into()) } else { Ok(()) }
}
/// A document is open and it is not in isolation mode: Object › Lock's and Object › Hide's items,
/// Unlock All and Show All are off in isolation mode. Pattern editing mode and opacity mask
/// editing isolate their art too, and do not count as isolation mode here while their own layer
/// is the isolated one. An object isolated inside them counts.
pub fn outside_isolation(s: &Session) -> std::result::Result<(), String> {
let st = s.active().ok_or("no document open")?;
let editing_layer = |l| st.doc.pattern_edit.as_ref().is_some_and(|e| e.layer == l) || st.doc.mask_edit.as_ref().is_some_and(|e| e.layer == l);
if st.isolation.is_some_and(|l| !editing_layer(l)) { Err("exit isolation mode first".into()) } else { Ok(()) }
/// The isolated group, layer or object in isolation mode. Pattern editing mode and opacity mask
/// editing isolate their own layer, which does not count here; an object isolated inside them
/// counts.
pub(crate) fn ordinary_isolation(st: &crate::DocState) -> Option<vectorcraft_doc::NodeId> {
st.isolation.filter(|l| !st.doc.pattern_edit.as_ref().is_some_and(|e| e.layer == *l) && !st.doc.mask_edit.as_ref().is_some_and(|e| e.layer == *l))
}
/// Objects are selected ([`has_selection`]) and the document is not in isolation mode
/// ([`outside_isolation`]).
pub fn has_selection_outside_isolation(s: &Session) -> std::result::Result<(), String> {
outside_isolation(s)?;
has_selection(s)
/// Objects are selected ([`has_selection`]), and in isolation mode ([`ordinary_isolation`]) at
/// least one of them is inside the isolated object: Object › Lock's and Object › Hide's items.
pub fn has_selected_member(s: &Session) -> std::result::Result<(), String> {
let st = s.active().ok_or("no document open")?;
let Some(root) = ordinary_isolation(st) else { return has_selection(s) };
if st.selection.objects.iter().any(|id| inside_isolation(&st.doc, root, *id)) { Ok(()) } else { Err("nothing selected".into()) }
}
/// Whether `id` lies inside the isolated object `root` (the root itself does not).
pub(crate) fn inside_isolation(d: &vectorcraft_doc::Document, root: vectorcraft_doc::NodeId, id: vectorcraft_doc::NodeId) -> bool {
id != root && d.ancestry(id).is_some_and(|a| a.contains(&root))
}
pub fn can_undo(s: &Session) -> std::result::Result<(), String> {
s.active().filter(|d| !d.history.undo.is_empty()).map(|_| ()).ok_or_else(|| "nothing to undo".into())