use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use teksilo_core::ObserverHandle;
use teksilo_core::signal::Signal;
use crate::TreeModel;
use crate::dnd_types::{DragEligibility, DragSource, DropCommit, DropQuery, DropResponse};
use crate::tree_change::{NodeId, TreeChange};
use crate::tree_data_source::{
FlatEntry, TreeDataSource, tree_apply_reorder, tree_is_desc_or_self,
};
pub struct TreeSlice<T: 'static> {
tree: TreeModel<T>,
expanded: Rc<RefCell<HashSet<NodeId>>>,
flattened: Rc<RefCell<Vec<FlatEntry>>>,
positions: Rc<RefCell<HashMap<NodeId, usize>>>,
version: Signal<u64>,
version_counter: Rc<std::cell::Cell<u64>>,
divergence: Rc<std::cell::Cell<Option<usize>>>,
_tree_observer: ObserverHandle,
}
impl<T: 'static> TreeSlice<T> {
pub fn new(tree: TreeModel<T>) -> Self {
let expanded: Rc<RefCell<HashSet<NodeId>>> = Rc::new(RefCell::new(HashSet::new()));
let flattened: Rc<RefCell<Vec<FlatEntry>>> = Rc::new(RefCell::new(Vec::new()));
let positions: Rc<RefCell<HashMap<NodeId, usize>>> = Rc::new(RefCell::new(HashMap::new()));
let version = Signal::new(0_u64);
let version_counter = Rc::new(std::cell::Cell::new(0_u64));
let divergence = Rc::new(std::cell::Cell::new(None));
Self::rebuild_flat_list(
&tree,
&expanded.borrow(),
&mut flattened.borrow_mut(),
&mut positions.borrow_mut(),
);
let exp = expanded.clone();
let flat = flattened.clone();
let pos = positions.clone();
let tree_for_obs = tree.clone();
let ver = version.clone();
let vc = version_counter.clone();
let div = divergence.clone();
let observer = tree.observe_changes(move |change| {
let mut d = Self::rebuild_flat_list(
&tree_for_obs,
&exp.borrow(),
&mut flat.borrow_mut(),
&mut pos.borrow_mut(),
);
if let TreeChange::NodeUpdated { node } = change
&& let Some(&p) = pos.borrow().get(node)
{
d = d.min(p);
}
div.set(Some(d));
let next = vc.get() + 1;
vc.set(next);
ver.set(next);
});
Self {
tree,
expanded,
flattened,
positions,
version,
version_counter,
divergence,
_tree_observer: observer,
}
}
pub fn visible_count(&self) -> usize {
self.flattened.borrow().len()
}
pub fn with_entry<R>(
&self,
flat_index: usize,
f: impl FnOnce(&T, &FlatEntry) -> R,
) -> Option<R> {
let flat = self.flattened.borrow();
let entry = flat.get(flat_index)?;
let node_id = entry.node_id;
self.tree.with_item(node_id, |item| f(item, entry))
}
pub fn visible_node_id(&self, flat_index: usize) -> Option<NodeId> {
self.flattened.borrow().get(flat_index).map(|e| e.node_id)
}
pub fn entry_at(&self, flat_index: usize) -> Option<FlatEntry> {
self.flattened.borrow().get(flat_index).cloned()
}
pub fn depth_at(&self, flat_index: usize) -> usize {
self.flattened
.borrow()
.get(flat_index)
.map(|e| e.depth)
.unwrap_or(0)
}
pub fn flat_index_of(&self, node: NodeId) -> Option<usize> {
self.positions.borrow().get(&node).copied()
}
pub fn is_expanded(&self, node: NodeId) -> bool {
self.expanded.borrow().contains(&node)
}
pub fn expand(&self, node: NodeId) {
{
let mut exp = self.expanded.borrow_mut();
if !exp.insert(node) {
return; }
}
self.reflatten_and_notify();
}
pub fn collapse(&self, node: NodeId) {
{
let mut exp = self.expanded.borrow_mut();
if !exp.remove(&node) {
return; }
}
self.reflatten_and_notify();
}
pub fn toggle(&self, node: NodeId) {
{
let mut exp = self.expanded.borrow_mut();
if exp.contains(&node) {
exp.remove(&node);
} else {
exp.insert(node);
}
}
self.reflatten_and_notify();
}
pub fn expand_all(&self) {
{
let mut exp = self.expanded.borrow_mut();
self.expand_all_recursive(&mut exp);
}
self.reflatten_and_notify();
}
pub fn collapse_all(&self) {
{
let mut exp = self.expanded.borrow_mut();
exp.clear();
}
self.reflatten_and_notify();
}
pub fn expanded_nodes(&self) -> Vec<NodeId> {
self.expanded.borrow().iter().copied().collect()
}
pub fn set_expanded_nodes(&self, nodes: &[NodeId]) {
{
let mut exp = self.expanded.borrow_mut();
exp.clear();
for &node in nodes {
exp.insert(node);
}
}
self.reflatten_and_notify();
}
pub fn version_signal(&self) -> Signal<u64> {
self.version.clone()
}
pub fn first_changed_index(&self) -> Option<usize> {
self.divergence.get()
}
pub fn tree(&self) -> &TreeModel<T> {
&self.tree
}
pub fn handle(&self) -> TreeSliceHandle<T> {
TreeSliceHandle {
tree: self.tree.clone(),
expanded: self.expanded.clone(),
flattened: self.flattened.clone(),
positions: self.positions.clone(),
version: self.version.clone(),
version_counter: self.version_counter.clone(),
divergence: self.divergence.clone(),
}
}
fn reflatten_and_notify(&self) {
let d = Self::rebuild_flat_list(
&self.tree,
&self.expanded.borrow(),
&mut self.flattened.borrow_mut(),
&mut self.positions.borrow_mut(),
);
self.divergence.set(Some(d));
let next = self.version_counter.get() + 1;
self.version_counter.set(next);
self.version.set(next);
}
fn expand_all_recursive(&self, expanded: &mut HashSet<NodeId>) {
let root_count = self.tree.root_count();
for i in 0..root_count {
let root = self.tree.root(i);
Self::expand_subtree_recursive(&self.tree, root, expanded);
}
}
fn expand_subtree_recursive(tree: &TreeModel<T>, root: NodeId, expanded: &mut HashSet<NodeId>) {
let mut stack = vec![root];
while let Some(node) = stack.pop() {
if tree.has_children(node) {
expanded.insert(node);
for child in tree.children(node) {
stack.push(child);
}
}
}
}
fn rebuild_flat_list(
tree: &TreeModel<T>,
expanded: &HashSet<NodeId>,
out: &mut Vec<FlatEntry>,
pos: &mut HashMap<NodeId, usize>,
) -> usize {
let old = std::mem::take(out);
out.reserve(old.len());
let root_count = tree.root_count();
for i in 0..root_count {
let root = tree.root(i);
Self::flatten_node(tree, root, 0, expanded, out);
}
pos.clear();
pos.extend(out.iter().enumerate().map(|(i, e)| (e.node_id, i)));
old.iter()
.zip(out.iter())
.take_while(|(a, b)| a == b)
.count()
}
fn flatten_node(
tree: &TreeModel<T>,
root: NodeId,
depth: usize,
expanded: &HashSet<NodeId>,
out: &mut Vec<FlatEntry>,
) {
let mut stack = vec![(root, depth)];
while let Some((node, depth)) = stack.pop() {
let has_children = tree.has_children(node);
let is_expanded = expanded.contains(&node);
out.push(FlatEntry {
node_id: node,
depth,
has_children,
is_expanded,
});
if is_expanded && has_children {
for child in tree.children(node).into_iter().rev() {
stack.push((child, depth + 1));
}
}
}
}
}
impl<T: 'static> std::fmt::Debug for TreeSlice<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TreeSlice")
.field("visible_count", &self.visible_count())
.field("expanded_count", &self.expanded.borrow().len())
.finish()
}
}
pub struct TreeSliceHandle<T: 'static> {
tree: TreeModel<T>,
expanded: Rc<RefCell<HashSet<NodeId>>>,
flattened: Rc<RefCell<Vec<FlatEntry>>>,
positions: Rc<RefCell<HashMap<NodeId, usize>>>,
version: Signal<u64>,
version_counter: Rc<std::cell::Cell<u64>>,
divergence: Rc<std::cell::Cell<Option<usize>>>,
}
impl<T: 'static> TreeSliceHandle<T> {
pub fn visible_count(&self) -> usize {
self.flattened.borrow().len()
}
pub fn entry_at(&self, flat_index: usize) -> Option<FlatEntry> {
self.flattened.borrow().get(flat_index).cloned()
}
pub fn visible_node_id(&self, flat_index: usize) -> Option<NodeId> {
self.flattened.borrow().get(flat_index).map(|e| e.node_id)
}
pub fn expand(&self, node: NodeId) {
let inserted = self.expanded.borrow_mut().insert(node);
if inserted {
self.reflatten_and_notify();
}
}
pub fn collapse(&self, node: NodeId) {
let removed = self.expanded.borrow_mut().remove(&node);
if removed {
self.reflatten_and_notify();
}
}
pub fn is_expanded(&self, node: NodeId) -> bool {
self.expanded.borrow().contains(&node)
}
pub fn toggle_expand(&self, node: NodeId) {
{
let mut exp = self.expanded.borrow_mut();
if exp.contains(&node) {
exp.remove(&node);
} else {
exp.insert(node);
}
}
self.reflatten_and_notify();
}
pub fn tree(&self) -> &TreeModel<T> {
&self.tree
}
pub fn expand_all(&self) {
{
let mut exp = self.expanded.borrow_mut();
let root_count = self.tree.root_count();
for i in 0..root_count {
let root = self.tree.root(i);
TreeSlice::<T>::expand_subtree_recursive(&self.tree, root, &mut exp);
}
}
self.reflatten_and_notify();
}
pub fn first_changed_index(&self) -> Option<usize> {
self.divergence.get()
}
fn reflatten_and_notify(&self) {
let d = TreeSlice::<T>::rebuild_flat_list(
&self.tree,
&self.expanded.borrow(),
&mut self.flattened.borrow_mut(),
&mut self.positions.borrow_mut(),
);
self.divergence.set(Some(d));
let next = self.version_counter.get() + 1;
self.version_counter.set(next);
self.version.set(next);
}
}
impl<T: 'static> Clone for TreeSliceHandle<T> {
fn clone(&self) -> Self {
Self {
tree: self.tree.clone(),
expanded: self.expanded.clone(),
flattened: self.flattened.clone(),
positions: self.positions.clone(),
version: self.version.clone(),
version_counter: self.version_counter.clone(),
divergence: self.divergence.clone(),
}
}
}
impl<T: 'static> TreeDataSource for TreeSlice<T> {
type Item = T;
type Key = NodeId;
fn visible_count(&self) -> usize {
TreeSlice::visible_count(self)
}
fn with_entry<R>(
&self,
flat_index: usize,
f: impl FnOnce(&Self::Item, &FlatEntry<Self::Key>) -> R,
) -> Option<R> {
TreeSlice::with_entry(self, flat_index, f)
}
fn key_at(&self, flat_index: usize) -> Option<NodeId> {
self.visible_node_id(flat_index)
}
fn flat_index_of(&self, key: &NodeId) -> Option<usize> {
TreeSlice::flat_index_of(self, *key)
}
fn parent(&self, key: &NodeId) -> Option<NodeId> {
self.tree().parent(*key)
}
fn child_keys(&self, key: &NodeId) -> Vec<NodeId> {
self.tree().children(*key)
}
fn version_signal(&self) -> Signal<u64> {
TreeSlice::version_signal(self)
}
fn first_changed_index(&self) -> Option<usize> {
TreeSlice::first_changed_index(self)
}
fn contains_key(&self, key: &NodeId) -> bool {
self.tree().with_item(*key, |_| ()).is_some()
}
fn is_expanded(&self, key: &NodeId) -> bool {
TreeSlice::is_expanded(self, *key)
}
fn set_expanded(&self, key: &NodeId, expanded: bool) {
if expanded {
self.expand(*key);
} else {
self.collapse(*key);
}
}
fn drag(&self, _key: &NodeId) -> DragEligibility {
DragEligibility::CanDrag
}
fn can_accept(&self, query: &DropQuery<'_, NodeId>) -> DropResponse {
match &query.source {
DragSource::SameView { key: source } => {
if *source == query.target
|| tree_is_desc_or_self(self.tree(), query.target, *source)
{
DropResponse::Reject
} else {
DropResponse::Accept
}
}
DragSource::Foreign { .. } => DropResponse::Reject,
}
}
fn accept_drop(&self, commit: DropCommit<'_, NodeId>) -> bool {
match commit.source {
DragSource::SameView { key: source } => {
tree_apply_reorder(self.tree(), source, commit.target, commit.position)
}
DragSource::Foreign { .. } => false,
}
}
fn on_drag_out(&self, key: &NodeId) {
if self.tree().with_item(*key, |_| ()).is_some() {
self.tree().remove(*key);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dnd_types::DropPosition;
fn sample_tree() -> TreeModel<&'static str> {
let tree = TreeModel::new();
let a = tree.insert_root(0, "A");
let a1 = tree.insert_child(a, 0, "A1");
tree.insert_child(a1, 0, "A1a");
tree.insert_child(a, 1, "A2");
let b = tree.insert_root(1, "B");
tree.insert_child(b, 0, "B1");
tree.insert_root(2, "C");
tree
}
#[test]
fn initial_state_shows_only_roots() {
let tree = sample_tree();
let slice = TreeSlice::new(tree);
assert_eq!(slice.visible_count(), 3); assert_eq!(
slice.with_entry(0, |item, entry| {
assert_eq!(*item, "A");
assert_eq!(entry.depth, 0);
assert!(entry.has_children);
assert!(!entry.is_expanded);
}),
Some(())
);
assert_eq!(slice.with_entry(1, |item, _| *item), Some("B"));
assert_eq!(slice.with_entry(2, |item, _| *item), Some("C"));
}
#[test]
fn expand_shows_children() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree);
assert_eq!(slice.visible_count(), 3);
slice.expand(a);
assert_eq!(slice.visible_count(), 5);
assert_eq!(slice.with_entry(0, |item, _| *item), Some("A"));
assert_eq!(
slice.with_entry(1, |item, entry| {
assert_eq!(*item, "A1");
assert_eq!(entry.depth, 1);
assert!(entry.has_children); }),
Some(())
);
assert_eq!(slice.with_entry(2, |item, _| *item), Some("A2"));
assert_eq!(slice.with_entry(3, |item, _| *item), Some("B"));
}
#[test]
fn collapse_hides_children() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree);
slice.expand(a);
assert_eq!(slice.visible_count(), 5);
slice.collapse(a);
assert_eq!(slice.visible_count(), 3);
}
#[test]
fn deep_expand() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree.clone());
slice.expand(a);
let a1 = slice.visible_node_id(1).unwrap();
slice.expand(a1);
assert_eq!(slice.visible_count(), 6);
assert_eq!(
slice.with_entry(2, |item, entry| {
assert_eq!(*item, "A1a");
assert_eq!(entry.depth, 2);
}),
Some(())
);
}
#[test]
fn toggle() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree);
slice.toggle(a);
assert_eq!(slice.visible_count(), 5); assert!(slice.is_expanded(a));
slice.toggle(a);
assert_eq!(slice.visible_count(), 3); assert!(!slice.is_expanded(a));
}
#[test]
fn expand_all() {
let tree = sample_tree();
let slice = TreeSlice::new(tree);
slice.expand_all();
assert_eq!(slice.visible_count(), 7);
}
#[test]
fn collapse_all() {
let tree = sample_tree();
let slice = TreeSlice::new(tree);
slice.expand_all();
assert_eq!(slice.visible_count(), 7);
slice.collapse_all();
assert_eq!(slice.visible_count(), 3);
}
#[test]
fn handle_expand_all_matches_slice() {
let tree = sample_tree();
let slice = TreeSlice::new(tree);
let handle = slice.handle();
assert_eq!(slice.visible_count(), 3); handle.expand_all();
assert_eq!(slice.visible_count(), 7);
}
#[test]
fn two_slices_independent_expand() {
let tree = sample_tree();
let a = tree.root(0);
let b = tree.root(1);
let slice1 = TreeSlice::new(tree.clone());
let slice2 = TreeSlice::new(tree);
slice1.expand(a);
slice2.expand(b);
assert_eq!(slice1.visible_count(), 5); assert!(slice1.is_expanded(a));
assert!(!slice1.is_expanded(b));
assert_eq!(slice2.visible_count(), 4); assert!(!slice2.is_expanded(a));
assert!(slice2.is_expanded(b));
}
#[test]
fn tree_mutation_updates_slice() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree.clone());
slice.expand(a);
assert_eq!(slice.visible_count(), 5);
tree.insert_child(a, 2, "A3");
assert_eq!(slice.visible_count(), 6); }
#[test]
fn tree_remove_updates_slice() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree.clone());
slice.expand(a);
let a1 = slice.visible_node_id(1).unwrap();
tree.remove(a1);
assert_eq!(slice.visible_count(), 4); }
#[test]
fn version_signal_increments() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree.clone());
let v0 = slice.version_signal().get();
slice.expand(a);
let v1 = slice.version_signal().get();
assert!(v1 > v0, "version should increment on expand");
tree.insert_root(3, "D");
let v2 = slice.version_signal().get();
assert!(v2 > v1, "version should increment on tree mutation");
}
#[test]
fn flat_index_of() {
let tree = sample_tree();
let a = tree.root(0);
let b = tree.root(1);
let slice = TreeSlice::new(tree);
assert_eq!(slice.flat_index_of(a), Some(0));
assert_eq!(slice.flat_index_of(b), Some(1));
}
fn assert_positions_match_iteration_order<T>(slice: &TreeSlice<T>) {
for i in 0..slice.visible_count() {
let node = slice.visible_node_id(i).unwrap();
assert_eq!(
slice.flat_index_of(node),
Some(i),
"flat_index_of({node:?}) should be the iteration position {i}"
);
}
}
#[test]
fn flat_index_of_matches_iteration_order_across_mutations() {
let tree = sample_tree();
let a = tree.root(0);
let b = tree.root(1);
let slice = TreeSlice::new(tree.clone());
assert_positions_match_iteration_order(&slice);
slice.expand(a);
assert_positions_match_iteration_order(&slice);
slice.expand(b);
assert_positions_match_iteration_order(&slice);
slice.collapse(a);
assert_positions_match_iteration_order(&slice);
tree.insert_root(3, "D");
assert_positions_match_iteration_order(&slice);
tree.remove(b);
assert_positions_match_iteration_order(&slice);
}
#[test]
fn persistence_save_restore() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree.clone());
slice.expand(a);
let saved = slice.expanded_nodes();
assert_eq!(saved.len(), 1);
slice.collapse_all();
assert_eq!(slice.visible_count(), 3);
slice.set_expanded_nodes(&saved);
assert_eq!(slice.visible_count(), 5); }
#[test]
fn out_of_bounds_returns_none() {
let tree = sample_tree();
let slice = TreeSlice::new(tree);
assert_eq!(slice.with_entry(99, |_, _| ()), None);
assert_eq!(slice.visible_node_id(99), None);
}
#[test]
fn divergence_unknown_before_first_reflatten() {
let tree = sample_tree();
let slice = TreeSlice::new(tree);
assert_eq!(slice.first_changed_index(), None);
}
#[test]
fn divergence_on_expand_is_the_toggled_row() {
let tree = sample_tree();
let b = tree.root(1);
let slice = TreeSlice::new(tree);
slice.expand(b);
assert_eq!(slice.first_changed_index(), Some(1));
slice.collapse(b);
assert_eq!(slice.first_changed_index(), Some(1));
}
#[test]
fn divergence_on_append_is_old_len() {
let tree = sample_tree();
let slice = TreeSlice::new(tree.clone());
tree.insert_root(3, "D"); assert_eq!(slice.first_changed_index(), Some(3));
}
#[test]
fn divergence_on_remove_is_removed_position() {
let tree = sample_tree();
let b = tree.root(1);
let slice = TreeSlice::new(tree.clone());
tree.remove(b); assert_eq!(slice.first_changed_index(), Some(1));
}
#[test]
fn divergence_on_node_update_is_its_flat_index() {
let tree = sample_tree();
let c = tree.root(2);
let slice = TreeSlice::new(tree.clone());
tree.update(c, "C-updated");
assert_eq!(slice.first_changed_index(), Some(2));
}
#[test]
fn divergence_on_invisible_update_is_visible_count() {
let tree = sample_tree();
let a = tree.root(0);
let a1 = tree.children(a)[0];
let slice = TreeSlice::new(tree.clone());
tree.update(a1, "A1-updated");
assert_eq!(slice.first_changed_index(), Some(slice.visible_count()));
}
#[test]
fn divergence_via_handle_toggle() {
let tree = sample_tree();
let b = tree.root(1);
let slice = TreeSlice::new(tree);
let handle = slice.handle();
handle.toggle_expand(b);
assert_eq!(handle.first_changed_index(), Some(1));
assert_eq!(slice.first_changed_index(), Some(1));
}
#[test]
fn tree_source_accept_drop_reparents_into() {
let tree = sample_tree();
let a = tree.root(0);
let b = tree.root(1);
let slice = TreeSlice::new(tree.clone());
assert!(slice.accept_drop(DropCommit {
source: DragSource::SameView { key: b },
target: a,
position: DropPosition::Into,
}));
assert_eq!(tree.root_count(), 2);
assert_eq!(tree.parent(b), Some(a));
}
#[test]
fn tree_source_can_accept_rejects_cycle_and_refuses_drop() {
let tree = sample_tree();
let a = tree.root(0);
let slice = TreeSlice::new(tree.clone());
slice.expand(a);
let a1 = slice.visible_node_id(1).unwrap();
assert_eq!(
slice.can_accept(&DropQuery {
source: DragSource::SameView { key: a },
target: a1,
position: DropPosition::Into,
}),
DropResponse::Reject
);
assert!(!slice.accept_drop(DropCommit {
source: DragSource::SameView { key: a },
target: a1,
position: DropPosition::Into,
}));
}
#[test]
fn tree_source_reorders_root_siblings() {
let tree = sample_tree();
let a = tree.root(0);
let c = tree.root(2);
let slice = TreeSlice::new(tree.clone());
assert!(slice.accept_drop(DropCommit {
source: DragSource::SameView { key: c },
target: a,
position: DropPosition::Before,
}));
assert_eq!(slice.with_entry(0, |v, _| *v), Some("C"));
assert_eq!(slice.with_entry(1, |v, _| *v), Some("A"));
assert_eq!(slice.with_entry(2, |v, _| *v), Some("B"));
}
#[test]
fn tree_reorder_within_filters_descendants_of_selected() {
let tree = sample_tree();
let a = tree.root(0);
let c = tree.root(2);
let slice = TreeSlice::new(tree.clone());
let a1 = slice.child_keys(&a)[0];
assert!(slice.reorder_within(&[a, a1], &c, DropPosition::After));
assert_eq!(slice.with_entry(0, |v, _| *v), Some("B"));
assert_eq!(slice.with_entry(1, |v, _| *v), Some("C"));
assert_eq!(slice.with_entry(2, |v, _| *v), Some("A"));
assert_eq!(slice.child_keys(&a).len(), 2);
}
#[test]
fn tree_on_drag_out_removes_node_and_subtree() {
let tree = sample_tree();
let b = tree.root(1);
let slice = TreeSlice::new(tree.clone());
slice.on_drag_out(&b);
assert_eq!(slice.visible_count(), 2);
assert_eq!(slice.with_entry(0, |v, _| *v), Some("A"));
assert_eq!(slice.with_entry(1, |v, _| *v), Some("C"));
}
#[test]
fn deep_chain_flattens_and_expands_without_overflow() {
const DEPTH: usize = 50_000;
let tree = TreeModel::new();
let root = tree.insert_root(0, 0usize);
let mut leaf = root;
for i in 1..DEPTH {
leaf = tree.insert_child(leaf, 0, i);
}
let slice = TreeSlice::new(tree);
slice.expand_all();
assert_eq!(slice.visible_count(), DEPTH);
assert_eq!(slice.flat_index_of(leaf), Some(DEPTH - 1));
assert_eq!(slice.depth_at(DEPTH - 1), DEPTH - 1);
}
}