Minor optimizations in node allocation
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: RefCell<Option<Cache>>,
23}
24
25pub struct Node(Rc<RefCell<InternalNode>>);
26
27impl Node {
28 pub fn new_leaf(style: Style, measure: Option<MeasureFunc>) -> Node {
29 Node(Rc::new(RefCell::new(InternalNode {
30 style,
31 parents: Vec::with_capacity(1),
32 children: Vec::with_capacity(0),
33 measure,
34 layout_cache: RefCell::new(None),
35 })))
36 }
37
38 pub fn new(style: Style, children: Vec<&Node>) -> Node {
39 let parent = Node(Rc::new(RefCell::new(InternalNode {
40 style,
41 parents: Vec::with_capacity(1),
42 children: Vec::with_capacity(children.len()),
43 measure: None,
44 layout_cache: RefCell::new(None),
45 })));
46
47 for child in children {
48 child.0.borrow_mut().parents.push(Rc::downgrade(&parent.0));
49 parent.0.borrow_mut().children.push(Rc::clone(&child.0));
50 }
51
52 parent
53 }
54
55 pub fn add_child(&mut self, child: &Node) {
56 child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
57 self.0.borrow_mut().children.push(Rc::clone(&child.0));
58 self.mark_dirty();
59 }
60
61 pub fn set_children(&mut self, children: Vec<&Node>) {
62 for child in &self.0.borrow().children {
63 let position =
64 child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
65 child.borrow_mut().parents.remove(position);
66 }
67
68 self.0.borrow_mut().children = Vec::with_capacity(children.len());
69
70 for child in children {
71 child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
72 self.0.borrow_mut().children.push(Rc::clone(&child.0));
73 }
74
75 self.mark_dirty();
76 }
77
78 pub fn remove_child(&mut self, child: &Node) -> Node {
79 self.remove_child_at_index({
80 let parent = self.0.borrow();
81 parent.children.iter().position(|x| Rc::ptr_eq(&x, &child.0)).unwrap()
82 })
83 }
84
85 pub fn remove_child_at_index(&mut self, index: usize) -> Node {
86 let child = {
87 let mut parent = self.0.borrow_mut();
88 let child = parent.children.remove(index);
89 let position =
90 child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
91 child.borrow_mut().parents.remove(position);
92 child
93 };
94
95 self.mark_dirty();
96 Node(child)
97 }
98
99 pub fn replace_child_at_index(&mut self, index: usize, child: &Node) -> Node {
100 child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
101 let old_child = std::mem::replace(&mut self.0.borrow_mut().children[index], Rc::clone(&child.0));
102
103 let position =
104 old_child.borrow().parents.iter().position(|x| Rc::ptr_eq(&x.upgrade().unwrap(), &self.0)).unwrap();
105 old_child.borrow_mut().parents.remove(position);
106
107 self.mark_dirty();
108
109 Node(old_child)
110 }
111
112 pub fn children(&self) -> Vec<Node> {
113 let node = self.0.borrow_mut();
114 node.children.iter().map(|child| Node(Rc::clone(child))).collect()
115 }
116
117 pub fn set_style(&mut self, style: Style) {
118 self.0.borrow_mut().style = style;
119 self.mark_dirty();
120 }
121
122 pub fn style(&self) -> Style {
123 self.0.borrow().style
124 }
125
126 pub fn mark_dirty(&mut self) {
127 let node = self.0.borrow_mut();
128 node.layout_cache.replace(None);
129
130 for parent in &node.parents {
131 if let Some(parent) = parent.upgrade() {
132 Node(parent).mark_dirty();
133 }
134 }
135 }
136
137 pub fn is_dirty(&mut self) -> bool {
138 let node = self.0.borrow();
139 let layout_cache = node.layout_cache.borrow();
140 if let Some(_) = layout_cache.as_ref() {
141 false
142 } else {
143 true
144 }
145 }
146
147 pub fn compute_layout(&self, size: Size<Number>) -> Result<Layout> {
148 algo::compute(&self.0.borrow(), size)
149 }
150}
151
152impl fmt::Debug for Node {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 let style = &self.0.borrow().style;
155 let children: Vec<_> = self.0.borrow().children.iter().map(|c| Node(Rc::clone(c))).collect();
156 write!(f, "Node {{ style: {:?}, children: {:?} }}", style, children)
157 }
158}
159
160impl PartialEq for Node {
161 fn eq(&self, other: &Node) -> bool {
162 Rc::ptr_eq(&self.0, &other.0)
163 }
164}
165
166impl Eq for Node {}