mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-28 09:58:12 +08:00
Make the Data panel able to display data from selected nodes living in subgraphs (#4064)
Enable the Data panel to display data from selected nodes living in subgraphs
This commit is contained in:
@@ -27,7 +27,9 @@ pub struct DataPanelMessageContext<'a> {
|
||||
/// The data panel allows for graph data to be previewed.
|
||||
#[derive(Default, Debug, Clone, ExtractField)]
|
||||
pub struct DataPanelMessageHandler {
|
||||
introspected_node: Option<NodeId>,
|
||||
/// Full path from the root network to the introspected node, with the node itself as the last element.
|
||||
/// Empty when nothing is being introspected.
|
||||
introspected_node_path: Vec<NodeId>,
|
||||
introspected_data: Option<Arc<dyn Any + Send + Sync>>,
|
||||
element_path: Vec<PathStep>,
|
||||
active_vector_table_tab: VectorTableTab,
|
||||
@@ -38,12 +40,12 @@ impl MessageHandler<DataPanelMessage, DataPanelMessageContext<'_>> for DataPanel
|
||||
fn process_message(&mut self, message: DataPanelMessage, responses: &mut VecDeque<Message>, context: DataPanelMessageContext) {
|
||||
match message {
|
||||
DataPanelMessage::UpdateLayout { mut inspect_result } => {
|
||||
self.introspected_node = Some(inspect_result.inspect_node);
|
||||
self.introspected_data = inspect_result.take_data();
|
||||
self.introspected_node_path = inspect_result.inspect_node_path;
|
||||
self.update_layout(responses, context);
|
||||
}
|
||||
DataPanelMessage::ClearLayout => {
|
||||
self.introspected_node = None;
|
||||
self.introspected_node_path.clear();
|
||||
self.introspected_data = None;
|
||||
self.element_path.clear();
|
||||
self.active_vector_table_tab = VectorTableTab::default();
|
||||
@@ -93,8 +95,9 @@ impl DataPanelMessageHandler {
|
||||
let mut widgets = Vec::new();
|
||||
|
||||
// Selected layer/node name
|
||||
if let Some(node_id) = self.introspected_node {
|
||||
let is_layer = network_interface.is_layer(&node_id, &[]);
|
||||
if let Some((node_id, parent_path)) = self.introspected_node_path.split_last() {
|
||||
let node_id = *node_id;
|
||||
let is_layer = network_interface.is_layer(&node_id, parent_path);
|
||||
|
||||
widgets.extend([
|
||||
if is_layer {
|
||||
@@ -103,7 +106,7 @@ impl DataPanelMessageHandler {
|
||||
IconLabel::new("Node").tooltip_description("Name of the selected node.").widget_instance()
|
||||
},
|
||||
Separator::new(SeparatorStyle::Related).widget_instance(),
|
||||
TextInput::new(network_interface.display_name(&node_id, &[]))
|
||||
TextInput::new(network_interface.display_name(&node_id, parent_path))
|
||||
.tooltip_description(if is_layer { "Name of the selected layer." } else { "Name of the selected node." })
|
||||
.on_update(move |text_input| {
|
||||
NodeGraphMessage::SetDisplayName {
|
||||
|
||||
@@ -1686,6 +1686,12 @@ impl DocumentMessageHandler {
|
||||
self.network_interface.document_metadata()
|
||||
}
|
||||
|
||||
/// Path to the subnetwork that the user's selection is currently scoped to.
|
||||
/// Empty when the selection lives in the root document network.
|
||||
pub fn selection_network_path(&self) -> &[NodeId] {
|
||||
&self.selection_network_path
|
||||
}
|
||||
|
||||
pub fn serialize_document(&self) -> String {
|
||||
let val = serde_json::to_string(self);
|
||||
// We fully expect the serialization to succeed
|
||||
|
||||
@@ -1868,22 +1868,31 @@ impl PortfolioMessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the ID of the selected node that should be used as the current source for the Data panel.
|
||||
pub fn node_to_inspect(&self) -> Option<NodeId> {
|
||||
/// Returns the full path from the root network to the selected node that should drive the Data panel.
|
||||
/// The last element is the node itself; preceding elements identify the nested subnetwork it lives in
|
||||
/// so the Data panel can introspect nodes inside subgraphs. An empty `Vec` signals "nothing to inspect".
|
||||
pub fn node_to_inspect(&self) -> Vec<NodeId> {
|
||||
// Skip if the Data panel is not open
|
||||
if !self.workspace_panel_layout.is_panel_visible(PanelType::Data) || self.workspace_panel_layout.focus_document {
|
||||
return None;
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let document = self.document(self.active_document_id?)?;
|
||||
let selected_nodes = document.network_interface.selected_nodes().0;
|
||||
let Some(document) = self.active_document_id.and_then(|id| self.document(id)) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let network_path = document.selection_network_path();
|
||||
let Some(selected_nodes) = document.network_interface.selected_nodes_in_nested_network(network_path) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
// Skip if there is not exactly one selected node
|
||||
if selected_nodes.len() != 1 {
|
||||
return None;
|
||||
}
|
||||
let [node_id] = selected_nodes.0.as_slice() else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
selected_nodes.first().copied()
|
||||
let mut path = network_path.to_vec();
|
||||
path.push(*node_id);
|
||||
path
|
||||
}
|
||||
|
||||
/// Remove a dockable panel type from whichever panel group currently contains it. Does not prune empty groups.
|
||||
|
||||
Reference in New Issue
Block a user