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

proposal for custom layout solvers #648

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 2 additions & 4 deletions examples/custom_tree_owned_partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,8 @@ impl Iterator for ChildIter {
}

impl taffy::TraversePartialTree for Node {
type ChildIter<'a> = ChildIter;

fn child_ids(&self, _node_id: NodeId) -> Self::ChildIter<'_> {
ChildIter(0..self.children.len())
fn child_ids<'a>(&'a self, _node_id: NodeId) -> Box<dyn Iterator<Item = NodeId> + 'a> {
Box::new(ChildIter(0..self.children.len()))
}

fn child_count(&self, _node_id: NodeId) -> usize {
Expand Down
6 changes: 2 additions & 4 deletions examples/custom_tree_owned_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,8 @@ unsafe fn node_from_id_mut<'a>(node_id: NodeId) -> &'a mut Node {

struct StatelessLayoutTree;
impl TraversePartialTree for StatelessLayoutTree {
type ChildIter<'a> = ChildIter<'a>;

fn child_ids(&self, node_id: NodeId) -> Self::ChildIter<'_> {
unsafe { ChildIter(node_from_id(node_id).children.iter()) }
fn child_ids<'a>(&'a self, node_id: NodeId) -> Box<dyn Iterator<Item = NodeId> + 'a> {
Box::new(unsafe { ChildIter(node_from_id(node_id).children.iter()) })
}

fn child_count(&self, node_id: NodeId) -> usize {
Expand Down
6 changes: 2 additions & 4 deletions examples/custom_tree_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,8 @@ impl<'a> Iterator for ChildIter<'a> {
}

impl taffy::TraversePartialTree for Tree {
type ChildIter<'a> = ChildIter<'a>;

fn child_ids(&self, node_id: NodeId) -> Self::ChildIter<'_> {
ChildIter(self.node_from_id(node_id).children.iter())
fn child_ids<'a>(&'a self, node_id: NodeId) -> Box<dyn Iterator<Item = NodeId> + 'a> {
Box::new(ChildIter(self.node_from_id(node_id).children.iter()))
}

fn child_count(&self, node_id: NodeId) -> usize {
Expand Down
12 changes: 12 additions & 0 deletions src/style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ pub enum Display {
/// The children will follow the CSS Grid layout algorithm
#[cfg(feature = "grid")]
Grid,
/// The children will follow the algorithm provided by the user
Custom {
/// name for this custom display
name: &'static str,
/// solver for this custom display
solver: fn(
tree: Box<&mut dyn crate::LayoutPartialTree>,
node: crate::NodeId,
inputs: crate::LayoutInput,
) -> crate::LayoutOutput,
},
/// The children will not be laid out, and will follow absolute positioning
None,
}
Expand Down Expand Up @@ -76,6 +87,7 @@ impl core::fmt::Display for Display {
Display::Flex => write!(f, "FLEX"),
#[cfg(feature = "grid")]
Display::Grid => write!(f, "GRID"),
Display::Custom { name, .. } => write!(f, "{name}"),
}
}
}
Expand Down
14 changes: 6 additions & 8 deletions src/tree/taffy_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,9 @@ impl<'a> Iterator for TaffyTreeChildIter<'a> {

// TraversePartialTree impl for TaffyTree
impl<NodeContext> TraversePartialTree for TaffyTree<NodeContext> {
type ChildIter<'a> = TaffyTreeChildIter<'a> where Self: 'a;

#[inline(always)]
fn child_ids(&self, parent_node_id: NodeId) -> Self::ChildIter<'_> {
TaffyTreeChildIter(self.children[parent_node_id.into()].iter())
fn child_ids<'a>(&'a self, parent_node_id: NodeId) -> Box<dyn Iterator<Item = NodeId> + 'a> {
Box::new(TaffyTreeChildIter(self.children[parent_node_id.into()].iter()))
}

#[inline(always)]
Expand Down Expand Up @@ -207,6 +205,7 @@ impl<NodeContext> PrintTree for TaffyTree<NodeContext> {
}
#[cfg(feature = "grid")]
(_, Display::Grid) => "GRID",
(_, Display::Custom { name, .. }) => name,
}
}

Expand Down Expand Up @@ -234,11 +233,9 @@ impl<'t, NodeContext, MeasureFunction> TraversePartialTree for TaffyView<'t, Nod
where
MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
{
type ChildIter<'a> = TaffyTreeChildIter<'a> where Self: 'a;

#[inline(always)]
fn child_ids(&self, parent_node_id: NodeId) -> Self::ChildIter<'_> {
self.taffy.child_ids(parent_node_id)
fn child_ids<'a>(&'a self, parent_node_id: NodeId) -> Box<dyn Iterator<Item = NodeId> + 'a> {
Box::new(self.taffy.child_ids(parent_node_id))
}

#[inline(always)]
Expand Down Expand Up @@ -314,6 +311,7 @@ where
(Display::Flex, true) => compute_flexbox_layout(tree, node, inputs),
#[cfg(feature = "grid")]
(Display::Grid, true) => compute_grid_layout(tree, node, inputs),
(Display::Custom { solver, .. }, true) => solver(Box::new(tree), node, inputs),
(_, false) => {
let node_key = node.into();
let style = &tree.taffy.nodes[node_key].style;
Expand Down
7 changes: 1 addition & 6 deletions src/tree/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,8 @@ use crate::style::{AvailableSpace, Style};
/// This trait is Taffy's abstraction for downward tree traversal.
/// However, this trait does *not* require access to any node's other than a single container node's immediate children unless you also intend to implement `TraverseTree`.
pub trait TraversePartialTree {
/// Type representing an iterator of the children of a node
type ChildIter<'a>: Iterator<Item = NodeId>
where
Self: 'a;

/// Get the list of children IDs for the given node
fn child_ids(&self, parent_node_id: NodeId) -> Self::ChildIter<'_>;
fn child_ids<'a>(&'a self, parent_node_id: NodeId) -> Box<dyn Iterator<Item = NodeId> + 'a>;

/// Get the number of children for the given node
fn child_count(&self, parent_node_id: NodeId) -> usize;
Expand Down
Loading