use crate::{ IdLike, Widget, WidgetData, WidgetId, util::{DynBorrower, HashSet, SlotVec}, }; pub struct Widgets { pub needs_redraw: HashSet, vec: SlotVec>, } impl Default for Widgets { fn default() -> Self { Self { needs_redraw: Default::default(), vec: Default::default(), } } } impl Widgets { pub fn has_updates(&self) -> bool { !self.needs_redraw.is_empty() } pub fn get_dyn(&self, id: WidgetId) -> Option<&dyn Widget> { Some(self.vec.get(id)?.widget.as_ref()) } pub fn get_dyn_mut(&mut self, id: WidgetId) -> Option<&mut dyn Widget> { self.needs_redraw.insert(id); Some(self.vec.get_mut(id)?.widget.as_mut()) } /// get_dyn but dynamic borrow checking of widgets /// lets you do recursive (tree) operations, like the painter does pub(crate) fn get_dyn_dynamic<'a>(&self, id: WidgetId) -> WidgetWrapper<'a, State> { // SAFETY: must guarantee no other mutable references to this widget exist // done through the borrow variable #[allow(mutable_transmutes)] let data = unsafe { std::mem::transmute::<&WidgetData, &mut WidgetData>( self.vec.get(id).unwrap(), ) }; if data.borrowed { panic!("tried to mutably borrow the same widget twice"); } WidgetWrapper::new(data.widget.as_mut(), &mut data.borrowed) } pub fn get>(&self, id: &I) -> Option<&I::Widget> where I::Widget: Sized, { self.get_dyn(id.id())?.as_any().downcast_ref() } pub fn get_mut>(&mut self, id: &I) -> Option<&mut I::Widget> where I::Widget: Sized, { self.get_dyn_mut(id.id())?.as_any_mut().downcast_mut() } pub fn add>(&mut self, widget: W) -> WidgetId { self.vec.add(WidgetData::new(widget)) } pub fn data(&self, id: impl IdLike) -> Option<&WidgetData> { self.vec.get(id.id()) } pub fn label(&self, id: impl IdLike) -> &String { &self.data(id.id()).unwrap().label } pub fn data_mut(&mut self, id: impl IdLike) -> Option<&mut WidgetData> { self.vec.get_mut(id.id()) } pub fn delete(&mut self, id: impl IdLike) { self.vec.free(id.id()); // not sure if there's any point in this // self.updates.remove(&id); } #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.vec.len() } } pub type WidgetWrapper<'a, State> = DynBorrower<'a, dyn Widget>;