operad 8.0.1

A cross-platform GUI library for Rust.
Documentation
use super::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SeparatorOrientation {
    Horizontal,
    Vertical,
}

impl SeparatorOrientation {
    pub const fn is_horizontal(self) -> bool {
        matches!(self, Self::Horizontal)
    }
}

#[derive(Debug, Clone)]
pub struct SeparatorOptions {
    pub orientation: SeparatorOrientation,
    pub layout: Option<LayoutStyle>,
    pub visual: UiVisual,
    pub thickness: f32,
    pub margin: f32,
    pub accessibility_label: Option<String>,
}

impl SeparatorOptions {
    pub fn horizontal() -> Self {
        Self {
            orientation: SeparatorOrientation::Horizontal,
            ..Default::default()
        }
    }

    pub fn vertical() -> Self {
        Self {
            orientation: SeparatorOrientation::Vertical,
            ..Default::default()
        }
    }

    pub fn with_layout(mut self, layout: impl Into<LayoutStyle>) -> Self {
        self.layout = Some(layout.into());
        self
    }

    pub fn with_margin(mut self, margin: f32) -> Self {
        self.margin = margin;
        self
    }
}

impl Default for SeparatorOptions {
    fn default() -> Self {
        Self {
            orientation: SeparatorOrientation::Horizontal,
            layout: None,
            visual: UiVisual::panel(ColorRgba::new(67, 78, 95, 255), None, 0.0),
            thickness: 1.0,
            margin: 6.0,
            accessibility_label: None,
        }
    }
}

pub fn separator(
    document: &mut UiDocument,
    parent: UiNodeId,
    name: impl Into<String>,
    options: SeparatorOptions,
) -> UiNodeId {
    let name = name.into();
    let layout = options.layout.unwrap_or_else(|| {
        if options.orientation.is_horizontal() {
            LayoutStyle::from_taffy_style(Style {
                size: TaffySize {
                    width: Dimension::percent(1.0),
                    height: length(options.thickness.max(0.0)),
                },
                margin: taffy::prelude::Rect {
                    left: taffy::prelude::LengthPercentageAuto::length(0.0),
                    right: taffy::prelude::LengthPercentageAuto::length(0.0),
                    top: taffy::prelude::LengthPercentageAuto::length(options.margin.max(0.0)),
                    bottom: taffy::prelude::LengthPercentageAuto::length(options.margin.max(0.0)),
                },
                flex_shrink: 0.0,
                ..Default::default()
            })
        } else {
            LayoutStyle::from_taffy_style(Style {
                size: TaffySize {
                    width: length(options.thickness.max(0.0)),
                    height: Dimension::percent(1.0),
                },
                margin: taffy::prelude::Rect {
                    left: taffy::prelude::LengthPercentageAuto::length(options.margin.max(0.0)),
                    right: taffy::prelude::LengthPercentageAuto::length(options.margin.max(0.0)),
                    top: taffy::prelude::LengthPercentageAuto::length(0.0),
                    bottom: taffy::prelude::LengthPercentageAuto::length(0.0),
                },
                flex_shrink: 0.0,
                ..Default::default()
            })
        }
    });
    document.add_child(
        parent,
        UiNode::container(name.clone(), layout)
            .with_visual(options.visual)
            .with_accessibility(
                AccessibilityMeta::new(AccessibilityRole::Separator)
                    .label(options.accessibility_label.unwrap_or(name)),
            ),
    )
}

pub fn spacer(
    document: &mut UiDocument,
    parent: UiNodeId,
    name: impl Into<String>,
    layout: impl Into<LayoutStyle>,
) -> UiNodeId {
    let layout = layout.into();
    document.add_child(parent, UiNode::container(name, layout))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn separator_defaults_to_accessible_horizontal_rule() {
        let mut document = UiDocument::new(root_style(320.0, 120.0));
        let root = document.root;
        let node = separator(
            &mut document,
            root,
            "section.rule",
            SeparatorOptions::default(),
        );

        assert_eq!(
            document.node(node).accessibility.as_ref().unwrap().role,
            AccessibilityRole::Separator
        );
        assert_eq!(document.node(node).style.layout.size.height, length(1.0));
    }
}