use crate::widget::Element; use std::any::{self, Any}; pub struct Tree { pub tag: Tag, pub state: State, pub children: Vec, } impl Tree { pub fn empty() -> Self { Self { tag: Tag::stateless(), state: State::None, children: Vec::new(), } } pub fn new( element: &Element<'_, Message, Renderer>, ) -> Self { Self { tag: element.as_widget().tag(), state: element.as_widget().state(), children: element.as_widget().children(), } } pub fn diff( &mut self, new: &Element<'_, Message, Renderer>, ) { if self.tag == new.as_widget().tag() { new.as_widget().diff(self) } else { *self = Self::new(new); } } pub fn diff_children( &mut self, new_children: &[Element<'_, Message, Renderer>], ) { if self.children.len() > new_children.len() { self.children.truncate(new_children.len()); } for (child_state, new) in self.children.iter_mut().zip(new_children.iter()) { child_state.diff(new); } if self.children.len() < new_children.len() { self.children.extend( new_children[self.children.len()..].iter().map(Self::new), ); } } } #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct Tag(any::TypeId); impl Tag { pub fn of() -> Self where T: 'static, { Self(any::TypeId::of::()) } pub fn stateless() -> Self { Self::of::<()>() } } pub enum State { None, Some(Box), } impl State { pub fn new(state: T) -> Self where T: 'static, { State::Some(Box::new(state)) } pub fn downcast_ref(&self) -> &T where T: 'static, { match self { State::None => panic!("Downcast on stateless state"), State::Some(state) => { state.downcast_ref().expect("Downcast widget state") } } } pub fn downcast_mut(&mut self) -> &mut T where T: 'static, { match self { State::None => panic!("Downcast on stateless state"), State::Some(state) => { state.downcast_mut().expect("Downcast widget state") } } } }