use crate::{ HashMap, Painter, Widget, WidgetId, WidgetLike, primitive::Primitives, util::{ID, IDTracker}, }; use std::{ any::{Any, TypeId}, ops::{Index, IndexMut}, }; #[derive(Default)] pub struct Ui { ids: IDTracker, base: Option, widgets: Widgets, updates: Vec, primitives: Primitives, full_redraw: bool, } #[derive(Default)] pub struct Widgets(HashMap>); impl Ui { pub fn add(&mut self, w: impl WidgetLike) -> WidgetId { w.add(self) } pub fn add_widget(&mut self, w: W) -> WidgetId { self.push(w) } pub fn push(&mut self, w: W) -> WidgetId { let id = self.ids.next(); self.widgets.insert(id.duplicate(), w); WidgetId::new(id, TypeId::of::()) } pub fn set(&mut self, i: &WidgetId, w: W) { self.widgets.insert(i.id.duplicate(), w); } pub fn set_base(&mut self, w: impl WidgetLike) { self.base = Some(w.add(self).erase_type()); self.full_redraw = true; } pub fn new() -> Self { Self::default() } pub fn get(&self, id: &WidgetId) -> Option<&W> { self.widgets.get(id) } pub fn get_mut(&mut self, id: &WidgetId) -> Option<&mut W> { self.widgets.get_mut(id) } pub fn id(&mut self) -> WidgetId { WidgetId::new(self.ids.next(), TypeId::of::()) } pub fn redraw_all(&mut self) { let mut painter = Painter::new(&self.widgets); if let Some(base) = &self.base { painter.draw(base); } self.primitives = painter.finish(); } pub fn update(&mut self) -> Option<&Primitives> { if self.full_redraw { self.redraw_all(); self.full_redraw = false; return Some(&self.primitives); } if self.updates.is_empty() { return None; } self.redraw_all(); self.updates.drain(..); Some(&self.primitives) } pub fn needs_redraw(&self) -> bool { self.full_redraw || !self.updates.is_empty() } } impl Index<&WidgetId> for Ui { type Output = W; fn index(&self, id: &WidgetId) -> &Self::Output { self.get(id).unwrap() } } impl IndexMut<&WidgetId> for Ui { fn index_mut(&mut self, id: &WidgetId) -> &mut Self::Output { self.updates.push(id.clone().erase_type()); self.get_mut(id).unwrap() } } impl Widgets { pub fn get_dyn(&self, id: &WidgetId) -> &dyn Widget { self.0.get(&id.id).unwrap().as_ref() } pub fn get(&self, id: &WidgetId) -> Option<&W> { self.0.get(&id.id).unwrap().as_any().downcast_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(&self) -> &dyn Any { self } pub fn as_any_mut(&mut self) -> &mut dyn Any { self } }