gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 501HTML 254C 19JavaScript 81412 Definitions

⎇ a26a7d4db504ae855ff17373114a23981a726f5e src/node.rs Rust · 162 lines · 4.6 KB History Who touched what raw

Add unit tests for node api a26a7d4db · Emil Sjölander ·

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