gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 709HTML 662Markdown 12TOML 62348 Sutichaykuna

⎇ 7c39d8dd65971d6517551920c8fbe7ac52fc23eb src/node.rs Rust · 174 siq'ikuna · 5.1 KB Ñawpa willay Pi imata llamkarqan ch'uya

Load of small fixes, updates API, and added tests af085fac4 · 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: 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 {}