use std::any::TypeId;
use crate::component::Component;
use crate::node::{NodeId, WidthConstraint};
use crate::renderer::Renderer;
pub(crate) trait Element: Send {
fn build(self: Box<Self>, renderer: &mut Renderer, parent: NodeId) -> NodeId;
fn update(self: Box<Self>, _renderer: &mut Renderer, _node_id: NodeId) {}
}
impl<C: Component> Element for C {
fn build(self: Box<Self>, renderer: &mut Renderer, parent: NodeId) -> NodeId {
renderer.append_child(parent, *self)
}
fn update(self: Box<Self>, renderer: &mut Renderer, node_id: NodeId) {
renderer.swap_component(node_id, *self);
}
}
pub(crate) struct ElementEntry {
pub(crate) element: Box<dyn Element>,
pub(crate) children: Option<Elements>,
pub(crate) key: Option<String>,
pub(crate) type_id: TypeId,
pub(crate) width_constraint: WidthConstraint,
}
pub struct Elements {
items: Vec<ElementEntry>,
}
impl Elements {
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn add<C: Component>(&mut self, component: C) -> ElementHandle<'_> {
let type_id = TypeId::of::<C>();
self.items.push(ElementEntry {
element: Box::new(component),
children: None,
key: None,
type_id,
width_constraint: WidthConstraint::default(),
});
ElementHandle {
entry: self.items.last_mut().unwrap(),
}
}
#[allow(dead_code)]
pub(crate) fn add_element<E: Element + 'static>(&mut self, element: E) -> ElementHandle<'_> {
let type_id = TypeId::of::<E>();
self.items.push(ElementEntry {
element: Box::new(element),
children: None,
key: None,
type_id,
width_constraint: WidthConstraint::default(),
});
ElementHandle {
entry: self.items.last_mut().unwrap(),
}
}
#[allow(dead_code)]
pub(crate) fn add_element_with_children<E: Element + 'static>(
&mut self,
element: E,
children: Elements,
) -> ElementHandle<'_> {
let type_id = TypeId::of::<E>();
self.items.push(ElementEntry {
element: Box::new(element),
children: Some(children),
key: None,
type_id,
width_constraint: WidthConstraint::default(),
});
ElementHandle {
entry: self.items.last_mut().unwrap(),
}
}
pub fn add_with_children<C: Component>(
&mut self,
component: C,
children: Elements,
) -> ElementHandle<'_> {
let type_id = TypeId::of::<C>();
self.items.push(ElementEntry {
element: Box::new(component),
children: Some(children),
key: None,
type_id,
width_constraint: WidthConstraint::default(),
});
ElementHandle {
entry: self.items.last_mut().unwrap(),
}
}
pub fn group(&mut self, children: Elements) -> ElementHandle<'_> {
self.add_with_children(crate::component::VStack, children)
}
pub fn hstack(&mut self, children: Elements) -> ElementHandle<'_> {
self.add_with_children(crate::component::HStack, children)
}
pub fn splice(&mut self, other: Elements) {
self.items.extend(other.items);
}
pub(crate) fn into_items(self) -> Vec<ElementEntry> {
self.items
}
}
impl Default for Elements {
fn default() -> Self {
Self::new()
}
}
impl Elements {
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
}
pub struct ElementHandle<'a> {
entry: &'a mut ElementEntry,
}
impl<'a> ElementHandle<'a> {
pub fn key(self, key: impl Into<String>) -> Self {
self.entry.key = Some(key.into());
self
}
pub fn width(self, constraint: WidthConstraint) -> Self {
self.entry.width_constraint = constraint;
self
}
}