Skip to content
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

Merged
merged 42 commits into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d6c3a1e
Deny missing docs :3
alice-i-cecile Jun 8, 2022
559ac6a
Module level docs
alice-i-cecile Jun 8, 2022
3065802
Merge branch 'main' into deny-missing-docs
alice-i-cecile Jun 8, 2022
6dfc13b
Document geometry.rs
alice-i-cecile Jun 8, 2022
851a7fd
Document layout.rs
alice-i-cecile Jun 8, 2022
37245f3
Document prelude.rs
alice-i-cecile Jun 8, 2022
b4c118d
Document lib.rs
alice-i-cecile Jun 8, 2022
3541aa5
Document node.rs
alice-i-cecile Jun 8, 2022
cce66c0
Document number.rs
alice-i-cecile Jun 8, 2022
82e478a
Partial docs for style.rs
alice-i-cecile Jun 9, 2022
ff8f13f
Warn that padding broken :(
alice-i-cecile Jun 9, 2022
058faa2
Add docs to forest.rs
alice-i-cecile Jun 9, 2022
0afc9bd
Merge branch 'main' into deny-missing-docs
alice-i-cecile Jun 9, 2022
75546cc
Fix typo
alice-i-cecile Jun 9, 2022
21c5fb5
Fix docs for geometry.rs
alice-i-cecile Jun 9, 2022
ac1a88c
Typo fix
alice-i-cecile Jun 9, 2022
f333976
Typo fix
alice-i-cecile Jun 9, 2022
59bea78
Revert non-exhaustive annotation
alice-i-cecile Jun 9, 2022
549ab65
Rename unclear method names on Rect
alice-i-cecile Jun 9, 2022
af8243e
Clarify wording of mark_dirty field
alice-i-cecile Jun 9, 2022
bb48a23
Clarify wording of mark_dirty field
alice-i-cecile Jun 9, 2022
acbc511
Use `parent` as the argument name over `node` in methods on `Forest`
alice-i-cecile Jun 9, 2022
467c465
index -> child_index
alice-i-cecile Jun 9, 2022
2ea5bad
Fix incorrect comment
alice-i-cecile Jun 9, 2022
806de4c
More docs for style.rs
alice-i-cecile Jun 9, 2022
2dcf858
Merge branch 'main' into deny-missing-docs
alice-i-cecile Jun 9, 2022
545330f
Fix merge error
alice-i-cecile Jun 9, 2022
98a7aed
Document JustifyContent
alice-i-cecile Jun 9, 2022
b461525
Merge branch 'main' into deny-missing-docs
alice-i-cecile Jun 9, 2022
ba44c89
Finish documenting style.rs
alice-i-cecile Jun 9, 2022
b870891
Small improvements to style.rs docs
alice-i-cecile Jun 9, 2022
3a33105
Typo fix
alice-i-cecile Jun 9, 2022
1a716b6
Merge branch 'main' into deny-missing-docs
alice-i-cecile Jun 9, 2022
6806b43
Document sys.rs
alice-i-cecile Jun 9, 2022
7e53765
Document more of forest.rs
alice-i-cecile Jun 9, 2022
8b2335d
Docs tweaks
alice-i-cecile Jun 10, 2022
ec7a460
Typos
alice-i-cecile Jun 10, 2022
410c807
Caching notes
alice-i-cecile Jun 10, 2022
cc72d0a
Merge remote-tracking branch 'origin/deny-missing-docs' into deny-mis…
alice-i-cecile Jun 10, 2022
d50fdd4
Merge branch 'main' into deny-missing-docs
alice-i-cecile Jun 10, 2022
dba84c8
Complete internal documentation
alice-i-cecile Jun 10, 2022
cb9ee01
Cargo fmt
alice-i-cecile Jun 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions src/flexbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ impl Forest {
};

let node_inner_size = Size {
width: node_size.width - padding_border.horizontal(),
height: node_size.height - padding_border.vertical(),
width: node_size.width - padding_border.horizontal_axis_sum(),
height: node_size.height - padding_border.vertical_axis_sum(),
};

let container_size = Size::zero();
Expand Down Expand Up @@ -274,10 +274,10 @@ impl Forest {
constants: &AlgoConstants,
) -> Size<Number> {
Size {
width: node_size.width.or_else(parent_size.width - constants.margin.horizontal())
- constants.padding_border.horizontal(),
height: node_size.height.or_else(parent_size.height - constants.margin.vertical())
- constants.padding_border.vertical(),
width: node_size.width.or_else(parent_size.width - constants.margin.horizontal_axis_sum())
- constants.padding_border.horizontal_axis_sum(),
height: node_size.height.or_else(parent_size.height - constants.margin.vertical_axis_sum())
- constants.padding_border.vertical_axis_sum(),
}
}

Expand Down Expand Up @@ -405,8 +405,9 @@ impl Forest {
// used min and max main sizes (and flooring the content box size at zero).

for child in flex_items {
child.inner_flex_basis =
child.flex_basis - child.padding.main(constants.dir) - child.border.main(constants.dir);
child.inner_flex_basis = child.flex_basis
- child.padding.main_axis_sum(constants.dir)
- child.border.main_axis_sum(constants.dir);

// TODO - not really spec abiding but needs to be done somewhere. probably somewhere else though.
// The following logic was developed not from the spec but by trail and error looking into how
Expand All @@ -427,7 +428,7 @@ impl Forest {

child.hypothetical_outer_size.set_main(
constants.dir,
child.hypothetical_inner_size.main(constants.dir) + child.margin.main(constants.dir),
child.hypothetical_inner_size.main(constants.dir) + child.margin.main_axis_sum(constants.dir),
);
}
}
Expand Down Expand Up @@ -544,9 +545,10 @@ impl Forest {
// TODO this should really only be set inside the if-statement below but
// that causes the target_main_size to never be set for some items

child
.outer_target_size
.set_main(constants.dir, child.target_size.main(constants.dir) + child.margin.main(constants.dir));
child.outer_target_size.set_main(
constants.dir,
child.target_size.main(constants.dir) + child.margin.main_axis_sum(constants.dir),
);

let child_style = &self.nodes[child.node].style;
if (child_style.flex_grow == 0.0 && child_style.flex_shrink == 0.0)
Expand All @@ -565,7 +567,7 @@ impl Forest {
.items
.iter()
.map(|child| {
child.margin.main(constants.dir)
child.margin.main_axis_sum(constants.dir)
+ if child.frozen { child.target_size.main(constants.dir) } else { child.flex_basis }
})
.sum();
Expand All @@ -592,7 +594,7 @@ impl Forest {
.items
.iter()
.map(|child| {
child.margin.main(constants.dir)
child.margin.main_axis_sum(constants.dir)
+ if child.frozen { child.target_size.main(constants.dir) } else { child.flex_basis }
})
.sum();
Expand Down Expand Up @@ -687,9 +689,10 @@ impl Forest {
let clamped = child.target_size.main(constants.dir).maybe_min(max_main).maybe_max(min_main).max(0.0);
child.violation = clamped - child.target_size.main(constants.dir);
child.target_size.set_main(constants.dir, clamped);
child
.outer_target_size
.set_main(constants.dir, child.target_size.main(constants.dir) + child.margin.main(constants.dir));
child.outer_target_size.set_main(
constants.dir,
child.target_size.main(constants.dir) + child.margin.main_axis_sum(constants.dir),
);

acc + child.violation
});
Expand Down Expand Up @@ -766,7 +769,7 @@ impl Forest {

child.hypothetical_outer_size.set_cross(
constants.dir,
child.hypothetical_inner_size.cross(constants.dir) + child.margin.cross(constants.dir),
child.hypothetical_inner_size.cross(constants.dir) + child.margin.cross_axis_sum(constants.dir),
);
}
}
Expand Down Expand Up @@ -860,7 +863,7 @@ impl Forest {
) {
if flex_lines.len() == 1 && node_size.cross(constants.dir).is_defined() {
flex_lines[0].cross_size =
(node_size.cross(constants.dir) - constants.padding_border.cross(constants.dir)).or_else(0.0);
(node_size.cross(constants.dir) - constants.padding_border.cross_axis_sum(constants.dir)).or_else(0.0);
} else {
for line in flex_lines.iter_mut() {
// 1. Collect all the flex items whose inline-axis is parallel to the main-axis, whose
Expand Down Expand Up @@ -915,7 +918,7 @@ impl Forest {
{
let total_cross: f32 = flex_lines.iter().map(|line| line.cross_size).sum();
let inner_cross =
(node_size.cross(constants.dir) - constants.padding_border.cross(constants.dir)).or_else(0.0);
(node_size.cross(constants.dir) - constants.padding_border.cross_axis_sum(constants.dir)).or_else(0.0);

if total_cross < inner_cross {
let remaining = inner_cross - total_cross;
Expand Down Expand Up @@ -950,7 +953,7 @@ impl Forest {
&& child_style.cross_margin_end(constants.dir) != Dimension::Auto
&& child_style.cross_size(constants.dir) == Dimension::Auto
{
(line_cross_size - child.margin.cross(constants.dir))
(line_cross_size - child.margin.cross_axis_sum(constants.dir))
.maybe_max(child.min_size.cross(constants.dir))
.maybe_min(child.max_size.cross(constants.dir))
} else {
Expand All @@ -960,7 +963,7 @@ impl Forest {

child.outer_target_size.set_cross(
constants.dir,
child.target_size.cross(constants.dir) + child.margin.cross(constants.dir),
child.target_size.cross(constants.dir) + child.margin.cross_axis_sum(constants.dir),
);
}
}
Expand Down Expand Up @@ -1213,12 +1216,14 @@ impl Forest {

constants.container_size.set_cross(
constants.dir,
node_size.cross(constants.dir).or_else(total_cross_size + constants.padding_border.cross(constants.dir)),
node_size
.cross(constants.dir)
.or_else(total_cross_size + constants.padding_border.cross_axis_sum(constants.dir)),
);

constants.inner_container_size.set_cross(
constants.dir,
constants.container_size.cross(constants.dir) - constants.padding_border.cross(constants.dir),
constants.container_size.cross(constants.dir) - constants.padding_border.cross_axis_sum(constants.dir),
);

total_cross_size
Expand Down Expand Up @@ -1331,7 +1336,7 @@ impl Forest {
};

total_offset_main +=
child.offset_main + child.margin.main(constants.dir) + result.size.main(constants.dir);
child.offset_main + child.margin.main_axis_sum(constants.dir) + result.size.main(constants.dir);
};

if constants.dir.is_reverse() {
Expand Down Expand Up @@ -1534,8 +1539,8 @@ impl Forest {

return ComputeResult {
size: Size {
width: node_size.width.or_else(0.0) + constants.padding_border.horizontal(),
height: node_size.height.or_else(0.0) + constants.padding_border.vertical(),
width: node_size.width.or_else(0.0) + constants.padding_border.horizontal_axis_sum(),
height: node_size.height.or_else(0.0) + constants.padding_border.vertical_axis_sum(),
},
};
}
Expand Down Expand Up @@ -1580,7 +1585,7 @@ impl Forest {
acc.max(length)
});

let size = longest_line + constants.padding_border.main(constants.dir);
let size = longest_line + constants.padding_border.main_axis_sum(constants.dir);
match available_space.main(constants.dir) {
Defined(val) if flex_lines.len() > 1 && size < val => val,
_ => size,
Expand All @@ -1590,7 +1595,7 @@ impl Forest {

constants.inner_container_size.set_main(
constants.dir,
constants.container_size.main(constants.dir) - constants.padding_border.main(constants.dir),
constants.container_size.main(constants.dir) - constants.padding_border.main_axis_sum(constants.dir),
);

// 9.4. Cross Size Determination
Expand Down
68 changes: 48 additions & 20 deletions src/forest.rs
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;
Expand All @@ -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)
Copy link
Collaborator

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)

Copy link
Collaborator Author

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.

///
/// Stored in a [`Forest`].
pub(crate) struct NodeData {
pub(crate) style: Style,
pub(crate) measure: Option<MeasureFunc>,
Expand All @@ -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,
Expand All @@ -29,6 +33,8 @@ impl NodeData {
}
}

/// Create the data for a new node
// TODO: why is this different from new_leaf?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't allow to provide a MeasureFunc, while new_leaf does.
If we want to change something here I think we should also create an issue such that the TODO isn't buried in the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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,
Expand All @@ -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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that you changed this from pub to pub(crate), is this a breaking change? To be honest, this crate is the first time I have ever seen pub(crate) so I'm not entirely sure what it does.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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.

pub(crate) says "anything within this crate can use this type, but nothing else". pub(super) is the other variant you might run across, which restricts visibility to the parent module.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(pub(crate) would be somewhat similar to internal in C# if you are familiar with that, @TimJentzsch)

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);
Expand All @@ -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`.
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
}
}
Loading