-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Add flex resize, focus mode, hard-coded limits for now #2704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
1cfe283
5123376
7557b11
ce46669
03852d8
607b196
5529868
ceda076
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -65,6 +65,14 @@ pub struct Container { | |||||||||||||||||
| layout: Layout, | ||||||||||||||||||
| children: Vec<ViewId>, | ||||||||||||||||||
| area: Rect, | ||||||||||||||||||
| node_bounds: Vec<ContainerBounds>, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| #[derive(Debug, Clone, Copy)] | ||||||||||||||||||
| pub struct ContainerBounds { | ||||||||||||||||||
| width: usize, | ||||||||||||||||||
| height: usize, | ||||||||||||||||||
| focus: bool, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| impl Container { | ||||||||||||||||||
|
|
@@ -73,8 +81,80 @@ impl Container { | |||||||||||||||||
| layout, | ||||||||||||||||||
| children: Vec::new(), | ||||||||||||||||||
| area: Rect::default(), | ||||||||||||||||||
| node_bounds: Vec::new(), | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn get_child_by_view_id(&mut self, node: ViewId) -> Option<&mut ContainerBounds> { | ||||||||||||||||||
| if let Some(index) = self.children.iter().position(|child| child == &node) { | ||||||||||||||||||
| return self.node_bounds.get_mut(index); | ||||||||||||||||||
| }; | ||||||||||||||||||
| None | ||||||||||||||||||
|
Comment on lines
+99
to
+102
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn push_child(&mut self, node: ViewId) -> &mut Self { | ||||||||||||||||||
| self.children.push(node); | ||||||||||||||||||
| self.add_child_bounds(); | ||||||||||||||||||
| self | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn insert_child(&mut self, index: usize, node: ViewId) -> &mut Self { | ||||||||||||||||||
| self.children.insert(index, node); | ||||||||||||||||||
| self.insert_child_bounds(index); | ||||||||||||||||||
| self | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn remove_child(&mut self, index: usize) -> &mut Self { | ||||||||||||||||||
| self.children.remove(index); | ||||||||||||||||||
| self.remove_child_bounds(index); | ||||||||||||||||||
| self | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn add_child_bounds(&mut self) -> &mut Self { | ||||||||||||||||||
| self.node_bounds.push(ContainerBounds { | ||||||||||||||||||
| width: 10, | ||||||||||||||||||
| height: 10, | ||||||||||||||||||
| focus: false, | ||||||||||||||||||
| }); | ||||||||||||||||||
| self | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn insert_child_bounds(&mut self, index: usize) -> &mut Self { | ||||||||||||||||||
| self.node_bounds.insert( | ||||||||||||||||||
| index, | ||||||||||||||||||
| ContainerBounds { | ||||||||||||||||||
| width: 10, | ||||||||||||||||||
| height: 10, | ||||||||||||||||||
| focus: false, | ||||||||||||||||||
| }, | ||||||||||||||||||
| ); | ||||||||||||||||||
| self | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn remove_child_bounds(&mut self, index: usize) -> &mut Self { | ||||||||||||||||||
| self.node_bounds.remove(index); | ||||||||||||||||||
| self | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn calculate_slots_width(&self) -> usize { | ||||||||||||||||||
| self.node_bounds | ||||||||||||||||||
| .iter() | ||||||||||||||||||
| .map(|bounds| match bounds.focus { | ||||||||||||||||||
| true => 40, | ||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 40 is hard-coded in a few places. Can we make it a pub const that gets shared between the modules that use it? It could make sense to have this be configurable in the future for those that like resizing to be more fine-grained (or not). |
||||||||||||||||||
| false => bounds.width, | ||||||||||||||||||
| }) | ||||||||||||||||||
| .sum() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn calculate_slots_height(&self) -> usize { | ||||||||||||||||||
| self.node_bounds | ||||||||||||||||||
| .iter() | ||||||||||||||||||
| .map(|bounds| match bounds.focus { | ||||||||||||||||||
| true => 40, | ||||||||||||||||||
| false => bounds.height, | ||||||||||||||||||
| }) | ||||||||||||||||||
| .sum() | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| impl Default for Container { | ||||||||||||||||||
|
|
@@ -131,7 +211,7 @@ impl Tree { | |||||||||||||||||
| pos + 1 | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| container.children.insert(pos, node); | ||||||||||||||||||
| container.insert_child(pos, node); | ||||||||||||||||||
| // focus the new node | ||||||||||||||||||
| self.focus = node; | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -168,7 +248,7 @@ impl Tree { | |||||||||||||||||
| .unwrap(); | ||||||||||||||||||
| pos + 1 | ||||||||||||||||||
| }; | ||||||||||||||||||
| container.children.insert(pos, node); | ||||||||||||||||||
| container.insert_child(pos, node); | ||||||||||||||||||
| self.nodes[node].parent = parent; | ||||||||||||||||||
| } else { | ||||||||||||||||||
| let mut split = Node::container(layout); | ||||||||||||||||||
|
|
@@ -182,8 +262,8 @@ impl Tree { | |||||||||||||||||
| } => container, | ||||||||||||||||||
| _ => unreachable!(), | ||||||||||||||||||
| }; | ||||||||||||||||||
| container.children.push(focus); | ||||||||||||||||||
| container.children.push(node); | ||||||||||||||||||
| container.push_child(focus); | ||||||||||||||||||
| container.push_child(node); | ||||||||||||||||||
| self.nodes[focus].parent = split; | ||||||||||||||||||
| self.nodes[node].parent = split; | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -232,7 +312,7 @@ impl Tree { | |||||||||||||||||
| } = &mut self.nodes[parent_id] | ||||||||||||||||||
| { | ||||||||||||||||||
| if let Some(pos) = container.children.iter().position(|&child| child == index) { | ||||||||||||||||||
| container.children.remove(pos); | ||||||||||||||||||
| container.remove_child(pos); | ||||||||||||||||||
|
|
||||||||||||||||||
| // TODO: if container now only has one child, remove it and place child in parent | ||||||||||||||||||
| if container.children.is_empty() && parent_id != self.root { | ||||||||||||||||||
|
|
@@ -340,12 +420,17 @@ impl Tree { | |||||||||||||||||
| match container.layout { | ||||||||||||||||||
| Layout::Horizontal => { | ||||||||||||||||||
| let len = container.children.len(); | ||||||||||||||||||
|
|
||||||||||||||||||
| let height = area.height / len as u16; | ||||||||||||||||||
|
|
||||||||||||||||||
| let slots = container.calculate_slots_height(); | ||||||||||||||||||
| let slot_height = area.height as f32 / slots as f32; | ||||||||||||||||||
| let mut child_y = area.y; | ||||||||||||||||||
|
|
||||||||||||||||||
| for (i, child) in container.children.iter().enumerate() { | ||||||||||||||||||
| let bounds = container.node_bounds[i]; | ||||||||||||||||||
| let height = match bounds.focus { | ||||||||||||||||||
| true => (40.0 * slot_height) as u16, | ||||||||||||||||||
| false => (slot_height * bounds.height as f32).floor() as u16, | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| let mut area = Rect::new( | ||||||||||||||||||
| container.area.x, | ||||||||||||||||||
| child_y, | ||||||||||||||||||
|
|
@@ -354,7 +439,7 @@ impl Tree { | |||||||||||||||||
| ); | ||||||||||||||||||
| child_y += height; | ||||||||||||||||||
|
|
||||||||||||||||||
| // last child takes the remaining width because we can get uneven | ||||||||||||||||||
| // last child takes the remaining height because we can get uneven | ||||||||||||||||||
| // space from rounding | ||||||||||||||||||
| if i == len - 1 { | ||||||||||||||||||
| area.height = container.area.y + container.area.height - area.y; | ||||||||||||||||||
|
|
@@ -365,15 +450,20 @@ impl Tree { | |||||||||||||||||
| } | ||||||||||||||||||
| Layout::Vertical => { | ||||||||||||||||||
| let len = container.children.len(); | ||||||||||||||||||
|
|
||||||||||||||||||
| let width = area.width / len as u16; | ||||||||||||||||||
| let slots = container.calculate_slots_width(); | ||||||||||||||||||
| let slot_width: f32 = area.width as f32 / slots as f32; | ||||||||||||||||||
| let mut child_x = area.x; | ||||||||||||||||||
|
|
||||||||||||||||||
| let inner_gap = 1u16; | ||||||||||||||||||
| // let total_gap = inner_gap * (len as u16 - 1); | ||||||||||||||||||
|
|
||||||||||||||||||
| let mut child_x = area.x; | ||||||||||||||||||
|
|
||||||||||||||||||
| for (i, child) in container.children.iter().enumerate() { | ||||||||||||||||||
| let bounds = container.node_bounds[i]; | ||||||||||||||||||
| let width = match bounds.focus { | ||||||||||||||||||
| true => (40.0 * slot_width) as u16, | ||||||||||||||||||
| false => (slot_width * bounds.width as f32).floor() as u16, | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| let mut area = Rect::new( | ||||||||||||||||||
| child_x, | ||||||||||||||||||
| container.area.y, | ||||||||||||||||||
|
|
@@ -538,6 +628,80 @@ impl Tree { | |||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| fn get_active_node_bounds_mut( | ||||||||||||||||||
| &mut self, | ||||||||||||||||||
| expect_layout: Layout, | ||||||||||||||||||
| ) -> Option<&mut ContainerBounds> { | ||||||||||||||||||
| let mut focus = self.focus; | ||||||||||||||||||
| let mut parent = self.nodes[focus].parent; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Parent expected to be container | ||||||||||||||||||
| if let Some(focused_layout) = match &self.nodes[parent].content { | ||||||||||||||||||
| Content::View(_) => unreachable!(), | ||||||||||||||||||
| Content::Container(node) => Some(node.layout), | ||||||||||||||||||
| } { | ||||||||||||||||||
| // if we want to make a width change and we have a `Horizontal` layout focused, | ||||||||||||||||||
| // alter the parent `Vertical` layout instead and vice versa | ||||||||||||||||||
| if focused_layout != expect_layout { | ||||||||||||||||||
| focus = parent; | ||||||||||||||||||
| parent = self.nodes[parent].parent; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if let Content::Container(node) = &mut self.nodes[parent].content { | ||||||||||||||||||
| return node.as_mut().get_child_by_view_id(focus); | ||||||||||||||||||
| }; | ||||||||||||||||||
| } | ||||||||||||||||||
| None | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub fn grow_buffer_width(&mut self) { | ||||||||||||||||||
| if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Vertical) { | ||||||||||||||||||
| if bounds.width < 20 { | ||||||||||||||||||
| bounds.width += 1; | ||||||||||||||||||
| self.recalculate(); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub fn shrink_buffer_width(&mut self) { | ||||||||||||||||||
| if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Vertical) { | ||||||||||||||||||
| if bounds.width > 1 { | ||||||||||||||||||
| bounds.width -= 1; | ||||||||||||||||||
| self.recalculate(); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub fn grow_buffer_height(&mut self) { | ||||||||||||||||||
| if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Horizontal) { | ||||||||||||||||||
| if bounds.height < 20 { | ||||||||||||||||||
| bounds.height += 1; | ||||||||||||||||||
| self.recalculate(); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub fn shrink_buffer_height(&mut self) { | ||||||||||||||||||
| if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Horizontal) { | ||||||||||||||||||
| if bounds.height > 1 { | ||||||||||||||||||
| bounds.height -= 1; | ||||||||||||||||||
| self.recalculate(); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub fn buffer_focus_mode(&mut self) { | ||||||||||||||||||
| if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Horizontal) { | ||||||||||||||||||
| bounds.focus = !bounds.focus; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Vertical) { | ||||||||||||||||||
| bounds.focus = !bounds.focus; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| self.recalculate(); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| pub fn swap_split_in_direction(&mut self, direction: Direction) -> Option<()> { | ||||||||||||||||||
| let focus = self.focus; | ||||||||||||||||||
| let target = self.find_split_in_direction(focus, direction)?; | ||||||||||||||||||
|
|
||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.