-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document entire crate #96
Changes from 30 commits
d6c3a1e
559ac6a
3065802
6dfc13b
851a7fd
37245f3
b4c118d
3541aa5
cce66c0
82e478a
ff8f13f
058faa2
0afc9bd
75546cc
21c5fb5
ac1a88c
f333976
59bea78
549ab65
af8243e
bb48a23
acbc511
467c465
2ea5bad
806de4c
2dcf858
545330f
98a7aed
b461525
ba44c89
b870891
3a33105
1a716b6
6806b43
7e53765
8b2335d
ec7a460
410c807
cc72d0a
d50fdd4
dba84c8
cb9ee01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
//! Forest - ECS like datastructure for storing node trees. | ||
//! Forest - a struct-of-arrays data structure for storing node trees. | ||
//! | ||
//! Backing datastructure for `Sprawl` structs. | ||
use crate::geometry::Size; | ||
|
@@ -8,6 +8,9 @@ use crate::number::Number; | |
use crate::style::Style; | ||
use crate::sys::{new_vec_with_capacity, ChildrenVec, ParentsVec, Vec}; | ||
|
||
/// Layout information for a given [`Node`](crate::node::Node) | ||
/// | ||
/// Stored in a [`Forest`]. | ||
pub(crate) struct NodeData { | ||
pub(crate) style: Style, | ||
pub(crate) measure: Option<MeasureFunc>, | ||
|
@@ -18,6 +21,7 @@ pub(crate) struct NodeData { | |
} | ||
|
||
impl NodeData { | ||
/// Create the data for a new leaf node | ||
fn new_leaf(style: Style, measure: MeasureFunc) -> Self { | ||
Self { | ||
style, | ||
|
@@ -29,6 +33,8 @@ impl NodeData { | |
} | ||
} | ||
|
||
/// Create the data for a new node | ||
// TODO: why is this different from new_leaf? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function doesn't allow to provide a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. I think that MeasureFunc is just a bad design, TBH. |
||
fn new(style: Style) -> Self { | ||
Self { | ||
style, | ||
|
@@ -51,30 +57,34 @@ impl NodeData { | |
} | ||
} | ||
|
||
/// A collection of UI layout trees used to store [`NodeData`] associated with specific [`Nodes`](crate::node::Node) | ||
pub(crate) struct Forest { | ||
pub(crate) nodes: Vec<NodeData>, | ||
pub(crate) children: Vec<ChildrenVec<NodeId>>, | ||
pub(crate) parents: Vec<ParentsVec<NodeId>>, | ||
} | ||
|
||
impl Forest { | ||
pub fn with_capacity(capacity: usize) -> Self { | ||
/// Creates a new [`Forest`] that can store up to `capacity` [`Nodes`](crate::node::Node) before needing to be expanded | ||
pub(crate) fn with_capacity(capacity: usize) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that you changed this from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it's not. The type is not public, so the method cannot be used outside the crate anyways.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ( |
||
Self { | ||
nodes: new_vec_with_capacity(capacity), | ||
children: new_vec_with_capacity(capacity), | ||
parents: new_vec_with_capacity(capacity), | ||
} | ||
} | ||
|
||
pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> NodeId { | ||
/// Adds a new unattached leaf node to the forest, and returns the [`NodeId`] of the new node | ||
pub(crate) fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> NodeId { | ||
let id = self.nodes.len(); | ||
self.nodes.push(NodeData::new_leaf(style, measure)); | ||
self.children.push(new_vec_with_capacity(0)); | ||
self.parents.push(new_vec_with_capacity(1)); | ||
id | ||
} | ||
|
||
pub fn new_node(&mut self, style: Style, children: ChildrenVec<NodeId>) -> NodeId { | ||
/// Adds a new unparented node to the forest with the associated children attached, and returns the [`NodeId`] of the new node | ||
pub(crate) fn new_node(&mut self, style: Style, children: ChildrenVec<NodeId>) -> NodeId { | ||
let id = self.nodes.len(); | ||
for child in &children { | ||
self.parents[*child].push(id); | ||
|
@@ -85,20 +95,27 @@ impl Forest { | |
id | ||
} | ||
|
||
pub fn add_child(&mut self, node: NodeId, child: NodeId) { | ||
self.parents[child].push(node); | ||
self.children[node].push(child); | ||
self.mark_dirty(node) | ||
/// Adds a `child` node to the `parent` node | ||
pub(crate) fn add_child(&mut self, parent: NodeId, child: NodeId) { | ||
self.parents[child].push(parent); | ||
self.children[parent].push(child); | ||
self.mark_dirty(parent) | ||
} | ||
|
||
pub fn clear(&mut self) { | ||
/// Removes all nodes and resets the data structure | ||
/// | ||
/// The capacity is retained. | ||
pub(crate) fn clear(&mut self) { | ||
self.nodes.clear(); | ||
self.children.clear(); | ||
self.parents.clear(); | ||
} | ||
|
||
/// Removes a node and swaps with the last node. | ||
pub fn swap_remove(&mut self, node: NodeId) -> Option<NodeId> { | ||
/// Removes the specified `node` | ||
/// | ||
/// The last existing node is moved to its previous position, in order to ensure compactness. | ||
/// Returns the previous [`NodeId`] of the moved node, if one was moved. | ||
pub(crate) fn swap_remove(&mut self, node: NodeId) -> Option<NodeId> { | ||
self.nodes.swap_remove(node); | ||
|
||
// Now the last element is swapped in at index `node`. | ||
|
@@ -166,19 +183,28 @@ impl Forest { | |
} | ||
} | ||
|
||
pub fn remove_child(&mut self, node: NodeId, child: NodeId) -> NodeId { | ||
let index = self.children[node].iter().position(|n| *n == child).unwrap(); | ||
self.remove_child_at_index(node, index) | ||
/// Breaks the link between the `parent` node and the `child` node | ||
/// | ||
/// The `child`'s data is not removed. | ||
pub(crate) fn remove_child(&mut self, parent: NodeId, child: NodeId) -> NodeId { | ||
let index = self.children[parent].iter().position(|n| *n == child).unwrap(); | ||
self.remove_child_at_index(parent, index) | ||
} | ||
|
||
pub fn remove_child_at_index(&mut self, node: NodeId, index: usize) -> NodeId { | ||
let child = self.children[node].remove(index); | ||
self.parents[child].retain(|p| *p != node); | ||
self.mark_dirty(node); | ||
/// Breaks the link between the `parent` node and the n-th child node | ||
/// | ||
/// The child's data is not removed. | ||
pub(crate) fn remove_child_at_index(&mut self, parent: NodeId, child_index: usize) -> NodeId { | ||
let child = self.children[parent].remove(child_index); | ||
self.parents[child].retain(|p| *p != parent); | ||
self.mark_dirty(parent); | ||
child | ||
} | ||
|
||
pub fn mark_dirty(&mut self, node: NodeId) { | ||
/// Marks the `node` as needing layout recalculation | ||
/// | ||
/// Any cached layout information is cleared. | ||
alice-i-cecile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub(crate) fn mark_dirty(&mut self, node: NodeId) { | ||
// Performs a recursive depth-first search up the tree until the root node is reached | ||
// WARNING: this will stack-overflow if the tree contains a cycle | ||
fn mark_dirty_recursive(nodes: &mut Vec<NodeData>, parents: &[ParentsVec<NodeId>], node_id: NodeId) { | ||
|
@@ -192,7 +218,9 @@ impl Forest { | |
mark_dirty_recursive(&mut self.nodes, &self.parents, node); | ||
} | ||
|
||
pub fn compute_layout(&mut self, node: NodeId, size: Size<Number>) { | ||
/// Computes the layout of the `node` and its children | ||
pub(crate) fn compute_layout(&mut self, node: NodeId, size: Size<Number>) { | ||
// TODO: It's not clear why this method is distinct | ||
alice-i-cecile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.compute(node, size) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the smallest nit, but I noticed that you do not include a full stop at the end of the first line of the doc comments, but I did in
flexbox.rs
. Are there style guidelines/conventions for this in Rust? Do we care enough to make this consistent? (If not it's totally fine to ignore)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't care enough right now; if you'd like feel free to put together a style guide PR.