polyhorn-layout 0.2.0

Abstraction over flexbox layout algorithms.
Documentation
use polyhorn_ui::geometry::{Dimension, Point, Size};
use polyhorn_ui::styles::ViewStyle;

use super::Algorithm;
use crate::{Layout, MeasureFunc};

mod convert;

pub use convert::IntoStretch;

pub struct Flexbox(stretch::Stretch);

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Node(stretch::node::Node);

impl Algorithm for Flexbox {
    type Node = Node;

    fn new() -> Flexbox {
        Flexbox(stretch::Stretch::new())
    }

    fn new_node(&mut self, style: ViewStyle, children: &[Self::Node]) -> Self::Node {
        Node(
            self.0
                .new_node(
                    style.into_stretch(),
                    &children.into_iter().map(|node| node.0).collect::<Vec<_>>(),
                )
                .unwrap(),
        )
    }

    fn new_leaf(&mut self, style: ViewStyle, measure: MeasureFunc) -> Self::Node {
        Node(
            self.0
                .new_leaf(style.into_stretch(), measure.into_stretch())
                .unwrap(),
        )
    }

    fn add_child(&mut self, parent: Self::Node, child: Self::Node) {
        self.0.add_child(parent.0, child.0).unwrap();
    }

    fn remove_child(&mut self, parent: Self::Node, child: Self::Node) {
        self.0.remove_child(parent.0, child.0).unwrap();
    }

    fn child_count(&self, parent: Self::Node) -> usize {
        self.0.child_count(parent.0).unwrap()
    }

    fn remove(&mut self, node: Self::Node) {
        self.0.remove(node.0);
    }

    fn set_style(&mut self, node: Self::Node, style: ViewStyle) {
        self.0.set_style(node.0, style.into_stretch()).unwrap();
    }

    fn set_measure(&mut self, node: Self::Node, measure: MeasureFunc) {
        self.0
            .set_measure(node.0, Some(measure.into_stretch()))
            .unwrap();
    }

    fn compute_layout(&mut self, node: Self::Node, size: Size<Dimension<f32>>) {
        self.0
            .compute_layout(
                node.0,
                stretch::geometry::Size {
                    width: match size.width {
                        Dimension::Points(pixels) => stretch::number::Number::Defined(pixels),
                        _ => stretch::number::Number::Undefined,
                    },
                    height: match size.height {
                        Dimension::Points(pixels) => stretch::number::Number::Defined(pixels),
                        _ => stretch::number::Number::Undefined,
                    },
                },
            )
            .unwrap();
    }

    fn layout(&self, node: Self::Node) -> Layout {
        let layout = self.0.layout(node.0).unwrap();

        Layout {
            origin: Point {
                x: layout.location.x,
                y: layout.location.y,
            },
            size: Size {
                width: layout.size.width,
                height: layout.size.height,
            },
        }
    }
}