diff --git a/src/forest.rs b/src/forest.rs
index 289cb08d8..ac9c4a465 100644
--- a/src/forest.rs
+++ b/src/forest.rs
@@ -68,6 +68,75 @@ impl Forest {
self.mark_dirty(node)
}
+ pub fn clear(&mut self) {
+ self.nodes.clear();
+ self.children.clear();
+ self.parents.clear();
+ }
+
+ /// Removes a node and swaps with the last node.
+ pub fn swap_remove(&mut self, node: NodeId) -> Option<NodeId> {
+ self.nodes.swap_remove(node);
+
+ // Now the last element is swapped in at index `node`.
+ if self.nodes.is_empty() {
+ self.children.clear();
+ self.parents.clear();
+ return None;
+ }
+
+ // Remove old node as parent from all its chilren.
+ for child in &self.children[node] {
+ let parents_child = &mut self.parents[*child];
+ let mut pos = 0;
+ while pos < parents_child.len() {
+ if parents_child[pos] == node {
+ parents_child.swap_remove(pos);
+ } else {
+ pos += 1;
+ }
+ }
+ }
+
+ // Remove old node as child from all its parents.
+ for parent in &self.parents[node] {
+ let childrens_parent = &mut self.children[*parent];
+ let mut pos = 0;
+ while pos < childrens_parent.len() {
+ if childrens_parent[pos] == node {
+ childrens_parent.swap_remove(pos);
+ } else {
+ pos += 1;
+ }
+ }
+ }
+
+ let last = self.nodes.len();
+
+ // Update ids for every child of the swapped in node.
+ for child in &self.children[last] {
+ for parent in &mut self.parents[*child] {
+ if *parent == last {
+ *parent = node;
+ }
+ }
+ }
+
+ // Update ids for every parent of the swapped in node.
+ for parent in &self.parents[last] {
+ for child in &mut self.children[*parent] {
+ if *child == last {
+ *child = node;
+ }
+ }
+ }
+
+ self.children.swap_remove(node);
+ self.parents.swap_remove(node);
+
+ Some(last)
+ }
+
pub unsafe fn remove_child(&mut self, node: NodeId, child: NodeId) -> NodeId {
let index = self.children[node].iter().position(|n| *n == child).unwrap();
self.remove_child_at_index(node, index)
diff --git a/src/node.rs b/src/node.rs
index bf6175c13..fa12adcbe 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -71,13 +71,6 @@ impl Stretch {
}
}
- /// Removes all nodes.
- ///
- /// All associated nodes will be invalid.
- pub fn clear(&mut self) {
- unimplemented!()
- }
-
pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> Node {
let node = self.allocate_node();
let id = self.forest.new_leaf(style, measure);
@@ -93,6 +86,31 @@ impl Stretch {
Ok(node)
}
+ /// Removes all nodes.
+ ///
+ /// All associated nodes will be invalid.
+ pub fn clear(&mut self) {
+ for node in self.nodes_to_ids.keys() {
+ self.nodes.free(&[node.local]);
+ }
+ self.nodes_to_ids.clear();
+ self.ids_to_nodes.clear();
+ self.forest.clear();
+ }
+
+ /// Remove nodes.
+ pub fn remove(&mut self, node: Node) {
+ let id = if let Ok(id) = self.find_node(node) { id } else { return };
+
+ self.nodes_to_ids.remove(&node);
+ self.ids_to_nodes.remove(&id);
+
+ if let Some(new_id) = self.forest.swap_remove(id) {
+ let new = self.ids_to_nodes.remove(&new_id).unwrap();
+ self.nodes_to_ids.insert(new, id);
+ }
+ }
+
pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), Error> {
let id = self.find_node(node)?;
self.forest.nodes[id].measure = measure;
diff --git a/tests/node.rs b/tests/node.rs
index 689b5dc0c..136d2fa7e 100644
--- a/tests/node.rs
+++ b/tests/node.rs
@@ -95,6 +95,32 @@ mod node {
assert_eq!(stretch.children(node).unwrap()[0], child2);
}
+ #[test]
+ fn removesaaa() {
+ let mut stretch = Stretch::new();
+
+ let style2 = Style {
+ flex_direction: FlexDirection::Column,
+ ..Style::default()
+ };
+
+ // Build a linear tree layout: <0> <- <1> <- <2>
+ let node2 = stretch.new_node(style2, vec![]).unwrap();
+ let node1 = stretch.new_node(Style::default(), vec![node2]).unwrap();
+ let node0 = stretch.new_node(Style::default(), vec![node1]).unwrap();
+
+ assert_eq!(stretch.children(node0).unwrap(), vec![node1]);
+
+ // Disconnect the tree: <0> <2>
+ stretch.remove(node1);
+
+ assert!(stretch.style(node1).is_err());
+
+ assert!(stretch.children(node0).unwrap().is_empty());
+ assert!(stretch.children(node2).unwrap().is_empty());
+ assert_eq!(stretch.style(node2).unwrap().flex_direction, style2.flex_direction);
+ }
+
#[test]
fn set_children() {
let mut stretch = Stretch::new();