Skip to content

Commit 6b11b47

Browse files
authored
Improve the Data panel with type-specific detail pages and nested-layer support (#4070)
* Improve the Data panel with more type-specific detail pages * Add network_path to SetDisplayName so renames target any network depth * Track nested layers via full editor:layer paths and rename parent_layer to path_of_subgraph * Polish the data panel NodeId leaf page with an editable name field * Make lock and visibility toggles work for layers in nested subgraphs * Fix formatting * Fix connected_to_output running in the wrong network for nested-layer toggles
1 parent 84fb901 commit 6b11b47

19 files changed

Lines changed: 366 additions & 154 deletions

File tree

editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,14 @@ impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHa
3535
});
3636
responses.add(NodeGraphMessage::SetDisplayNameImpl {
3737
node_id,
38+
network_path: Vec::new(),
3839
alias: "Background".to_string(),
3940
});
40-
responses.add(NodeGraphMessage::SetLocked { node_id, locked: true });
41+
responses.add(NodeGraphMessage::SetLocked {
42+
node_id,
43+
network_path: Vec::new(),
44+
locked: true,
45+
});
4146
} else if self.dimensions.x > 0 && self.dimensions.y > 0 {
4247
// Finite canvas: create an artboard with the specified dimensions
4348
responses.add(GraphOperationMessage::NewArtboard {

editor/src/messages/portfolio/document/data_panel/data_panel_message.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ pub enum DataPanelMessage {
1010
inspect_result: InspectResult,
1111
},
1212
ClearLayout,
13+
/// Re-render the existing layout against the latest network interface state. Use this when node metadata
14+
/// (display name, visibility, locked, etc.) changes but the introspected output value hasn't.
15+
Refresh,
1316

1417
PushToElementPath {
1518
step: PathStep,

editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs

Lines changed: 213 additions & 76 deletions
Large diffs are not rendered by default.

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
699699
if let Some(name) = name {
700700
responses.add(NodeGraphMessage::SetDisplayName {
701701
node_id: layer.to_node(),
702+
network_path: Vec::new(),
702703
alias: name,
703704
skip_adding_history_step: false,
704705
});
@@ -756,6 +757,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
756757
if let Some(name) = name {
757758
responses.add(NodeGraphMessage::SetDisplayName {
758759
node_id: layer.to_node(),
760+
network_path: Vec::new(),
759761
alias: name,
760762
skip_adding_history_step: false,
761763
});

editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,12 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
197197

198198
responses.add(NodeGraphMessage::SetDisplayNameImpl {
199199
node_id: id,
200+
network_path: Vec::new(),
200201
alias: layer_alias.to_string(),
201202
});
202203
responses.add(NodeGraphMessage::SetDisplayNameImpl {
203204
node_id: control_path_id,
205+
network_path: Vec::new(),
204206
alias: path_alias.to_string(),
205207
});
206208
}
@@ -245,6 +247,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
245247
network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
246248
responses.add(NodeGraphMessage::SetDisplayNameImpl {
247249
node_id: id,
250+
network_path: Vec::new(),
248251
alias: "Boolean Operation".to_string(),
249252
});
250253
responses.add(NodeGraphMessage::RunDocumentGraph);
@@ -343,6 +346,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
343346

344347
responses.add(NodeGraphMessage::SetDisplayName {
345348
node_id,
349+
network_path: Vec::new(),
346350
alias: network_interface.display_name(&artboard.to_node(), &[]),
347351
skip_adding_history_step: true,
348352
});

editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
236236
// Derive the parent layer's NodeId from the document path
237237
DocumentNode {
238238
inputs: vec![NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath)],
239-
implementation: DocumentNodeImplementation::ProtoNode(graphic::parent_layer::IDENTIFIER),
239+
implementation: DocumentNodeImplementation::ProtoNode(graphic::path_of_subgraph::IDENTIFIER),
240240
..Default::default()
241241
},
242242
// Stamp each row of the content with the parent layer's NodeId via the `editor:layer` attribute,
@@ -299,7 +299,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
299299
},
300300
..Default::default()
301301
},
302-
// 2: parent_layer
302+
// 2: path_of_subgraph
303303
DocumentNodeMetadata {
304304
persistent_metadata: DocumentNodePersistentMetadata {
305305
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, 1)),
@@ -371,7 +371,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
371371
// Derive the parent layer's NodeId from the document path
372372
DocumentNode {
373373
inputs: vec![NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath)],
374-
implementation: DocumentNodeImplementation::ProtoNode(graphic::parent_layer::IDENTIFIER),
374+
implementation: DocumentNodeImplementation::ProtoNode(graphic::path_of_subgraph::IDENTIFIER),
375375
..Default::default()
376376
},
377377
// Stamp each row of the content with the parent layer's NodeId via the `editor:layer` attribute,
@@ -461,7 +461,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
461461
},
462462
..Default::default()
463463
},
464-
// 1: parent_layer
464+
// 1: path_of_subgraph
465465
DocumentNodeMetadata {
466466
persistent_metadata: DocumentNodePersistentMetadata {
467467
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, 3)),

