iced_core/widget/
tree.rs
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
97 self.children.iter_mut().zip(new_children.iter())
98 {
99 diff(child_state, new);
100 }
101
102 if self.children.len() < new_children.len() {
103 self.children.extend(
104 new_children[self.children.len()..].iter().map(new_state),
105 );
106 }
107 }
108}
109
110pub fn diff_children_custom_with_search<T>(
116 current_children: &mut Vec<Tree>,
117 new_children: &[T],
118 diff: impl Fn(&mut Tree, &T),
119 maybe_changed: impl Fn(usize) -> bool,
120 new_state: impl Fn(&T) -> Tree,
121) {
122 if new_children.is_empty() {
123 current_children.clear();
124 return;
125 }
126
127 if current_children.is_empty() {
128 current_children.extend(new_children.iter().map(new_state));
129 return;
130 }
131
132 let first_maybe_changed = maybe_changed(0);
133 let last_maybe_changed = maybe_changed(current_children.len() - 1);
134
135 if current_children.len() > new_children.len() {
136 if !first_maybe_changed && last_maybe_changed {
137 current_children.truncate(new_children.len());
138 } else {
139 let difference_index = if first_maybe_changed {
140 0
141 } else {
142 (1..current_children.len())
143 .find(|&i| maybe_changed(i))
144 .unwrap_or(0)
145 };
146
147 let _ = current_children.splice(
148 difference_index
149 ..difference_index
150 + (current_children.len() - new_children.len()),
151 std::iter::empty(),
152 );
153 }
154 }
155
156 if current_children.len() < new_children.len() {
157 let first_maybe_changed = maybe_changed(0);
158 let last_maybe_changed = maybe_changed(current_children.len() - 1);
159
160 if !first_maybe_changed && last_maybe_changed {
161 current_children.extend(
162 new_children[current_children.len()..].iter().map(new_state),
163 );
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,
175 new_children[difference_index
176 ..difference_index
177 + (new_children.len() - current_children.len())]
178 .iter()
179 .map(new_state),
180 );
181 }
182 }
183
184 for (child_state, new) in
186 current_children.iter_mut().zip(new_children.iter())
187 {
188 diff(child_state, new);
189 }
190}
191
192#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
194pub struct Tag(any::TypeId);
195
196impl Tag {
197 pub fn of<T>() -> Self
199 where
200 T: 'static,
201 {
202 Self(any::TypeId::of::<T>())
203 }
204
205 pub fn stateless() -> Self {
207 Self::of::<()>()
208 }
209}
210
211pub enum State {
213 None,
215
216 Some(Box<dyn Any>),
218}
219
220impl State {
221 pub fn new<T>(state: T) -> Self
223 where
224 T: 'static,
225 {
226 State::Some(Box::new(state))
227 }
228
229 pub fn downcast_ref<T>(&self) -> &T
234 where
235 T: 'static,
236 {
237 match self {
238 State::None => panic!("Downcast on stateless state"),
239 State::Some(state) => {
240 state.downcast_ref().expect("Downcast widget state")
241 }
242 }
243 }
244
245 pub fn downcast_mut<T>(&mut self) -> &mut T
250 where
251 T: 'static,
252 {
253 match self {
254 State::None => panic!("Downcast on stateless state"),
255 State::Some(state) => {
256 state.downcast_mut().expect("Downcast widget state")
257 }
258 }
259 }
260}
261
262impl fmt::Debug for State {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 match self {
265 Self::None => write!(f, "State::None"),
266 Self::Some(_) => write!(f, "State::Some"),
267 }
268 }
269}