Skip to content

Commit 5f988b8

Browse files
committed
refactor: move children and bounds into a Children struct
this makes it easier to keep bounds and views in sync and makes it harder to accidentally modify the views without modifying the bounds and vice-versa.
1 parent e68b527 commit 5f988b8

File tree

1 file changed

+95
-56
lines changed

1 file changed

+95
-56
lines changed

helix-view/src/tree.rs

Lines changed: 95 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{graphics::Rect, View, ViewId};
22
use slotmap::HopSlotMap;
3+
use std::ops::{Index, IndexMut};
34

45
// the dimensions are recomputed on window resize/tree change.
56
//
@@ -73,82 +74,120 @@ pub enum Direction {
7374
#[derive(Debug)]
7475
pub struct Container {
7576
layout: Layout,
76-
children: Vec<ViewId>,
77+
children: Children,
7778
area: Rect,
78-
node_bounds: Vec<ContainerBounds>,
7979
}
8080

81-
#[derive(Debug, Clone, Copy)]
82-
pub struct ContainerBounds {
83-
portion: f64,
81+
#[derive(Debug)]
82+
struct Children {
83+
pub views: Vec<ViewId>,
84+
pub bounds: Vec<ContainerBounds>,
8485
}
8586

86-
impl Container {
87-
pub fn new(layout: Layout) -> Self {
88-
Self {
89-
layout,
90-
children: Vec::new(),
91-
area: Rect::default(),
92-
node_bounds: Vec::new(),
87+
impl Children {
88+
fn new() -> Self {
89+
Children {
90+
views: Vec::new(),
91+
bounds: Vec::new(),
9392
}
9493
}
9594

96-
fn push_child(&mut self, node: ViewId) -> &mut Self {
97-
self.children.push(node);
98-
self.add_child_bounds();
99-
self
95+
pub fn iter(&self) -> std::slice::Iter<'_, ViewId> {
96+
self.views.iter()
10097
}
10198

102-
fn insert_child(&mut self, index: usize, node: ViewId) -> &mut Self {
103-
self.children.insert(index, node);
104-
self.insert_child_bounds(index);
105-
self
99+
pub fn len(&self) -> usize {
100+
debug_assert_eq!(self.views.len(), self.bounds.len());
101+
self.views.len()
106102
}
107103

108-
fn pop_child(&mut self) -> Option<ViewId> {
109-
let bound = self.node_bounds.pop()?;
104+
pub fn is_empty(&self) -> bool {
105+
self.len() == 0
106+
}
107+
}
110108

111-
let prev = 1.0 - bound.portion;
112-
for bound in &mut self.node_bounds {
113-
bound.portion /= prev;
109+
impl Children {
110+
fn push(&mut self, node: ViewId) {
111+
self.views.push(node);
112+
113+
let portion = 1.0 / self.views.len() as f64;
114+
115+
let prev = 1.0 - portion;
116+
for bound in &mut self.bounds {
117+
bound.portion *= prev;
118+
}
119+
120+
self.bounds.push(ContainerBounds { portion });
121+
}
122+
123+
fn insert(&mut self, index: usize, node: ViewId) {
124+
self.views.insert(index, node);
125+
126+
let portion = 1.0 / self.views.len() as f64;
127+
128+
let prev = 1.0 - portion;
129+
for bound in &mut self.bounds {
130+
bound.portion *= prev;
114131
}
115132

116-
self.children.pop()
133+
self.bounds.insert(index, ContainerBounds { portion });
117134
}
118135

119-
fn remove_child(&mut self, index: usize) -> ViewId {
120-
let bound = self.node_bounds.remove(index);
136+
fn pop(&mut self) -> Option<ViewId> {
137+
let bound = self.bounds.pop()?;
121138

122139
let prev = 1.0 - bound.portion;
123-
for bound in &mut self.node_bounds {
140+
for bound in &mut self.bounds {
124141
bound.portion /= prev;
125142
}
126143

127-
self.children.remove(index)
144+
self.views.pop()
128145
}
129146

130-
fn add_child_bounds(&mut self) -> &mut Self {
131-
let portion = 1.0 / self.children.len() as f64;
147+
fn remove(&mut self, index: usize) -> ViewId {
148+
let bound = self.bounds.remove(index);
132149

133-
let prev = 1.0 - portion;
134-
for bound in &mut self.node_bounds {
135-
bound.portion *= prev;
150+
let prev = 1.0 - bound.portion;
151+
for bound in &mut self.bounds {
152+
bound.portion /= prev;
136153
}
137154

138-
self.node_bounds.push(ContainerBounds { portion });
139-
self
155+
self.views.remove(index)
140156
}
157+
}
141158

142-
fn insert_child_bounds(&mut self, index: usize) -> &mut Self {
143-
let portion = 1.0 / self.children.len() as f64;
159+
impl<Idx> Index<Idx> for Children
160+
where
161+
Idx: std::slice::SliceIndex<[ViewId]>,
162+
{
163+
type Output = Idx::Output;
164+
fn index(&self, index: Idx) -> &Self::Output {
165+
self.views.index(index)
166+
}
167+
}
144168

145-
let prev = 1.0 - portion;
146-
for bound in &mut self.node_bounds {
147-
bound.portion *= prev;
148-
}
169+
impl<Idx> IndexMut<Idx> for Children
170+
where
171+
Idx: std::slice::SliceIndex<[ViewId]>,
172+
{
173+
#[inline(always)]
174+
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
175+
self.views.index_mut(index)
176+
}
177+
}
149178

150-
self.node_bounds.insert(index, ContainerBounds { portion });
151-
self
179+
#[derive(Debug, Clone, Copy)]
180+
pub struct ContainerBounds {
181+
portion: f64,
182+
}
183+
184+
impl Container {
185+
pub fn new(layout: Layout) -> Self {
186+
Self {
187+
layout,
188+
children: Children::new(),
189+
area: Rect::default(),
190+
}
152191
}
153192
}
154193

@@ -206,7 +245,7 @@ impl Tree {
206245
pos + 1
207246
};
208247

209-
container.insert_child(pos, node);
248+
container.children.insert(pos, node);
210249
// focus the new node
211250
self.focus = node;
212251

@@ -243,7 +282,7 @@ impl Tree {
243282
.unwrap();
244283
pos + 1
245284
};
246-
container.insert_child(pos, node);
285+
container.children.insert(pos, node);
247286
self.nodes[node].parent = parent;
248287
} else {
249288
let mut split = Node::container(layout);
@@ -257,8 +296,8 @@ impl Tree {
257296
} => container,
258297
_ => unreachable!(),
259298
};
260-
container.push_child(focus);
261-
container.push_child(node);
299+
container.children.push(focus);
300+
container.children.push(node);
262301
self.nodes[focus].parent = split;
263302
self.nodes[node].parent = split;
264303

@@ -318,7 +357,7 @@ impl Tree {
318357
container.children[pos] = new;
319358
self.nodes[new].parent = parent;
320359
} else {
321-
container.remove_child(pos);
360+
container.children.remove(pos);
322361
}
323362
}
324363

@@ -337,7 +376,7 @@ impl Tree {
337376
if parent_container.children.len() == 1 && !parent_is_root {
338377
// Lets merge the only child back to its grandparent so that Views
339378
// are equally spaced.
340-
let sibling = parent_container.pop_child().unwrap();
379+
let sibling = parent_container.children.pop().unwrap();
341380
self.remove_or_replace(parent, Some(sibling));
342381
}
343382

@@ -461,7 +500,7 @@ impl Tree {
461500
let mut child_y = area.y;
462501

463502
for (i, child) in container.children.iter().enumerate() {
464-
let bounds = container.node_bounds[i];
503+
let bounds = container.children.bounds[i];
465504
let height = (area.height as f64 * bounds.portion).floor() as u16;
466505

467506
let mut area = Rect::new(
@@ -493,7 +532,7 @@ impl Tree {
493532
let mut child_x = area.x;
494533

495534
for (i, child) in container.children.iter().enumerate() {
496-
let bounds = container.node_bounds[i];
535+
let bounds = container.children.bounds[i];
497536
let width = (used_area as f64 * bounds.portion).floor() as u16;
498537

499538
let mut area = Rect::new(
@@ -553,7 +592,7 @@ impl Tree {
553592
// It's possible to move in the desired direction within
554593
// the parent container so an attempt is made to find the
555594
// correct child.
556-
match self.find_child(id, &parent_container.children, direction) {
595+
match self.find_child(id, &parent_container.children.views, direction) {
557596
// Child is found, search is ended
558597
Some(id) => Some(id),
559598
// A child is not found. This could be because of either two scenarios
@@ -726,10 +765,10 @@ impl Tree {
726765
};
727766
let diff = diff * count as f64;
728767

729-
let bounds = &mut container.node_bounds;
730-
731768
let min = 0.05;
732769
let max = 1.0 - ((container.children.len() - 1) as f64 * min);
770+
771+
let bounds = &mut container.children.bounds;
733772
if bounds[idx].portion <= min && bounds[idx].portion >= max {
734773
return;
735774
}

0 commit comments

Comments
 (0)