@@ -526,6 +526,24 @@ impl Tree {
526
526
}
527
527
}
528
528
529
+ pub fn swap_split_in_direction ( & mut self , direction : Direction ) {
530
+ if let Some ( id) = self . find_split_in_direction ( self . focus , direction) {
531
+ if let Some ( [ focused, target] ) = self . nodes . get_disjoint_mut ( [ self . focus , id] ) {
532
+ match ( & mut focused. content , & mut target. content ) {
533
+ ( Content :: View ( focused) , Content :: View ( target) ) => {
534
+ std:: mem:: swap ( & mut focused. doc , & mut target. doc ) ;
535
+ std:: mem:: swap ( & mut focused. id , & mut target. id ) ;
536
+ self . focus = id;
537
+ }
538
+ // self.focus always points to a view which has a content of Content::View
539
+ // and find_split_in_direction() only returns a view which has content of
540
+ // Content::View.
541
+ _ => unreachable ! ( ) ,
542
+ }
543
+ }
544
+ }
545
+ }
546
+
529
547
pub fn area ( & self ) -> Rect {
530
548
self . area
531
549
}
@@ -637,4 +655,133 @@ mod test {
637
655
assert_eq ! ( None , tree. find_split_in_direction( r0, Direction :: Right ) ) ;
638
656
assert_eq ! ( None , tree. find_split_in_direction( r0, Direction :: Up ) ) ;
639
657
}
658
+
659
+ #[ test]
660
+ fn swap_split_in_direction ( ) {
661
+ let mut tree = Tree :: new ( Rect {
662
+ x : 0 ,
663
+ y : 0 ,
664
+ width : 180 ,
665
+ height : 80 ,
666
+ } ) ;
667
+
668
+ let doc_l0 = DocumentId :: default ( ) ;
669
+ let mut view = View :: new (
670
+ doc_l0,
671
+ vec ! [ GutterType :: Diagnostics , GutterType :: LineNumbers ] ,
672
+ ) ;
673
+ view. area = Rect :: new ( 0 , 0 , 180 , 80 ) ;
674
+ tree. insert ( view) ;
675
+
676
+ let l0 = tree. focus ;
677
+
678
+ let doc_r0 = DocumentId :: default ( ) ;
679
+ let view = View :: new (
680
+ doc_r0,
681
+ vec ! [ GutterType :: Diagnostics , GutterType :: LineNumbers ] ,
682
+ ) ;
683
+ tree. split ( view, Layout :: Vertical ) ;
684
+ let r0 = tree. focus ;
685
+
686
+ tree. focus = l0;
687
+
688
+ let doc_l1 = DocumentId :: default ( ) ;
689
+ let view = View :: new (
690
+ doc_l1,
691
+ vec ! [ GutterType :: Diagnostics , GutterType :: LineNumbers ] ,
692
+ ) ;
693
+ tree. split ( view, Layout :: Horizontal ) ;
694
+ let l1 = tree. focus ;
695
+
696
+ tree. focus = l0;
697
+
698
+ let doc_l2 = DocumentId :: default ( ) ;
699
+ let view = View :: new (
700
+ doc_l2,
701
+ vec ! [ GutterType :: Diagnostics , GutterType :: LineNumbers ] ,
702
+ ) ;
703
+ tree. split ( view, Layout :: Vertical ) ;
704
+ let l2 = tree. focus ;
705
+
706
+ // Views in test
707
+ // | L0 | L2 | |
708
+ // | L1 | R0 |
709
+
710
+ // Document IDs in test
711
+ // | l0 | l2 | |
712
+ // | l1 | r0 |
713
+
714
+ fn doc_id ( tree : & Tree , view_id : ViewId ) -> Option < DocumentId > {
715
+ if let Content :: View ( view) = & tree. nodes [ view_id] . content {
716
+ Some ( view. doc )
717
+ } else {
718
+ None
719
+ }
720
+ }
721
+
722
+ tree. focus = l0;
723
+ // `*` marks the view in focus from view table (here L0)
724
+ // | l0* | l2 | |
725
+ // | l1 | r0 |
726
+ tree. swap_split_in_direction ( Direction :: Down ) ;
727
+ // | l1 | l2 | |
728
+ // | l0* | r0 |
729
+ assert_eq ! ( tree. focus, l1) ;
730
+ assert_eq ! ( doc_id( & tree, l0) , Some ( doc_l1) ) ;
731
+ assert_eq ! ( doc_id( & tree, l1) , Some ( doc_l0) ) ;
732
+ assert_eq ! ( doc_id( & tree, l2) , Some ( doc_l2) ) ;
733
+ assert_eq ! ( doc_id( & tree, r0) , Some ( doc_r0) ) ;
734
+
735
+ tree. swap_split_in_direction ( Direction :: Right ) ;
736
+
737
+ // | l1 | l2 | |
738
+ // | r0 | l0* |
739
+ assert_eq ! ( tree. focus, r0) ;
740
+ assert_eq ! ( doc_id( & tree, l0) , Some ( doc_l1) ) ;
741
+ assert_eq ! ( doc_id( & tree, l1) , Some ( doc_r0) ) ;
742
+ assert_eq ! ( doc_id( & tree, l2) , Some ( doc_l2) ) ;
743
+ assert_eq ! ( doc_id( & tree, r0) , Some ( doc_l0) ) ;
744
+
745
+ // cannot swap, nothing changes
746
+ tree. swap_split_in_direction ( Direction :: Up ) ;
747
+ // | l1 | l2 | |
748
+ // | r0 | l0* |
749
+ assert_eq ! ( tree. focus, r0) ;
750
+ assert_eq ! ( doc_id( & tree, l0) , Some ( doc_l1) ) ;
751
+ assert_eq ! ( doc_id( & tree, l1) , Some ( doc_r0) ) ;
752
+ assert_eq ! ( doc_id( & tree, l2) , Some ( doc_l2) ) ;
753
+ assert_eq ! ( doc_id( & tree, r0) , Some ( doc_l0) ) ;
754
+
755
+ // cannot swap, nothing changes
756
+ tree. swap_split_in_direction ( Direction :: Down ) ;
757
+ // | l1 | l2 | |
758
+ // | r0 | l0* |
759
+ assert_eq ! ( tree. focus, r0) ;
760
+ assert_eq ! ( doc_id( & tree, l0) , Some ( doc_l1) ) ;
761
+ assert_eq ! ( doc_id( & tree, l1) , Some ( doc_r0) ) ;
762
+ assert_eq ! ( doc_id( & tree, l2) , Some ( doc_l2) ) ;
763
+ assert_eq ! ( doc_id( & tree, r0) , Some ( doc_l0) ) ;
764
+
765
+ tree. focus = l2;
766
+ // | l1 | l2* | |
767
+ // | r0 | l0 |
768
+
769
+ tree. swap_split_in_direction ( Direction :: Down ) ;
770
+ // | l1 | r0 | |
771
+ // | l2* | l0 |
772
+ assert_eq ! ( tree. focus, l1) ;
773
+ assert_eq ! ( doc_id( & tree, l0) , Some ( doc_l1) ) ;
774
+ assert_eq ! ( doc_id( & tree, l1) , Some ( doc_l2) ) ;
775
+ assert_eq ! ( doc_id( & tree, l2) , Some ( doc_r0) ) ;
776
+ assert_eq ! ( doc_id( & tree, r0) , Some ( doc_l0) ) ;
777
+
778
+ tree. swap_split_in_direction ( Direction :: Up ) ;
779
+ // | l2* | r0 | |
780
+ // | l1 | l0 |
781
+ assert_eq ! ( tree. focus, l0) ;
782
+ assert_eq ! ( doc_id( & tree, l0) , Some ( doc_l2) ) ;
783
+ assert_eq ! ( doc_id( & tree, l1) , Some ( doc_l1) ) ;
784
+ assert_eq ! ( doc_id( & tree, l2) , Some ( doc_r0) ) ;
785
+ assert_eq ! ( doc_id( & tree, r0) , Some ( doc_l0) ) ;
786
+ }
640
787
}
0 commit comments