@@ -538,6 +538,24 @@ impl Tree {
541+ pub fn swap_split_in_direction(&mut self, direction: Direction) {
542+ if let Some(id) = self.find_split_in_direction(self.focus, direction) {
543+ if let Some([focused, target]) = self.nodes.get_disjoint_mut([self.focus, id]) {
544+ match (&mut focused.content, &mut target.content) {
545+ (Content::View(focused), Content::View(target)) => {
546+ std::mem::swap(&mut focused.doc, &mut target.doc);
547+ std::mem::swap(&mut focused.id, &mut target.id);
550+ // self.focus always points to a view which has a content of Content::View
551+ // and find_split_in_direction() only returns a view which has content of
553+ _ => unreachable!(),
541 pub fn area(&self) -> Rect {
559 pub fn area(&self) -> Rect {
542 self.area
560 self.area
@@ -649,4 +667,133 @@ mod test {
649 assert_eq!(None, tree.find_split_in_direction(r0, Direction::Right));
667 assert_eq!(None, tree.find_split_in_direction(r0, Direction::Right));
650 assert_eq!(None, tree.find_split_in_direction(r0, Direction::Up));
668 assert_eq!(None, tree.find_split_in_direction(r0, Direction::Up));
672+ fn swap_split_in_direction() {
673+ let mut tree = Tree::new(Rect {
680+ let doc_l0 = DocumentId::default();
681+ let mut view = View::new(
683+ vec![GutterType::Diagnostics, GutterType::LineNumbers],
685+ view.area = Rect::new(0, 0, 180, 80);
688+ let l0 = tree.focus;
690+ let doc_r0 = DocumentId::default();
691+ let view = View::new(
693+ vec![GutterType::Diagnostics, GutterType::LineNumbers],
695+ tree.split(view, Layout::Vertical);
696+ let r0 = tree.focus;
700+ let doc_l1 = DocumentId::default();
701+ let view = View::new(
703+ vec![GutterType::Diagnostics, GutterType::LineNumbers],
705+ tree.split(view, Layout::Horizontal);
706+ let l1 = tree.focus;
710+ let doc_l2 = DocumentId::default();
711+ let view = View::new(
713+ vec![GutterType::Diagnostics, GutterType::LineNumbers],
715+ tree.split(view, Layout::Vertical);
716+ let l2 = tree.focus;
722+ // Document IDs in test
726+ fn doc_id(tree: &Tree, view_id: ViewId) -> Option<DocumentId> {
727+ if let Content::View(view) = &tree.nodes[view_id].content {
735+ // `*` marks the view in focus from view table (here L0)
738+ tree.swap_split_in_direction(Direction::Down);
741+ assert_eq!(tree.focus, l1);
742+ assert_eq!(doc_id(&tree, l0), Some(doc_l1));
743+ assert_eq!(doc_id(&tree, l1), Some(doc_l0));
744+ assert_eq!(doc_id(&tree, l2), Some(doc_l2));
745+ assert_eq!(doc_id(&tree, r0), Some(doc_r0));
747+ tree.swap_split_in_direction(Direction::Right);
751+ assert_eq!(tree.focus, r0);
752+ assert_eq!(doc_id(&tree, l0), Some(doc_l1));
753+ assert_eq!(doc_id(&tree, l1), Some(doc_r0));
754+ assert_eq!(doc_id(&tree, l2), Some(doc_l2));
755+ assert_eq!(doc_id(&tree, r0), Some(doc_l0));
757+ // cannot swap, nothing changes
758+ tree.swap_split_in_direction(Direction::Up);
761+ assert_eq!(tree.focus, r0);
762+ assert_eq!(doc_id(&tree, l0), Some(doc_l1));
763+ assert_eq!(doc_id(&tree, l1), Some(doc_r0));
764+ assert_eq!(doc_id(&tree, l2), Some(doc_l2));
765+ assert_eq!(doc_id(&tree, r0), Some(doc_l0));
767+ // cannot swap, nothing changes
768+ tree.swap_split_in_direction(Direction::Down);
771+ assert_eq!(tree.focus, r0);
772+ assert_eq!(doc_id(&tree, l0), Some(doc_l1));
773+ assert_eq!(doc_id(&tree, l1), Some(doc_r0));
774+ assert_eq!(doc_id(&tree, l2), Some(doc_l2));
775+ assert_eq!(doc_id(&tree, r0), Some(doc_l0));
781+ tree.swap_split_in_direction(Direction::Down);
784+ assert_eq!(tree.focus, l1);
785+ assert_eq!(doc_id(&tree, l0), Some(doc_l1));
786+ assert_eq!(doc_id(&tree, l1), Some(doc_l2));
787+ assert_eq!(doc_id(&tree, l2), Some(doc_r0));
788+ assert_eq!(doc_id(&tree, r0), Some(doc_l0));
790+ tree.swap_split_in_direction(Direction::Up);
793+ assert_eq!(tree.focus, l0);
794+ assert_eq!(doc_id(&tree, l0), Some(doc_l2));
795+ assert_eq!(doc_id(&tree, l1), Some(doc_l1));
796+ assert_eq!(doc_id(&tree, l2), Some(doc_r0));
797+ assert_eq!(doc_id(&tree, r0), Some(doc_l0));