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