@@ -0,0 +1,173 @@
1+use crate::View;
2+use slotmap::{DefaultKey as Key, HopSlotMap};
3+use tui::layout::Rect;
4+
5+// the dimensions are recomputed on windo resize/tree change.
6+//
7+pub struct Tree {
8+ root: Key,
9+ // (container, index inside the container)
10+ current: (Key, usize),
11+ pub focus: Key,
12+ fullscreen: bool,
13+ area: Rect,
14+
15+ nodes: HopSlotMap<Key, Node>,
16+
17+ // used for traversals
18+ stack: Vec<(Key, Rect)>,
19+}
20+
21+pub enum Node {
22+ View(Box<View>),
23+ Container(Box<Container>),
24+}
25+
26+impl Node {
27+ pub fn container(area: Rect) -> Self {
28+ Self::Container(Box::new(Container::new()))
29+ }
30+
31+ pub fn view(view: View) -> Self {
32+ Self::View(Box::new(view))
33+ }
34+}
35+
36+// TODO: screen coord to container + container coordinate helpers
37+
38+pub enum Layout {
39+ Horizontal,
40+ Vertical,
41+ // could explore stacked/tabbed
42+}
43+
44+pub struct Container {
45+ layout: Layout,
46+ children: Vec<Key>,
47+ area: Rect,
48+}
49+
50+impl Container {
51+ pub fn new() -> Self {
52+ Self {
53+ layout: Layout::Horizontal,
54+ children: Vec::new(),
55+ area: Rect::default(),
56+ }
57+ }
58+}
59+
60+impl Tree {
61+ pub fn new(area: Rect) -> Self {
62+ let root = Node::container(area);
63+ let mut nodes = HopSlotMap::new();
64+ let root = nodes.insert(root);
65+
66+ Self {
67+ root,
68+ current: (root, 0),
69+ focus: Key::default(),
70+ fullscreen: false,
71+ area,
72+ nodes,
73+ stack: Vec::new(),
74+ }
75+ }
76+
77+ pub fn insert(&mut self, view: View) -> Key {
78+ let node = self.nodes.insert(Node::view(view));
79+ let (id, pos) = self.current;
80+ let container = match &mut self.nodes[id] {
81+ Node::Container(container) => container,
82+ _ => unreachable!(),
83+ };
84+
85+ // insert node after the current item if there is children already
86+ let pos = if container.children.is_empty() {
87+ pos
88+ } else {
89+ pos + 1
90+ };
91+
92+ container.children.insert(pos, node);
93+ // focus the new node
94+ self.current = (id, pos);
95+ self.focus = node;
96+
97+ // recalculate all the sizes
98+ self.traverse();
99+
100+ node
101+ }
102+
103+ pub fn views(&mut self) -> impl Iterator<Item = (&mut View, bool)> {
104+ let focus = self.focus;
105+ self.nodes
106+ .iter_mut()
107+ .filter_map(move |(key, node)| match node {
108+ Node::View(view) => Some((view.as_mut(), focus == key)),
109+ Node::Container(..) => None,
110+ })
111+ }
112+
113+ pub fn get(&self, index: Key) -> &View {
114+ match &self.nodes[index] {
115+ Node::View(view) => view,
116+ _ => unreachable!(),
117+ }
118+ }
119+
120+ pub fn get_mut(&mut self, index: Key) -> &mut View {
121+ match &mut self.nodes[index] {
122+ Node::View(view) => view,
123+ _ => unreachable!(),
124+ }
125+ }
126+
127+ pub fn resize(&mut self, area: Rect) {
128+ self.area = area;
129+ self.traverse();
130+ }
131+
132+ pub fn traverse(&mut self) {
133+ self.stack.push((self.root, self.area));
134+
135+ // take the area
136+ // fetch the node
137+ // a) node is view, give it whole area
138+ // b) node is container, calculate areas for each child and push them on the stack
139+
140+ while let Some((key, area)) = self.stack.pop() {
141+ let node = &mut self.nodes[key];
142+
143+ match node {
144+ Node::View(view) => {
145+ // debug!!("setting view area {:?}", area);
146+ view.area = area;
147+ } // TODO: call f()
148+ Node::Container(container) => {
149+ // debug!!("setting container area {:?}", area);
150+ container.area = area;
151+
152+ match container.layout {
153+ Layout::Vertical => unimplemented!(),
154+ Layout::Horizontal => {
155+ let len = container.children.len() as u16;
156+
157+ let width = area.width / len;
158+
159+ let mut child_x = area.x;
160+
161+ for (_i, child) in container.children.iter().enumerate() {
162+ let area = Rect::new(child_x, area.y, width, area.height);
163+ child_x += width;
164+
165+ self.stack.push((*child, area));
166+ }
167+ }
168+ }
169+ }
170+ }
171+ }
172+ }
173+}