diff options
| author | denis <denismaximov98@gmail.com> | 2021-01-29 06:24:59 +0200 |
|---|---|---|
| committer | denis <denismaximov98@gmail.com> | 2021-01-29 06:24:59 +0200 |
| commit | 6a3481f54f0ee789ceeb994d8f302e3ce119c031 (patch) | |
| tree | 60d4ad8d08c2349571d29d68c357ac07c6acce63 /src/client | |
| parent | wip: oops shouldn't forget that (diff) | |
| parent | feat(statusbar): max status bar height (#156) (diff) | |
| download | sl0ppij-6a3481f54f0ee789ceeb994d8f302e3ce119c031.tar.gz sl0ppij-6a3481f54f0ee789ceeb994d8f302e3ce119c031.tar.xz sl0ppij-6a3481f54f0ee789ceeb994d8f302e3ce119c031.zip | |
Merge branch 'main' into restructure
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/panes/plugin_pane.rs | 8 | ||||
| -rw-r--r-- | src/client/panes/terminal_pane.rs | 8 | ||||
| -rw-r--r-- | src/client/tab.rs | 259 |
3 files changed, 241 insertions, 34 deletions
diff --git a/src/client/panes/plugin_pane.rs b/src/client/panes/plugin_pane.rs index a93ff8c0..aeda170a 100644 --- a/src/client/panes/plugin_pane.rs +++ b/src/client/panes/plugin_pane.rs @@ -13,6 +13,7 @@ pub struct PluginPane { pub position_and_size: PositionAndSize, pub position_and_size_override: Option<PositionAndSize>, pub send_plugin_instructions: SenderWithContext<PluginInstruction>, + pub max_height: Option<usize>, } impl PluginPane { @@ -28,6 +29,7 @@ impl PluginPane { position_and_size, position_and_size_override: None, send_plugin_instructions, + max_height: None, } } } @@ -100,6 +102,9 @@ impl Pane for PluginPane { fn set_selectable(&mut self, selectable: bool) { self.selectable = selectable; } + fn set_max_height(&mut self, max_height: usize) { + self.max_height = Some(max_height); + } fn render(&mut self) -> Option<String> { // if self.should_render { if true { @@ -172,4 +177,7 @@ impl Pane for PluginPane { fn clear_scroll(&mut self) { unimplemented!() } + fn max_height(&self) -> Option<usize> { + self.max_height + } } diff --git a/src/client/panes/terminal_pane.rs b/src/client/panes/terminal_pane.rs index 853ae064..fe7fb585 100644 --- a/src/client/panes/terminal_pane.rs +++ b/src/client/panes/terminal_pane.rs @@ -46,6 +46,7 @@ pub struct TerminalPane { pub position_and_size: PositionAndSize, pub position_and_size_override: Option<PositionAndSize>, pub cursor_key_mode: bool, // DECCKM - when set, cursor keys should send ANSI direction codes (eg. "OD") instead of the arrow keys (eg. "[D") + pub max_height: Option<usize>, pending_styles: CharacterStyles, clear_viewport_before_rendering: bool, } @@ -177,6 +178,12 @@ impl Pane for TerminalPane { fn set_selectable(&mut self, selectable: bool) { self.selectable = selectable; } + fn set_max_height(&mut self, max_height: usize) { + self.max_height = Some(max_height); + } + fn max_height(&self) -> Option<usize> { + self.max_height + } fn render(&mut self) -> Option<String> { // if self.should_render { if true { @@ -309,6 +316,7 @@ impl TerminalPane { position_and_size_override: None, cursor_key_mode: false, clear_viewport_before_rendering: false, + max_height: None, } } pub fn mark_for_rerender(&mut self) { diff --git a/src/client/tab.rs b/src/client/tab.rs index 6c65958f..190292a0 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -21,6 +21,8 @@ use std::{io::Write, sync::mpsc::channel}; */ const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this +const MIN_TERMINAL_HEIGHT: usize = 2; +const MIN_TERMINAL_WIDTH: usize = 4; type BorderAndPaneIds = (usize, Vec<PaneId>); @@ -84,6 +86,7 @@ pub trait Pane { fn set_should_render(&mut self, should_render: bool); fn selectable(&self) -> bool; fn set_selectable(&mut self, selectable: bool); + fn set_max_height(&mut self, max_height: usize); fn render(&mut self) -> Option<String>; fn pid(&self) -> PaneId; fn reduce_height_down(&mut self, count: usize); @@ -140,6 +143,18 @@ pub trait Pane { std::cmp::min(self.x() + self.columns(), other.x() + other.columns()) - std::cmp::max(self.x(), other.x()) } + fn min_width(&self) -> usize { + MIN_TERMINAL_WIDTH + } + fn min_height(&self) -> usize { + MIN_TERMINAL_HEIGHT + } + fn max_width(&self) -> Option<usize> { + None + } + fn max_height(&self) -> Option<usize> { + None + } } impl Tab { @@ -273,19 +288,32 @@ impl Tab { } else { // TODO: check minimum size of active terminal - let (_longest_edge, terminal_id_to_split) = self.get_panes().fold( - (0, PaneId::Terminal(0)), // FIXME: This is a bit hacky, try to use a maximum method? - |(current_longest_edge, current_terminal_id_to_split), id_and_terminal_to_check| { + let (_largest_terminal_size, terminal_id_to_split) = self.get_panes().fold( + (0, None), + |(current_largest_terminal_size, current_terminal_id_to_split), + id_and_terminal_to_check| { let (id_of_terminal_to_check, terminal_to_check) = id_and_terminal_to_check; let terminal_size = (terminal_to_check.rows() * CURSOR_HEIGHT_WIDTH_RATIO) * terminal_to_check.columns(); - if terminal_size > current_longest_edge { - (terminal_size, *id_of_terminal_to_check) + let terminal_can_be_split = terminal_to_check.columns() >= MIN_TERMINAL_WIDTH + && terminal_to_check.rows() >= MIN_TERMINAL_HEIGHT + && ((terminal_to_check.columns() >= terminal_to_check.min_width() * 2 + 1) + || (terminal_to_check.rows() + >= terminal_to_check.min_height() * 2 + 1)); + if terminal_can_be_split && terminal_size > current_largest_terminal_size { + (terminal_size, Some(*id_of_terminal_to_check)) } else { - (current_longest_edge, current_terminal_id_to_split) + (current_largest_terminal_size, current_terminal_id_to_split) } }, ); + if terminal_id_to_split.is_none() { + self.send_pty_instructions + .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty + .unwrap(); + return; // likely no terminal large enough to split + } + let terminal_id_to_split = terminal_id_to_split.unwrap(); let terminal_to_split = self.panes.get_mut(&terminal_id_to_split).unwrap(); let terminal_ws = PositionAndSize { rows: terminal_to_split.rows(), @@ -293,7 +321,9 @@ impl Tab { x: terminal_to_split.x(), y: terminal_to_split.y(), }; - if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.columns() { + if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.columns() + && terminal_to_split.rows() >= terminal_to_split.min_height() * 2 + 1 + { // FIXME: This could use a second look if let PaneId::Terminal(term_pid) = pid { let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws); @@ -314,23 +344,23 @@ impl Tab { } self.active_terminal = Some(pid); } - } else { + } else if terminal_to_split.columns() >= terminal_to_split.min_width() * 2 + 1 { // FIXME: This could use a second look if let PaneId::Terminal(term_pid) = pid { - let (left_winszie, right_winsize) = split_vertically_with_gap(&terminal_ws); + let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws); let new_terminal = TerminalPane::new(term_pid, right_winsize); self.os_api.set_terminal_size_using_fd( new_terminal.pid, right_winsize.columns as u16, right_winsize.rows as u16, ); - terminal_to_split.change_pos_and_size(&left_winszie); + terminal_to_split.change_pos_and_size(&left_winsize); self.panes.insert(pid, Box::new(new_terminal)); if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split { self.os_api.set_terminal_size_using_fd( terminal_id_to_split, - left_winszie.columns as u16, - left_winszie.rows as u16, + left_winsize.columns as u16, + left_winsize.rows as u16, ); } } @@ -362,6 +392,12 @@ impl Tab { // TODO: check minimum size of active terminal let active_pane_id = &self.get_active_pane_id().unwrap(); let active_pane = self.panes.get_mut(active_pane_id).unwrap(); + if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 { + self.send_pty_instructions + .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty + .unwrap(); + return; + } let terminal_ws = PositionAndSize { x: active_pane.x(), y: active_pane.y(), @@ -416,6 +452,12 @@ impl Tab { // TODO: check minimum size of active terminal let active_pane_id = &self.get_active_pane_id().unwrap(); let active_pane = self.panes.get_mut(active_pane_id).unwrap(); + if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 { + self.send_pty_instructions + .send(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty + .unwrap(); + return; + } let terminal_ws = PositionAndSize { x: active_pane.x(), y: active_pane.y(), @@ -1373,29 +1415,173 @@ impl Tab { self.increase_pane_width_left(&terminal_id, count); } } - fn panes_exist_above(&self, pane_id: &PaneId) -> bool { - let pane = self.panes.get(pane_id).expect("pane does not exist"); - pane.y() > 0 + fn can_increase_pane_and_surroundings_right( + &self, + pane_id: &PaneId, + increase_by: usize, + ) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let can_increase_pane_size = pane + .max_width() + .map(|max_width| pane.columns() + increase_by <= max_width) + .unwrap_or(true); // no max width, increase to your heart's content + if !can_increase_pane_size { + return false; + } + if let Some(panes_to_the_right) = self.pane_ids_directly_right_of(&pane_id) { + return panes_to_the_right.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.columns() > increase_by && p.columns() - increase_by >= p.min_width() + }); + } else { + return false; + } + } + fn can_increase_pane_and_surroundings_left( + &self, + pane_id: &PaneId, + increase_by: usize, + ) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let can_increase_pane_size = pane + .max_width() + .map(|max_width| pane.columns() + increase_by <= max_width) + .unwrap_or(true); // no max width, increase to your heart's content + if !can_increase_pane_size { + return false; + } + if let Some(panes_to_the_left) = self.pane_ids_directly_left_of(&pane_id) { + return panes_to_the_left.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.columns() > increase_by && p.columns() - increase_by >= p.min_width() + }); + } else { + return false; + } + } + fn can_increase_pane_and_surroundings_down( + &self, + pane_id: &PaneId, + increase_by: usize, + ) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let can_increase_pane_size = pane + .max_height() + .map(|max_height| pane.rows() + increase_by <= max_height) + .unwrap_or(true); // no max width, increase to your heart's content + if !can_increase_pane_size { + return false; + } + if let Some(panes_below) = self.pane_ids_directly_below(&pane_id) { + return panes_below.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.rows() > increase_by && p.rows() - increase_by >= p.min_height() + }); + } else { + return false; + } + } + fn can_increase_pane_and_surroundings_up(&self, pane_id: &PaneId, increase_by: usize) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let can_increase_pane_size = pane + .max_height() + .map(|max_height| pane.rows() + increase_by <= max_height) + .unwrap_or(true); // no max width, increase to your heart's content + if !can_increase_pane_size { + return false; + } + if let Some(panes_above) = self.pane_ids_directly_above(&pane_id) { + return panes_above.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.rows() > increase_by && p.rows() - increase_by >= p.min_height() + }); + } else { + return false; + } } - fn panes_exist_below(&self, pane_id: &PaneId) -> bool { - let pane = self.panes.get(pane_id).expect("pane does not exist"); - pane.y() + pane.rows() < self.full_screen_ws.rows + fn can_reduce_pane_and_surroundings_right(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let pane_columns = pane.columns(); + let can_reduce_pane_size = + pane_columns > reduce_by && pane_columns - reduce_by >= pane.min_width(); + if !can_reduce_pane_size { + return false; + } + if let Some(panes_to_the_left) = self.pane_ids_directly_left_of(&pane_id) { + return panes_to_the_left.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.max_width() + .map(|max_width| p.columns() + reduce_by <= max_width) + .unwrap_or(true) // no max width, increase to your heart's content + }); + } else { + return false; + } } - fn panes_exist_to_the_right(&self, pane_id: &PaneId) -> bool { - let pane = self.panes.get(pane_id).expect("pane does not exist"); - pane.x() + pane.columns() < self.full_screen_ws.columns + fn can_reduce_pane_and_surroundings_left(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let pane_columns = pane.columns(); + let can_reduce_pane_size = + pane_columns > reduce_by && pane_columns - reduce_by >= pane.min_width(); + if !can_reduce_pane_size { + return false; + } + if let Some(panes_to_the_right) = self.pane_ids_directly_right_of(&pane_id) { + return panes_to_the_right.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.max_width() + .map(|max_width| p.columns() + reduce_by <= max_width) + .unwrap_or(true) // no max width, increase to your heart's content + }); + } else { + return false; + } } - fn panes_exist_to_the_left(&self, pane_id: &PaneId) -> bool { - let pane = self.panes.get(pane_id).expect("pane does not exist"); - pane.x() > 0 + fn can_reduce_pane_and_surroundings_down(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let pane_rows = pane.rows(); + let can_reduce_pane_size = + pane_rows > reduce_by && pane_rows - reduce_by >= pane.min_height(); + if !can_reduce_pane_size { + return false; + } + if let Some(panes_above) = self.pane_ids_directly_above(&pane_id) { + return panes_above.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.max_height() + .map(|max_height| p.rows() + reduce_by <= max_height) + .unwrap_or(true) // no max height, increase to your heart's content + }); + } else { + return false; + } + } + fn can_reduce_pane_and_surroundings_up(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + let pane = self.panes.get(pane_id).unwrap(); + let pane_rows = pane.rows(); + let can_reduce_pane_size = + pane_rows > reduce_by && pane_rows - reduce_by >= pane.min_height(); + if !can_reduce_pane_size { + return false; + } + if let Some(panes_below) = self.pane_ids_directly_below(&pane_id) { + return panes_below.iter().all(|id| { + let p = self.panes.get(id).unwrap(); + p.max_height() + .map(|max_height| p.rows() + reduce_by <= max_height) + .unwrap_or(true) // no max height, increase to your heart's content + }); + } else { + return false; + } } pub fn resize_right(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much let count = 10; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.panes_exist_to_the_right(&active_pane_id) { + if self.can_increase_pane_and_surroundings_right(&active_pane_id, count) { self.increase_pane_and_surroundings_right(&active_pane_id, count); - } else if self.panes_exist_to_the_left(&active_pane_id) { + } else if self.can_reduce_pane_and_surroundings_right(&active_pane_id, count) { self.reduce_pane_and_surroundings_right(&active_pane_id, count); } self.render(); @@ -1405,10 +1591,10 @@ impl Tab { // TODO: find out by how much we actually reduced and only reduce by that much let count = 10; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.panes_exist_to_the_right(&active_pane_id) { - self.reduce_pane_and_surroundings_left(&active_pane_id, count); - } else if self.panes_exist_to_the_left(&active_pane_id) { + if self.can_increase_pane_and_surroundings_left(&active_pane_id, count) { self.increase_pane_and_surroundings_left(&active_pane_id, count); + } else if self.can_reduce_pane_and_surroundings_left(&active_pane_id, count) { + self.reduce_pane_and_surroundings_left(&active_pane_id, count); } self.render(); } @@ -1417,10 +1603,10 @@ impl Tab { // TODO: find out by how much we actually reduced and only reduce by that much let count = 2; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.panes_exist_above(&active_pane_id) { - self.reduce_pane_and_surroundings_down(&active_pane_id, count); - } else if self.panes_exist_below(&active_pane_id) { + if self.can_increase_pane_and_surroundings_down(&active_pane_id, count) { self.increase_pane_and_surroundings_down(&active_pane_id, count); + } else if self.can_reduce_pane_and_surroundings_down(&active_pane_id, count) { + self.reduce_pane_and_surroundings_down(&active_pane_id, count); } self.render(); } @@ -1429,9 +1615,9 @@ impl Tab { // TODO: find out by how much we actually reduced and only reduce by that much let count = 2; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.panes_exist_above(&active_pane_id) { + if self.can_increase_pane_and_surroundings_up(&active_pane_id, count) { self.increase_pane_and_surroundings_up(&active_pane_id, count); - } else if self.panes_exist_below(&active_pane_id) { + } else if self.can_reduce_pane_and_surroundings_up(&active_pane_id, count) { self.reduce_pane_and_surroundings_up(&active_pane_id, count); } self.render(); @@ -1709,6 +1895,11 @@ impl Tab { } } } + pub fn set_pane_max_height(&mut self, id: PaneId, max_height: usize) { + if let Some(pane) = self.panes.get_mut(&id) { + pane.set_max_height(max_height); + } + } pub fn close_pane(&mut self, id: PaneId) { if self.panes.get(&id).is_some() { self.close_pane_without_rerender(id); |
