godoru 0.1.0

UI Framework for Rust using Godot
use crate::{AssetLoader, ImageHandle};

use super::{
    Button, ButtonBuilder, Checkbox, CheckboxBuilder, Component, Container, ContainerBuilder,
    Image, ImageBuilder, Scroll, ScrollBuilder, Text, TextBuilder, TextInput, TextInputBuilder,
};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum NoAction {}

#[derive(Clone, Debug, PartialEq)]
pub enum UiNode<A = NoAction> {
    Container(Container<A>),
    Text(Text<A>),
    Image(Image<A>),
    Button(Button<A>),
    TextInput(TextInput<A>),
    Checkbox(Checkbox<A>),
    Scroll(Scroll<A>),
}

#[derive(Clone, Debug, PartialEq)]
pub struct Ui<A = NoAction> {
    pub nodes: Vec<UiNode<A>>,
}

impl<A: Clone> Ui<A> {
    pub fn new() -> Self {
        Self { nodes: Vec::new() }
    }

    pub fn container(&mut self) -> ContainerBuilder<'_, A> {
        ContainerBuilder::new(self)
    }

    pub fn text(&mut self, value: impl Into<String>) -> TextBuilder<'_, A> {
        TextBuilder::new(self, value)
    }

    pub fn image(&mut self, image: ImageHandle) -> ImageBuilder<'_, A> {
        ImageBuilder::new(self, image)
    }

    pub fn button(&mut self, text: impl Into<String>) -> ButtonBuilder<'_, A> {
        ButtonBuilder::new(self, text)
    }

    pub fn textInput(&mut self, value: impl Into<String>) -> TextInputBuilder<'_, A> {
        TextInputBuilder::new(self, value)
    }

    pub fn checkbox(&mut self, checked: bool) -> CheckboxBuilder<'_, A> {
        CheckboxBuilder::new(self, checked)
    }

    pub fn scroll(&mut self) -> ScrollBuilder<'_, A> {
        ScrollBuilder::new(self)
    }

    pub fn key(&mut self, key: impl Into<String>, build: impl FnOnce(&mut Ui<A>)) {
        let mut ui = Ui::new();
        build(&mut ui);
        let key = key.into();
        for mut node in ui.nodes {
            node.setKey(key.clone());
            self.nodes.push(node);
        }
    }

    pub fn assets(&self) -> AssetLoader {
        AssetLoader::default()
    }
}

impl<A> UiNode<A> {
    pub fn key(&self) -> Option<&str> {
        match self {
            UiNode::Container(node) => node.key.as_deref(),
            UiNode::Text(node) => node.key.as_deref(),
            UiNode::Image(node) => node.key.as_deref(),
            UiNode::Button(node) => node.key.as_deref(),
            UiNode::TextInput(node) => node.key.as_deref(),
            UiNode::Checkbox(node) => node.key.as_deref(),
            UiNode::Scroll(node) => node.key.as_deref(),
        }
    }

    pub fn component(&self) -> Component {
        match self {
            UiNode::Container(_) => Component::Container,
            UiNode::Text(_) => Component::Text,
            UiNode::Image(_) => Component::Image,
            UiNode::Button(_) => Component::Button,
            UiNode::TextInput(_) => Component::TextInput,
            UiNode::Checkbox(_) => Component::Checkbox,
            UiNode::Scroll(_) => Component::Scroll,
        }
    }

    pub fn sameIdentity(&self, other: &Self) -> bool {
        self.component() == other.component()
            && match (self.key(), other.key()) {
                (Some(left), Some(right)) => left == right,
                (None, None) => true,
                _ => false,
            }
    }

    fn setKey(&mut self, key: String) {
        match self {
            UiNode::Container(node) => node.key = Some(key),
            UiNode::Text(node) => node.key = Some(key),
            UiNode::Image(node) => node.key = Some(key),
            UiNode::Button(node) => node.key = Some(key),
            UiNode::TextInput(node) => node.key = Some(key),
            UiNode::Checkbox(node) => node.key = Some(key),
            UiNode::Scroll(node) => node.key = Some(key),
        }
    }
}

impl<A: Clone> Default for Ui<A> {
    fn default() -> Self {
        Self::new()
    }
}