editor/src/messages/portfolio/document/node_graph/node_graph_message.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,15 @@ pub enum NodeGraphMessage {
157157
},
158158
SetDisplayName {
159159
node_id: NodeId,
160+
/// The path to the network containing `node_id`. Empty for nodes at the root document network.
161+
/// Lets the rename target a node at any nesting depth, independent of the current selection network.
162+
network_path: Vec<NodeId>,
160163
alias: String,
161164
skip_adding_history_step: bool,
162165
},
163166
SetDisplayNameImpl {
164167
node_id: NodeId,
168+
network_path: Vec<NodeId>,
165169
alias: String,
166170
},
167171
SetToNodeOrLayer {
@@ -199,26 +203,35 @@ pub enum NodeGraphMessage {
199203
ToggleSelectedLocked,
200204
ToggleLocked {
201205
node_id: NodeId,
206+
/// The path to the network containing `node_id`. Empty for nodes at the root document network.
207+
/// Lets the toggle target a node at any nesting depth, independent of the current selection network.
208+
network_path: Vec<NodeId>,
202209
},
203210
SetLocked {
204211
node_id: NodeId,
212+
network_path: Vec<NodeId>,
205213
locked: bool,
206214
},
207215
ToggleSelectedIsPinned,
208216
ToggleSelectedVisibility,
209217
ToggleVisibility {
210218
node_id: NodeId,
219+
/// The path to the network containing `node_id`. Empty for nodes at the root document network.
220+
/// Lets the toggle target a node at any nesting depth, independent of the current selection network.
221+
network_path: Vec<NodeId>,
211222
},
212223
SetPinned {
213224
node_id: NodeId,
214225
pinned: bool,
215226
},
216227
SetVisibility {
217228
node_id: NodeId,
229+
network_path: Vec<NodeId>,
218230
visible: bool,
219231
},
220232
SetLockedOrVisibilitySideEffects {
221233
node_ids: Vec<NodeId>,
234+
network_path: Vec<NodeId>,
222235
},
223236
UpdateEdges,
224237
UpdateBoxSelection,

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
659659
});
660660
responses.add(NodeGraphMessage::SetDisplayNameImpl {
661661
node_id: encapsulating_node_id,
662+
network_path: selection_network_path.to_vec(),
662663
alias: "Untitled Node".to_string(),
663664
});
664665

@@ -909,13 +910,19 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
909910

910911
// Toggle visibility of clicked node and return
911912
if let Some(clicked_visibility) = network_interface.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Visibility, selection_network_path) {
912-
responses.add(NodeGraphMessage::ToggleVisibility { node_id: clicked_visibility });
913+
responses.add(NodeGraphMessage::ToggleVisibility {
914+
node_id: clicked_visibility,
915+
network_path: selection_network_path.to_vec(),
916+
});
913917
return;
914918
}
915919

916920
// Toggle lock of clicked node and return
917921
if let Some(clicked_lock) = network_interface.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Lock, selection_network_path) {
918-
responses.add(NodeGraphMessage::ToggleLocked { node_id: clicked_lock });
922+
responses.add(NodeGraphMessage::ToggleLocked {
923+
node_id: clicked_lock,
924+
network_path: selection_network_path.to_vec(),
925+
});
919926
return;
920927
}
921928

