1use itertools::Itertools;
2use serde::{Deserialize, Serialize};
3use std::ops::Range;
4
5use crate::MoveDir;
6use crate::displayed_item::DisplayedItemRef;
7
8#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
9pub struct Node {
10 pub item_ref: DisplayedItemRef,
11 pub level: u8,
13 pub unfolded: bool,
15 pub selected: bool,
16}
17
18#[derive(Debug, PartialEq, Eq, Clone, Copy)]
19pub enum MoveError {
20 InvalidIndex,
21 InvalidLevel,
22 CircularMove,
23 LevelTooDeep,
24}
25
26#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
28pub struct VisibleItemIndex(pub usize);
29
30#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)]
32pub struct ItemIndex(pub usize);
33
34#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
35pub struct TargetPosition {
36 pub before: ItemIndex,
38 pub level: u8, }
41
42pub struct VisibleItemIterator<'a> {
43 items: &'a Vec<Node>,
44 next_idx: usize,
45}
46
47impl<'a> Iterator for VisibleItemIterator<'a> {
48 type Item = &'a Node;
49
50 fn next(&mut self) -> Option<Self::Item> {
51 let this_idx = self.next_idx;
52
53 let this_item = self.items.get(this_idx);
54 if this_item.is_some() {
55 self.next_idx = next_visible_item(self.items, this_idx);
56 }
57 this_item
58 }
59}
60
61#[must_use = "iterators are lazy and do nothing unless consumed"]
62pub struct VisibleItemIteratorMut<'a> {
63 items: &'a mut Vec<Node>,
64 next_idx: usize,
66}
67
68impl<'a> Iterator for VisibleItemIteratorMut<'a> {
69 type Item = &'a mut Node;
70
71 fn next(&mut self) -> Option<Self::Item> {
72 let this_idx = self.next_idx;
73
74 if this_idx < self.items.len() {
75 self.next_idx = next_visible_item(self.items, this_idx);
76
77 let ptr = self.items.as_mut_ptr();
78 Some(unsafe { &mut *ptr.add(this_idx) })
83 } else {
84 None
85 }
86 }
87}
88
89pub struct Info<'a> {
90 pub node: &'a Node,
91 pub idx: ItemIndex,
92 pub vidx: VisibleItemIndex,
93 pub has_children: bool,
94 pub last: bool,
95}
96
97pub struct VisibleItemIteratorExtraInfo<'a> {
98 items: &'a Vec<Node>,
99 next_idx: usize,
101 next_vidx: usize,
102}
103
104impl<'a> Iterator for VisibleItemIteratorExtraInfo<'a> {
105 type Item = Info<'a>;
106
107 fn next(&mut self) -> Option<Self::Item> {
108 let this_idx = self.next_idx;
109 let this_vidx = self.next_vidx;
110 if this_idx < self.items.len() {
111 self.next_idx = next_visible_item(self.items, this_idx);
112 self.next_vidx += 1;
113
114 let this_level = self.items[this_idx].level;
115 let has_child = self
116 .items
117 .get(this_idx + 1)
118 .is_some_and(|item| item.level > this_level);
119 Some(Info {
120 node: &self.items[this_idx],
121 idx: ItemIndex(this_idx),
122 vidx: VisibleItemIndex(this_vidx),
123 has_children: has_child,
124 last: self.next_idx >= self.items.len(),
125 })
126 } else {
127 None
128 }
129 }
130}
131
132#[derive(Default, Serialize, Deserialize, Debug, Clone)]
144pub struct DisplayedItemTree {
145 items: Vec<Node>,
146}
147
148impl DisplayedItemTree {
149 #[must_use]
150 pub fn new() -> Self {
151 DisplayedItemTree { items: vec![] }
152 }
153
154 #[must_use]
155 pub fn len(&self) -> usize {
156 self.items.len()
157 }
158
159 #[must_use]
160 pub fn is_empty(&self) -> bool {
161 self.items.is_empty()
162 }
163
164 pub fn iter(&self) -> impl Iterator<Item = &Node> + use<'_> {
165 self.items.iter()
166 }
167
168 #[must_use]
170 pub fn iter_visible(&self) -> VisibleItemIterator<'_> {
171 VisibleItemIterator {
172 items: &self.items,
173 next_idx: 0,
174 }
175 }
176
177 pub fn iter_visible_mut(&mut self) -> VisibleItemIteratorMut<'_> {
178 VisibleItemIteratorMut {
179 items: &mut self.items,
180 next_idx: 0,
181 }
182 }
183
184 #[must_use]
185 pub fn iter_visible_extra(&self) -> VisibleItemIteratorExtraInfo<'_> {
186 VisibleItemIteratorExtraInfo {
187 items: &self.items,
188 next_idx: 0,
189 next_vidx: 0,
190 }
191 }
192
193 pub fn iter_visible_selected(&self) -> impl Iterator<Item = &Node> + use<'_> {
194 self.iter_visible().filter(|i| i.selected)
195 }
196
197 #[must_use]
199 pub fn get_visible(&self, index: VisibleItemIndex) -> Option<&Node> {
200 self.iter_visible().nth(index.0)
201 }
202
203 #[must_use]
204 pub fn get_visible_extra(&self, index: VisibleItemIndex) -> Option<Info<'_>> {
205 self.iter_visible_extra().nth(index.0)
206 }
207
208 #[must_use]
209 pub fn get(&self, index: ItemIndex) -> Option<&Node> {
210 self.items.get(index.0)
211 }
212
213 pub fn get_mut(&mut self, index: ItemIndex) -> Option<&mut Node> {
214 self.items.get_mut(index.0)
215 }
216
217 #[must_use]
218 pub fn to_displayed(&self, index: VisibleItemIndex) -> Option<ItemIndex> {
219 self.get_visible_extra(index)?.idx.into()
220 }
221
222 pub fn insert_item(
224 &mut self,
225 item: DisplayedItemRef,
226 position: TargetPosition,
227 ) -> Result<ItemIndex, MoveError> {
228 check_location(&self.items, position)?;
229
230 self.items.insert(
231 position.before.0,
232 Node {
233 item_ref: item,
234 level: position.level,
235 unfolded: true,
236 selected: false,
237 },
238 );
239
240 Ok(position.before)
241 }
242
243 fn subtree_end(&self, start_idx: usize) -> usize {
245 let level = self.items[start_idx].level;
246 self.items
247 .iter()
248 .skip(start_idx + 1)
249 .enumerate()
250 .find_map(|(idx, x)| (x.level <= level).then_some(idx + start_idx + 1))
251 .unwrap_or(self.items.len())
252 }
253
254 pub fn remove_recursive(&mut self, ItemIndex(item): ItemIndex) -> Vec<DisplayedItemRef> {
255 let end = self.subtree_end(item);
256 self.items
257 .drain(item..end)
258 .map(|x| x.item_ref)
259 .collect_vec()
260 }
261
262 pub fn remove_dissolve(&mut self, ItemIndex(item): ItemIndex) -> DisplayedItemRef {
263 let end = self.subtree_end(item);
264 self.items[item + 1..end]
265 .iter_mut()
266 .for_each(|x| x.level -= 1);
267 self.items.remove(item).item_ref
268 }
269
270 pub fn drain_recursive_if<F>(&mut self, f: F) -> Vec<DisplayedItemRef>
271 where
272 F: Fn(&Node) -> bool,
273 {
274 let mut removed = vec![];
275
276 let mut idx = 0;
277 while idx < self.items.len() {
278 if f(self.items.get(idx).unwrap()) {
279 let end = self.subtree_end(idx);
280 removed.extend(self.items.drain(idx..end).map(|x| x.item_ref));
281 } else {
282 idx += 1;
283 }
284 }
285
286 removed
287 }
288
289 fn visible_predecessor(&self, mut idx: usize) -> Option<usize> {
291 if idx == 0 || idx > self.items.len() {
292 return None;
293 }
294
295 let start_level = self.items[idx].level;
296 let mut candidate = idx - 1;
297 let mut limit_level = self.items[candidate].level;
298
299 loop {
300 idx -= 1;
301 let looking_item = &self.items[idx];
302 if looking_item.level < limit_level {
304 limit_level = looking_item.level;
305 if !looking_item.unfolded {
308 candidate = idx;
309 }
310 }
311 if self.items[idx].level <= start_level || idx == 0 {
312 return Some(candidate);
313 }
314 }
315 }
316
317 pub fn move_item<F>(
328 &mut self,
329 vidx: VisibleItemIndex,
330 direction: MoveDir,
331 f: F,
332 ) -> Result<VisibleItemIndex, MoveError>
333 where
334 F: Fn(&Node) -> bool,
335 {
336 let Some(ItemIndex(idx)) = self.to_displayed(vidx) else {
337 return Err(MoveError::InvalidIndex);
338 };
339
340 let this_level = self.items[idx].level;
341 let end = self.subtree_end(idx);
342 let new_index = match direction {
343 MoveDir::Down => match self.items.get(end) {
344 None => {
346 shift_subtree_to_level(
347 &mut self.items[idx..end],
348 this_level.saturating_sub(1),
349 )?;
350 vidx
351 }
352 Some(Node { level, .. }) if *level < this_level => {
354 shift_subtree_to_level(&mut self.items[idx..end], this_level - 1)?;
355 vidx
356 }
357 Some(
359 node @ Node {
360 unfolded: true,
361 level,
362 ..
363 },
364 ) if f(node) => {
365 self.move_items(
366 vec![ItemIndex(idx)],
367 TargetPosition {
368 before: ItemIndex(end + 1),
369 level: *level + 1,
370 },
371 )?;
372 VisibleItemIndex(vidx.0 + 1)
373 }
374 _ => {
376 self.move_items(
377 vec![ItemIndex(idx)],
378 TargetPosition {
379 before: ItemIndex(self.subtree_end(end)),
380 level: this_level,
381 },
382 )?;
383 VisibleItemIndex(vidx.0 + 1)
384 }
385 },
386 MoveDir::Up => {
387 match self.visible_predecessor(idx).map(|i| (i, &self.items[i])) {
388 None => vidx,
389 Some((_node_idx, node))
392 if (node.level >= this_level && f(node) && node.unfolded)
393 | (node.level > this_level) =>
394 {
395 shift_subtree_to_level(&mut self.items[idx..end], this_level + 1)?;
396 vidx
397 }
398 Some((node_idx, node)) => {
399 self.move_items(
400 vec![ItemIndex(idx)],
401 TargetPosition {
402 before: ItemIndex(node_idx),
403 level: node.level,
404 },
405 )?;
406 VisibleItemIndex(vidx.0 - 1)
407 }
408 }
409 }
410 };
411 Ok(new_index)
412 }
413
414 pub fn move_items(
433 &mut self,
434 indices: Vec<ItemIndex>,
435 target: TargetPosition,
436 ) -> Result<(), MoveError> {
437 if let Some(idx) = indices.last()
438 && idx.0 >= self.items.len()
439 {
440 return Err(MoveError::InvalidIndex);
441 }
442
443 let indices = indices
448 .into_iter()
449 .sorted_by_key(|ii| usize::MAX - ii.0)
450 .dedup()
451 .collect_vec();
452
453 let mut result = self.items.clone();
454 let mut extracted = vec![];
455
456 let mut shifted_target = target.before.0;
457 for ItemIndex(start) in indices {
458 let end = self.subtree_end(start);
459 if ((start + 1)..end).contains(&shifted_target) {
460 return Err(MoveError::CircularMove);
461 }
462
463 if start < shifted_target {
465 shifted_target -= end - start;
466 }
467
468 shift_subtree_to_level(&mut result[start..end], target.level)?;
469 extracted.splice(0..0, result.drain(start..end));
470 }
471
472 check_location(
473 &result,
474 TargetPosition {
475 before: ItemIndex(shifted_target),
476 level: target.level,
477 },
478 )?;
479
480 result.splice(shifted_target..shifted_target, extracted);
481
482 assert_eq!(self.items.len(), result.len());
483 self.items = result;
484 Ok(())
485 }
486
487 pub fn valid_levels_visible<F>(&self, item: VisibleItemIndex, f: F) -> Range<u8>
492 where
493 F: Fn(&Node) -> bool,
494 {
495 let Some(split) = item.0.checked_sub(1) else {
496 return 0..1;
497 };
498 match self
499 .iter_visible()
500 .skip(split)
501 .take(2)
502 .collect_vec()
503 .as_slice()
504 {
505 [] => 0..1, [last] => {
507 0..last
508 .level
509 .saturating_add(1 + u8::from(f(last) && last.unfolded))
510 }
511 [pre, post, ..] => {
512 post.level
513 ..pre
514 .level
515 .saturating_add(1 + u8::from(f(pre) && pre.unfolded))
516 }
517 }
518 }
519
520 pub fn xfold(&mut self, ItemIndex(item): ItemIndex, unfolded: bool) {
521 self.items[item].unfolded = unfolded;
522 if !unfolded {
523 let end = self.subtree_end(item);
524 for x in &mut self.items[item..end] {
525 x.selected = false;
526 }
527 }
528 }
529
530 pub fn xfold_all(&mut self, unfolded: bool) {
531 for x in &mut self.items {
532 x.unfolded = unfolded;
533 if !unfolded && x.level > 0 {
534 x.selected = false;
535 }
536 }
537 }
538
539 pub fn xfold_recursive(&mut self, ItemIndex(item): ItemIndex, unfolded: bool) {
540 let end = self.subtree_end(item);
541 self.items[item].unfolded = unfolded;
542 for x in &mut self.items[item + 1..end] {
543 x.unfolded = unfolded;
544 if !unfolded {
545 x.selected = false;
546 }
547 }
548 }
549
550 pub fn xselect(&mut self, vidx: VisibleItemIndex, selected: bool) {
551 if let Some(idx) = self.to_displayed(vidx) {
552 self.items[idx.0].selected = selected;
553 }
554 }
555
556 pub fn xselect_all_visible(&mut self, selected: bool) {
558 for x in &mut self.iter_visible_mut() {
559 x.selected = selected;
560 }
561 }
562
563 pub fn xselect_visible_range(
565 &mut self,
566 VisibleItemIndex(from): VisibleItemIndex,
567 VisibleItemIndex(to): VisibleItemIndex,
568 selected: bool,
569 ) {
570 let (from, to) = if from < to {
571 (from, to + 1)
572 } else {
573 (to, from + 1)
574 };
575 for node in self.iter_visible_mut().skip(from).take(to - from) {
576 node.selected = selected;
577 }
578 }
579
580 #[must_use]
581 pub fn subtree_contains(
582 &self,
583 ItemIndex(root): ItemIndex,
584 ItemIndex(candidate): ItemIndex,
585 ) -> bool {
586 let end = self.subtree_end(candidate);
587 (root..end).contains(&candidate)
588 }
589}
590
591fn next_visible_item(items: &[Node], this_idx: usize) -> usize {
595 let this_level = items[this_idx].level;
596 let mut next_idx = this_idx + 1;
597 if !items[this_idx].unfolded {
598 while next_idx < items.len() && items[next_idx].level > this_level {
599 next_idx += 1;
600 }
601 }
602 next_idx
603}
604
605fn check_location(items: &[Node], target_position: TargetPosition) -> Result<(), MoveError> {
609 if target_position.before.0 > items.len() {
610 return Err(MoveError::InvalidIndex);
611 }
612 let before = target_position
613 .before
614 .0
615 .checked_sub(1)
616 .and_then(|i| items.get(i));
617 let after = items.get(target_position.before.0);
618 let valid_range = match (before.map(|n| n.level), after.map(|n| n.level)) {
619 (None, _) => 0..=0,
621 (Some(before), None) => 0..=before.saturating_add(1),
624 (Some(before), Some(after)) if after > before => after..=after,
627 (Some(before), Some(after)) if after == before => before..=after.saturating_add(1),
630 (Some(before), Some(after)) => after..=before.saturating_add(1),
635 };
636
637 if valid_range.contains(&target_position.level) {
638 Ok(())
639 } else {
640 Err(MoveError::InvalidLevel)
641 }
642}
643
644fn shift_subtree_to_level(nodes: &mut [Node], target_level: u8) -> Result<(), MoveError> {
645 let Some(from_level) = nodes.first().map(|node| node.level) else {
646 return Ok(());
647 };
648 let level_corr = i16::from(target_level) - i16::from(from_level);
649 for elem in nodes.iter_mut() {
650 elem.level = (i16::from(elem.level) + level_corr)
651 .try_into()
652 .map_err(|_| MoveError::InvalidLevel)?;
653 }
654 Ok(())
655}
656
657#[cfg(test)]
658mod tests {
659 use super::*;
660 use itertools::Itertools;
661
662 fn build_tree(nodes: &[(usize, u8, bool, bool)]) -> DisplayedItemTree {
663 let mut tree = DisplayedItemTree::new();
664 for &(item, level, unfolded, selected) in nodes {
665 tree.items.push(Node {
666 item_ref: DisplayedItemRef(item),
667 level,
668 unfolded,
669 selected,
670 });
671 }
672 tree
673 }
674
675 fn test_tree() -> DisplayedItemTree {
690 build_tree(&[
691 (0, 0, true, false),
692 (1, 0, false, false),
693 (2, 0, false, false),
694 (20, 1, true, false),
695 (200, 2, true, false),
696 (3, 0, true, false),
697 (30, 1, true, false),
698 (31, 1, true, false),
699 (4, 0, true, false),
700 (5, 0, true, false),
701 ])
702 }
703
704 #[test]
705 fn test_iter_visible() {
706 let tree = test_tree();
707 assert_eq!(
708 tree.iter_visible().map(|x| x.item_ref.0).collect_vec(),
709 vec![0, 1, 2, 3, 30, 31, 4, 5]
710 );
711 }
712
713 #[test]
714 fn test_iter_visible_extra() {
715 let tree = test_tree();
716 assert_eq!(
717 tree.iter_visible_extra()
718 .map(|info| (
719 info.node.item_ref.0,
720 info.idx.0,
721 info.vidx.0,
722 info.has_children,
723 info.last
724 ))
725 .collect_vec(),
726 vec![
727 (0, 0, 0, false, false),
728 (1, 1, 1, false, false),
729 (2, 2, 2, true, false),
730 (3, 5, 3, true, false),
731 (30, 6, 4, false, false),
732 (31, 7, 5, false, false),
733 (4, 8, 6, false, false),
734 (5, 9, 7, false, true),
735 ]
736 );
737 }
738
739 #[test]
740 fn test_insert_item_before_first() {
741 let mut tree = test_tree();
742 tree.insert_item(
743 DisplayedItemRef(0xff),
744 TargetPosition {
745 before: ItemIndex(0),
746 level: 0,
747 },
748 )
749 .expect("insert_item must succeed");
750 assert_eq!(
751 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
752 vec![0xff, 0, 1, 2, 20, 200, 3, 30, 31, 4, 5]
753 );
754 assert_eq!(tree.items[0].level, 0);
755 assert!(!tree.items[0].selected);
756 assert!(tree.items[0].unfolded);
757 }
758
759 #[test]
760 fn test_insert_item_after_into_subtree() {
763 let mut tree = test_tree();
764 tree.insert_item(
765 DisplayedItemRef(0xff),
766 TargetPosition {
767 before: ItemIndex(8),
768 level: 1,
769 },
770 )
771 .expect("insert_item must succeed");
772 assert_eq!(
773 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
774 vec![0, 1, 2, 20, 200, 3, 30, 31, 0xff, 4, 5]
775 );
776 assert_eq!(tree.items[7].level, 1);
777 assert!(!tree.items[7].selected);
778 assert!(tree.items[7].unfolded);
779 }
780
781 #[test]
782 fn test_insert_item_into() {
783 let mut tree = test_tree();
784 tree.insert_item(
785 DisplayedItemRef(0xff),
786 TargetPosition {
787 before: ItemIndex(7),
788 level: 2,
789 },
790 )
791 .expect("insert_item must succeed");
792 assert_eq!(
793 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
794 vec![0, 1, 2, 20, 200, 3, 30, 0xff, 31, 4, 5]
795 );
796 assert_eq!(tree.items[7].level, 2);
797 assert!(!tree.items[7].selected);
798 assert!(tree.items[7].unfolded);
799 }
800
801 #[test]
802 fn test_insert_item_end() {
803 let mut tree = test_tree();
804 tree.insert_item(
805 DisplayedItemRef(0xff),
806 TargetPosition {
807 before: ItemIndex(10),
808 level: 0,
809 },
810 )
811 .expect("insert_item must succeed");
812 assert_eq!(
813 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
814 vec![0, 1, 2, 20, 200, 3, 30, 31, 4, 5, 0xff]
815 );
816 assert_eq!(tree.items[10].level, 0);
817 }
818
819 #[test]
820 fn test_remove_recursive_no_children() {
821 let mut tree = test_tree();
822 let removed = tree.remove_recursive(ItemIndex(0));
823 assert_eq!(removed, vec![DisplayedItemRef(0)]);
824 assert_eq!(
825 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
826 vec![1, 2, 20, 200, 3, 30, 31, 4, 5]
827 );
828 }
829
830 #[test]
831 fn test_remove_recursive_with_children() {
832 let mut tree = test_tree();
833 let removed = tree.remove_recursive(ItemIndex(2));
834 assert_eq!(
835 removed,
836 vec![
837 DisplayedItemRef(2),
838 DisplayedItemRef(20),
839 DisplayedItemRef(200)
840 ]
841 );
842 assert_eq!(
843 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
844 vec![0, 1, 3, 30, 31, 4, 5]
845 );
846 }
847
848 #[test]
849 fn test_remove_dissolve_with_children() {
850 let mut tree = test_tree();
851 let removed = tree.remove_dissolve(ItemIndex(5));
852 assert_eq!(removed, DisplayedItemRef(3));
853 assert_eq!(
854 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
855 vec![0, 1, 2, 20, 200, 30, 31, 4, 5]
856 );
857 assert_eq!(tree.items[5].level, 0);
858 assert_eq!(tree.items[6].level, 0);
859 }
860
861 #[test]
862 fn test_move_item_up_unfolded_group() {
863 let mut tree = build_tree(&[
864 (0, 0, true, false),
865 (1, 0, true, false),
866 (10, 1, true, false),
867 (2, 0, true, false),
868 (3, 0, true, false),
869 ]);
870 let new_idx = tree
871 .move_item(VisibleItemIndex(3), MoveDir::Up, |node| {
872 node.item_ref.0 == 1
873 })
874 .expect("move must succeed");
875 assert_eq!(new_idx.0, 3);
876 assert_eq!(tree.items[3].level, 1);
877 assert_eq!(
878 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
879 vec![0, 1, 10, 2, 3]
880 );
881
882 let new_idx = tree
883 .move_item(new_idx, MoveDir::Up, |node| node.item_ref.0 == 1)
884 .expect("move must succeed");
885 assert_eq!(new_idx.0, 2);
886 assert_eq!(tree.items[2].level, 1);
887 assert_eq!(
888 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
889 vec![0, 1, 2, 10, 3]
890 );
891
892 let new_idx = tree
893 .move_item(new_idx, MoveDir::Up, |node| node.item_ref.0 == 1)
894 .expect("move must succeed");
895 assert_eq!(new_idx.0, 1);
896 assert_eq!(tree.items[1].level, 0);
897 assert_eq!(
898 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
899 vec![0, 2, 1, 10, 3]
900 );
901
902 let new_idx = tree
903 .move_item(new_idx, MoveDir::Up, |node| node.item_ref.0 == 1)
904 .expect("move must succeed");
905 assert_eq!(new_idx.0, 0);
906 assert_eq!(tree.items[0].level, 0);
907 assert_eq!(
908 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
909 vec![2, 0, 1, 10, 3]
910 );
911
912 let new_idx = tree
913 .move_item(new_idx, MoveDir::Up, |node| node.item_ref.0 == 1)
914 .expect("move must succeed");
915 assert_eq!(new_idx.0, 0);
916 assert_eq!(tree.items[0].level, 0);
917 assert_eq!(
918 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
919 vec![2, 0, 1, 10, 3]
920 );
921 }
922
923 #[test]
924 fn test_move_item_up_folded_group() {
925 let mut tree = build_tree(&[
926 (0, 0, true, false),
927 (1, 0, false, false),
928 (10, 1, true, false),
929 (11, 1, true, false),
930 (2, 0, true, false),
931 (3, 0, true, false),
932 ]);
933 let new_idx = tree
934 .move_item(VisibleItemIndex(2), MoveDir::Up, |node| {
935 node.item_ref.0 == 1
936 })
937 .expect("move must succeed");
938 assert_eq!(new_idx.0, 1);
939 assert_eq!(tree.items[1].level, 0);
940 assert_eq!(
941 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
942 vec![0, 2, 1, 10, 11, 3]
943 );
944
945 let new_idx = tree
946 .move_item(new_idx, MoveDir::Up, |node| node.item_ref.0 == 1)
947 .expect("move must succeed");
948 assert_eq!(new_idx.0, 0);
949 assert_eq!(tree.items[0].level, 0);
950 assert_eq!(
951 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
952 vec![2, 0, 1, 10, 11, 3]
953 );
954 }
955
956 #[test]
957 fn test_move_item_down_unfolded_group() {
958 let mut tree = build_tree(&[
959 (0, 0, true, false),
960 (1, 0, true, false),
961 (2, 0, true, false),
962 (20, 1, true, false),
963 (3, 0, true, false),
964 ]);
965 let new_idx = tree
966 .move_item(VisibleItemIndex(1), MoveDir::Down, |node| {
967 node.item_ref.0 == 2
968 })
969 .expect("move must succeed");
970 println!("{:?}", tree.items);
971 assert_eq!(new_idx.0, 2);
972 assert_eq!(tree.items[3].level, 1);
973 assert_eq!(
974 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
975 vec![0, 2, 1, 20, 3]
976 );
977
978 let new_idx = tree
979 .move_item(new_idx, MoveDir::Down, |node| node.item_ref.0 == 2)
980 .expect("move must succeed");
981 println!("{:?}", tree.items);
982 assert_eq!(new_idx.0, 3);
983 assert_eq!(tree.items[3].level, 1);
984 assert_eq!(
985 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
986 vec![0, 2, 20, 1, 3]
987 );
988
989 let new_idx = tree
990 .move_item(new_idx, MoveDir::Down, |node| node.item_ref.0 == 2)
991 .expect("move must succeed");
992 println!("{:?}", tree.items);
993 assert_eq!(new_idx.0, 3);
994 assert_eq!(tree.items[3].level, 0);
995 assert_eq!(
996 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
997 vec![0, 2, 20, 1, 3]
998 );
999
1000 let new_idx = tree
1001 .move_item(new_idx, MoveDir::Down, |node| node.item_ref.0 == 2)
1002 .expect("move must succeed");
1003 println!("{:?}", tree.items);
1004 assert_eq!(new_idx.0, 4);
1005 assert_eq!(tree.items[3].level, 0);
1006 assert_eq!(
1007 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1008 vec![0, 2, 20, 3, 1]
1009 );
1010
1011 let new_idx = tree
1012 .move_item(new_idx, MoveDir::Down, |node| node.item_ref.0 == 2)
1013 .expect("move must succeed");
1014 println!("{:?}", tree.items);
1015 assert_eq!(new_idx.0, 4);
1016 assert_eq!(tree.items[3].level, 0);
1017 assert_eq!(
1018 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1019 vec![0, 2, 20, 3, 1]
1020 );
1021 }
1022
1023 #[test]
1024 fn test_move_item_down_folded_group() {
1025 let mut tree = build_tree(&[
1026 (0, 0, true, false),
1027 (1, 0, true, false),
1028 (2, 0, false, false),
1029 (20, 1, true, false),
1030 (3, 0, true, false),
1031 ]);
1032 let new_idx = tree
1033 .move_item(VisibleItemIndex(1), MoveDir::Down, |node| {
1034 node.item_ref.0 == 2
1035 })
1036 .expect("move must succeed");
1037 println!("{:?}", tree.items);
1038 assert_eq!(new_idx.0, 2);
1039 assert_eq!(tree.items[3].level, 0);
1040 assert_eq!(
1041 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1042 vec![0, 2, 20, 1, 3]
1043 );
1044
1045 let new_idx = tree
1046 .move_item(new_idx, MoveDir::Down, |node| node.item_ref.0 == 2)
1047 .expect("move must succeed");
1048 println!("{:?}", tree.items);
1049 assert_eq!(new_idx.0, 3);
1050 assert_eq!(tree.items[3].level, 0);
1051 assert_eq!(
1052 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1053 vec![0, 2, 20, 3, 1]
1054 );
1055 }
1056
1057 #[test]
1058 fn test_move_items_single_to_start() {
1059 let mut tree = test_tree();
1060 tree.move_items(
1061 vec![ItemIndex(8)],
1062 TargetPosition {
1063 before: ItemIndex(0),
1064 level: 0,
1065 },
1066 )
1067 .expect("move_items must succeed");
1068 assert_eq!(
1069 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1070 vec![4, 0, 1, 2, 20, 200, 3, 30, 31, 5]
1071 );
1072 assert_eq!(tree.items[0].level, 0);
1073 }
1074
1075 #[test]
1076 fn test_move_items_single_to_end() {
1077 let mut tree = test_tree();
1078 tree.move_items(
1079 vec![ItemIndex(4)],
1080 TargetPosition {
1081 before: ItemIndex(10),
1082 level: 0,
1083 },
1084 )
1085 .expect("move_items must succeed");
1086 assert_eq!(
1087 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1088 vec![0, 1, 2, 20, 3, 30, 31, 4, 5, 200]
1089 );
1090 assert_eq!(tree.items[9].level, 0);
1091 }
1092
1093 #[test]
1094 fn test_move_items_multiple_connected() {
1095 let mut tree = test_tree();
1096 tree.move_items(
1097 vec![ItemIndex(8), ItemIndex(9)],
1098 TargetPosition {
1099 before: ItemIndex(1),
1100 level: 0,
1101 },
1102 )
1103 .expect("move_items must succeed");
1104 assert_eq!(
1105 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1106 vec![0, 4, 5, 1, 2, 20, 200, 3, 30, 31]
1107 );
1108 assert_eq!(tree.items[1].level, 0);
1109 assert_eq!(tree.items[2].level, 0);
1110 }
1111
1112 #[test]
1113 fn test_move_items_multiple_different_levels() {
1114 let mut tree = test_tree();
1115 tree.move_items(
1116 vec![ItemIndex(7), ItemIndex(8)],
1117 TargetPosition {
1118 before: ItemIndex(1),
1119 level: 0,
1120 },
1121 )
1122 .expect("move_items must succeed");
1123 assert_eq!(
1124 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1125 vec![0, 31, 4, 1, 2, 20, 200, 3, 30, 5]
1126 );
1127 assert_eq!(tree.items[1].level, 0);
1128 assert_eq!(tree.items[2].level, 0);
1129 }
1130
1131 #[test]
1132 fn test_move_items_multiple_unconnected() {
1133 let mut tree = test_tree();
1134 tree.move_items(
1135 vec![ItemIndex(1), ItemIndex(8)],
1136 TargetPosition {
1137 before: ItemIndex(5),
1138 level: 1,
1139 },
1140 )
1141 .expect("move_items must succeed");
1142 assert_eq!(
1143 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1144 vec![0, 2, 20, 200, 1, 4, 3, 30, 31, 5]
1145 );
1146 assert_eq!(tree.items[4].level, 1);
1147 assert_eq!(tree.items[5].level, 1);
1148 }
1149
1150 #[test]
1151 fn test_move_items_multiple_into() {
1152 let mut tree = test_tree();
1153 tree.move_items(
1154 vec![ItemIndex(1), ItemIndex(8)],
1155 TargetPosition {
1156 before: ItemIndex(4),
1157 level: 2,
1158 },
1159 )
1160 .expect("move_items must succeed");
1161 assert_eq!(
1162 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1163 vec![0, 2, 20, 1, 4, 200, 3, 30, 31, 5]
1164 );
1165 assert_eq!(tree.items[4].level, 2);
1166 assert_eq!(tree.items[5].level, 2);
1167 }
1168
1169 #[test]
1170 fn test_move_single_to_end() {
1171 let mut tree = build_tree(&[
1172 (0, 0, false, false),
1173 (1, 0, false, false),
1174 (2, 0, false, false),
1175 ]);
1176 tree.move_items(
1177 vec![ItemIndex(1)],
1178 TargetPosition {
1179 before: ItemIndex(3),
1180 level: 0,
1181 },
1182 )
1183 .expect("move_items must succeed");
1184 assert_eq!(
1185 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1186 vec![0, 2, 1]
1187 );
1188 }
1189
1190 #[test]
1191 fn test_move_items_before_self_same_depth_single() {
1192 let ref_tree = build_tree(&[
1193 (0, 0, false, false),
1194 (1, 0, false, false),
1195 (2, 0, false, false),
1196 ]);
1197 let mut tree = ref_tree.clone();
1198 tree.move_items(
1199 vec![ItemIndex(1)],
1200 TargetPosition {
1201 before: ItemIndex(1),
1202 level: 0,
1203 },
1204 )
1205 .expect("move_items must succeed");
1206 assert_eq!(tree.items, ref_tree.items);
1207 }
1208
1209 #[test]
1210 fn test_move_items_after_self_same_depth_single() {
1211 let ref_tree = build_tree(&[
1212 (0, 0, false, false),
1213 (1, 0, false, false),
1214 (2, 0, false, false),
1215 ]);
1216 let mut tree = ref_tree.clone();
1217 tree.move_items(
1218 vec![ItemIndex(1)],
1219 TargetPosition {
1220 before: ItemIndex(2),
1221 level: 0,
1222 },
1223 )
1224 .expect("move_items must succeed");
1225 assert_eq!(tree.items, ref_tree.items);
1226 }
1227 #[test]
1228 fn test_move_items_in_between_selected_same_depth() {
1229 let ref_tree = build_tree(&[
1230 (0, 0, false, false),
1231 (1, 0, false, false),
1232 (2, 0, false, false),
1233 (3, 0, false, false),
1234 (4, 0, false, false),
1235 ]);
1236 let mut tree = ref_tree.clone();
1237 tree.move_items(
1238 vec![ItemIndex(1), ItemIndex(2)],
1239 TargetPosition {
1240 before: ItemIndex(2),
1241 level: 0,
1242 },
1243 )
1244 .expect("move_items must succeed");
1245 assert_eq!(tree.items, ref_tree.items);
1246 }
1247
1248 #[test]
1249 fn test_move_items_before_self_same_depth() {
1252 let mut tree = test_tree();
1253 tree.move_items(
1254 vec![ItemIndex(0), ItemIndex(4), ItemIndex(9)],
1255 TargetPosition {
1256 before: ItemIndex(4),
1257 level: 2,
1258 },
1259 )
1260 .expect("move_items must succeed");
1261 assert_eq!(
1262 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1263 vec![1, 2, 20, 0, 200, 5, 3, 30, 31, 4]
1264 );
1265 assert_eq!(tree.items[3].level, 2);
1266 assert_eq!(tree.items[4].level, 2);
1267 assert_eq!(tree.items[5].level, 2);
1268 }
1269
1270 #[test]
1271 fn test_move_items_before_self_shallower() {
1274 let mut tree = test_tree();
1275 tree.move_items(
1276 vec![ItemIndex(0), ItemIndex(4), ItemIndex(9)],
1277 TargetPosition {
1278 before: ItemIndex(4),
1279 level: 1,
1280 },
1281 )
1282 .expect("move_items must succeed");
1283 assert_eq!(
1284 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1285 vec![1, 2, 20, 0, 200, 5, 3, 30, 31, 4]
1286 );
1287 assert_eq!(tree.items[3].level, 1);
1288 assert_eq!(tree.items[4].level, 1);
1289 assert_eq!(tree.items[5].level, 1);
1290 }
1291
1292 #[test]
1293 fn test_move_items_empty_list() {
1294 let mut tree = test_tree();
1295 tree.move_items(
1296 vec![],
1297 TargetPosition {
1298 before: ItemIndex(5),
1299 level: 0,
1300 },
1301 )
1302 .expect("move_items must succeed");
1303 assert_eq!(
1304 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1305 vec![0, 1, 2, 20, 200, 3, 30, 31, 4, 5]
1306 );
1307 assert_eq!(tree.items, test_tree().items);
1308 }
1309
1310 #[test]
1311 fn test_move_items_shared_subtree_no_overlap() {
1312 let mut tree = build_tree(&[
1313 (0, 0, true, false),
1314 (10, 1, false, false),
1315 (11, 1, false, false),
1316 (12, 1, false, false),
1317 (13, 1, false, false),
1318 ]);
1319 tree.move_items(
1320 vec![ItemIndex(2), ItemIndex(4)],
1321 TargetPosition {
1322 before: ItemIndex(4),
1323 level: 2,
1324 },
1325 )
1326 .expect("move_items must succeed");
1327 assert_eq!(
1328 tree.items.iter().map(|x| x.item_ref.0).collect_vec(),
1329 vec![0, 10, 12, 11, 13]
1330 );
1331 }
1332
1333 #[test]
1334 fn test_move_items_reject_into_self() {
1336 let mut tree = test_tree();
1337 let result = tree.move_items(
1338 vec![ItemIndex(2)],
1339 TargetPosition {
1340 before: ItemIndex(3),
1341 level: 1,
1342 },
1343 );
1344 assert_eq!(result, Err(MoveError::CircularMove));
1345 assert_eq!(tree.items, test_tree().items);
1346 }
1347
1348 #[test]
1349 fn test_move_items_reject_after_self_into_subtree() {
1352 let mut tree = test_tree();
1353 let result = tree.move_items(
1354 vec![ItemIndex(0), ItemIndex(3), ItemIndex(9)],
1355 TargetPosition {
1356 before: ItemIndex(4),
1357 level: 2,
1358 },
1359 );
1360 assert_eq!(result, Err(MoveError::CircularMove));
1361 assert_eq!(tree.items, test_tree().items);
1362 }
1363
1364 #[test]
1365 fn test_move_items_reject_into_subtree_distant() {
1369 let reference = build_tree(&[
1370 (1, 0, true, false),
1371 (10, 1, true, false),
1372 (100, 2, true, false),
1373 (11, 3, true, false),
1374 ]);
1375 let mut tree = reference.clone();
1376 let result = tree.move_items(
1377 vec![ItemIndex(1), ItemIndex(2)],
1378 TargetPosition {
1379 before: ItemIndex(4),
1380 level: 2,
1381 },
1382 );
1383 assert_eq!(result, Err(MoveError::CircularMove));
1384 assert_eq!(tree.items, reference.items);
1385 }
1386
1387 #[test]
1388 fn test_valid_levels() {
1389 let tree = build_tree(&[
1390 (0, 0, true, false),
1392 (1, 0, true, false),
1393 (2, 0, false, false),
1394 (20, 1, true, false),
1395 (3, 0, true, false),
1396 (30, 1, true, false),
1397 (300, 2, true, false),
1398 (4, 0, true, false),
1399 (40, 1, true, false),
1400 (400, 2, true, false),
1401 (41, 1, true, false),
1402 (410, 2, true, false),
1403 ]);
1404
1405 assert_eq!(
1408 tree.valid_levels_visible(VisibleItemIndex(0), |_| false),
1409 0..1
1410 );
1411 assert_eq!(
1412 tree.valid_levels_visible(VisibleItemIndex(0), |_| true),
1413 0..1
1414 );
1415
1416 assert_eq!(
1418 tree.valid_levels_visible(VisibleItemIndex(1), |_| false),
1419 0..1
1420 );
1421 assert_eq!(
1422 tree.valid_levels_visible(VisibleItemIndex(1), |_| true),
1423 0..2
1424 );
1425
1426 assert_eq!(
1428 tree.valid_levels_visible(VisibleItemIndex(3), |_| false),
1429 0..1
1430 );
1431 assert_eq!(
1432 tree.valid_levels_visible(VisibleItemIndex(3), |_| true),
1433 0..1
1434 );
1435
1436 assert_eq!(
1438 tree.valid_levels_visible(VisibleItemIndex(6), |_| false),
1439 0..3
1440 );
1441 assert_eq!(
1442 tree.valid_levels_visible(VisibleItemIndex(6), |_| true),
1443 0..4
1444 );
1445
1446 assert_eq!(
1449 tree.valid_levels_visible(VisibleItemIndex(9), |_| false),
1450 1..3
1451 );
1452 assert_eq!(
1453 tree.valid_levels_visible(VisibleItemIndex(9), |_| true),
1454 1..4
1455 );
1456
1457 assert_eq!(
1459 tree.valid_levels_visible(VisibleItemIndex(11), |_| false),
1460 0..3
1461 );
1462 assert_eq!(
1463 tree.valid_levels_visible(VisibleItemIndex(11), |_| true),
1464 0..4
1465 );
1466 }
1467}