1use crate::{graphics::Rect, View, ViewId};
2use slotmap::HopSlotMap;
4// the dimensions are recomputed on window resize/tree change.
9 // (container, index inside the container)
14 nodes: HopSlotMap<ViewId, Node>,
16 // used for traversals
17 stack: Vec<(ViewId, Rect)>,
29 Container(Box<Container>),
33 pub fn container(layout: Layout) -> Self {
35 parent: ViewId::default(),
36 content: Content::Container(Box::new(Container::new(layout))),
40 pub fn view(view: View) -> Self {
42 parent: ViewId::default(),
43 content: Content::View(Box::new(view)),
48// TODO: screen coord to container + container coordinate helpers
50#[derive(Debug, PartialEq, Eq)]
54 // could explore stacked/tabbed
60 children: Vec<ViewId>,
65 pub fn new(layout: Layout) -> Self {
69 area: Rect::default(),
74impl Default for Container {
75 fn default() -> Self {
76 Self::new(Layout::Vertical)
81 pub fn new(area: Rect) -> Self {
82 let root = Node::container(Layout::Vertical);
84 let mut nodes = HopSlotMap::with_key();
85 let root = nodes.insert(root);
87 // root is it's own parent
88 nodes[root].parent = root;
100 pub fn insert(&mut self, view: View) -> ViewId {
101 let focus = self.focus;
102 let parent = self.nodes[focus].parent;
103 let mut node = Node::view(view);
104 node.parent = parent;
105 let node = self.nodes.insert(node);
106 self.get_mut(node).id = node;
108 let container = match &mut self.nodes[parent] {
110 content: Content::Container(container),
116 // insert node after the current item if there is children already
117 let pos = if container.children.is_empty() {
123 .position(|&child| child == focus)
128 container.children.insert(pos, node);
129 // focus the new node
132 // recalculate all the sizes
138 pub fn split(&mut self, view: View, layout: Layout) -> ViewId {
139 let focus = self.focus;
140 let parent = self.nodes[focus].parent;
142 let node = Node::view(view);
143 let node = self.nodes.insert(node);
144 self.get_mut(node).id = node;
146 let container = match &mut self.nodes[parent] {
148 content: Content::Container(container),
154 if container.layout == layout {
155 // insert node after the current item if there is children already
156 let pos = if container.children.is_empty() {
162 .position(|&child| child == focus)
166 container.children.insert(pos, node);
167 self.nodes[node].parent = parent;
169 let mut split = Node::container(layout);
170 split.parent = parent;
171 let split = self.nodes.insert(split);
173 let container = match &mut self.nodes[split] {
175 content: Content::Container(container),
180 container.children.push(focus);
181 container.children.push(node);
182 self.nodes[focus].parent = split;
183 self.nodes[node].parent = split;
185 let container = match &mut self.nodes[parent] {
187 content: Content::Container(container),
196 .position(|&child| child == focus)
199 // replace focus on parent with split
200 container.children[pos] = split;
203 // focus the new node
206 // recalculate all the sizes
212 pub fn remove(&mut self, index: ViewId) {
213 let mut stack = Vec::new();
215 if self.focus == index {
216 // focus on something else
222 while let Some(index) = stack.pop() {
223 let parent_id = self.nodes[index].parent;
225 content: Content::Container(container),
227 } = &mut self.nodes[parent_id]
229 if let Some(pos) = container.children.iter().position(|&child| child == index) {
230 container.children.remove(pos);
232 // TODO: if container now only has one child, remove it and place child in parent
233 if container.children.is_empty() && parent_id != self.root {
234 // if container now empty, remove it
235 stack.push(parent_id);
239 self.nodes.remove(index);
245 pub fn views(&self) -> impl Iterator<Item = (&View, bool)> {
246 let focus = self.focus;
247 self.nodes.iter().filter_map(move |(key, node)| match node {
249 content: Content::View(view),
251 } => Some((view.as_ref(), focus == key)),
256 pub fn views_mut(&mut self) -> impl Iterator<Item = (&mut View, bool)> {
257 let focus = self.focus;
260 .filter_map(move |(key, node)| match node {
262 content: Content::View(view),
264 } => Some((view.as_mut(), focus == key)),
269 pub fn get(&self, index: ViewId) -> &View {
270 match &self.nodes[index] {
272 content: Content::View(view),
279 pub fn get_mut(&mut self, index: ViewId) -> &mut View {
280 match &mut self.nodes[index] {
282 content: Content::View(view),
289 pub fn is_empty(&self) -> bool {
290 match &self.nodes[self.root] {
292 content: Content::Container(container),
294 } => container.children.is_empty(),
299 pub fn resize(&mut self, area: Rect) -> bool {
300 if self.area != area {
308 pub fn recalculate(&mut self) {
313 self.stack.push((self.root, self.area));
317 // a) node is view, give it whole area
318 // b) node is container, calculate areas for each child and push them on the stack
320 while let Some((key, area)) = self.stack.pop() {
321 let node = &mut self.nodes[key];
323 match &mut node.content {
324 Content::View(view) => {
325 // debug!!("setting view area {:?}", area);
328 Content::Container(container) => {
329 // debug!!("setting container area {:?}", area);
330 container.area = area;
332 match container.layout {
333 Layout::Horizontal => {
334 let len = container.children.len();
336 let height = area.height / len as u16;
338 let mut child_y = area.y;
340 for (i, child) in container.children.iter().enumerate() {
341 let mut area = Rect::new(
344 container.area.width,
349 // last child takes the remaining width because we can get uneven
350 // space from rounding
352 area.height = container.area.y + container.area.height - area.y;
355 self.stack.push((*child, area));
358 Layout::Vertical => {
359 let len = container.children.len();
361 let width = area.width / len as u16;
363 let inner_gap = 1u16;
364 // let total_gap = inner_gap * (len as u16 - 1);
366 let mut child_x = area.x;
368 for (i, child) in container.children.iter().enumerate() {
369 let mut area = Rect::new(
373 container.area.height,
375 child_x += width + inner_gap;
377 // last child takes the remaining width because we can get uneven
378 // space from rounding
380 area.width = container.area.x + container.area.width - area.x;
383 self.stack.push((*child, area));
392 pub fn traverse(&self) -> Traverse {
396 pub fn focus_next(&mut self) {
397 // This function is very dumb, but that's because we don't store any parent links.
398 // (we'd be able to go parent.next_sibling() recursively until we find something)
399 // For now that's okay though, since it's unlikely you'll be able to open a large enough
400 // number of splits to notice.
403 // let found = loop do {
404 // node = focus.parent;
405 // let found = node.next_sibling_of(current)
411 // return first child of root;
417 // use found next sibling
419 // if found = view -> focus = found, return
420 // if found = container -> found = first child
423 let iter = self.traverse();
425 let mut iter = iter.skip_while(|&(key, _view)| key != self.focus);
426 iter.next(); // take the focused value
428 if let Some((key, _)) = iter.next() {
431 // extremely crude, take the first item again
432 let (key, _) = self.traverse().next().unwrap();
437 pub fn area(&self) -> Rect {
443pub struct Traverse<'a> {
445 stack: Vec<ViewId>, // TODO: reuse the one we use on update
448impl<'a> Traverse<'a> {
449 fn new(tree: &'a Tree) -> Self {
452 stack: vec![tree.root],
457impl<'a> Iterator for Traverse<'a> {
458 type Item = (ViewId, &'a View);
460 fn next(&mut self) -> Option<Self::Item> {
462 let key = self.stack.pop()?;
464 let node = &self.tree.nodes[key];
466 match &node.content {
467 Content::View(view) => return Some((key, view)),
468 Content::Container(container) => {
469 self.stack.extend(container.children.iter().rev());
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list