nightshade 0.13.3

A cross-platform data-oriented game engine.
Documentation
use nalgebra_glm::{Vec2, Vec4};

use crate::ecs::text::components::{TextAlignment, VerticalAlignment};
use crate::ecs::ui::builder::UiTreeBuilder;
use crate::ecs::ui::components::*;
use crate::ecs::ui::layout_types::FlowDirection;
use crate::ecs::ui::state::UiBase;
use crate::ecs::ui::units::{Ab, Rl};

impl<'a> UiTreeBuilder<'a> {
    pub fn add_label(&mut self, text: &str) -> freecs::Entity {
        let font_size = self.active_theme().font_size;
        let text_slot = self.world_mut().resources.text_cache.add_text(text);

        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, font_size * 1.5)))
            .with_text_slot(text_slot, font_size)
            .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
            .with_theme_color::<UiBase>(ThemeColor::Text)
            .without_pointer_events()
            .done()
    }

    pub fn add_label_with_slot(&mut self, slot: usize) -> freecs::Entity {
        let font_size = self.active_theme().font_size;

        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, font_size * 1.5)))
            .with_text_slot(slot, font_size)
            .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
            .with_theme_color::<UiBase>(ThemeColor::Text)
            .without_pointer_events()
            .done()
    }

    pub fn add_label_wrapped(&mut self, text: &str) -> freecs::Entity {
        let font_size = self.active_theme().font_size;
        let text_slot = self.world_mut().resources.text_cache.add_text(text);

        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)))
            .with_text_slot(text_slot, font_size)
            .with_text_alignment(TextAlignment::Left, VerticalAlignment::Top)
            .with_text_wrap()
            .with_theme_color::<UiBase>(ThemeColor::Text)
            .without_pointer_events()
            .done()
    }

    pub fn add_dynamic_label(&mut self, text: &str) -> (freecs::Entity, usize) {
        let slot = self.world_mut().resources.text_cache.add_text(text);
        let entity = self.add_label_with_slot(slot);
        (entity, slot)
    }

    pub fn add_label_colored(&mut self, text: &str, color: Vec4) -> freecs::Entity {
        let theme = self
            .world_mut()
            .resources
            .retained_ui
            .theme_state
            .active_theme();
        let font_size = theme.font_size;

        let text_slot = self.world_mut().resources.text_cache.add_text(text);

        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, font_size * 1.5)))
            .with_text_slot(text_slot, font_size)
            .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
            .with_color::<UiBase>(color)
            .without_pointer_events()
            .done()
    }

    pub fn add_heading(&mut self, text: &str) -> freecs::Entity {
        let theme = self
            .world_mut()
            .resources
            .retained_ui
            .theme_state
            .active_theme();
        let font_size = theme.font_size * 1.4;

        let text_slot = self.world_mut().resources.text_cache.add_text(text);

        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, font_size * 1.5)))
            .with_text_slot(text_slot, font_size)
            .with_text_alignment(TextAlignment::Left, VerticalAlignment::Middle)
            .with_theme_color::<UiBase>(ThemeColor::TextAccent)
            .without_pointer_events()
            .done()
    }

    pub fn add_separator(&mut self) -> freecs::Entity {
        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)) + Ab(Vec2::new(0.0, 1.0)))
            .with_rect(0.0, 0.0, Vec4::new(0.0, 0.0, 0.0, 0.0))
            .with_theme_color::<UiBase>(ThemeColor::Border)
            .without_pointer_events()
            .done()
    }

    pub fn add_spacing(&mut self, amount: f32) -> freecs::Entity {
        self.add_node()
            .flow_child(Ab(Vec2::new(amount, amount)))
            .without_pointer_events()
            .done()
    }

    pub fn add_spring(&mut self) -> freecs::Entity {
        self.add_node()
            .flow_child(Ab(Vec2::new(0.0, 0.0)))
            .flex_grow(1.0)
            .without_pointer_events()
            .done()
    }

    /// Creates a horizontal flow container (row). Children are laid out
    /// left-to-right with 4 px spacing. Returns the row entity which can
    /// be used as a parent for nested children.
    ///
    /// ```ignore
    /// let row = tree.add_row();
    /// tree.push_parent(row);
    /// tree.add_label("Left");
    /// tree.add_label("Right");
    /// tree.pop_parent();
    /// ```
    pub fn add_row(&mut self) -> freecs::Entity {
        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)))
            .flow(FlowDirection::Horizontal, 0.0, 4.0)
            .without_pointer_events()
            .entity()
    }

    /// Creates a vertical flow container (column). Children are laid out
    /// top-to-bottom with 4 px spacing. Returns the column entity.
    ///
    /// ```ignore
    /// let col = tree.add_column();
    /// tree.push_parent(col);
    /// tree.add_toggle(true);
    /// tree.add_checkbox("Enable", false);
    /// tree.pop_parent();
    /// ```
    pub fn add_column(&mut self) -> freecs::Entity {
        self.add_node()
            .flow_child(Rl(Vec2::new(100.0, 0.0)))
            .flow(FlowDirection::Vertical, 0.0, 4.0)
            .without_pointer_events()
            .entity()
    }
}