@@ -1816,13 +1823,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
18161823
}
18171824
NodeGraphMessage::SetDisplayName {
18181825
node_id,
1826+
network_path,
18191827
alias,
18201828
skip_adding_history_step,
18211829
} => {
18221830
if !skip_adding_history_step {
18231831
responses.add(DocumentMessage::StartTransaction);
18241832
}
1825-
responses.add(NodeGraphMessage::SetDisplayNameImpl { node_id, alias });
1833+
responses.add(NodeGraphMessage::SetDisplayNameImpl { node_id, network_path, alias });
18261834
if !skip_adding_history_step {
18271835
// Does not add a history step if the name was not changed
18281836
responses.add(DocumentMessage::EndTransaction);
@@ -1831,9 +1839,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
18311839
responses.add(DocumentMessage::RenderScrollbars);
18321840
responses.add(NodeGraphMessage::SendGraph);
18331841
responses.add(OverlaysMessage::Draw); // Redraw overlays to update artboard names
1842+
responses.add(DataPanelMessage::Refresh);
18341843
}
1835-
NodeGraphMessage::SetDisplayNameImpl { node_id, alias } => {
1836-
network_interface.set_display_name(&node_id, alias, selection_network_path);
1844+
NodeGraphMessage::SetDisplayNameImpl { node_id, network_path, alias } => {
1845+
network_interface.set_display_name(&node_id, alias, &network_path);
18371846
}
18381847
NodeGraphMessage::SetImportExportName { name, index } => {
18391848
responses.add(DocumentMessage::StartTransaction);
@@ -1872,25 +1881,34 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
18721881
responses.add(DocumentMessage::AddTransaction);
18731882

18741883
for node_id in &node_ids {
1875-
responses.add(NodeGraphMessage::SetLocked { node_id: *node_id, locked });
1884+
responses.add(NodeGraphMessage::SetLocked {
1885+
node_id: *node_id,
1886+
network_path: selection_network_path.to_vec(),
1887+
locked,
1888+
});
18761889
}
18771890

1878-
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids })
1891+
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects {
1892+
node_ids,
1893+
network_path: selection_network_path.to_vec(),
1894+
})
18791895
}
1880-
NodeGraphMessage::ToggleLocked { node_id } => {
1881-
let Some(node_metadata) = network_interface.document_network_metadata().persistent_metadata.node_metadata.get(&node_id) else {
1882-
log::error!("Cannot get node {node_id:?} in NodeGraphMessage::ToggleLocked");
1883-
return;
1884-
};
1885-
1886-
let locked = !node_metadata.persistent_metadata.locked;
1896+
NodeGraphMessage::ToggleLocked { node_id, network_path } => {
1897+
let locked = !network_interface.is_locked(&node_id, &network_path);
18871898

18881899
responses.add(DocumentMessage::AddTransaction);
1889-
responses.add(NodeGraphMessage::SetLocked { node_id, locked });
1890-
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids: vec![node_id] })
1900+
responses.add(NodeGraphMessage::SetLocked {
1901+
node_id,
1902+
network_path: network_path.clone(),
1903+
locked,
1904+
});
1905+
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects {
1906+
node_ids: vec![node_id],
1907+
network_path,
1908+
});
18911909
}
1892-
NodeGraphMessage::SetLocked { node_id, locked } => {
1893-
network_interface.set_locked(&node_id, selection_network_path, locked);
1910+
NodeGraphMessage::SetLocked { node_id, network_path, locked } => {
1911+
network_interface.set_locked(&node_id, &network_path, locked);
18941912
}
18951913
NodeGraphMessage::ToggleSelectedIsPinned => {
18961914
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
@@ -1906,7 +1924,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
19061924
for node_id in &node_ids {
19071925
responses.add(NodeGraphMessage::SetPinned { node_id: *node_id, pinned });
19081926
}
1909-
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids });
1927+
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects {
1928+
node_ids,
1929+
network_path: selection_network_path.to_vec(),
1930+
});
19101931
}
19111932
NodeGraphMessage::ToggleSelectedVisibility => {
19121933
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
@@ -1920,31 +1941,46 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
19201941

19211942
responses.add(DocumentMessage::AddTransaction);
19221943
for node_id in &node_ids {
1923-
responses.add(NodeGraphMessage::SetVisibility { node_id: *node_id, visible });
1944+
responses.add(NodeGraphMessage::SetVisibility {
1945+
node_id: *node_id,
1946+
network_path: selection_network_path.to_vec(),
1947+
visible,
1948+
});
19241949
}
1925-
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids });
1950+
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects {
1951+
node_ids,
1952+
network_path: selection_network_path.to_vec(),
1953+
});
19261954
}
1927-
NodeGraphMessage::ToggleVisibility { node_id } => {
1928-
let visible = !network_interface.is_visible(&node_id, selection_network_path);
1955+
NodeGraphMessage::ToggleVisibility { node_id, network_path } => {
1956+
let visible = !network_interface.is_visible(&node_id, &network_path);
19291957

19301958
responses.add(DocumentMessage::AddTransaction);
1931-
responses.add(NodeGraphMessage::SetVisibility { node_id, visible });
1932-
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids: vec![node_id] });
1959+
responses.add(NodeGraphMessage::SetVisibility {
1960+
node_id,
1961+
network_path: network_path.clone(),
1962+
visible,
1963+
});
1964+
responses.add(NodeGraphMessage::SetLockedOrVisibilitySideEffects {
1965+
node_ids: vec![node_id],
1966+
network_path,
1967+
});
19331968
}
19341969
NodeGraphMessage::SetPinned { node_id, pinned } => {
19351970
network_interface.set_pinned(&node_id, selection_network_path, pinned);
19361971
}
1937-
NodeGraphMessage::SetVisibility { node_id, visible } => {
1938-
network_interface.set_visibility(&node_id, selection_network_path, visible);
1972+
NodeGraphMessage::SetVisibility { node_id, network_path, visible } => {
1973+
network_interface.set_visibility(&node_id, &network_path, visible);
19391974
}
1940-
NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids } => {
1941-
if node_ids.iter().any(|node_id| network_interface.connected_to_output(node_id, selection_network_path)) {
1975+
NodeGraphMessage::SetLockedOrVisibilitySideEffects { node_ids, network_path } => {
1976+
if node_ids.iter().any(|node_id| network_interface.connected_to_output(node_id, &network_path)) {
19421977
responses.add(NodeGraphMessage::RunDocumentGraph);
19431978
}
19441979
responses.add(NodeGraphMessage::UpdateActionButtons);
19451980
responses.add(NodeGraphMessage::SendGraph);
19461981

19471982
responses.add(PropertiesPanelMessage::Refresh);
1983+
responses.add(DataPanelMessage::Refresh);
19481984
}
19491985
NodeGraphMessage::UpdateBoxSelection => {
19501986
if let Some((box_selection_start, _)) = self.box_selection_start {
@@ -2397,6 +2433,7 @@ impl NodeGraphMessageHandler {
23972433
let mut properties = Vec::new();
23982434

23992435
if let [node_id] = *nodes.as_slice() {
2436+
let network_path = context.selection_network_path.to_vec();
24002437
properties.push(LayoutGroup::row(vec![
24012438
Separator::new(SeparatorStyle::Related).widget_instance(),
24022439
IconLabel::new("Node").tooltip_description("Name of the selected node.").widget_instance(),
@@ -2406,6 +2443,7 @@ impl NodeGraphMessageHandler {
24062443
.on_update(move |text_input| {
24072444
NodeGraphMessage::SetDisplayName {
24082445
node_id,
2446+
network_path: network_path.clone(),
24092447
alias: text_input.value.clone(),
24102448
skip_adding_history_step: false,
24112449
}
@@ -2468,6 +2506,7 @@ impl NodeGraphMessageHandler {
24682506
return Vec::new();
24692507
}
24702508

2509+
let layer_network_path = context.selection_network_path.to_vec();
24712510
let mut layer_properties = vec![LayoutGroup::row(vec![
24722511
Separator::new(SeparatorStyle::Related).widget_instance(),
24732512
IconLabel::new("Layer").tooltip_description("Name of the selected layer.").widget_instance(),
@@ -2477,6 +2516,7 @@ impl NodeGraphMessageHandler {
24772516
.on_update(move |text_input| {
24782517
NodeGraphMessage::SetDisplayName {
24792518
node_id: layer,
2519+
network_path: layer_network_path.clone(),
24802520
alias: text_input.value.clone(),
24812521
skip_adding_history_step: false,
24822522
}

editor/src/messages/portfolio/document_migration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ pub fn document_migration_reset_node_definition(document_serialized_content: &st
10161016
return true;
10171017
}
10181018

1019-
// The `source_node_id` proto node was removed in favor of `parent_layer` + `write_attribute`.
1019+
// The `source_node_id` proto node was removed in favor of `path_of_subgraph` + `write_attribute`.
10201020
// Documents that still reference it inside their Merge or Artboard layer networks need those layer definitions
10211021
// reset to the current default so the new internal plumbing replaces the obsolete node.
10221022
if document_serialized_content.contains("graphic_nodes::graphic::SourceNodeIdNode")

0 commit comments

Comments
 (0)