diff --git a/editor/src/messages/layout/utility_types/layout_widget.rs b/editor/src/messages/layout/utility_types/layout_widget.rs index fef1061f27..02302290d7 100644 --- a/editor/src/messages/layout/utility_types/layout_widget.rs +++ b/editor/src/messages/layout/utility_types/layout_widget.rs @@ -340,6 +340,7 @@ pub enum LayoutGroup { description: String, visible: bool, pinned: bool, + expanded: bool, id: u64, layout: Layout, }, @@ -439,6 +440,7 @@ impl Diffable for LayoutGroup { description: current_description, visible: current_visible, pinned: current_pinned, + expanded: current_expanded, id: current_id, layout: current_layout, }, @@ -447,6 +449,7 @@ impl Diffable for LayoutGroup { description: new_description, visible: new_visible, pinned: new_pinned, + expanded: new_expanded, id: new_id, layout: new_layout, }, @@ -458,6 +461,7 @@ impl Diffable for LayoutGroup { || *current_description != new_description || *current_visible != new_visible || *current_pinned != new_pinned + || *current_expanded != new_expanded || *current_id != new_id { // Update self to reflect new changes @@ -465,6 +469,7 @@ impl Diffable for LayoutGroup { current_description.clone_from(&new_description); *current_visible = new_visible; *current_pinned = new_pinned; + *current_expanded = new_expanded; *current_id = new_id; current_layout.clone_from(&new_layout); @@ -474,6 +479,7 @@ impl Diffable for LayoutGroup { description: new_description, visible: new_visible, pinned: new_pinned, + expanded: new_expanded, id: new_id, layout: new_layout, } diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index d364a78774..c37d3c6185 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -125,6 +125,7 @@ impl<'a> ModifyInputsContext<'a> { pub fn create_layer(&mut self, new_id: NodeId) -> LayerNodeIdentifier { let new_merge_node = resolve_network_node_type("Merge").expect("Merge node").default_node_template(); self.network_interface.insert_node(new_id, new_merge_node, &[]); + self.responses.add(PropertiesPanelMessage::SetSectionExpanded { node_id: new_id.0, expanded: false }); LayerNodeIdentifier::new(new_id, self.network_interface) } diff --git a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs index 1f72162800..3e3c79d0a1 100644 --- a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs +++ b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs @@ -35,6 +35,7 @@ pub struct NodePropertiesContext<'a> { pub network_interface: &'a mut NodeNetworkInterface, pub selection_network_path: &'a [NodeId], pub document_name: &'a str, + pub section_expanded: &'a HashMap, } impl NodePropertiesContext<'_> { diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index eb08935e7c..9c3858bb25 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -1843,12 +1843,20 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper let visible = context.network_interface.is_visible(&node_id, context.selection_network_path); let pinned = context.network_interface.is_pinned(&node_id, context.selection_network_path); + let expanded = context.section_expanded.get(&node_id.0).copied().unwrap_or_else(|| { + !context + .network_interface + .reference(&node_id, context.selection_network_path) + .as_ref() + .is_some_and(|id| id.implementation_name_from_identifier() == "Merge") + }); LayoutGroup::Section { name, description, visible, pinned, + expanded, id: node_id.0, layout: Layout(layout), } diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs index a87d8fb07d..954c909dee 100644 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs +++ b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs @@ -6,4 +6,6 @@ pub enum PropertiesPanelMessage { // Messages Clear, Refresh, + SetAllSectionsExpanded { expanded: bool }, + SetSectionExpanded { node_id: u64, expanded: bool }, } diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs index b5706ec1e5..716a5903e2 100644 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use graphene_std::uuid::NodeId; use crate::messages::layout::utility_types::widget_prelude::*; @@ -18,7 +20,9 @@ pub struct PropertiesPanelMessageContext<'a> { } #[derive(Debug, Clone, Default, ExtractField)] -pub struct PropertiesPanelMessageHandler {} +pub struct PropertiesPanelMessageHandler { + pub section_expanded: HashMap, +} #[message_handler_data] impl MessageHandler> for PropertiesPanelMessageHandler { @@ -52,6 +56,7 @@ impl MessageHandler> f selection_network_path, document_name, executor, + section_expanded: &self.section_expanded, }; let layout = Layout(NodeGraphMessageHandler::collate_properties(&mut node_properties_context)); @@ -60,6 +65,31 @@ impl MessageHandler> f layout_target: LayoutTarget::PropertiesPanel, }); } + PropertiesPanelMessage::SetAllSectionsExpanded { expanded } => { + let mut layout = { + let mut node_properties_context = NodePropertiesContext { + persistent_data, + responses, + network_interface, + selection_network_path, + document_name, + executor, + section_expanded: &self.section_expanded, + }; + Layout(NodeGraphMessageHandler::collate_properties(&mut node_properties_context)) + }; + + Self::update_all_section_expansion_recursive(&mut layout.0, expanded, &mut self.section_expanded); + + responses.add(LayoutMessage::SendLayout { + layout, + layout_target: LayoutTarget::PropertiesPanel, + }); + } + PropertiesPanelMessage::SetSectionExpanded { node_id, expanded } => { + self.section_expanded.insert(node_id, expanded); + responses.add(PropertiesPanelMessage::Refresh); + } } } @@ -67,3 +97,19 @@ impl MessageHandler> f actions!(PropertiesMessageDiscriminant;) } } + +impl PropertiesPanelMessageHandler { + fn update_all_section_expansion_recursive(layout: &mut [LayoutGroup], expanded: bool, section_expanded: &mut HashMap) { + for group in layout { + if let LayoutGroup::Section { + id, layout, expanded: group_expanded, .. + } = group + { + *group_expanded = expanded; + section_expanded.insert(*id, expanded); + + Self::update_all_section_expansion_recursive(&mut layout.0, expanded, section_expanded); + } + } + } +} diff --git a/frontend/src/components/widgets/WidgetSection.svelte b/frontend/src/components/widgets/WidgetSection.svelte index af55fe7f3d..d01b46e579 100644 --- a/frontend/src/components/widgets/WidgetSection.svelte +++ b/frontend/src/components/widgets/WidgetSection.svelte @@ -3,6 +3,7 @@ import type { Editor } from "@graphite/editor"; import { isWidgetSpanRow, isWidgetSection, type WidgetSection as WidgetSectionFromJsMessages, type LayoutTarget } from "@graphite/messages"; + import { operatingSystem } from "@graphite/utility-functions/platform"; import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte"; @@ -16,14 +17,24 @@ export { className as class }; export let classes: Record = {}; - let expanded = true; + $: expanded = widgetData.expanded; const editor = getContext("editor"); - -