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 self.diff_children_custom(
78 new_children,
79 |tree, widget| tree.diff(widget.borrow_mut()),
80 |widget| Self::new(widget.borrow()),
81 );
82 }
83
84 pub fn diff_children_custom<T>(
87 &mut self,
88 new_children: &mut [T],
89 diff: impl Fn(&mut Tree, &mut 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 if self.children.len() < new_children.len() {
97 self.children
98 .extend(new_children[self.children.len()..].iter().map(new_state));
99 }
100
101 for (child_state, new) in self.children.iter_mut().zip(new_children.iter_mut()) {
102 diff(child_state, new);
103 }
104 }
105}
106
107pub fn diff_children_custom_with_search<T>(
113 current_children: &mut Vec<Tree>,
114 new_children: &mut [T],
115 diff: impl Fn(&mut Tree, &mut 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
127 for (child_state, new) in current_children.iter_mut().zip(new_children.iter_mut()) {
129 diff(child_state, new);
130 }
131
132 return;
133 }
134
135 let first_maybe_changed = maybe_changed(0);
136 let last_maybe_changed = maybe_changed(current_children.len() - 1);
137
138 if current_children.len() > new_children.len() {
139 if !first_maybe_changed && last_maybe_changed {
140 current_children.truncate(new_children.len());
141 } else {
142 let difference_index = if first_maybe_changed {
143 0
144 } else {
145 (1..current_children.len())
146 .find(|&i| maybe_changed(i))
147 .unwrap_or(0)
148 };
149
150 let _ = current_children.splice(
151 difference_index..difference_index + (current_children.len() - new_children.len()),
152 std::iter::empty(),
153 );
154 }
155 }
156
157 if current_children.len() < new_children.len() {
158 let first_maybe_changed = maybe_changed(0);
159 let last_maybe_changed = maybe_changed(current_children.len() - 1);
160
161 if !first_maybe_changed && last_maybe_changed {
162 current_children.extend(new_children[current_children.len()..].iter().map(new_state));
163 } else {
164 let difference_index = if first_maybe_changed {
165 0
166 } else {
167 (1..current_children.len())
168 .find(|&i| maybe_changed(i))
169 .unwrap_or(0)
170 };
171
172 let _ = current_children.splice(
173 difference_index..difference_index,
174 new_children[difference_index
175 ..difference_index + (new_children.len() - current_children.len())]
176 .iter()
177 .map(new_state),
178 );
179 }
180 }
181
182 for (child_state, new) in current_children.iter_mut().zip(new_children.iter_mut()) {
184 diff(child_state, new);
185 }
186}
187
188#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
190pub struct Tag(any::TypeId);
191
192impl Tag {
193 pub fn of<T>() -> Self
195 where
196 T: 'static,
197 {
198 Self(any::TypeId::of::<T>())
199 }
200
201 pub fn stateless() -> Self {
203 Self::of::<()>()
204 }
205}
206
207pub enum State {
209 None,
211
212 Some(Box<dyn Any>),
214}
215
216impl State {
217 pub fn new<T>(state: T) -> Self
219 where
220 T: 'static,
221 {
222 State::Some(Box::new(state))
223 }
224
225 pub fn downcast_ref<T>(&self) -> &T
230 where
231 T: 'static,
232 {
233 match self {
234 State::None => panic!("Downcast on stateless state"),
235 State::Some(state) => state.downcast_ref().expect("Downcast widget state"),
236 }
237 }
238
239 pub fn downcast_mut<T>(&mut self) -> &mut T
244 where
245 T: 'static,
246 {
247 match self {
248 State::None => panic!("Downcast on stateless state"),
249 State::Some(state) => state.downcast_mut().expect("Downcast widget state"),
250 }
251 }
252}
253
254impl fmt::Debug for State {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 match self {
257 Self::None => write!(f, "State::None"),
258 Self::Some(_) => write!(f, "State::Some"),
259 }
260 }
261}