1use crate::{Size, Vector, Widget};
3
4use std::any::{self, Any};
5use std::fmt;
6
7#[derive(Debug)]
11pub struct Tree {
12 pub tag: Tag,
14
15 pub state: State,
17
18 pub translation: Vector,
20
21 pub size: Size,
23
24 pub children: Vec<Tree>,
26}
27
28impl Tree {
29 pub fn empty() -> Self {
31 Self {
32 tag: Tag::stateless(),
33 state: State::None,
34 translation: Vector::ZERO,
35 size: Size::ZERO,
36 children: Vec::new(),
37 }
38 }
39
40 pub fn new<Message, Theme, Renderer>(widget: &impl Widget<Message, Theme, Renderer>) -> Self
42 where
43 Renderer: crate::Renderer,
44 {
45 Self {
46 tag: widget.tag(),
47 state: widget.state(),
48 translation: Vector::ZERO,
49 size: Size::ZERO,
50 children: Vec::new(),
51 }
52 }
53
54 pub fn diff<Message, Theme, Renderer>(
63 &mut self,
64 new: &mut impl Widget<Message, Theme, Renderer>,
65 ) where
66 Renderer: crate::Renderer,
67 {
68 if self.tag != new.tag() {
69 *self = Self::new(new);
70 }
71
72 new.diff(self);
73 }
74
75 pub fn diff_children<Message, Theme, Renderer>(
77 &mut self,
78 new_children: &mut [impl Widget<Message, Theme, Renderer>],
79 ) where
80 Renderer: crate::Renderer,
81 {
82 diff_children(&mut self.children, new_children);
83 }
84
85 pub fn diff_children_custom<T>(
88 &mut self,
89 new_children: &mut [T],
90 diff: impl Fn(&mut Tree, &mut T),
91 new_state: impl Fn(&T) -> Self,
92 ) {
93 diff_children_custom(&mut self.children, new_children, diff, new_state);
94 }
95}
96
97pub fn diff_children<Message, Theme, Renderer>(
99 old_children: &mut Vec<Tree>,
100 new_children: &mut [impl Widget<Message, Theme, Renderer>],
101) where
102 Renderer: crate::Renderer,
103{
104 diff_children_custom(old_children, new_children, Tree::diff, |widget| {
105 Tree::new(widget)
106 });
107}
108
109pub fn diff_children_custom<T>(
112 old_children: &mut Vec<Tree>,
113 new_children: &mut [T],
114 diff: impl Fn(&mut Tree, &mut T),
115 new_state: impl Fn(&T) -> Tree,
116) {
117 if old_children.len() > new_children.len() {
118 old_children.truncate(new_children.len());
119 }
120
121 if old_children.len() < new_children.len() {
122 old_children.extend(new_children[old_children.len()..].iter().map(new_state));
123 }
124
125 for (child_state, new) in old_children.iter_mut().zip(new_children.iter_mut()) {
126 diff(child_state, new);
127 }
128}
129
130pub fn diff_children_custom_with_search<T>(
136 current_children: &mut Vec<Tree>,
137 new_children: &mut [T],
138 diff: impl Fn(&mut Tree, &mut T),
139 maybe_changed: impl Fn(usize) -> bool,
140 new_state: impl Fn(&T) -> Tree,
141) {
142 if new_children.is_empty() {
143 current_children.clear();
144 return;
145 }
146
147 if current_children.is_empty() {
148 current_children.extend(new_children.iter().map(new_state));
149
150 for (child_state, new) in current_children.iter_mut().zip(new_children.iter_mut()) {
152 diff(child_state, new);
153 }
154
155 return;
156 }
157
158 let first_maybe_changed = maybe_changed(0);
159 let last_maybe_changed = maybe_changed(current_children.len() - 1);
160
161 if current_children.len() > new_children.len() {
162 if !first_maybe_changed && last_maybe_changed {
163 current_children.truncate(new_children.len());
164 } else {
165 let difference_index = if first_maybe_changed {
166 0
167 } else {
168 (1..current_children.len())
169 .find(|&i| maybe_changed(i))
170 .unwrap_or(0)
171 };
172
173 let _ = current_children.splice(
174 difference_index..difference_index + (current_children.len() - new_children.len()),
175 std::iter::empty(),
176 );
177 }
178 }
179
180 if current_children.len() < new_children.len() {
181 let first_maybe_changed = maybe_changed(0);
182 let last_maybe_changed = maybe_changed(current_children.len() - 1);
183
184 if !first_maybe_changed && last_maybe_changed {
185 current_children.extend(new_children[current_children.len()..].iter().map(new_state));
186 } else {
187 let difference_index = if first_maybe_changed {
188 0
189 } else {
190 (1..current_children.len())
191 .find(|&i| maybe_changed(i))
192 .unwrap_or(0)
193 };
194
195 let _ = current_children.splice(
196 difference_index..difference_index,
197 new_children[difference_index
198 ..difference_index + (new_children.len() - current_children.len())]
199 .iter()
200 .map(new_state),
201 );
202 }
203 }
204
205 for (child_state, new) in current_children.iter_mut().zip(new_children.iter_mut()) {
207 diff(child_state, new);
208 }
209}
210
211#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
213pub struct Tag(any::TypeId);
214
215impl Tag {
216 pub fn of<T>() -> Self
218 where
219 T: 'static,
220 {
221 Self(any::TypeId::of::<T>())
222 }
223
224 pub fn stateless() -> Self {
226 Self::of::<()>()
227 }
228}
229
230pub enum State {
232 None,
234
235 Some(Box<dyn Any>),
237}
238
239impl State {
240 pub fn new<T>(state: T) -> Self
242 where
243 T: 'static,
244 {
245 State::Some(Box::new(state))
246 }
247
248 pub fn downcast_ref<T>(&self) -> &T
253 where
254 T: 'static,
255 {
256 match self {
257 State::None => panic!("Downcast on stateless state"),
258 State::Some(state) => state.downcast_ref().expect("Downcast widget state"),
259 }
260 }
261
262 pub fn downcast_mut<T>(&mut self) -> &mut T
267 where
268 T: 'static,
269 {
270 match self {
271 State::None => panic!("Downcast on stateless state"),
272 State::Some(state) => state.downcast_mut().expect("Downcast widget state"),
273 }
274 }
275}
276
277impl fmt::Debug for State {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 match self {
280 Self::None => write!(f, "State::None"),
281 Self::Some(_) => write!(f, "State::Some"),
282 }
283 }
284}