diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index 63e5ebe7f..822972e27 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -171,6 +171,7 @@ pub enum DocumentMessage { AddTransaction, ToggleLayerExpansion { id: NodeId, + recursive: bool, }, ToggleSelectedVisibility, ToggleSelectedLocked, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index b7f68eb3c..c954ad451 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -1192,13 +1192,27 @@ impl MessageHandler> for DocumentMessag responses.add_front(DocumentMessage::CommitTransaction); responses.add_front(DocumentMessage::StartTransaction); } - DocumentMessage::ToggleLayerExpansion { id } => { + DocumentMessage::ToggleLayerExpansion { id, recursive } => { let layer = LayerNodeIdentifier::new(id, &self.network_interface, &[]); - if self.collapsed.0.contains(&layer) { - self.collapsed.0.retain(|&collapsed_layer| collapsed_layer != layer); + let metadata = self.metadata(); + + let is_collapsed = self.collapsed.0.contains(&layer); + + if is_collapsed { + if recursive { + let children: HashSet<_> = layer.children(metadata).collect(); + self.collapsed.0.retain(|collapsed_layer| !children.contains(collapsed_layer) && collapsed_layer != &layer); + } else { + self.collapsed.0.retain(|collapsed_layer| collapsed_layer != &layer); + } } else { + if recursive { + let children_to_add: Vec<_> = layer.children(metadata).filter(|child| !self.collapsed.0.contains(child)).collect(); + self.collapsed.0.extend(children_to_add); + } self.collapsed.0.push(layer); } + responses.add(NodeGraphMessage::SendGraph); } DocumentMessage::ToggleSelectedLocked => responses.add(NodeGraphMessage::ToggleSelectedLocked), diff --git a/frontend/src/components/Editor.svelte b/frontend/src/components/Editor.svelte index ba94e33e5..e811cac24 100644 --- a/frontend/src/components/Editor.svelte +++ b/frontend/src/components/Editor.svelte @@ -152,8 +152,11 @@ transparent calc((3px * sqrt(2) / 2) + 0.5px), transparent calc(6px * sqrt(2) / 2) ); - --inheritance-dots-background: url('data:image/svg+xml;utf8,\ - \ + --inheritance-dots-background-4-dimgray: url('data:image/svg+xml;utf8,\ + \ + '); + --inheritance-dots-background-6-lowergray: url('data:image/svg+xml;utf8,\ + \ '); // Array of 2x3 dots (fill: --color-e-nearwhite) diff --git a/frontend/src/components/panels/Layers.svelte b/frontend/src/components/panels/Layers.svelte index f98058fea..24ae3d745 100644 --- a/frontend/src/components/panels/Layers.svelte +++ b/frontend/src/components/panels/Layers.svelte @@ -135,8 +135,11 @@ editor.handle.toggleLayerLock(id); } - function handleExpandArrowClick(id: bigint) { - editor.handle.toggleLayerExpansion(id); + function handleExpandArrowClickWithModifiers(e: MouseEvent, id: bigint) { + const accel = platformIsMac() ? e.metaKey : e.ctrlKey; + const collapseRecursive = e.altKey || accel; + editor.handle.toggleLayerExpansion(id, collapseRecursive); + e.stopPropagation(); } async function onEditLayerName(listing: LayerListingInfo) { @@ -432,8 +435,10 @@ class="expand-arrow" class:expanded={listing.entry.expanded} disabled={!listing.entry.childrenPresent} - title={listing.entry.expanded ? "Collapse" : `Expand${listing.entry.ancestorOfSelected ? "\n(A selected layer is contained within)" : ""}`} - on:click|stopPropagation={() => handleExpandArrowClick(listing.entry.id)} + title={listing.entry.expanded + ? "Collapse (Click) / Collapse All (Alt Click)" + : `Expand (Click) / Expand All (Alt Click)${listing.entry.ancestorOfSelected ? "\n(A selected layer is contained within)" : ""}`} + on:click={(e) => handleExpandArrowClickWithModifiers(e, listing.entry.id)} tabindex="0" > {/if} @@ -545,11 +550,11 @@ } &.ancestor-of-selected .expand-arrow:not(.expanded) { - background-image: var(--inheritance-stripes-background); + background-image: var(--inheritance-dots-background-6-lowergray); } &.descendant-of-selected { - background-image: var(--inheritance-dots-background); + background-image: var(--inheritance-dots-background-4-dimgray); } &.selected-but-not-in-selected-network { diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index cc5f4d31d..ec824b0cb 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -700,9 +700,9 @@ impl EditorHandle { /// Toggle expansions state of a layer from the layer list #[wasm_bindgen(js_name = toggleLayerExpansion)] - pub fn toggle_layer_expansion(&self, id: u64) { + pub fn toggle_layer_expansion(&self, id: u64, recursive: bool) { let id = NodeId(id); - let message = DocumentMessage::ToggleLayerExpansion { id }; + let message = DocumentMessage::ToggleLayerExpansion { id, recursive }; self.dispatch(message); }