1use crate::id::{Id, Internal};
3use crate::Widget;
4use std::any::{self, Any};
5use std::borrow::{Borrow, BorrowMut, Cow};
6use std::collections::{HashMap, VecDeque};
7use std::hash::Hash;
8use std::{fmt, mem};
9
10thread_local! {
11 pub static NAMED: std::cell::RefCell<HashMap<Cow<'static, str>, (State, Vec<(usize, Tree)>)>> = std::cell::RefCell::new(HashMap::new());
13}
14
15#[derive(Debug)]
19pub struct Tree {
20 pub tag: Tag,
22
23 pub id: Option<Id>,
25
26 pub state: State,
28
29 pub children: Vec<Tree>,
31}
32
33impl Tree {
34 pub fn empty() -> Self {
36 Self {
37 id: None,
38 tag: Tag::stateless(),
39 state: State::None,
40 children: Vec::new(),
41 }
42 }
43
44 pub fn new<'a, Message, Theme, Renderer>(
46 widget: impl Borrow<dyn Widget<Message, Theme, Renderer> + 'a>,
47 ) -> Self
48 where
49 Renderer: crate::Renderer,
50 {
51 let widget = widget.borrow();
52
53 Self {
54 id: widget.id(),
55 tag: widget.tag(),
56 state: widget.state(),
57 children: widget.children(),
58 }
59 }
60
61 pub fn take_all_named(
63 &mut self,
64 ) -> HashMap<Cow<'static, str>, (State, Vec<(usize, Tree)>)> {
65 let mut named = HashMap::new();
66 struct Visit {
67 parent: Cow<'static, str>,
68 index: usize,
69 visited: bool,
70 }
71 let mut stack = vec![(self, None)];
74 while let Some((tree, visit)) = stack.pop() {
75 if let Some(Id(Internal::Custom(_, n))) = tree.id.clone() {
76 let state = mem::replace(&mut tree.state, State::None);
77 let children_count = tree.children.len();
78 let children =
79 tree.children.iter_mut().enumerate().rev().map(|(i, c)| {
80 if matches!(c.id, Some(Id(Internal::Custom(_, _)))) {
81 (c, None)
82 } else {
83 (
84 c,
85 Some(Visit {
86 index: i,
87 parent: n.clone(),
88 visited: false,
89 }),
90 )
91 }
92 });
93 _ = named.insert(
94 n.clone(),
95 (state, Vec::with_capacity(children_count)),
96 );
97 stack.extend(children);
98 } else if let Some(visit) = visit {
99 if visit.visited {
100 named.get_mut(&visit.parent).unwrap().1.push((
101 visit.index,
102 mem::replace(
103 tree,
104 Tree {
105 id: tree.id.clone(),
106 tag: tree.tag,
107 ..Tree::empty()
108 },
109 ),
110 ));
111 } else {
112 let ptr = tree as *mut Tree;
113
114 stack.push((
115 #[allow(unsafe_code)]
117 unsafe {
119 ptr.as_mut().unwrap()
120 },
121 Some(Visit {
122 visited: true,
123 ..visit
124 }),
125 ));
126 stack.extend(tree.children.iter_mut().map(|c| (c, None)));
127 }
128 } else {
129 stack.extend(tree.children.iter_mut().map(|s| (s, None)));
130 }
131 }
132
133 named
134 }
135
136 pub fn find<'a>(&'a self, id: &Id) -> Option<&'a Tree> {
138 if self.id == Some(id.clone()) {
139 return Some(self);
140 }
141
142 for child in self.children.iter() {
143 if let Some(tree) = child.find(id) {
144 return Some(tree);
145 }
146 }
147
148 None
149 }
150
151 pub fn diff<'a, Message, Theme, Renderer>(
160 &mut self,
161 mut new: impl BorrowMut<dyn Widget<Message, Theme, Renderer> + 'a>,
162 ) where
163 Renderer: crate::Renderer,
164 {
165 let borrowed: &mut dyn Widget<Message, Theme, Renderer> =
166 new.borrow_mut();
167
168 let mut tag_match = self.tag == borrowed.tag();
169 if tag_match {
170 if let Some(Id(Internal::Custom(_, n))) = borrowed.id() {
171 if let Some((mut state, children)) = NAMED
172 .with(|named| named.borrow_mut().remove(&n))
173 .or_else(|| {
174 if let Some(Id(Internal::Custom(_, ref name))) = self.id
176 {
177 if name == &n {
178 Some((
179 mem::replace(&mut self.state, State::None),
180 self.children
181 .iter_mut()
182 .map(|s| {
183 mem::replace(
185 s,
186 Tree {
187 id: s.id.clone(),
188 tag: s.tag,
189 ..Tree::empty()
190 },
191 )
192 })
193 .enumerate()
194 .collect(),
195 ))
196 } else {
197 None
198 }
199 } else {
200 None
201 }
202 })
203 {
204 std::mem::swap(&mut self.state, &mut state);
205 let widget_children = borrowed.children();
206 if !tag_match
207 || self.children.len() != widget_children.len()
208 {
209 self.children = borrowed.children();
210 } else {
211 for (old_i, mut old) in children {
212 let Some(my_state) = self.children.get_mut(old_i)
213 else {
214 continue;
215 };
216 if my_state.tag != old.tag || {
217 !match (&old.id, &my_state.id) {
218 (
219 Some(Id(Internal::Custom(
220 _,
221 ref old_name,
222 ))),
223 Some(Id(Internal::Custom(
224 _,
225 ref my_name,
226 ))),
227 ) => old_name == my_name,
228 (
229 Some(Id(Internal::Set(a))),
230 Some(Id(Internal::Set(b))),
231 ) => a.len() == b.len(),
232 (
233 Some(Id(Internal::Unique(_))),
234 Some(Id(Internal::Unique(_))),
235 ) => true,
236 (None, None) => true,
237 _ => false,
238 }
239 } {
240 continue;
241 }
242
243 mem::swap(my_state, &mut old);
244 }
245 }
246 } else {
247 tag_match = false;
248 }
249 } else {
250 if let Some(id) = self.id.clone() {
251 borrowed.set_id(id);
252 }
253 if self.children.len() != borrowed.children().len() {
254 self.children = borrowed.children();
255 }
256 }
257 }
258 if tag_match {
259 borrowed.diff(self);
260 } else {
261 *self = Self::new(borrowed);
262 let borrowed = new.borrow_mut();
263 borrowed.diff(self);
264 }
265 }
266
267 pub fn diff_children<'a, Message, Theme, Renderer>(
269 &mut self,
270 new_children: &mut [impl BorrowMut<
271 dyn Widget<Message, Theme, Renderer> + 'a,
272 >],
273 ) where
274 Renderer: crate::Renderer,
275 {
276 self.diff_children_custom(
277 new_children,
278 new_children.iter().map(|c| c.borrow().id()).collect(),
279 |tree, widget| {
280 let borrowed: &mut dyn Widget<_, _, _> = widget.borrow_mut();
281
282 tree.diff(borrowed);
283 },
284 |widget| {
285 let borrowed: &dyn Widget<_, _, _> = widget.borrow();
286 Self::new(borrowed)
287 },
288 );
289 }
290
291 pub fn diff_children_custom<T>(
294 &mut self,
295 new_children: &mut [T],
296 new_ids: Vec<Option<Id>>,
297 diff: impl Fn(&mut Tree, &mut T),
298 new_state: impl Fn(&T) -> Self,
299 ) {
300 if self.children.len() > new_children.len() {
301 self.children.truncate(new_children.len());
302 }
303
304 let children_len = self.children.len();
305 let (mut id_map, mut id_list): (
306 HashMap<String, &mut Tree>,
307 VecDeque<(usize, &mut Tree)>,
308 ) = self.children.iter_mut().enumerate().fold(
309 (HashMap::new(), VecDeque::with_capacity(children_len)),
310 |(mut id_map, mut id_list), (i, c)| {
311 if let Some(id) = c.id.as_ref() {
312 if let Internal::Custom(_, ref name) = id.0 {
313 let _ = id_map.insert(name.to_string(), c);
314 } else {
315 id_list.push_back((i, c));
316 }
317 } else {
318 id_list.push_back((i, c));
319 }
320 (id_map, id_list)
321 },
322 );
323
324 let mut new_trees: Vec<(Tree, usize)> =
325 Vec::with_capacity(new_children.len());
326 for (i, (new, new_id)) in
327 new_children.iter_mut().zip(new_ids.iter()).enumerate()
328 {
329 let child_state = if let Some(c) = new_id.as_ref().and_then(|id| {
330 if let Internal::Custom(_, ref name) = id.0 {
331 id_map.remove(name.as_ref())
332 } else {
333 None
334 }
335 }) {
336 c
337 } else if let Some(i) = {
338 let mut found = None;
339 for c_i in 0..id_list.len() {
340 if id_list[c_i].0 == i {
341 found = Some(c_i);
342 break;
343 }
344 if i < c_i {
345 break;
346 }
347 }
348 found
349 } {
350 let c = id_list.remove(i).unwrap().1;
351 c
352 } else {
353 let mut my_new_state = new_state(new);
354 diff(&mut my_new_state, new);
355 new_trees.push((my_new_state, i));
356 continue;
357 };
358
359 diff(child_state, new);
360 }
361
362 for (new_tree, i) in new_trees {
363 if self.children.len() > i {
364 self.children[i] = new_tree;
365 } else {
366 self.children.push(new_tree);
367 }
368 }
369 }
370}
371
372pub fn diff_children_custom_with_search<T>(
378 current_children: &mut Vec<Tree>,
379 new_children: &mut [T],
380 diff: impl Fn(&mut Tree, &mut T),
381 maybe_changed: impl Fn(usize) -> bool,
382 new_state: impl Fn(&T) -> Tree,
383) {
384 if new_children.is_empty() {
385 current_children.clear();
386 return;
387 }
388
389 if current_children.is_empty() {
390 current_children.extend(new_children.iter().map(new_state));
391 return;
392 }
393
394 let first_maybe_changed = maybe_changed(0);
395 let last_maybe_changed = maybe_changed(current_children.len() - 1);
396
397 if current_children.len() > new_children.len() {
398 if !first_maybe_changed && last_maybe_changed {
399 current_children.truncate(new_children.len());
400 } else {
401 let difference_index = if first_maybe_changed {
402 0
403 } else {
404 (1..current_children.len())
405 .find(|&i| maybe_changed(i))
406 .unwrap_or(0)
407 };
408
409 let _ = current_children.splice(
410 difference_index
411 ..difference_index
412 + (current_children.len() - new_children.len()),
413 std::iter::empty(),
414 );
415 }
416 }
417
418 if current_children.len() < new_children.len() {
419 let first_maybe_changed = maybe_changed(0);
420 let last_maybe_changed = maybe_changed(current_children.len() - 1);
421
422 if !first_maybe_changed && last_maybe_changed {
423 current_children.extend(
424 new_children[current_children.len()..].iter().map(new_state),
425 );
426 } else {
427 let difference_index = if first_maybe_changed {
428 0
429 } else {
430 (1..current_children.len())
431 .find(|&i| maybe_changed(i))
432 .unwrap_or(0)
433 };
434
435 let _ = current_children.splice(
436 difference_index..difference_index,
437 new_children[difference_index
438 ..difference_index
439 + (new_children.len() - current_children.len())]
440 .iter()
441 .map(new_state),
442 );
443 }
444 }
445
446 for (child_state, new) in
448 current_children.iter_mut().zip(new_children.iter_mut())
449 {
450 diff(child_state, new);
451 }
452}
453
454#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
456pub struct Tag(any::TypeId);
457
458impl Tag {
459 pub fn of<T>() -> Self
461 where
462 T: 'static,
463 {
464 Self(any::TypeId::of::<T>())
465 }
466
467 pub fn stateless() -> Self {
469 Self::of::<()>()
470 }
471}
472
473pub enum State {
475 None,
477
478 Some(Box<dyn Any>),
480}
481
482impl State {
483 pub fn new<T>(state: T) -> Self
485 where
486 T: 'static,
487 {
488 State::Some(Box::new(state))
489 }
490
491 pub fn downcast_ref<T>(&self) -> &T
496 where
497 T: 'static,
498 {
499 match self {
500 State::None => panic!("Downcast on stateless state"),
501 State::Some(state) => {
502 state.downcast_ref().expect("Downcast widget state")
503 }
504 }
505 }
506
507 pub fn downcast_mut<T>(&mut self) -> &mut T
512 where
513 T: 'static,
514 {
515 match self {
516 State::None => panic!("Downcast on stateless state"),
517 State::Some(state) => {
518 state.downcast_mut().expect("Downcast widget state")
519 }
520 }
521 }
522}
523
524impl fmt::Debug for State {
525 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526 match self {
527 Self::None => write!(f, "State::None"),
528 Self::Some(_) => write!(f, "State::Some"),
529 }
530 }
531}