Load of small fixes, updates API, and added tests
1#[cfg(not(feature = "std"))]
2use alloc::{vec, vec::Vec};
3
4use std::cell::RefCell;
5use std::fmt;
6use std::rc::Rc;
7use std::rc::Weak;
8
9use crate::algo;
10use crate::geometry::Size;
11use crate::number::Number;
12use crate::result::{Cache, Layout, Result};
13use crate::style::*;
14
15type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>>>;
16
17pub(crate) struct InternalNode {
18 pub(crate) style: Style,
19 pub(crate) parents: Vec<Weak<RefCell<InternalNode>>>,
20 pub(crate) children: Vec<Rc<RefCell<InternalNode>>>,
21 pub(crate) measure: Option<MeasureFunc>,
22 pub(crate) layout_cache: Option<Cache>,
23 pub(crate) is_dirty: bool,
24}
25
26pub struct Node(Rc<RefCell<InternalNode>>);
27
28impl Node {
29 pub fn new_leaf(style: Style, measure: MeasureFunc) -> Node {
30 Node(Rc::new(RefCell::new(InternalNode {
31 style,
32 parents: Vec::with_capacity(1),
33 children: Vec::with_capacity(0),
34 measure: Some(measure),
35 layout_cache: None,
36 is_dirty: true,
37 })))
38 }
39
40 pub fn new(style: Style, children: Vec<&Node>) -> Node {
41 let parent = Node(Rc::new(RefCell::new(InternalNode {
42 style,
43 parents: Vec::with_capacity(1),
44 children: Vec::with_capacity(children.len()),
45 measure: None,
46 layout_cache: None,
47 is_dirty: true,
48 })));
49
50 for child in children {
51 child.0.borrow_mut().parents.push(Rc::downgrade(&parent.0));
52 parent.0.borrow_mut().children.push(Rc::clone(&child.0));
53 }
54
55 parent
56 }
57
58 pub fn set_measure(&mut self, measure: Option<MeasureFunc>) {
59 self.0.borrow_mut().measure = measure;
60 self.mark_dirty();
61 }
62
63 pub fn add_child(&mut self, child: &Node) {
64 child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
65 self.0.borrow_mut().children.push(Rc::clone(&child.0));
66 self.mark_dirty();
67 }
68
69 pub fn set_children(&mut self, children: Vec<&Node>) {
70 for child in &self.0.borrow().children {
71 let position =
72 child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
73 child.borrow_mut().parents.remove(position);
74 }
75
76 self.0.borrow_mut().children = Vec::with_capacity(children.len());
77
78 for child in children {
79 child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
80 self.0.borrow_mut().children.push(Rc::clone(&child.0));
81 }
82
83 self.mark_dirty();
84 }
85
86 pub fn remove_child(&mut self, child: &Node) -> Node {
87 self.remove_child_at_index({
88 let parent = self.0.borrow();
89 parent.children.iter().position(|x| Rc::ptr_eq(&x, &child.0)).unwrap()
90 })
91 }
92
93 pub fn remove_child_at_index(&mut self, index: usize) -> Node {
94 let child = {
95 let mut parent = self.0.borrow_mut();
96 let child = parent.children.remove(index);
97 let position =
98 child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
99 child.borrow_mut().parents.remove(position);
100 child
101 };
102
103 self.mark_dirty();
104 Node(child)
105 }
106
107 pub fn replace_child_at_index(&mut self, index: usize, child: &Node) -> Node {
108 child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
109 let old_child = std::mem::replace(&mut self.0.borrow_mut().children[index], Rc::clone(&child.0));
110
111 let position =
112 old_child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
113 old_child.borrow_mut().parents.remove(position);
114
115 self.mark_dirty();
116
117 Node(old_child)
118 }
119
120 pub fn children(&self) -> Vec<Node> {
121 let node = self.0.borrow_mut();
122 node.children.iter().map(|child| Node(Rc::clone(child))).collect()
123 }
124
125 pub fn child_count(&self) -> usize {
126 let node = self.0.borrow_mut();
127 node.children.len()
128 }
129
130 pub fn set_style(&mut self, style: Style) {
131 self.0.borrow_mut().style = style;
132 self.mark_dirty();
133 }
134
135 pub fn style(&self) -> Style {
136 self.0.borrow().style
137 }
138
139 pub fn mark_dirty(&mut self) {
140 let mut node = self.0.borrow_mut();
141 node.layout_cache = None;
142 node.is_dirty = true;
143
144 for parent in &node.parents {
145 if let Some(parent) = parent.upgrade() {
146 Node(parent).mark_dirty();
147 }
148 }
149 }
150
151 pub fn dirty(&self) -> bool {
152 self.0.borrow().is_dirty
153 }
154
155 pub fn compute_layout(&self, size: Size<Number>) -> Result<Layout> {
156 algo::compute(&mut self.0.borrow_mut(), size)
157 }
158}
159
160impl fmt::Debug for Node {
161 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162 let style = &self.0.borrow().style;
163 let children: Vec<_> = self.0.borrow().children.iter().map(|c| Node(Rc::clone(c))).collect();
164 write!(f, "Node {{ style: {:?}, children: {:?} }}", style, children)
165 }
166}
167
168impl PartialEq for Node {
169 fn eq(&self, other: &Node) -> bool {
170 Rc::ptr_eq(&self.0, &other.0)
171 }
172}
173
174impl Eq for Node {}