use crate::{ primitive::{Painter, Primitives}, util::{IDTracker, ID}, HashMap, Widget, WidgetId, WidgetLike, WidgetRef, }; use std::{ any::{Any, TypeId}, cell::RefCell, rc::Rc, }; pub struct UI { ids: IDTracker, base: Option, pub widgets: Widgets, } pub struct Widgets(HashMap>); #[derive(Clone)] pub struct UIBuilder { ui: Rc>, } impl From for UIBuilder { fn from(ui: UI) -> Self { UIBuilder { ui: Rc::new(RefCell::new(ui)), } } } impl UIBuilder { pub fn add(&mut self, w: impl WidgetLike) -> WidgetRef { WidgetRef::new([w.add(self).erase_type()]) } pub fn add_widget(&mut self, w: W) -> WidgetRef { WidgetRef::new([self.push(w)]) } pub fn push(&mut self, w: W) -> WidgetId { let mut ui = self.ui.borrow_mut(); let id = ui.ids.next(); ui.widgets.insert(id.duplicate(), w); WidgetId::new(id, TypeId::of::()) } pub fn finish(mut self, base: W) -> UI { let base = base.add(&mut self).erase_type(); let mut ui = Rc::into_inner(self.ui).unwrap().into_inner(); ui.base = Some(base); ui } } impl UI { pub fn build() -> UIBuilder { Self::empty().into() } pub fn empty() -> Self { Self { ids: IDTracker::new(), base: None, widgets: Widgets::new(), } } pub fn to_primitives(&self) -> Primitives { let mut painter = Painter::new(&self.widgets); if let Some(base) = &self.base { painter.draw(base); } painter.finish() } } impl Widgets { fn new() -> Self { Self(HashMap::new()) } pub fn get(&self, id: &WidgetId) -> &dyn Widget { self.0.get(&id.id).unwrap().as_ref() } pub fn get_mut(&mut self, id: &WidgetId) -> Option<&mut W> { self.0.get_mut(&id.id).unwrap().as_any_mut().downcast_mut() } pub fn insert(&mut self, id: ID, widget: impl Widget) { self.0.insert(id, Box::new(widget)); } pub fn insert_any(&mut self, id: ID, widget: Box) { self.0.insert(id, widget); } } impl dyn Widget { pub fn as_any_mut(&mut self) -> &mut dyn Any { self } }