diff options
Diffstat (limited to 'native/src/widget/tree.rs')
-rw-r--r-- | native/src/widget/tree.rs | 187 |
1 files changed, 0 insertions, 187 deletions
diff --git a/native/src/widget/tree.rs b/native/src/widget/tree.rs deleted file mode 100644 index 0af40c33..00000000 --- a/native/src/widget/tree.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! Store internal widget state in a state tree to ensure continuity. -use crate::Widget; - -use std::any::{self, Any}; -use std::borrow::Borrow; -use std::fmt; - -/// A persistent state widget tree. -/// -/// A [`Tree`] is normally associated with a specific widget in the widget tree. -#[derive(Debug)] -pub struct Tree { - /// The tag of the [`Tree`]. - pub tag: Tag, - - /// The [`State`] of the [`Tree`]. - pub state: State, - - /// The children of the root widget of the [`Tree`]. - pub children: Vec<Tree>, -} - -impl Tree { - /// Creates an empty, stateless [`Tree`] with no children. - pub fn empty() -> Self { - Self { - tag: Tag::stateless(), - state: State::None, - children: Vec::new(), - } - } - - /// Creates a new [`Tree`] for the provided [`Widget`]. - pub fn new<'a, Message, Renderer>( - widget: impl Borrow<dyn Widget<Message, Renderer> + 'a>, - ) -> Self - where - Renderer: crate::Renderer, - { - let widget = widget.borrow(); - - Self { - tag: widget.tag(), - state: widget.state(), - children: widget.children(), - } - } - - /// Reconciliates the current tree with the provided [`Widget`]. - /// - /// If the tag of the [`Widget`] matches the tag of the [`Tree`], then the - /// [`Widget`] proceeds with the reconciliation (i.e. [`Widget::diff`] is called). - /// - /// Otherwise, the whole [`Tree`] is recreated. - /// - /// [`Widget::diff`]: crate::Widget::diff - pub fn diff<'a, Message, Renderer>( - &mut self, - new: impl Borrow<dyn Widget<Message, Renderer> + 'a>, - ) where - Renderer: crate::Renderer, - { - if self.tag == new.borrow().tag() { - new.borrow().diff(self) - } else { - *self = Self::new(new); - } - } - - /// Reconciliates the children of the tree with the provided list of widgets. - pub fn diff_children<'a, Message, Renderer>( - &mut self, - new_children: &[impl Borrow<dyn Widget<Message, Renderer> + 'a>], - ) where - Renderer: crate::Renderer, - { - self.diff_children_custom( - new_children, - |tree, widget| tree.diff(widget.borrow()), - |widget| Self::new(widget.borrow()), - ) - } - - /// Reconciliates the children of the tree with the provided list of widgets using custom - /// logic both for diffing and creating new widget state. - pub fn diff_children_custom<T>( - &mut self, - new_children: &[T], - diff: impl Fn(&mut Tree, &T), - new_state: impl Fn(&T) -> Self, - ) { - 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()) - { - diff(child_state, new); - } - - if self.children.len() < new_children.len() { - self.children.extend( - new_children[self.children.len()..].iter().map(new_state), - ); - } - } -} - -/// The identifier of some widget state. -#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct Tag(any::TypeId); - -impl Tag { - /// Creates a [`Tag`] for a state of type `T`. - pub fn of<T>() -> Self - where - T: 'static, - { - Self(any::TypeId::of::<T>()) - } - - /// Creates a [`Tag`] for a stateless widget. - pub fn stateless() -> Self { - Self::of::<()>() - } -} - -/// The internal [`State`] of a widget. -pub enum State { - /// No meaningful internal state. - None, - - /// Some meaningful internal state. - Some(Box<dyn Any>), -} - -impl State { - /// Creates a new [`State`]. - pub fn new<T>(state: T) -> Self - where - T: 'static, - { - State::Some(Box::new(state)) - } - - /// Downcasts the [`State`] to `T` and returns a reference to it. - /// - /// # Panics - /// This method will panic if the downcast fails or the [`State`] is [`State::None`]. - pub fn downcast_ref<T>(&self) -> &T - where - T: 'static, - { - match self { - State::None => panic!("Downcast on stateless state"), - State::Some(state) => { - state.downcast_ref().expect("Downcast widget state") - } - } - } - - /// Downcasts the [`State`] to `T` and returns a mutable reference to it. - /// - /// # Panics - /// This method will panic if the downcast fails or the [`State`] is [`State::None`]. - pub fn downcast_mut<T>(&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") - } - } - } -} - -impl fmt::Debug for State { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::None => write!(f, "State::None"), - Self::Some(_) => write!(f, "State::Some"), - } - } -} |