diff --git a/src/node.rs b/src/node.rs
index cbf3b1f44..645c1f677 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -2,6 +2,7 @@
use alloc::{vec, vec::Vec};
use std::cell::RefCell;
+use std::fmt;
use std::rc::Rc;
use std::rc::Weak;
@@ -91,7 +92,7 @@ impl Node {
Node(child)
}
- pub fn replace_child(&mut self, child: &Node, index: usize) -> Node {
+ pub fn replace_child_at_index(&mut self, index: usize, child: &Node) -> Node {
child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
let old_child = std::mem::replace(&mut self.0.borrow_mut().children[index], Rc::clone(&child.0));
@@ -114,6 +115,10 @@ impl Node {
self.mark_dirty();
}
+ pub fn style(&self) -> Style {
+ self.0.borrow().style
+ }
+
pub fn mark_dirty(&mut self) {
let node = self.0.borrow_mut();
node.layout_cache.replace(None);
@@ -125,7 +130,33 @@ impl Node {
}
}
+ pub fn is_dirty(&mut self) -> bool {
+ let node = self.0.borrow();
+ let layout_cache = node.layout_cache.borrow();
+ if let Some(_) = layout_cache.as_ref() {
+ false
+ } else {
+ true
+ }
+ }
+
pub fn compute_layout(&self, size: Size<Number>) -> Result<Layout> {
algo::compute(&self.0.borrow(), size)
}
}
+
+impl fmt::Debug for Node {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let style = &self.0.borrow().style;
+ let children: Vec<_> = self.0.borrow().children.iter().map(|c| Node(Rc::clone(c))).collect();
+ write!(f, "Node {{ style: {:?}, children: {:?} }}", style, children)
+ }
+}
+
+impl PartialEq for Node {
+ fn eq(&self, other: &Node) -> bool {
+ Rc::ptr_eq(&self.0, &other.0)
+ }
+}
+
+impl Eq for Node {}
diff --git a/src/style.rs b/src/style.rs
index 6ac803685..c4b4eb175 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -202,7 +202,7 @@ impl Default for Size<Dimension> {
}
}
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug)]
pub struct Style {
pub display: Display,
pub position_type: PositionType,
diff --git a/tests/node.rs b/tests/node.rs
new file mode 100644
index 000000000..a113c1a6e
--- /dev/null
+++ b/tests/node.rs
@@ -0,0 +1,126 @@
+#[cfg(test)]
+mod node {
+ use stretch::node::Node;
+ use stretch::style::*;
+
+ #[test]
+ fn children() {
+ let child1 = Node::new(Style::default(), vec![]);
+ let child2 = Node::new(Style::default(), vec![]);
+ let node = Node::new(Style::default(), vec![&child1, &child2]);
+
+ assert_eq!(node.children().len(), 2);
+ assert_eq!(node.children()[0], child1);
+ assert_eq!(node.children()[1], child2);
+ }
+
+ #[test]
+ fn add_child() {
+ let mut node = Node::new(Style::default(), vec![]);
+ assert_eq!(node.children().len(), 0);
+
+ node.add_child(&Node::new(Style::default(), vec![]));
+ assert_eq!(node.children().len(), 1);
+
+ node.add_child(&Node::new(Style::default(), vec![]));
+ assert_eq!(node.children().len(), 2);
+ }
+
+ #[test]
+ fn remove_child() {
+ let child1 = Node::new(Style::default(), vec![]);
+ let child2 = Node::new(Style::default(), vec![]);
+
+ let mut node = Node::new(Style::default(), vec![&child1, &child2]);
+ assert_eq!(node.children().len(), 2);
+
+ node.remove_child(&child1);
+ assert_eq!(node.children().len(), 1);
+ assert_eq!(node.children()[0], child2);
+
+ node.remove_child(&child2);
+ assert_eq!(node.children().len(), 0);
+ }
+
+ #[test]
+ fn remove_child_at_index() {
+ let child1 = Node::new(Style::default(), vec![]);
+ let child2 = Node::new(Style::default(), vec![]);
+
+ let mut node = Node::new(Style::default(), vec![&child1, &child2]);
+ assert_eq!(node.children().len(), 2);
+
+ node.remove_child_at_index(0);
+ assert_eq!(node.children().len(), 1);
+ assert_eq!(node.children()[0], child2);
+
+ node.remove_child_at_index(0);
+ assert_eq!(node.children().len(), 0);
+ }
+
+ #[test]
+ fn replace_child_at_index() {
+ let child1 = Node::new(Style::default(), vec![]);
+ let child2 = Node::new(Style::default(), vec![]);
+
+ let mut node = Node::new(Style::default(), vec![&child1]);
+ assert_eq!(node.children().len(), 1);
+ assert_eq!(node.children()[0], child1);
+
+ node.replace_child_at_index(0, &child2);
+ assert_eq!(node.children().len(), 1);
+ assert_eq!(node.children()[0], child2);
+ }
+
+ #[test]
+ fn set_children() {
+ let child1 = Node::new(Style::default(), vec![]);
+ let child2 = Node::new(Style::default(), vec![]);
+ let mut node = Node::new(Style::default(), vec![&child1, &child2]);
+
+ assert_eq!(node.children().len(), 2);
+ assert_eq!(node.children()[0], child1);
+ assert_eq!(node.children()[1], child2);
+
+ let child3 = Node::new(Style::default(), vec![]);
+ let child4 = Node::new(Style::default(), vec![]);
+ node.set_children(vec![&child3, &child4]);
+
+ assert_eq!(node.children().len(), 2);
+ assert_eq!(node.children()[0], child3);
+ assert_eq!(node.children()[1], child4);
+ }
+
+ #[test]
+ fn set_style() {
+ let mut node = Node::new(Style::default(), vec![]);
+ assert_eq!(node.style().display, Display::Flex);
+
+ node.set_style(Style { display: Display::None, ..Style::default() });
+ assert_eq!(node.style().display, Display::None);
+ }
+
+ #[test]
+ fn mark_dirty() {
+ let mut child1 = Node::new(Style::default(), vec![]);
+ let mut child2 = Node::new(Style::default(), vec![]);
+ let mut node = Node::new(Style::default(), vec![&child1, &child2]);
+
+ node.compute_layout(stretch::geometry::Size::undefined()).unwrap();
+
+ assert_eq!(child1.is_dirty(), false);
+ assert_eq!(child2.is_dirty(), false);
+ assert_eq!(node.is_dirty(), false);
+
+ node.mark_dirty();
+ assert_eq!(child1.is_dirty(), false);
+ assert_eq!(child2.is_dirty(), false);
+ assert_eq!(node.is_dirty(), true);
+
+ node.compute_layout(stretch::geometry::Size::undefined()).unwrap();
+ child1.mark_dirty();
+ assert_eq!(child1.is_dirty(), true);
+ assert_eq!(child2.is_dirty(), false);
+ assert_eq!(node.is_dirty(), true);
+ }
+}