1use crate::Widget;
3
4use std::any::{self, Any};
5use std::borrow::Borrow;
6use std::fmt;
7
8#[derive(Debug)]
12pub struct Tree {
13 pub tag: Tag,
15
16 pub state: State,
18
19 pub children: Vec<Tree>,
21}
22
23impl Tree {
24 pub fn empty() -> Self {
26 Self {
27 tag: Tag::stateless(),
28 state: State::None,
29 children: Vec::new(),
30 }
31 }
32
33 pub fn new<'a, Message, Theme, Renderer>(
35 widget: impl Borrow<dyn Widget<Message, Theme, Renderer> + 'a>,
36 ) -> Self
37 where
38 Renderer: crate::Renderer,
39 {
40 let widget = widget.borrow();
41
42 Self {
43 tag: widget.tag(),
44 state: widget.state(),
45 children: widget.children(),
46 }
47 }
48
49 pub fn diff<'a, Message, Theme, Renderer>(
58 &mut self,
59 new: impl Borrow<dyn Widget<Message, Theme, Renderer> + 'a>,
60 ) where
61 Renderer: crate::Renderer,
62 {
63 if self.tag == new.borrow().tag() {
64 new.borrow().diff(self);
65 } else {
66 *self = Self::new(new);
67 }
68 }
69
70 pub fn diff_children<'a, Message, Theme, Renderer>(
72 &mut self,
73 new_children: &[impl Borrow<dyn Widget<Message, Theme, Renderer> + 'a>],
74 ) where
75 Renderer: crate::Renderer,
76 {
77 self.diff_children_custom(
78 new_children,
79 |tree, widget| tree.diff(widget.borrow()),
80 |widget| Self::new(widget.borrow()),
81 );
82 }
83
84 pub fn diff_children_custom<T>(
87 &mut self,
88 new_children: &[T],
89 diff: impl Fn(&mut Tree, &T),
90 new_state: impl Fn(&T) -> Self,
91 ) {
92 if self.children.len() > new_children.len() {
93 self.children.truncate(new_children.len());
94 }
95
96 for (child_state, new) in self.children.iter_mut().zip(new_children.iter()) {
97 diff(child_state, new);
98 }
99
100 if self.children.len() < new_children.len() {
101 self.children
102 .extend(new_children[self.children.len()..].iter().map(new_state));
103 }
104 }
105}
106
107pub fn diff_children_custom_with_search<T>(
113 current_children: &mut Vec<Tree>,
114 new_children: &[T],
115 diff: impl Fn(&mut Tree, &T),
116 maybe_changed: impl Fn(usize) -> bool,
117 new_state: impl Fn(&T) -> Tree,
118) {
119 if new_children.is_empty() {
120 current_children.clear();
121 return;
122 }
123
124 if current_children.is_empty() {
125 current_children.extend(new_children.iter().map(new_state));
126 return;
127 }
128
129 let first_maybe_changed = maybe_changed(0);
130 let last_maybe_changed = maybe_changed(current_children.len() - 1);
131
132 if current_children.len() > new_children.len() {
133 if !first_maybe_changed && last_maybe_changed {
134 current_children.truncate(new_children.len());
135 } else {
136 let difference_index = if first_maybe_changed {
137 0
138 } else {
139 (1..current_children.len())
140 .find(|&i| maybe_changed(i))
141 .unwrap_or(0)
142 };
143
144 let _ = current_children.splice(
145 difference_index..difference_index + (current_children.len() - new_children.len()),
146 std::iter::empty(),
147 );
148 }
149 }
150
151 if current_children.len() < new_children.len() {
152 let first_maybe_changed = maybe_changed(0);
153 let last_maybe_changed = maybe_changed(current_children.len() - 1);
154
155 if !first_maybe_changed && last_maybe_changed {
156 current_children.extend(new_children[current_children.len()..].iter().map(new_state));
157 } else {
158 let difference_index = if first_maybe_changed {
159 0
160 } else {
161 (1..current_children.len())
162 .find(|&i| maybe_changed(i))
163 .unwrap_or(0)
164 };
165
166 let _ = current_children.splice(
167 difference_index..difference_index,
168 new_children[difference_index
169 ..difference_index + (new_children.len() - current_children.len())]
170 .iter()
171 .map(new_state),
172 );
173 }
174 }
175
176 for (child_state, new) in current_children.iter_mut().zip(new_children.iter()) {
178 diff(child_state, new);
179 }
180}
181
182#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
184pub struct Tag(any::TypeId);
185
186impl Tag {
187 pub fn of<T>() -> Self
189 where
190 T: 'static,
191 {
192 Self(any::TypeId::of::<T>())
193 }
194
195 pub fn stateless() -> Self {
197 Self::of::<()>()
198 }
199}
200
201pub enum State {
203 None,
205
206 Some(Box<dyn Any>),
208}
209
210impl State {
211 pub fn new<T>(state: T) -> Self
213 where
214 T: 'static,
215 {
216 State::Some(Box::new(state))
217 }
218
219 pub fn downcast_ref<T>(&self) -> &T
224 where
225 T: 'static,
226 {
227 match self {
228 State::None => panic!("Downcast on stateless state"),
229 State::Some(state) => state.downcast_ref().expect("Downcast widget state"),
230 }
231 }
232
233 pub fn downcast_mut<T>(&mut self) -> &mut T
238 where
239 T: 'static,
240 {
241 match self {
242 State::None => panic!("Downcast on stateless state"),
243 State::Some(state) => state.downcast_mut().expect("Downcast widget state"),
244 }
245 }
246}
247
248impl fmt::Debug for State {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 match self {
251 Self::None => write!(f, "State::None"),
252 Self::Some(_) => write!(f, "State::Some"),
253 }
254 }
255}