-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Enhance Properties panel section behavior and persistence #3787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
0735b87
f4055c5
7571e47
14253f5
f7588f5
894f9c0
c3c315d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -98,9 +98,6 @@ pub struct DocumentMessageHandler { | |
| /// Tracks which layer occurrences are collapsed in the Layers panel, keyed by tree path. | ||
| #[serde(deserialize_with = "deserialize_collapsed_layers", default)] | ||
| pub collapsed: CollapsedLayers, | ||
| /// The node IDs whose section is collapsed in the Properties panel. | ||
| #[serde(default)] | ||
| pub properties_panel_collapsed_sections: Vec<NodeId>, | ||
| /// The full Git commit hash of the Graphite repository that was used to build the editor. | ||
| /// We save this to provide a hint about which version of the editor was used to create the document. | ||
| pub commit_hash: String, | ||
|
|
@@ -178,7 +175,6 @@ impl Default for DocumentMessageHandler { | |
| network_interface: default_document_network_interface(), | ||
| resources: ResourceMessageHandler::default(), | ||
| collapsed: CollapsedLayers::default(), | ||
| properties_panel_collapsed_sections: Vec::new(), | ||
| commit_hash: GRAPHITE_GIT_COMMIT_HASH.to_string(), | ||
| document_ptz: PTZ::default(), | ||
| render_mode: RenderMode::default(), | ||
|
|
@@ -253,7 +249,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes | |
| document_name: self.name.as_str(), | ||
| fonts, | ||
| properties_panel_open, | ||
| properties_panel_collapsed_sections: &self.properties_panel_collapsed_sections, | ||
| properties_panel_collapsed_sections: &[], | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The Prompt for AI agents |
||
| }; | ||
| self.properties_panel_message_handler.process_message(message, responses, context); | ||
| } | ||
|
|
@@ -277,7 +273,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes | |
| breadcrumb_network_path: &self.breadcrumb_network_path, | ||
| document_id, | ||
| collapsed: &mut self.collapsed, | ||
| properties_panel_collapsed_sections: &mut self.properties_panel_collapsed_sections, | ||
| ipp, | ||
| graph_view_overlay_open: self.graph_view_overlay_open, | ||
| graph_fade_artwork_percentage: self.graph_fade_artwork_percentage, | ||
|
|
@@ -1411,12 +1406,12 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes | |
| responses.add(NodeGraphMessage::SendGraph); | ||
| } | ||
| DocumentMessage::ToggleNodePropertiesSectionExpanded { node_id } => { | ||
| if let Some(index) = self.properties_panel_collapsed_sections.iter().position(|id| *id == node_id) { | ||
| self.properties_panel_collapsed_sections.remove(index); | ||
| } else { | ||
| self.properties_panel_collapsed_sections.push(node_id); | ||
| } | ||
| responses.add(PropertiesPanelMessage::Refresh); | ||
| let collapsed = !self.network_interface.is_collapsed(&node_id, &[]); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||
| responses.add(NodeGraphMessage::SetCollapsed { node_id, collapsed }); | ||
| responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { | ||
| node_ids: vec![node_id], | ||
| network_path: vec![], | ||
| }); | ||
| } | ||
| DocumentMessage::ToggleSelectedLocked => responses.add(NodeGraphMessage::ToggleSelectedLocked), | ||
| DocumentMessage::ToggleSelectedVisibility => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,6 +65,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 }); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: During bulk SVG import this queues a large flood of PropertiesPanelMessage cascades (SetCollapsed + SetLockedOrVisibilitySideEffects → RunDocumentGraph/SendGraph/UpdateLayerPanel/AutoSave/Refresh) for every created layer, since create_layer is invoked once per node. The collapsed section state is only needed for layers the user creates interactively, so guard the emission with Prompt for AI agents |
||
| LayerNodeIdentifier::new(new_id, self.network_interface) | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,8 @@ use graphene_std::vector::Vector; | |
| use graphene_std::*; | ||
| use std::collections::{HashMap, VecDeque}; | ||
|
|
||
| pub const MERGE_NODE_IDENTIFIER: &str = "Merge"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The new pub const MERGE_NODE_IDENTIFIER is used in only one place, while the identical literal "Merge" remains hardcoded in sibling comparisons (e.g. document_node_derive.rs, view.rs is_merge/is_collapsed, document_migration.rs, graph_modification_utils.rs). Since the constant names the shared Merge network identifier, using it consistently avoids future drift if the display/identifier value ever changes. Consider referencing MERGE_NODE_IDENTIFIER in those checks as well, or dropping the constant if only this one site is intended. Prompt for AI agents |
||
|
|
||
| pub struct NodePropertiesContext<'a> { | ||
| pub responses: &'a mut VecDeque<Message>, | ||
| pub executor: &'a mut NodeGraphExecutor, | ||
|
|
@@ -145,7 +147,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi | |
| properties: None, | ||
| }, | ||
| DocumentNodeDefinition { | ||
| identifier: "Merge", | ||
| identifier: MERGE_NODE_IDENTIFIER, | ||
| category: "General", | ||
| node_template: NodeTemplate { | ||
| implementation: NodeTemplateImplementation::Network(NodeNetworkTemplate { | ||
|
|
@@ -1543,7 +1545,6 @@ impl DocumentNodeDefinition { | |
| template | ||
| } | ||
|
|
||
| /// Converts the [DocumentNodeDefinition] type to a [NodeTemplate], completely default. | ||
| pub fn default_node_template(&self) -> NodeTemplate { | ||
| self.node_template_input_override(self.node_template.inputs.clone().into_iter().map(Some)) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,7 +39,6 @@ pub struct NodeGraphMessageContext<'a> { | |
| pub breadcrumb_network_path: &'a [NodeId], | ||
| pub document_id: DocumentId, | ||
| pub collapsed: &'a mut CollapsedLayers, | ||
| pub properties_panel_collapsed_sections: &'a mut Vec<NodeId>, | ||
| pub ipp: &'a InputPreprocessorMessageHandler, | ||
| pub graph_view_overlay_open: bool, | ||
| pub graph_fade_artwork_percentage: f64, | ||
|
|
@@ -111,7 +110,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG | |
| breadcrumb_network_path, | ||
| document_id, | ||
| collapsed, | ||
| properties_panel_collapsed_sections, | ||
| ipp, | ||
| graph_view_overlay_open, | ||
| graph_fade_artwork_percentage, | ||
|
|
@@ -193,10 +191,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG | |
|
|
||
| // Prune the Layers panel collapsed state for any layer tree paths whose nodes no longer exist, so it doesn't accumulate across loads | ||
| collapsed.0.retain(|path| path.iter().all(|&node_id| network_interface.document_network().nodes.contains_key(&node_id))); | ||
|
|
||
| // Prune the Properties panel node section collapsed state for any nodes (in any nested network) that no longer exist, so it doesn't accumulate across loads | ||
| let existing_nodes = network_interface.document_network().recursive_nodes().map(|(node_id, ..)| *node_id).collect::<HashSet<_>>(); | ||
| properties_panel_collapsed_sections.retain(|node_id| existing_nodes.contains(node_id)); | ||
| } | ||
| NodeGraphMessage::SelectedNodesUpdated => { | ||
| let selected_layers = network_interface.selected_nodes().selected_layers(network_interface.document_metadata()).collect::<Vec<_>>(); | ||
|
|
@@ -2029,6 +2023,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG | |
| NodeGraphMessage::SetPinned { node_id, pinned } => { | ||
| network_interface.set_pinned(&node_id, selection_network_path, pinned); | ||
| } | ||
| NodeGraphMessage::SetCollapsed { node_id, collapsed } => { | ||
| network_interface.set_collapsed(&node_id, selection_network_path, collapsed); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Root Properties sections can fail to expand or collapse when the current selection is inside a nested network: Prompt for AI agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Expanding or collapsing a Properties section is not undoable because this handler mutates the persistent node metadata without ensuring a transaction has started. Start a document transaction before dispatching Prompt for AI agents |
||
| } | ||
| NodeGraphMessage::SetVisibility { node_id, network_path, visible } => { | ||
| network_interface.set_visibility(&node_id, &network_path, visible); | ||
| } | ||
|
|
@@ -2038,6 +2035,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG | |
| } | ||
| responses.add(NodeGraphMessage::UpdateActionButtons); | ||
| responses.add(NodeGraphMessage::SendGraph); | ||
| responses.add(NodeGraphMessage::UpdateLayerPanel); | ||
| responses.add(PortfolioMessage::AutoSaveActiveDocument); | ||
|
|
||
| responses.add(PropertiesPanelMessage::Refresh); | ||
| responses.add(DataPanelMessage::Refresh); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -119,6 +119,7 @@ impl NodeTemplate { | |
| output_names, | ||
| locked, | ||
| pinned, | ||
| collapsed: _, | ||
| node_type_metadata, | ||
| network_metadata, | ||
| } = persistent_node_metadata; | ||
|
|
@@ -201,6 +202,7 @@ impl NodeTemplate { | |
| output_names, | ||
| locked, | ||
| pinned, | ||
| collapsed: None, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: The new Prompt for AI agents |
||
| node_type_metadata, | ||
| network_metadata, | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -640,6 +640,8 @@ pub struct DocumentNodePersistentMetadata { | |
| /// Indicates that the node will be shown in the Properties panel when it would otherwise be empty, letting a user easily edit its properties by just deselecting everything. | ||
| #[serde(default)] | ||
| pub pinned: bool, | ||
| #[serde(default)] | ||
| pub collapsed: Option<bool>, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Explicit Properties-panel collapse choices are lost on persistence, so reopening a document can restore a section to the implementation default instead of the user’s state. Carry Prompt for AI agents |
||
| /// Metadata that is specific to either nodes or layers, which are chosen states for displaying as a left-to-right node or bottom-to-top layer. | ||
| /// All fields in NodeTypePersistentMetadata should automatically be updated by using the network interface API | ||
| pub node_type_metadata: NodeTypePersistentMetadata, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -192,6 +192,12 @@ impl<'a, 'p> NetworkView<'a, 'p> { | |
| Ok(self.node_metadata(node_id)?.persistent_metadata.pinned) | ||
| } | ||
|
|
||
| pub fn is_collapsed(&self, node_id: &NodeId) -> Result<bool, NetworkError> { | ||
| let node_metadata = self.node_metadata(node_id)?; | ||
| let collapsed = node_metadata.persistent_metadata.collapsed.unwrap_or_else(|| self.implementation_name(node_id) == "Merge"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: This compares the implementation name against a hardcoded Prompt for AI agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The fallback identity check Prompt for AI agents |
||
| Ok(collapsed) | ||
| } | ||
|
|
||
| pub fn is_visible(&self, node_id: &NodeId) -> Result<bool, NetworkError> { | ||
| Ok(self.node(node_id)?.visible) | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Opening a document saved by the previous editor drops its Properties-panel collapse preferences. Retaining a legacy serde field and migrating its node IDs into
persistent_metadata.collapsedduring deserialization would preserve existing documents.Prompt for AI agents