@ -214,33 +214,56 @@ impl Tree {
node
node
}
}
pub fn remove ( & mut self , index : ViewId ) {
/// Get a mutable reference to a [Container] by index.
let mut stack = Vec ::new ( ) ;
/// # Panics
/// Panics if `index` is not in self.nodes, or if the node's content is not a [Content::Container].
if self . focus = = index {
fn container_mut ( & mut self , index : ViewId ) -> & mut Container {
// focus on something else
match & mut self . nodes [ index ] {
self . focus = self . prev ( ) ;
Node {
content : Content ::Container ( container ) ,
..
} = > container ,
_ = > unreachable! ( ) ,
}
}
}
stack . push ( index ) ;
fn remove_or_replace ( & mut self , child : ViewId , replacement : Option < ViewId > ) {
let parent = self . nodes [ child ] . parent ;
while let Some ( index ) = stack . pop ( ) {
self . nodes . remove ( child ) ;
let parent_id = self . nodes [ index ] . parent ;
if let Node {
let container = self . container_mut ( parent ) ;
content : Content ::Container ( container ) ,
let pos = container
..
. children
} = & mut self . nodes [ parent_id ]
. iter ( )
{
. position ( | & item | item = = child )
if let Some ( pos ) = container . children . iter ( ) . position ( | & child | child = = index ) {
. unwrap ( ) ;
if let Some ( new ) = replacement {
container . children [ pos ] = new ;
self . nodes [ new ] . parent = parent ;
} else {
container . children . remove ( pos ) ;
container . children . remove ( pos ) ;
// TODO: if container now only has one child, remove it and place child in parent
if container . children . is_empty ( ) & & parent_id ! = self . root {
// if container now empty, remove it
stack . push ( parent_id ) ;
}
}
}
}
pub fn remove ( & mut self , index : ViewId ) {
if self . focus = = index {
// focus on something else
self . focus = self . prev ( ) ;
}
}
self . nodes . remove ( index ) ;
let parent = self . nodes [ index ] . parent ;
let parent_is_root = parent = = self . root ;
self . remove_or_replace ( index , None ) ;
let parent_container = self . container_mut ( parent ) ;
if parent_container . children . len ( ) = = 1 & & ! parent_is_root {
// Lets merge the only child back to its grandparent so that Views
// are equally spaced.
let sibling = parent_container . children . pop ( ) . unwrap ( ) ;
self . remove_or_replace ( parent , Some ( sibling ) ) ;
}
}
self . recalculate ( )
self . recalculate ( )
@ -873,4 +896,42 @@ mod test {
assert_eq! ( doc_id ( & tree , l2 ) , Some ( doc_r0 ) ) ;
assert_eq! ( doc_id ( & tree , l2 ) , Some ( doc_r0 ) ) ;
assert_eq! ( doc_id ( & tree , r0 ) , Some ( doc_l0 ) ) ;
assert_eq! ( doc_id ( & tree , r0 ) , Some ( doc_l0 ) ) ;
}
}
#[ test ]
fn all_vertical_views_have_same_width ( ) {
let tree_area_width = 180 ;
let mut tree = Tree ::new ( Rect {
x : 0 ,
y : 0 ,
width : tree_area_width ,
height : 80 ,
} ) ;
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
view . area = Rect ::new ( 0 , 0 , 180 , 80 ) ;
tree . insert ( view ) ;
let view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
tree . split ( view , Layout ::Vertical ) ;
let view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
tree . split ( view , Layout ::Horizontal ) ;
tree . remove ( tree . focus ) ;
let view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
tree . split ( view , Layout ::Vertical ) ;
// Make sure that we only have one level in the tree.
assert_eq! ( 3 , tree . views ( ) . count ( ) ) ;
assert_eq! (
vec! [
tree_area_width / 3 ,
tree_area_width / 3 ,
tree_area_width / 3 - 2 // Rounding in `recalculate`.
] ,
tree . views ( )
. map ( | ( view , _ ) | view . area . width )
. collect ::< Vec < _ > > ( )
) ;
}
}
}