1use std::fmt::Debug;
4
5use shipyard::{
6 Component,
7 EntitiesViewMut,
8 Get,
9 View,
10 ViewMut,
11};
12
13use crate::NodeId;
14
15#[derive(PartialEq, Eq, Clone, Debug, Component)]
17pub struct ShadowTree {
18 pub shadow_roots: Vec<NodeId>,
20 pub slot: Option<NodeId>,
22}
23
24#[derive(PartialEq, Eq, Clone, Debug, Component)]
26pub struct Node {
27 parent: Option<NodeId>,
28 children: Vec<NodeId>,
29 child_subtree: Option<ShadowTree>,
30 slot_for_light_tree: Option<NodeId>,
32 root_for_light_tree: Option<NodeId>,
34 height: u16,
35}
36
37pub type TreeRefView<'a> = View<'a, Node>;
39pub type TreeMutView<'a> = (EntitiesViewMut<'a>, ViewMut<'a, Node>);
41
42pub trait TreeRef {
44 #[inline]
46 fn parent_id_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Option<NodeId> {
47 let root_for_light_tree = self.root_for_light_tree(id);
49 match (root_for_light_tree, enter_shadow_dom) {
50 (Some(id), true) => Some(id),
51 _ => {
52 let parent_id = self.parent_id(id);
53 if enter_shadow_dom {
54 parent_id.map(|id| {
56 self.shadow_tree(id)
57 .and_then(|tree| tree.slot)
58 .unwrap_or(id)
59 })
60 } else {
61 parent_id
62 }
63 }
64 }
65 }
66 fn parent_id(&self, id: NodeId) -> Option<NodeId>;
68 #[inline]
70 fn children_ids_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Vec<NodeId> {
71 let shadow_tree = self.shadow_tree(id);
72 let slot_of_light_tree = self.slot_for_light_tree(id);
73 match (shadow_tree, slot_of_light_tree, enter_shadow_dom) {
74 (Some(tree), _, true) => tree.shadow_roots.clone(),
76 (None, Some(id), true) => self.children_ids(id),
78 _ => self.children_ids(id),
79 }
80 }
81 fn children_ids(&self, id: NodeId) -> Vec<NodeId>;
83 fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree>;
85 fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId>;
87 fn root_for_light_tree(&self, id: NodeId) -> Option<NodeId>;
89 fn height(&self, id: NodeId) -> Option<u16>;
91 fn contains(&self, id: NodeId) -> bool;
93}
94
95pub trait TreeMut: TreeRef {
97 fn remove(&mut self, id: NodeId);
99 fn create_node(&mut self, id: NodeId);
101 fn add_child(&mut self, parent: NodeId, new: NodeId);
103 fn replace(&mut self, old_id: NodeId, new_id: NodeId);
105 fn insert_before(&mut self, old_id: NodeId, new_id: NodeId);
107 fn insert_after(&mut self, old_id: NodeId, new_id: NodeId);
109 fn create_subtree(&mut self, id: NodeId, shadow_roots: Vec<NodeId>, slot: Option<NodeId>);
111 fn remove_subtree(&mut self, id: NodeId);
113}
114
115impl TreeRef for TreeRefView<'_> {
116 fn parent_id(&self, id: NodeId) -> Option<NodeId> {
117 self.get(id).ok()?.parent
118 }
119
120 fn children_ids(&self, id: NodeId) -> Vec<NodeId> {
121 self.get(id)
122 .map(|node| node.children.clone())
123 .unwrap_or_default()
124 }
125
126 fn height(&self, id: NodeId) -> Option<u16> {
127 Some(self.get(id).ok()?.height)
128 }
129
130 fn contains(&self, id: NodeId) -> bool {
131 self.get(id).is_ok()
132 }
133
134 fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree> {
135 self.get(id).ok()?.child_subtree.as_ref()
136 }
137
138 fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
139 self.get(id).ok()?.slot_for_light_tree
140 }
141
142 fn root_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
143 self.get(id).ok()?.root_for_light_tree
144 }
145}
146
147impl TreeMut for TreeMutView<'_> {
148 fn remove(&mut self, id: NodeId) {
149 fn recurse(tree: &mut TreeMutView<'_>, id: NodeId) {
150 let (light_tree, children) = {
151 let node = (&mut tree.1).get(id).unwrap();
152 (node.slot_for_light_tree, std::mem::take(&mut node.children))
153 };
154
155 for child in children {
156 recurse(tree, child);
157 }
158
159 if let Some(light_tree) = light_tree {
161 let root_for_light_tree = (&mut tree.1).get(light_tree).unwrap();
162
163 if let Some(shadow_tree) = &mut root_for_light_tree.child_subtree {
164 shadow_tree.slot = None;
165 }
166
167 debug_assert!(
168 root_for_light_tree.children.is_empty(),
169 "ShadowTree root should have no children when slot is removed."
170 );
171 }
172 }
173
174 {
175 let mut node_data_mut = &mut self.1;
176 if let Some(parent) = node_data_mut.get(id).unwrap().parent {
177 let parent = (&mut node_data_mut).get(parent).unwrap();
178 parent.children.retain(|&child| child != id);
179 }
180 }
181
182 recurse(self, id);
183 }
184
185 fn create_node(&mut self, id: NodeId) {
186 let (entities, node_data_mut) = self;
187 entities.add_component(
188 id,
189 node_data_mut,
190 Node {
191 parent: None,
192 children: Vec::new(),
193 height: 0,
194 child_subtree: None,
195 slot_for_light_tree: None,
196 root_for_light_tree: None,
197 },
198 );
199 }
200
201 fn add_child(&mut self, parent: NodeId, new: NodeId) {
202 {
203 let mut node_state = &mut self.1;
204 (&mut node_state).get(new).unwrap().parent = Some(parent);
205 let parent = (&mut node_state).get(parent).unwrap();
206 parent.children.push(new);
207 }
208 let height = child_height((&self.1).get(parent).unwrap(), self);
209 set_height(self, new, height);
210 }
211
212 fn replace(&mut self, old_id: NodeId, new_id: NodeId) {
213 {
214 let mut node_state = &mut self.1;
215 if let Some(parent_id) = node_state.get(old_id).unwrap().parent {
217 let parent = (&mut node_state).get(parent_id).unwrap();
218 for id in &mut parent.children {
219 if *id == old_id {
220 *id = new_id;
221 break;
222 }
223 }
224 let height = child_height((&self.1).get(parent_id).unwrap(), self);
225 set_height(self, new_id, height);
226 }
227 }
228 self.remove(old_id);
229 }
230
231 fn insert_before(&mut self, old_id: NodeId, new_id: NodeId) {
232 let new_parent_id = {
233 let new_id = self.1.get(new_id).unwrap();
234 new_id.parent
235 };
236 if let Some(new_parent_id) = new_parent_id {
237 (&mut self.1)
238 .get(new_parent_id)
239 .unwrap()
240 .children
241 .retain(|id| *id != new_id);
242 }
243
244 let parent_id = {
245 let old_node = self.1.get(old_id).unwrap();
246 old_node.parent.expect("tried to insert before root")
247 };
248 (&mut self.1).get(new_id).unwrap().parent = Some(parent_id);
249
250 let parent = (&mut self.1).get(parent_id).unwrap();
251 let index = parent
252 .children
253 .iter()
254 .position(|child| *child == old_id)
255 .unwrap();
256 parent.children.insert(index, new_id);
257 let height = child_height((&self.1).get(parent_id).unwrap(), self);
258 set_height(self, new_id, height);
259 }
260
261 fn insert_after(&mut self, old_id: NodeId, new_id: NodeId) {
262 let new_parent_id = {
263 let new_id = self.1.get(new_id).unwrap();
264 new_id.parent
265 };
266 if let Some(new_parent_id) = new_parent_id {
267 (&mut self.1)
268 .get(new_parent_id)
269 .unwrap()
270 .children
271 .retain(|id| *id != new_id);
272 }
273
274 let mut node_state = &mut self.1;
275 let old_node = node_state.get(old_id).unwrap();
276 let parent_id = old_node.parent.expect("tried to insert after root");
277 (&mut node_state).get(new_id).unwrap().parent = Some(parent_id);
278 let parent = (&mut node_state).get(parent_id).unwrap();
279 let index = parent
280 .children
281 .iter()
282 .position(|child| *child == old_id)
283 .unwrap();
284 parent.children.insert(index + 1, new_id);
285 let height = child_height((&self.1).get(parent_id).unwrap(), self);
286 set_height(self, new_id, height);
287 }
288
289 fn create_subtree(&mut self, id: NodeId, shadow_roots: Vec<NodeId>, slot: Option<NodeId>) {
290 let (_, node_data_mut) = self;
291
292 let light_root_height;
293 {
294 let shadow_tree = ShadowTree {
295 shadow_roots: shadow_roots.clone(),
296 slot,
297 };
298
299 let light_root = node_data_mut
300 .get(id)
301 .expect("tried to create shadow_tree with non-existent id");
302
303 light_root.child_subtree = Some(shadow_tree);
304 light_root_height = light_root.height;
305
306 if let Some(slot) = slot {
307 let slot = node_data_mut
308 .get(slot)
309 .expect("tried to create shadow_tree with non-existent slot");
310 slot.slot_for_light_tree = Some(id);
311 }
312 }
313
314 for root in shadow_roots {
316 (&mut self.1).get(root).unwrap().root_for_light_tree = Some(id);
317 set_height(self, root, light_root_height + 1);
318 }
319 }
320
321 fn remove_subtree(&mut self, id: NodeId) {
322 let (_, node_data_mut) = self;
323
324 if let Ok(node) = node_data_mut.get(id) {
325 if let Some(shadow_tree) = node.child_subtree.take() {
326 if let Some(slot) = shadow_tree.slot {
328 let slot = node_data_mut
329 .get(slot)
330 .expect("tried to remove shadow_tree with non-existent slot");
331 slot.slot_for_light_tree = None;
332 }
333
334 let node = node_data_mut.get(id).unwrap();
335
336 let height = node.height;
338 for child in node.children.clone() {
339 set_height(self, child, height + 1);
340 }
341
342 for root in &shadow_tree.shadow_roots {
344 set_height(self, *root, 0);
345 }
346 }
347 }
348 }
349}
350
351fn child_height(parent: &Node, tree: &impl TreeRef) -> u16 {
352 match &parent.child_subtree {
353 Some(shadow_tree) => {
354 if let Some(slot) = shadow_tree.slot {
355 tree.height(slot)
356 .expect("Attempted to read a slot that does not exist")
357 + 1
358 } else {
359 panic!("Attempted to read the height of a child of a node with a shadow tree, but the shadow tree does not have a slot. Every shadow tree attached to a node with children must have a slot.")
360 }
361 }
362 None => parent.height + 1,
363 }
364}
365
366fn set_height(tree: &mut TreeMutView<'_>, node: NodeId, height: u16) {
368 let (shadow_tree, light_tree, children) = {
369 let mut node_data_mut = &mut tree.1;
370 let node = (&mut node_data_mut).get(node).unwrap();
371 node.height = height;
372
373 (
374 node.child_subtree.clone(),
375 node.slot_for_light_tree,
376 node.children.clone(),
377 )
378 };
379
380 if let Some(shadow_tree) = shadow_tree {
382 for &shadow_root in &shadow_tree.shadow_roots {
384 set_height(tree, shadow_root, height + 1);
385 }
386 } else {
387 for child in children {
389 set_height(tree, child, height + 1);
390 }
391 }
392
393 if let Some(light_tree) = light_tree {
395 let children = (&tree.1).get(light_tree).unwrap().children.clone();
396 for child in children {
397 set_height(tree, child, height + 1);
398 }
399 }
400}
401
402impl TreeRef for TreeMutView<'_> {
403 fn parent_id(&self, id: NodeId) -> Option<NodeId> {
404 let node_data = &self.1;
405 node_data.get(id).unwrap().parent
406 }
407
408 fn children_ids(&self, id: NodeId) -> Vec<NodeId> {
409 let node_data = &self.1;
410 node_data
411 .get(id)
412 .map(|node| node.children.clone())
413 .unwrap_or_default()
414 }
415
416 fn height(&self, id: NodeId) -> Option<u16> {
417 let node_data = &self.1;
418 node_data.get(id).map(|node| node.height).ok()
419 }
420
421 fn contains(&self, id: NodeId) -> bool {
422 self.1.get(id).is_ok()
423 }
424
425 fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree> {
426 let node_data = &self.1;
427 node_data.get(id).ok()?.child_subtree.as_ref()
428 }
429
430 fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
431 let node_data = &self.1;
432 node_data.get(id).ok()?.slot_for_light_tree
433 }
434
435 fn root_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
436 let node_data = &self.1;
437 node_data.get(id).ok()?.root_for_light_tree
438 }
439}
440
441#[test]
442fn creation() {
443 use shipyard::World;
444 #[allow(dead_code)]
445 #[derive(Component)]
446 struct Num(i32);
447
448 let mut world = World::new();
449 let parent_id = world.add_entity(Num(1i32));
450 let child_id = world.add_entity(Num(0i32));
451
452 let mut tree = world.borrow::<TreeMutView>().unwrap();
453
454 tree.create_node(parent_id);
455 tree.create_node(child_id);
456
457 tree.add_child(parent_id, child_id);
458
459 assert_eq!(tree.height(parent_id), Some(0));
460 assert_eq!(tree.height(child_id), Some(1));
461 assert_eq!(tree.parent_id(parent_id), None);
462 assert_eq!(tree.parent_id(child_id).unwrap(), parent_id);
463 assert_eq!(tree.children_ids(parent_id), &[child_id]);
464}
465
466#[test]
467fn shadow_tree() {
468 use shipyard::World;
469 #[allow(dead_code)]
470 #[derive(Component)]
471 struct Num(i32);
472
473 let mut world = World::new();
474 let parent_id = world.add_entity(Num(1i32));
476 let child_id = world.add_entity(Num(0i32));
477
478 let shadow_parent_id = world.add_entity(Num(2i32));
480 let shadow_child_id = world.add_entity(Num(3i32));
481
482 let mut tree = world.borrow::<TreeMutView>().unwrap();
483
484 tree.create_node(parent_id);
485 tree.create_node(child_id);
486
487 tree.add_child(parent_id, child_id);
488
489 tree.create_node(shadow_parent_id);
490 tree.create_node(shadow_child_id);
491
492 tree.add_child(shadow_parent_id, shadow_child_id);
493
494 assert_eq!(tree.height(parent_id), Some(0));
496 assert_eq!(tree.height(child_id), Some(1));
497 assert_eq!(tree.parent_id(parent_id), None);
498 assert_eq!(tree.parent_id(child_id).unwrap(), parent_id);
499 assert_eq!(tree.children_ids(parent_id), &[child_id]);
500
501 assert_eq!(tree.height(shadow_parent_id), Some(0));
502 assert_eq!(tree.height(shadow_child_id), Some(1));
503 assert_eq!(tree.parent_id(shadow_parent_id), None);
504 assert_eq!(tree.parent_id(shadow_child_id).unwrap(), shadow_parent_id);
505 assert_eq!(tree.children_ids(shadow_parent_id), &[shadow_child_id]);
506
507 tree.create_subtree(parent_id, vec![shadow_parent_id], Some(shadow_child_id));
509
510 assert_eq!(tree.height(parent_id), Some(0));
511 assert_eq!(tree.height(shadow_parent_id), Some(1));
512 assert_eq!(tree.height(shadow_child_id), Some(2));
513 assert_eq!(tree.height(child_id), Some(3));
514 assert_eq!(
515 tree.1
516 .get(parent_id)
517 .unwrap()
518 .child_subtree
519 .as_ref()
520 .unwrap()
521 .shadow_roots,
522 &[shadow_parent_id]
523 );
524 assert_eq!(
525 tree.1.get(shadow_child_id).unwrap().slot_for_light_tree,
526 Some(parent_id)
527 );
528
529 tree.remove_subtree(parent_id);
531
532 assert_eq!(tree.height(parent_id), Some(0));
534 assert_eq!(tree.height(child_id), Some(1));
535 assert_eq!(tree.parent_id(parent_id), None);
536 assert_eq!(tree.parent_id(child_id).unwrap(), parent_id);
537 assert_eq!(tree.children_ids(parent_id), &[child_id]);
538
539 assert_eq!(tree.height(shadow_parent_id), Some(0));
540 assert_eq!(tree.height(shadow_child_id), Some(1));
541 assert_eq!(tree.parent_id(shadow_parent_id), None);
542 assert_eq!(tree.parent_id(shadow_child_id).unwrap(), shadow_parent_id);
543 assert_eq!(tree.children_ids(shadow_parent_id), &[shadow_child_id]);
544}
545
546#[test]
547fn insertion() {
548 use shipyard::World;
549 #[allow(dead_code)]
550 #[derive(Component)]
551 struct Num(i32);
552
553 let mut world = World::new();
554 let parent = world.add_entity(Num(0));
555 let child = world.add_entity(Num(2));
556 let before = world.add_entity(Num(1));
557 let after = world.add_entity(Num(3));
558
559 let mut tree = world.borrow::<TreeMutView>().unwrap();
560
561 tree.create_node(parent);
562 tree.create_node(child);
563 tree.create_node(before);
564 tree.create_node(after);
565
566 tree.add_child(parent, child);
567 tree.insert_before(child, before);
568 tree.insert_after(child, after);
569
570 assert_eq!(tree.height(parent), Some(0));
571 assert_eq!(tree.height(child), Some(1));
572 assert_eq!(tree.height(before), Some(1));
573 assert_eq!(tree.height(after), Some(1));
574 assert_eq!(tree.parent_id(before).unwrap(), parent);
575 assert_eq!(tree.parent_id(child).unwrap(), parent);
576 assert_eq!(tree.parent_id(after).unwrap(), parent);
577 assert_eq!(tree.children_ids(parent), &[before, child, after]);
578}
579
580#[test]
581fn deletion() {
582 use shipyard::World;
583 #[allow(dead_code)]
584 #[derive(Component)]
585 struct Num(i32);
586
587 let mut world = World::new();
588 let parent = world.add_entity(Num(0));
589 let child = world.add_entity(Num(2));
590 let before = world.add_entity(Num(1));
591 let after = world.add_entity(Num(3));
592
593 let mut tree = world.borrow::<TreeMutView>().unwrap();
594
595 tree.create_node(parent);
596 tree.create_node(child);
597 tree.create_node(before);
598 tree.create_node(after);
599
600 tree.add_child(parent, child);
601 tree.insert_before(child, before);
602 tree.insert_after(child, after);
603
604 assert_eq!(tree.height(parent), Some(0));
605 assert_eq!(tree.height(child), Some(1));
606 assert_eq!(tree.height(before), Some(1));
607 assert_eq!(tree.height(after), Some(1));
608 assert_eq!(tree.parent_id(before).unwrap(), parent);
609 assert_eq!(tree.parent_id(child).unwrap(), parent);
610 assert_eq!(tree.parent_id(after).unwrap(), parent);
611 assert_eq!(tree.children_ids(parent), &[before, child, after]);
612
613 tree.remove(child);
614
615 assert_eq!(tree.height(parent), Some(0));
616 assert_eq!(tree.height(before), Some(1));
617 assert_eq!(tree.height(after), Some(1));
618 assert_eq!(tree.parent_id(before).unwrap(), parent);
619 assert_eq!(tree.parent_id(after).unwrap(), parent);
620 assert_eq!(tree.children_ids(parent), &[before, after]);
621
622 tree.remove(before);
623
624 assert_eq!(tree.height(parent), Some(0));
625 assert_eq!(tree.height(after), Some(1));
626 assert_eq!(tree.parent_id(after).unwrap(), parent);
627 assert_eq!(tree.children_ids(parent), &[after]);
628
629 tree.remove(after);
630
631 assert_eq!(tree.height(parent), Some(0));
632 assert_eq!(tree.children_ids(parent), &[]);
633}