From 0cb40f5cab2225f320b7aa7bdca53031cf785fb5 Mon Sep 17 00:00:00 2001 From: "Tom A. Wagner" Date: Mon, 28 Aug 2023 13:11:13 +0200 Subject: [PATCH] Node: Rework adding of ports, sort ports and hide seperator when node has no ports This reworks the adding of a port to nodes, to avoid assigning multiple nodes to the same grid cell when a node which was not the last in its column has previously been removed. Instead, the grid is emptied and repopulated each time. This also lets us sort the nodes each time by name. Finally, this hides the seperator if a node has no nodes, as it is unneeded. --- src/ui/graph/node.rs | 72 +++++++++++++++++++++++++++++--------------- src/ui/graph/node.ui | 5 ++- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/ui/graph/node.rs b/src/ui/graph/node.rs index 1c3948a..e7f18d9 100644 --- a/src/ui/graph/node.rs +++ b/src/ui/graph/node.rs @@ -44,10 +44,10 @@ mod imp { #[template_child] pub(super) label: TemplateChild, #[template_child] + pub(super) separator: TemplateChild, + #[template_child] pub(super) port_grid: TemplateChild, pub(super) ports: RefCell>, - pub(super) num_ports_in: Cell, - pub(super) num_ports_out: Cell, } #[glib::object_subclass] @@ -85,6 +85,50 @@ mod imp { } impl WidgetImpl for Node {} + + impl Node { + /// Update the internal ports grid to reflect the ports stored in the ports set. + pub fn update_ports(&self) { + // We first remove all ports from the grid, then re-add them all, so that + // ports that have been removed do not leave gaps in the grid. + + while let Some(ref child) = self.port_grid.first_child() { + self.port_grid.remove(child); + } + + let ports = self.ports.borrow(); + + let mut ports_out = Vec::new(); + let mut ports_in = Vec::new(); + + ports + .iter() + .for_each(|port| match Direction::from_raw(port.direction()) { + Direction::Output => { + ports_out.push(port); + } + Direction::Input => { + ports_in.push(port); + } + _ => unreachable!(), + }); + + ports_out.sort_unstable_by_key(|port| port.name()); + ports_in.sort_unstable_by_key(|port| port.name()); + + // In case no ports have been added to the port, hide the seperator as it is not needed + self.separator + .set_visible(!ports_out.is_empty() || !ports_in.is_empty()); + + for (i, port) in ports_in.into_iter().enumerate() { + self.port_grid.attach(port, 0, i.try_into().unwrap(), 1, 1); + } + + for (i, port) in ports_out.into_iter().enumerate() { + self.port_grid.attach(port, 1, i.try_into().unwrap(), 1, 1); + } + } + } } glib::wrapper! { @@ -102,34 +146,14 @@ impl Node { pub fn add_port(&self, port: Port) { let imp = self.imp(); - - match Direction::from_raw(port.direction()) { - Direction::Input => { - imp.port_grid - .attach(&port, 0, imp.num_ports_in.get() + 1, 1, 1); - imp.num_ports_in.set(imp.num_ports_in.get() + 1); - } - Direction::Output => { - imp.port_grid - .attach(&port, 1, imp.num_ports_out.get() + 1, 1, 1); - imp.num_ports_out.set(imp.num_ports_out.get() + 1); - } - _ => unreachable!(), - } - imp.ports.borrow_mut().insert(port); + imp.update_ports(); } pub fn remove_port(&self, port: &Port) { let imp = self.imp(); if imp.ports.borrow_mut().remove(port) { - match Direction::from_raw(port.direction()) { - Direction::Input => imp.num_ports_in.set(imp.num_ports_in.get() - 1), - Direction::Output => imp.num_ports_in.set(imp.num_ports_out.get() - 1), - _ => unreachable!(), - } - - port.unparent(); + imp.update_ports(); } else { log::warn!("Tried to remove non-existant port widget from node"); } diff --git a/src/ui/graph/node.ui b/src/ui/graph/node.ui index a576681..fba8fbc 100644 --- a/src/ui/graph/node.ui +++ b/src/ui/graph/node.ui @@ -20,7 +20,10 @@ - + + + false +