1use crate::Widget;
3
4use std::any::{self, Any};
5use std::borrow::{Borrow, BorrowMut};
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: Vec::new(),
46 }
47 }
48
49 pub fn diff<'a, Message, Theme, Renderer>(
58 &mut self,
59 mut new: impl BorrowMut<dyn Widget<Message, Theme, Renderer> + 'a>,
60 ) where
61 Renderer: crate::Renderer,
62 {
63 if self.tag != new.borrow().tag() {
64 *self = Self::new(new.borrow());
65 }
66
67 new.borrow_mut().diff(self);
68 }
69
70 pub fn diff_children<'a, Message, Theme, Renderer>(
72 &mut self,
73 new_children: &mut [impl BorrowMut<dyn Widget<Message, Theme, Renderer> + 'a>],
74 ) where
75 Renderer: crate::Renderer,
76 {
77 diff_children(&mut self.children, new_children);
78 }
79
80 pub fn diff_children_custom<T>(
83 &mut self,
84 new_children: &mut [T],
85 diff: impl Fn(&mut Tree, &mut T),
86 new_state: impl Fn(&T) -> Self,
87 ) {
88 diff_children_custom(&mut self.children, new_children, diff, new_state);
89 }
90}
91
92pub fn diff_children<'a, Message, Theme, Renderer>(
94 old_children: &mut Vec<Tree>,
95 new_children: &mut [impl BorrowMut<dyn Widget<Message, Theme, Renderer> + 'a>],
96) where
97 Renderer: crate::Renderer,
98{
99 diff_children_custom(
100 old_children,
101 new_children,
102 |tree, widget| tree.diff(widget.borrow_mut()),
103 |widget| Tree::new(widget.borrow()),
104 );
105}
106
107pub fn diff_children_custom<T>(
110 old_children: &mut Vec<Tree>,
111 new_children: &mut [T],
112 diff: impl Fn(&mut Tree, &mut T),
113 new_state: impl Fn(&T) -> Tree,
114) {
115 if old_children.len() > new_children.len() {
116 old_children.truncate(new_children.len());
117 }
118
119 if old_children.len() < new_children.len() {
120 old_children.extend(new_children[old_children.len()..].iter().map(new_state));
121 }
122
123 for (child_state, new) in old_children.iter_mut().zip(new_children.iter_mut()) {
124 diff(child_state, new);
125 }
126}
127
128pub fn diff_children_custom_with_search<T>(
134 current_children: &mut Vec<Tree>,
135 new_children: &mut [T],
136 diff: impl Fn(&mut Tree, &mut T),
137 maybe_changed: impl Fn(usize) -> bool,
138 new_state: impl Fn(&T) -> Tree,
139) {
140 if new_children.is_empty() {
141 current_children.clear();
142 return;
143 }
144
145 if current_children.is_empty() {
146 current_children.extend(new_children.iter().map(new_state));
147
148 for (child_state, new) in current_children.iter_mut().zip(new_children.iter_mut()) {
150 diff(child_state, new);
151 }
152
153 return;
154 }
155
156 let first_maybe_changed = maybe_changed(0);
157 let last_maybe_changed = maybe_changed(current_children.len() - 1);
158
159 if current_children.len() > new_children.len() {
160 if !first_maybe_changed && last_maybe_changed {
161 current_children.truncate(new_children.len());
162 } else {
163 let difference_index = if first_maybe_changed {
164 0
165 } else {
166 (1..current_children.len())
167 .find(|&i| maybe_changed(i))
168 .unwrap_or(0)
169 };
170
171 let _ = current_children.splice(
172 difference_index..difference_index + (current_children.len() - new_children.len()),
173 std::iter::empty(),
174 );
175 }
176 }
177
178 if current_children.len() < new_children.len() {
179 let first_maybe_changed = maybe_changed(0);
180 let last_maybe_changed = maybe_changed(current_children.len() - 1);
181
182 if !first_maybe_changed && last_maybe_changed {
183 current_children.extend(new_children[current_children.len()..].iter().map(new_state));
184 } else {
185 let difference_index = if first_maybe_changed {
186 0
187 } else {
188 (1..current_children.len())
189 .find(|&i| maybe_changed(i))
190 .unwrap_or(0)
191 };
192
193 let _ = current_children.splice(
194 difference_index..difference_index,
195 new_children[difference_index
196 ..difference_index + (new_children.len() - current_children.len())]
197 .iter()
198 .map(new_state),
199 );
200 }
201 }
202
203 for (child_state, new) in current_children.iter_mut().zip(new_children.iter_mut()) {
205 diff(child_state, new);
206 }
207}
208
209#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
211pub struct Tag(any::TypeId);
212
213impl Tag {
214 pub fn of<T>() -> Self
216 where
217 T: 'static,
218 {
219 Self(any::TypeId::of::<T>())
220 }
221
222 pub fn stateless() -> Self {
224 Self::of::<()>()
225 }
226}
227
228pub enum State {
230 None,
232
233 Some(Box<dyn Any>),
235}
236
237impl State {
238 pub fn new<T>(state: T) -> Self
240 where
241 T: 'static,
242 {
243 State::Some(Box::new(state))
244 }
245
246 pub fn downcast_ref<T>(&self) -> &T
251 where
252 T: 'static,
253 {
254 match self {
255 State::None => panic!("Downcast on stateless state"),
256 State::Some(state) => state.downcast_ref().expect("Downcast widget state"),
257 }
258 }
259
260 pub fn downcast_mut<T>(&mut self) -> &mut T
265 where
266 T: 'static,
267 {
268 match self {
269 State::None => panic!("Downcast on stateless state"),
270 State::Some(state) => state.downcast_mut().expect("Downcast widget state"),
271 }
272 }
273}
274
275impl fmt::Debug for State {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 match self {
278 Self::None => write!(f, "State::None"),
279 Self::Some(_) => write!(f, "State::Some"),
280 }
281 }
282}