gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definitions

⎇ 8de95f09cab31cdf16888d276aa042613f80820d src/node.rs Rust · 250 lines · 7.7 KB History Who touched what raw

Add `#[must_use]` to all static methods (#125) 8de95f09c · Andreas Weibye ·

1use crate::forest::Forest;
2use crate::geometry::Size;
3use crate::layout::Layout;
4use crate::number::Number;
5use crate::style::Style;
6#[cfg(any(feature = "std", feature = "alloc"))]
7use crate::sys::Box;
8use crate::sys::{new_map_with_capacity, ChildrenVec, Map, Vec};
9use crate::Error;
10use core::sync::atomic::{AtomicUsize, Ordering};
11
12pub enum MeasureFunc {
13    Raw(fn(Size<Number>) -> Size<f32>),
14    #[cfg(any(feature = "std", feature = "alloc"))]
15    Boxed(Box<dyn Fn(Size<Number>) -> Size<f32>>),
16}
17
18/// Global sprawl instance id allocator.
19static INSTANCE_ALLOCATOR: Allocator = Allocator::new();
20
21#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
22#[cfg_attr(not(any(feature = "std", feature = "alloc")), derive(hash32_derive::Hash32))]
23pub struct Node {
24    instance: Id,
25    local: Id,
26}
27
28pub struct Sprawl {
29    id: Id,
30    nodes: Allocator,
31    nodes_to_ids: Map<Node, NodeId>,
32    ids_to_nodes: Map<NodeId, Node>,
33    forest: Forest,
34}
35
36impl Default for Sprawl {
37    fn default() -> Self {
38        Self::with_capacity(16)
39    }
40}
41
42impl Sprawl {
43    #[must_use]
44    pub fn new() -> Self {
45        Default::default()
46    }
47
48    pub fn with_capacity(capacity: usize) -> Self {
49        Self {
50            id: INSTANCE_ALLOCATOR.allocate(),
51            nodes: Allocator::new(),
52            nodes_to_ids: new_map_with_capacity(capacity),
53            ids_to_nodes: new_map_with_capacity(capacity),
54            forest: Forest::with_capacity(capacity),
55        }
56    }
57
58    fn allocate_node(&mut self) -> Node {
59        let local = self.nodes.allocate();
60        Node { instance: self.id, local }
61    }
62
63    fn add_node(&mut self, node: Node, id: NodeId) {
64        let _ = self.nodes_to_ids.insert(node, id);
65        let _ = self.ids_to_nodes.insert(id, node);
66    }
67
68    // Find node in the forest.
69    fn find_node(&self, node: Node) -> Result<NodeId, Error> {
70        match self.nodes_to_ids.get(&node) {
71            Some(id) => Ok(*id),
72            None => Err(Error::InvalidNode(node)),
73        }
74    }
75
76    pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> Result<Node, Error> {
77        let node = self.allocate_node();
78        let id = self.forest.new_leaf(style, measure);
79        self.add_node(node, id);
80        Ok(node)
81    }
82
83    pub fn new_node(&mut self, style: Style, children: &[Node]) -> Result<Node, Error> {
84        let node = self.allocate_node();
85        let children =
86            children.iter().map(|child| self.find_node(*child)).collect::<Result<ChildrenVec<_>, Error>>()?;
87        let id = self.forest.new_node(style, children);
88        self.add_node(node, id);
89        Ok(node)
90    }
91
92    /// Removes all nodes.
93    ///
94    /// All associated nodes will be invalid.
95    pub fn clear(&mut self) {
96        self.nodes_to_ids.clear();
97        self.ids_to_nodes.clear();
98        self.forest.clear();
99    }
100
101    /// Remove nodes.
102    pub fn remove(&mut self, node: Node) {
103        let id = if let Ok(id) = self.find_node(node) { id } else { return };
104
105        self.nodes_to_ids.remove(&node);
106        self.ids_to_nodes.remove(&id);
107
108        if let Some(new_id) = self.forest.swap_remove(id) {
109            let new = self.ids_to_nodes.remove(&new_id).unwrap();
110            let _ = self.nodes_to_ids.insert(new, id);
111            let _ = self.ids_to_nodes.insert(id, new);
112        }
113    }
114
115    pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), Error> {
116        let id = self.find_node(node)?;
117        self.forest.nodes[id].measure = measure;
118        self.forest.mark_dirty(id);
119        Ok(())
120    }
121
122    pub fn add_child(&mut self, parent: Node, child: Node) -> Result<(), Error> {
123        let node_id = self.find_node(parent)?;
124        let child_id = self.find_node(child)?;
125
126        self.forest.add_child(node_id, child_id);
127        Ok(())
128    }
129
130    pub fn set_children(&mut self, parent: Node, children: &[Node]) -> Result<(), Error> {
131        let node_id = self.find_node(parent)?;
132        let children_id = children.iter().map(|child| self.find_node(*child)).collect::<Result<ChildrenVec<_>, _>>()?;
133
134        // Remove node as parent from all its current children.
135        for child in &self.forest.children[node_id] {
136            self.forest.parents[*child].retain(|p| *p != node_id);
137        }
138
139        // Build up relation node <-> child
140        for child in &children_id {
141            self.forest.parents[*child].push(node_id);
142        }
143        self.forest.children[node_id] = children_id;
144
145        self.forest.mark_dirty(node_id);
146        Ok(())
147    }
148
149    pub fn remove_child(&mut self, parent: Node, child: Node) -> Result<Node, Error> {
150        let node_id = self.find_node(parent)?;
151        let child_id = self.find_node(child)?;
152
153        let prev_id = self.forest.remove_child(node_id, child_id);
154        Ok(self.ids_to_nodes[&prev_id])
155    }
156
157    pub fn remove_child_at_index(&mut self, parent: Node, child_index: usize) -> Result<Node, Error> {
158        let node_id = self.find_node(parent)?;
159        // TODO: index check
160
161        let prev_id = self.forest.remove_child_at_index(node_id, child_index);
162        Ok(self.ids_to_nodes[&prev_id])
163    }
164
165    pub fn replace_child_at_index(&mut self, parent: Node, child_index: usize, new_child: Node) -> Result<Node, Error> {
166        let node_id = self.find_node(parent)?;
167        let child_id = self.find_node(new_child)?;
168        // TODO: index check
169
170        self.forest.parents[child_id].push(node_id);
171        let old_child = core::mem::replace(&mut self.forest.children[node_id][child_index], child_id);
172        self.forest.parents[old_child].retain(|p| *p != node_id);
173
174        self.forest.mark_dirty(node_id);
175
176        Ok(self.ids_to_nodes[&old_child])
177    }
178
179    pub fn children(&self, parent: Node) -> Result<Vec<Node>, Error> {
180        let id = self.find_node(parent)?;
181        Ok(self.forest.children[id].iter().map(|child| self.ids_to_nodes[child]).collect())
182    }
183
184    pub fn child_at_index(&self, parent: Node, child_index: usize) -> Result<Node, Error> {
185        let id = self.find_node(parent)?;
186        Ok(self.ids_to_nodes[&self.forest.children[id][child_index]])
187    }
188
189    pub fn child_count(&self, parent: Node) -> Result<usize, Error> {
190        let id = self.find_node(parent)?;
191        Ok(self.forest.children[id].len())
192    }
193
194    pub fn set_style(&mut self, node: Node, style: Style) -> Result<(), Error> {
195        let id = self.find_node(node)?;
196        self.forest.nodes[id].style = style;
197        self.forest.mark_dirty(id);
198        Ok(())
199    }
200
201    pub fn style(&self, node: Node) -> Result<&Style, Error> {
202        let id = self.find_node(node)?;
203        Ok(&self.forest.nodes[id].style)
204    }
205
206    /// Return this node layout relative to its parent
207    pub fn layout(&self, node: Node) -> Result<&Layout, Error> {
208        let id = self.find_node(node)?;
209        Ok(&self.forest.nodes[id].layout)
210    }
211
212    pub fn mark_dirty(&mut self, node: Node) -> Result<(), Error> {
213        let id = self.find_node(node)?;
214        self.forest.mark_dirty(id);
215        Ok(())
216    }
217
218    pub fn dirty(&self, node: Node) -> Result<bool, Error> {
219        let id = self.find_node(node)?;
220        Ok(self.forest.nodes[id].is_dirty)
221    }
222
223    pub fn compute_layout(&mut self, node: Node, size: Size<Number>) -> Result<(), Error> {
224        let id = self.find_node(node)?;
225        self.forest.compute_layout(id, size);
226        Ok(())
227    }
228}
229
230/// Internal node id.
231pub(crate) type NodeId = usize;
232
233#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
234#[cfg_attr(not(any(feature = "std", feature = "alloc")), derive(hash32_derive::Hash32))]
235pub(crate) struct Id(usize);
236
237pub(crate) struct Allocator {
238    new_id: AtomicUsize,
239}
240
241impl Allocator {
242    #[must_use]
243    pub const fn new() -> Self {
244        Self { new_id: AtomicUsize::new(0) }
245    }
246
247    pub fn allocate(&self) -> Id {
248        Id(self.new_id.fetch_add(1, Ordering::Relaxed))
249    }
250}