This commit is contained in:
sander777 2024-11-20 21:57:45 -05:00 committed by GitHub
commit 6f49f93806
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 228 additions and 11 deletions

View File

@ -45,7 +45,7 @@
input::KeyEvent, input::KeyEvent,
keyboard::KeyCode, keyboard::KeyCode,
theme::Style, theme::Style,
tree, tree::{self, Dimension, Resize},
view::View, view::View,
Document, DocumentId, Editor, ViewId, Document, DocumentId, Editor, ViewId,
}; };
@ -420,6 +420,11 @@ pub fn doc(&self) -> &str {
goto_prev_change, "Goto previous change", goto_prev_change, "Goto previous change",
goto_first_change, "Goto first change", goto_first_change, "Goto first change",
goto_last_change, "Goto last change", goto_last_change, "Goto last change",
grow_buffer_width, "Grow focused container width",
shrink_buffer_width, "Shrink focused container width",
grow_buffer_height, "Grow focused container height",
shrink_buffer_height, "Shrink focused container height",
toggle_focus_window, "Toggle focus mode on buffer",
goto_line_start, "Goto line start", goto_line_start, "Goto line start",
goto_line_end, "Goto line end", goto_line_end, "Goto line end",
goto_next_buffer, "Goto next buffer", goto_next_buffer, "Goto next buffer",
@ -855,6 +860,25 @@ fn goto_line_start(cx: &mut Context) {
) )
} }
fn grow_buffer_width(cx: &mut Context) {
cx.editor.resize_buffer(Resize::Grow, Dimension::Width);
}
fn shrink_buffer_width(cx: &mut Context) {
cx.editor.resize_buffer(Resize::Shrink, Dimension::Width);
}
fn grow_buffer_height(cx: &mut Context) {
cx.editor.resize_buffer(Resize::Grow, Dimension::Height);
}
fn shrink_buffer_height(cx: &mut Context) {
cx.editor.resize_buffer(Resize::Shrink, Dimension::Height);
}
fn toggle_focus_window(cx: &mut Context) {
cx.editor.toggle_focus_window();
}
fn goto_next_buffer(cx: &mut Context) { fn goto_next_buffer(cx: &mut Context) {
goto_buffer(cx.editor, Direction::Forward, cx.count()); goto_buffer(cx.editor, Direction::Forward, cx.count());
} }

View File

@ -26,6 +26,22 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"home" => goto_line_start, "home" => goto_line_start,
"end" => goto_line_end, "end" => goto_line_end,
"A-w" => { "Alter Window"
"A-h"|"A-left" |"h"|"left" => shrink_buffer_width,
"A-l"|"A-right"|"l"|"right" => grow_buffer_width,
"A-j"|"A-down" |"j"|"down" => shrink_buffer_height,
"A-k"|"A-up" |"k"|"up" => grow_buffer_height,
"A-f"|"f" => toggle_focus_window,
},
"A-W" => { "Alter Window" sticky=true
"h"|"left" => shrink_buffer_width,
"l"|"right" => grow_buffer_width,
"j"|"down" => shrink_buffer_height,
"k"|"up" => grow_buffer_height,
"f" => toggle_focus_window,
},
"w" => move_next_word_start, "w" => move_next_word_start,
"b" => move_prev_word_start, "b" => move_prev_word_start,
"e" => move_next_word_end, "e" => move_next_word_end,

View File

@ -10,7 +10,7 @@
input::KeyEvent, input::KeyEvent,
register::Registers, register::Registers,
theme::{self, Theme}, theme::{self, Theme},
tree::{self, Tree}, tree::{self, Dimension, Resize, Tree},
Document, DocumentId, View, ViewId, Document, DocumentId, View, ViewId,
}; };
use dap::StackFrame; use dap::StackFrame;
@ -1917,6 +1917,14 @@ pub fn transpose_view(&mut self) {
self.tree.transpose(); self.tree.transpose();
} }
pub fn resize_buffer(&mut self, resize_type: Resize, dimension: Dimension) {
self.tree.resize_buffer(resize_type, dimension);
}
pub fn toggle_focus_window(&mut self) {
self.tree.toggle_focus_window();
}
pub fn should_close(&self) -> bool { pub fn should_close(&self) -> bool {
self.tree.is_empty() self.tree.is_empty()
} }

View File

