layout-cat 0.1.0

Box-model layout: cascade + block layout over a dom-cat tree using css-cat stylesheets. Produces a LayoutBox tree with positions and dimensions. No mut, no Rc/Arc, no interior mutability, no panics, exhaustive matches. Fourth sub-crate of a Servo-replacement webview runtime targeting Tauri.
//! The layout-box tree.

use dom_cat::NodeId;

use crate::length::{Edges, Rect};
use crate::style::ComputedStyle;

/// One box in the layout tree.  Each box back-references the
/// `dom-cat` node it was generated from.
#[derive(Debug, Clone, PartialEq)]
pub struct LayoutBox {
    dom_node: NodeId,
    style: ComputedStyle,
    rect: Rect,
    margin: Edges,
    border: Edges,
    padding: Edges,
    children: Vec<LayoutBox>,
}

impl Eq for LayoutBox {}

impl LayoutBox {
    /// Build a layout box.
    #[must_use]
    pub fn new(
        dom_node: NodeId,
        style: ComputedStyle,
        rect: Rect,
        margin: Edges,
        border: Edges,
        padding: Edges,
        children: Vec<LayoutBox>,
    ) -> Self {
        Self {
            dom_node,
            style,
            rect,
            margin,
            border,
            padding,
            children,
        }
    }

    /// The originating DOM node.
    #[must_use]
    pub fn dom_node(&self) -> NodeId {
        self.dom_node
    }

    /// The computed style.
    #[must_use]
    pub fn style(&self) -> &ComputedStyle {
        &self.style
    }

    /// The content-box rectangle (after subtracting margin/border/padding).
    #[must_use]
    pub fn rect(&self) -> Rect {
        self.rect
    }

    /// The margin edges.
    #[must_use]
    pub fn margin(&self) -> Edges {
        self.margin
    }

    /// The border edges.
    #[must_use]
    pub fn border(&self) -> Edges {
        self.border
    }

    /// The padding edges.
    #[must_use]
    pub fn padding(&self) -> Edges {
        self.padding
    }

    /// The child boxes in source order.
    #[must_use]
    pub fn children(&self) -> &[LayoutBox] {
        &self.children
    }
}

/// The viewport dimensions used as the initial containing block.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Viewport {
    width: u32,
    height: u32,
}

impl Viewport {
    /// Build a viewport.
    #[must_use]
    pub fn new(width: u32, height: u32) -> Self {
        Self { width, height }
    }

    /// The viewport width in CSS pixels.
    #[must_use]
    pub fn width(&self) -> u32 {
        self.width
    }

    /// The viewport height in CSS pixels.
    #[must_use]
    pub fn height(&self) -> u32 {
        self.height
    }
}

/// The complete layout tree.
#[derive(Debug, Clone, PartialEq)]
pub struct LayoutTree {
    root: Option<LayoutBox>,
    viewport: Viewport,
}

impl Eq for LayoutTree {}

impl LayoutTree {
    /// Build a tree.
    #[must_use]
    pub fn new(root: Option<LayoutBox>, viewport: Viewport) -> Self {
        Self { root, viewport }
    }

    /// The root box, if any.
    #[must_use]
    pub fn root_box(&self) -> Option<&LayoutBox> {
        self.root.as_ref()
    }

    /// The viewport this tree was laid out against.
    #[must_use]
    pub fn viewport(&self) -> Viewport {
        self.viewport
    }
}