ansiq-widgets 0.1.0

Widget builders and shell-oriented UI primitives for Ansiq.
Documentation
use ansiq_core::{
    Alignment, BlockFrame, BlockProps, BlockTitle, BorderType, Borders, Element, ElementKind,
    Layout, Length, Line, Padding, Rect, Style, TitlePosition,
};

pub struct Block<Message = ()> {
    element: Element<Message>,
}

impl<Message> Block<Message> {
    pub fn new() -> Self {
        Self {
            element: Element::new(ElementKind::Block(BlockProps {
                titles: Vec::new(),
                title_alignment: Alignment::Left,
                title_position: TitlePosition::Top,
                borders: Borders::NONE,
                border_type: BorderType::Plain,
                border_set: None,
                padding: Padding::zero(),
                border_style: Style::default(),
                title_style: Style::default(),
            }))
            .with_layout(Layout {
                width: Length::Fill,
                height: Length::Auto,
            }),
        }
    }

    pub fn bordered() -> Self {
        let mut block = Self::new();
        if let ElementKind::Block(props) = &mut block.element.kind {
            props.borders = Borders::ALL;
        }
        block
    }

    pub fn title<T>(mut self, title: T) -> Self
    where
        T: Into<Line>,
    {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.titles.push(BlockTitle::new(title));
        }
        self
    }

    pub fn title_top<T>(mut self, title: T) -> Self
    where
        T: Into<Line>,
    {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.titles.push(BlockTitle::top(title));
        }
        self
    }

    pub fn title_bottom<T>(mut self, title: T) -> Self
    where
        T: Into<Line>,
    {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.titles.push(BlockTitle::bottom(title));
        }
        self
    }

    pub fn title_alignment(mut self, alignment: Alignment) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.title_alignment = alignment;
        }
        self
    }

    pub fn title_position(mut self, position: TitlePosition) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.title_position = position;
        }
        self
    }

    pub fn bordered_flag(mut self, bordered: bool) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.borders = if bordered {
                Borders::ALL
            } else {
                Borders::NONE
            };
        }
        self
    }

    pub fn borders(mut self, borders: Borders) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.borders = borders;
        }
        self
    }

    pub fn border_type(mut self, border_type: BorderType) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.border_type = border_type;
        }
        self
    }

    pub fn border_set(mut self, border_set: ansiq_core::symbols::border::Set) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.border_set = Some(border_set);
        }
        self
    }

    pub fn padding(mut self, padding: Padding) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.padding = padding;
        }
        self
    }

    pub fn border_style<S: Into<Style>>(mut self, style: S) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.border_style = style.into();
        }
        self
    }

    pub fn title_style<S: Into<Style>>(mut self, style: S) -> Self {
        if let ElementKind::Block(props) = &mut self.element.kind {
            props.title_style = style.into();
        }
        self
    }

    pub fn child(mut self, child: Element<Message>) -> Self {
        self.element.children.push(child);
        self
    }

    pub fn children<I>(mut self, children: I) -> Self
    where
        I: IntoIterator<Item = Element<Message>>,
    {
        self.element.children.extend(children);
        self
    }

    pub fn layout(mut self, layout: Layout) -> Self {
        self.element.layout = layout;
        self
    }

    pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
        self.element.style = style.into();
        self
    }

    pub fn build(self) -> Element<Message> {
        self.element
    }

    pub fn inner(&self, rect: Rect) -> Rect {
        let ElementKind::Block(props) = &self.element.kind else {
            unreachable!("Block widgets always store Block props")
        };

        props.inner(rect)
    }

    pub fn into_frame(self) -> BlockFrame {
        let style = self.element.style;
        let ElementKind::Block(props) = self.element.kind else {
            unreachable!("Block widgets always store Block props")
        };

        BlockFrame { props, style }
    }
}