@ -29,6 +29,16 @@ pub enum Content {
Container(Box<Container>), Container(Box<Container>),
} }
pub enum Resize {
Shrink,
Grow,
}
pub enum Dimension {
Width,
Height,
}
impl Node { impl Node {
pub fn container(layout: Layout) -> Self { pub fn container(layout: Layout) -> Self {
Self { Self {
@ -65,6 +75,14 @@ pub struct Container {
layout: Layout, layout: Layout,
children: Vec<ViewId>, children: Vec<ViewId>,
area: Rect, area: Rect,
node_bounds: Vec<ContainerBounds>,
}
#[derive(Debug, Clone, Copy)]
pub struct ContainerBounds {
width: usize,
height: usize,
expand: bool,
} }
impl Container { impl Container {
@ -73,8 +91,69 @@ pub fn new(layout: Layout) -> Self {
layout, layout,
children: Vec::new(), children: Vec::new(),
area: Rect::default(), area: Rect::default(),
node_bounds: Vec::new(),
} }
} }
fn get_child_by_view_id(&mut self, node: ViewId) -> Option<&mut ContainerBounds> {
self.children
.iter()
.position(|child| child == &node)
.and_then(|index| self.node_bounds.get_mut(index))
}
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 add_child_bounds(&mut self) -> &mut Self {
self.node_bounds.push(ContainerBounds {
width: 10,
height: 10,
expand: false,
});
self
}
fn insert_child_bounds(&mut self, index: usize) -> &mut Self {
self.node_bounds.insert(
index,
ContainerBounds {
width: 10,
height: 10,
expand: false,
},
);
self
}
fn calculate_slots_width(&self) -> usize {
self.node_bounds
.iter()
.map(|bounds| match bounds.expand {
true => 40,
false => bounds.width,
})
.sum()
}
fn calculate_slots_height(&self) -> usize {
self.node_bounds
.iter()
.map(|bounds| match bounds.expand {
true => 40,
false => bounds.height,
})
.sum()
}
} }
impl Default for Container { impl Default for Container {
@ -131,7 +210,7 @@ pub fn insert(&mut self, view: View) -> ViewId {
pos + 1 pos + 1
}; };
container.children.insert(pos, node); container.insert_child(pos, node);
// focus the new node // focus the new node
self.focus = node; self.focus = node;
@ -168,7 +247,7 @@ pub fn split(&mut self, view: View, layout: Layout) -> ViewId {
.unwrap(); .unwrap();
pos + 1 pos + 1
}; };
container.children.insert(pos, node); container.insert_child(pos, node);
self.nodes[node].parent = parent; self.nodes[node].parent = parent;
} else { } else {
let mut split = Node::container(layout); let mut split = Node::container(layout);
@ -182,8 +261,8 @@ pub fn split(&mut self, view: View, layout: Layout) -> ViewId {
} => container, } => container,
_ => unreachable!(), _ => unreachable!(),
}; };
container.children.push(focus); container.push_child(focus);
container.children.push(node); container.push_child(node);
self.nodes[focus].parent = split; self.nodes[focus].parent = split;
self.nodes[node].parent = split; self.nodes[node].parent = split;
@ -382,12 +461,17 @@ pub fn recalculate(&mut self) {
match container.layout { match container.layout {
Layout::Horizontal => { Layout::Horizontal => {
let len = container.children.len(); let len = container.children.len();
let slots = container.calculate_slots_height();
let height = area.height / len as u16; let slot_height = area.height as f32 / slots as f32;
let mut child_y = area.y; let mut child_y = area.y;
for (i, child) in container.children.iter().enumerate() { for (i, child) in container.children.iter().enumerate() {
let bounds = container.node_bounds[i];
let height = match bounds.expand {
true => (40.0 * slot_height) as u16,
false => (slot_height * bounds.height as f32).floor() as u16,
};
let mut area = Rect::new( let mut area = Rect::new(
container.area.x, container.area.x,
child_y, child_y,
@ -396,7 +480,7 @@ pub fn recalculate(&mut self) {
); );
child_y += height; 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 // space from rounding
if i == len - 1 { if i == len - 1 {
area.height = container.area.y + container.area.height - area.y; area.height = container.area.y + container.area.height - area.y;
@ -413,11 +497,19 @@ pub fn recalculate(&mut self) {
let total_gap = inner_gap * len_u16.saturating_sub(2); let total_gap = inner_gap * len_u16.saturating_sub(2);
let used_area = area.width.saturating_sub(total_gap); let used_area = area.width.saturating_sub(total_gap);
let width = used_area / len_u16;
let slots = container.calculate_slots_width();
let slot_width: f32 = used_area as f32 / slots as f32;
let mut child_x = area.x; let mut child_x = area.x;
for (i, child) in container.children.iter().enumerate() { for (i, child) in container.children.iter().enumerate() {
let bounds = container.node_bounds[i];
let width = match bounds.expand {
true => (40.0 * slot_width) as u16,
false => (slot_width * bounds.width as f32).floor() as u16,
};
let mut area = Rect::new( let mut area = Rect::new(
child_x, child_x,
container.area.y, container.area.y,
@ -596,6 +688,83 @@ pub fn transpose(&mut self) {
} }
} }
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 resize_buffer(&mut self, resize_type: Resize, dimension: Dimension) {
match dimension {
Dimension::Width => {
if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Vertical) {
match resize_type {
Resize::Shrink => {
if bounds.width > 1 {
bounds.width -= 1;
}
}
Resize::Grow => {
if bounds.width < 20 {
bounds.width += 1;
}
}
};
self.recalculate();
}
}
Dimension::Height => {
if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Horizontal) {
match resize_type {
Resize::Shrink => {
if bounds.height > 1 {
bounds.height -= 1;
}
}
Resize::Grow => {
if bounds.height < 20 {
bounds.height += 1;
}
}
};
self.recalculate();
}
}
}
}
pub fn toggle_focus_window(&mut self) {
if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Horizontal) {
bounds.expand = !bounds.expand;
}
if let Some(bounds) = self.get_active_node_bounds_mut(Layout::Vertical) {
bounds.expand = !bounds.expand;
}
self.recalculate();
}
pub fn swap_split_in_direction(&mut self, direction: Direction) -> Option<()> { pub fn swap_split_in_direction(&mut self, direction: Direction) -> Option<()> {
let focus = self.focus; let focus = self.focus;
let target = self.find_split_in_direction(focus, direction)?; let target = self.find_split_in_direction(focus, direction)?;