From 5554910e08ae57bca4994bd606d977599d2ef38d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= <blaz@mxxn.io>
Date: Thu, 4 Feb 2021 17:26:11 +0900
Subject: [PATCH] Forgot to add the tree.rs definition...

---
 helix-view/src/tree.rs | 173 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 helix-view/src/tree.rs

diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs
new file mode 100644
index 00000000..5c583cbd
--- /dev/null
+++ b/helix-view/src/tree.rs
@@ -0,0 +1,173 @@
+use crate::View;
+use slotmap::{DefaultKey as Key, HopSlotMap};
+use tui::layout::Rect;
+
+// the dimensions are recomputed on windo resize/tree change.
+//
+pub struct Tree {
+    root: Key,
+    // (container, index inside the container)
+    current: (Key, usize),
+    pub focus: Key,
+    fullscreen: bool,
+    area: Rect,
+
+    nodes: HopSlotMap<Key, Node>,
+
+    // used for traversals
+    stack: Vec<(Key, Rect)>,
+}
+
+pub enum Node {
+    View(Box<View>),
+    Container(Box<Container>),
+}
+
+impl Node {
+    pub fn container(area: Rect) -> Self {
+        Self::Container(Box::new(Container::new()))
+    }
+
+    pub fn view(view: View) -> Self {
+        Self::View(Box::new(view))
+    }
+}
+
+// TODO: screen coord to container + container coordinate helpers
+
+pub enum Layout {
+    Horizontal,
+    Vertical,
+    // could explore stacked/tabbed
+}
+
+pub struct Container {
+    layout: Layout,
+    children: Vec<Key>,
+    area: Rect,
+}
+
+impl Container {
+    pub fn new() -> Self {
+        Self {
+            layout: Layout::Horizontal,
+            children: Vec::new(),
+            area: Rect::default(),
+        }
+    }
+}
+
+impl Tree {
+    pub fn new(area: Rect) -> Self {
+        let root = Node::container(area);
+        let mut nodes = HopSlotMap::new();
+        let root = nodes.insert(root);
+
+        Self {
+            root,
+            current: (root, 0),
+            focus: Key::default(),
+            fullscreen: false,
+            area,
+            nodes,
+            stack: Vec::new(),
+        }
+    }
+
+    pub fn insert(&mut self, view: View) -> Key {
+        let node = self.nodes.insert(Node::view(view));
+        let (id, pos) = self.current;
+        let container = match &mut self.nodes[id] {
+            Node::Container(container) => container,
+            _ => unreachable!(),
+        };
+
+        // insert node after the current item if there is children already
+        let pos = if container.children.is_empty() {
+            pos
+        } else {
+            pos + 1
+        };
+
+        container.children.insert(pos, node);
+        // focus the new node
+        self.current = (id, pos);
+        self.focus = node;
+
+        // recalculate all the sizes
+        self.traverse();
+
+        node
+    }
+
+    pub fn views(&mut self) -> impl Iterator<Item = (&mut View, bool)> {
+        let focus = self.focus;
+        self.nodes
+            .iter_mut()
+            .filter_map(move |(key, node)| match node {
+                Node::View(view) => Some((view.as_mut(), focus == key)),
+                Node::Container(..) => None,
+            })
+    }
+
+    pub fn get(&self, index: Key) -> &View {
+        match &self.nodes[index] {
+            Node::View(view) => view,
+            _ => unreachable!(),
+        }
+    }
+
+    pub fn get_mut(&mut self, index: Key) -> &mut View {
+        match &mut self.nodes[index] {
+            Node::View(view) => view,
+            _ => unreachable!(),
+        }
+    }
+
+    pub fn resize(&mut self, area: Rect) {
+        self.area = area;
+        self.traverse();
+    }
+
+    pub fn traverse(&mut self) {
+        self.stack.push((self.root, self.area));
+
+        // take the area
+        // fetch the node
+        // a) node is view, give it whole area
+        // b) node is container, calculate areas for each child and push them on the stack
+
+        while let Some((key, area)) = self.stack.pop() {
+            let node = &mut self.nodes[key];
+
+            match node {
+                Node::View(view) => {
+                    // debug!!("setting view area {:?}", area);
+                    view.area = area;
+                } // TODO: call f()
+                Node::Container(container) => {
+                    // debug!!("setting container area {:?}", area);
+                    container.area = area;
+
+                    match container.layout {
+                        Layout::Vertical => unimplemented!(),
+                        Layout::Horizontal => {
+                            let len = container.children.len() as u16;
+
+                            let width = area.width / len;
+
+                            let mut child_x = area.x;
+
+                            for (_i, child) in container.children.iter().enumerate() {
+                                let area = Rect::new(child_x, area.y, width, area.height);
+                                child_x += width;
+
+                                self.stack.push((*child, area));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}