on master help sign in
Move Tree nodes on view swap

Instead of moving the Node contents on view swap if they have the same parent reorder them to keep traversal order otherwise re-parent them.

commit6bd8924436636c252ec2bfcd02986771665f0c02 authorRoland Kovacs <zen3ger@tutanota.com> dateWed 11 May 2022, 21:12 (4 years ago) parent3f10473
1 file changed+71−19
helix-view/src/tree.rs+71−19
helix-view/src/tree.rs+71−19
@@ -538,20 +538,72 @@ impl Tree {
538538 }
539539 }
540540
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);
548− self.focus = id;
549− }
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
552− // Content::View.
553− _ => unreachable!(),
541+ pub fn swap_split_in_direction(&mut self, direction: Direction) -> Option<()> {
542+ let focus = self.focus;
543+ let target = self.find_split_in_direction(focus, direction)?;
544+ let focus_parent = self.nodes[focus].parent;
545+ let target_parent = self.nodes[target].parent;
546+
547+ if focus_parent == target_parent {
548+ let parent = focus_parent;
549+ let [parent, focus, target] = self.nodes.get_disjoint_mut([parent, focus, target])?;
550+ match (&mut parent.content, &mut focus.content, &mut target.content) {
551+ (
552+ Content::Container(parent),
553+ Content::View(focus_view),
554+ Content::View(target_view),
555+ ) => {
556+ let focus_pos = parent.children.iter().position(|id| focus_view.id == *id)?;
557+ let target_pos = parent
558+ .children
559+ .iter()
560+ .position(|id| target_view.id == *id)?;
561+ // swap node positions so that traversal order is kept
562+ parent.children[focus_pos] = target_view.id;
563+ parent.children[target_pos] = focus_view.id;
564+ // swap area so that views rendered at the correct location
565+ std::mem::swap(&mut focus_view.area, &mut target_view.area);
566+
567+ Some(())
554568 }
569+ _ => unreachable!(),
570+ }
571+ } else {
572+ let [focus_parent, target_parent, focus, target] =
573+ self.nodes
574+ .get_disjoint_mut([focus_parent, target_parent, focus, target])?;
575+ match (
576+ &mut focus_parent.content,
577+ &mut target_parent.content,
578+ &mut focus.content,
579+ &mut target.content,
580+ ) {
581+ (
582+ Content::Container(focus_parent),
583+ Content::Container(target_parent),
584+ Content::View(focus_view),
585+ Content::View(target_view),
586+ ) => {
587+ let focus_pos = focus_parent
588+ .children
589+ .iter()
590+ .position(|id| focus_view.id == *id)?;
591+ let target_pos = target_parent
592+ .children
593+ .iter()
594+ .position(|id| target_view.id == *id)?;
595+ // re-parent target and focus nodes
596+ std::mem::swap(
597+ &mut focus_parent.children[focus_pos],
598+ &mut target_parent.children[target_pos],
599+ );
600+ std::mem::swap(&mut focus.parent, &mut target.parent);
601+ // swap area so that views rendered at the correct location
602+ std::mem::swap(&mut focus_view.area, &mut target_view.area);
603+
604+ Some(())
605+ }
606+ _ => unreachable!(),
555607 }
556608 }
557609 }
@@ -738,7 +790,7 @@ mod test {
738790 tree.swap_split_in_direction(Direction::Down);
739791 // | l1 | l2 | |
740792 // | l0* | r0 |
741− assert_eq!(tree.focus, l1);
793+ assert_eq!(tree.focus, l0);
742794 assert_eq!(doc_id(&tree, l0), Some(doc_l1));
743795 assert_eq!(doc_id(&tree, l1), Some(doc_l0));
744796 assert_eq!(doc_id(&tree, l2), Some(doc_l2));
@@ -748,7 +800,7 @@ mod test {
748800
749801 // | l1 | l2 | |
750802 // | r0 | l0* |
751− assert_eq!(tree.focus, r0);
803+ assert_eq!(tree.focus, l0);
752804 assert_eq!(doc_id(&tree, l0), Some(doc_l1));
753805 assert_eq!(doc_id(&tree, l1), Some(doc_r0));
754806 assert_eq!(doc_id(&tree, l2), Some(doc_l2));
@@ -758,7 +810,7 @@ mod test {
758810 tree.swap_split_in_direction(Direction::Up);
759811 // | l1 | l2 | |
760812 // | r0 | l0* |
761− assert_eq!(tree.focus, r0);
813+ assert_eq!(tree.focus, l0);
762814 assert_eq!(doc_id(&tree, l0), Some(doc_l1));
763815 assert_eq!(doc_id(&tree, l1), Some(doc_r0));
764816 assert_eq!(doc_id(&tree, l2), Some(doc_l2));
@@ -768,7 +820,7 @@ mod test {
768820 tree.swap_split_in_direction(Direction::Down);
769821 // | l1 | l2 | |
770822 // | r0 | l0* |
771− assert_eq!(tree.focus, r0);
823+ assert_eq!(tree.focus, l0);
772824 assert_eq!(doc_id(&tree, l0), Some(doc_l1));
773825 assert_eq!(doc_id(&tree, l1), Some(doc_r0));
774826 assert_eq!(doc_id(&tree, l2), Some(doc_l2));
@@ -781,7 +833,7 @@ mod test {
781833 tree.swap_split_in_direction(Direction::Down);
782834 // | l1 | r0 | |
783835 // | l2* | l0 |
784− assert_eq!(tree.focus, l1);
836+ assert_eq!(tree.focus, l2);
785837 assert_eq!(doc_id(&tree, l0), Some(doc_l1));
786838 assert_eq!(doc_id(&tree, l1), Some(doc_l2));
787839 assert_eq!(doc_id(&tree, l2), Some(doc_r0));
@@ -790,7 +842,7 @@ mod test {
790842 tree.swap_split_in_direction(Direction::Up);
791843 // | l2* | r0 | |
792844 // | l1 | l0 |
793− assert_eq!(tree.focus, l0);
845+ assert_eq!(tree.focus, l2);
794846 assert_eq!(doc_id(&tree, l0), Some(doc_l2));
795847 assert_eq!(doc_id(&tree, l1), Some(doc_l1));
796848 assert_eq!(doc_id(&tree, l2), Some(doc_r0));