gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5364Rust 86Markdown 12TOML 91841 Definiciones

index: Implement node removal

96bbe0343300e79075d8be60bd12c8c2c990b261 · por msiglreith · (hace 7 años) · padre 390ae69f7 · ver el árbol en este commit

Delta semántico · 5

src/forest.rs

src/node.rs

tests/node.rs

3 archivos · +120 −7

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();