diff options
| author | a-kenji <aks.kenji@protonmail.com> | 2021-04-03 21:19:39 +0200 |
|---|---|---|
| committer | a-kenji <aks.kenji@protonmail.com> | 2021-04-03 21:19:39 +0200 |
| commit | 4f5f189373603d29fc8b042b72aae375efbd0a1c (patch) | |
| tree | d63b769a0c218d4956316fd3128f96ed33c2d9cf /src/client | |
| parent | Merge branch 'main' of https://github.com/zellij-org/zellij into config-file (diff) | |
| parent | Add Kyle to governance.md (diff) | |
| download | sl0ppij-4f5f189373603d29fc8b042b72aae375efbd0a1c.tar.gz sl0ppij-4f5f189373603d29fc8b042b72aae375efbd0a1c.tar.xz sl0ppij-4f5f189373603d29fc8b042b72aae375efbd0a1c.zip | |
Merge branch 'main' of https://github.com/zellij-org/zellij into config-file
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/mod.rs | 1 | ||||
| -rw-r--r-- | src/client/pane_resizer.rs | 508 | ||||
| -rw-r--r-- | src/client/panes/plugin_pane.rs | 12 | ||||
| -rw-r--r-- | src/client/panes/terminal_pane.rs | 12 | ||||
| -rw-r--r-- | src/client/tab.rs | 121 |
5 files changed, 630 insertions, 24 deletions
diff --git a/src/client/mod.rs b/src/client/mod.rs index 93f35e06..cba12a46 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,5 +1,6 @@ pub mod boundaries; pub mod layout; +pub mod pane_resizer; pub mod panes; pub mod tab; diff --git a/src/client/pane_resizer.rs b/src/client/pane_resizer.rs new file mode 100644 index 00000000..007dc33f --- /dev/null +++ b/src/client/pane_resizer.rs @@ -0,0 +1,508 @@ +use crate::os_input_output::OsApi; +use crate::panes::{PaneId, PositionAndSize}; +use crate::tab::Pane; +use std::collections::{BTreeMap, HashSet}; + +pub struct PaneResizer<'a> { + panes: &'a mut BTreeMap<PaneId, Box<dyn Pane>>, + os_api: &'a mut Box<dyn OsApi>, +} + +// TODO: currently there are some functions here duplicated with Tab +// the reason for this is that we need to get rid of the expansion_boundary +// otherwise we'll have a big separation of concerns issue +// once that is done, all resizing functions should move here + +impl<'a> PaneResizer<'a> { + pub fn new( + panes: &'a mut BTreeMap<PaneId, Box<dyn Pane>>, + os_api: &'a mut Box<dyn OsApi>, + ) -> Self { + PaneResizer { panes, os_api } + } + pub fn resize( + &mut self, + mut current_size: PositionAndSize, + new_size: PositionAndSize, + ) -> Option<(isize, isize)> { + // (column_difference, row_difference) + let mut successfully_resized = false; + let mut column_difference: isize = 0; + let mut row_difference: isize = 0; + if new_size.columns < current_size.columns { + let reduce_by = current_size.columns - new_size.columns; + find_reducible_vertical_chain( + &self.panes, + reduce_by, + current_size.columns, + current_size.rows, + ) + .map(|panes_to_resize| { + self.reduce_panes_left_and_pull_adjacents_left(panes_to_resize, reduce_by); + column_difference = new_size.columns as isize - current_size.columns as isize; + current_size.columns = (current_size.columns as isize + column_difference) as usize; + successfully_resized = true; + }); + } else if new_size.columns > current_size.columns { + let increase_by = new_size.columns - current_size.columns; + find_increasable_vertical_chain( + &self.panes, + increase_by, + current_size.columns, + current_size.rows, + ) + .map(|panes_to_resize| { + self.increase_panes_right_and_push_adjacents_right(panes_to_resize, increase_by); + column_difference = new_size.columns as isize - current_size.columns as isize; + current_size.columns = (current_size.columns as isize + column_difference) as usize; + successfully_resized = true; + }); + } + if new_size.rows < current_size.rows { + let reduce_by = current_size.rows - new_size.rows; + find_reducible_horizontal_chain( + &self.panes, + reduce_by, + current_size.columns, + current_size.rows, + ) + .map(|panes_to_resize| { + self.reduce_panes_up_and_pull_adjacents_up(panes_to_resize, reduce_by); + row_difference = new_size.rows as isize - current_size.rows as isize; + current_size.rows = (current_size.rows as isize + row_difference) as usize; + successfully_resized = true; + }); + } else if new_size.rows > current_size.rows { + let increase_by = new_size.rows - current_size.rows; + find_increasable_horizontal_chain( + &self.panes, + increase_by, + current_size.columns, + current_size.rows, + ) + .map(|panes_to_resize| { + self.increase_panes_down_and_push_down_adjacents(panes_to_resize, increase_by); + row_difference = new_size.rows as isize - current_size.rows as isize; + current_size.rows = (current_size.rows as isize + row_difference) as usize; + successfully_resized = true; + }); + } + if successfully_resized { + Some((column_difference, row_difference)) + } else { + None + } + } + fn reduce_panes_left_and_pull_adjacents_left( + &mut self, + panes_to_reduce: Vec<PaneId>, + reduce_by: usize, + ) { + let mut pulled_panes: HashSet<PaneId> = HashSet::new(); + for pane_id in panes_to_reduce { + let (pane_x, pane_y, pane_columns, pane_rows) = { + let pane = self.panes.get(&pane_id).unwrap(); + (pane.x(), pane.y(), pane.columns(), pane.rows()) + }; + let panes_to_pull = self.panes.values_mut().filter(|p| { + p.x() > pane_x + pane_columns + && (p.y() <= pane_y && p.y() + p.rows() >= pane_y + || p.y() >= pane_y && p.y() + p.rows() <= pane_y + pane_rows) + }); + for pane in panes_to_pull { + if !pulled_panes.contains(&pane.pid()) { + pane.pull_left(reduce_by); + pulled_panes.insert(pane.pid()); + } + } + self.reduce_pane_width_left(&pane_id, reduce_by); + } + } + fn reduce_panes_up_and_pull_adjacents_up( + &mut self, + panes_to_reduce: Vec<PaneId>, + reduce_by: usize, + ) { + let mut pulled_panes: HashSet<PaneId> = HashSet::new(); + for pane_id in panes_to_reduce { + let (pane_x, pane_y, pane_columns, pane_rows) = { + let pane = self.panes.get(&pane_id).unwrap(); + (pane.x(), pane.y(), pane.columns(), pane.rows()) + }; + let panes_to_pull = self.panes.values_mut().filter(|p| { + p.y() > pane_y + pane_rows + && (p.x() <= pane_x && p.x() + p.columns() >= pane_x + || p.x() >= pane_x && p.x() + p.columns() <= pane_x + pane_columns) + }); + for pane in panes_to_pull { + if !pulled_panes.contains(&pane.pid()) { + pane.pull_up(reduce_by); + pulled_panes.insert(pane.pid()); + } + } + self.reduce_pane_height_up(&pane_id, reduce_by); + } + } + fn increase_panes_down_and_push_down_adjacents( + &mut self, + panes_to_increase: Vec<PaneId>, + increase_by: usize, + ) { + let mut pushed_panes: HashSet<PaneId> = HashSet::new(); + for pane_id in panes_to_increase { + let (pane_x, pane_y, pane_columns, pane_rows) = { + let pane = self.panes.get(&pane_id).unwrap(); + (pane.x(), pane.y(), pane.columns(), pane.rows()) + }; + let panes_to_push = self.panes.values_mut().filter(|p| { + p.y() > pane_y + pane_rows + && (p.x() <= pane_x && p.x() + p.columns() >= pane_x + || p.x() >= pane_x && p.x() + p.columns() <= pane_x + pane_columns) + }); + for pane in panes_to_push { + if !pushed_panes.contains(&pane.pid()) { + pane.push_down(increase_by); + pushed_panes.insert(pane.pid()); + } + } + self.increase_pane_height_down(&pane_id, increase_by); + } + } + fn increase_panes_right_and_push_adjacents_right( + &mut self, + panes_to_increase: Vec<PaneId>, + increase_by: usize, + ) { + let mut pushed_panes: HashSet<PaneId> = HashSet::new(); + for pane_id in panes_to_increase { + let (pane_x, pane_y, pane_columns, pane_rows) = { + let pane = self.panes.get(&pane_id).unwrap(); + (pane.x(), pane.y(), pane.columns(), pane.rows()) + }; + let panes_to_push = self.panes.values_mut().filter(|p| { + p.x() > pane_x + pane_columns + && (p.y() <= pane_y && p.y() + p.rows() >= pane_y + || p.y() >= pane_y && p.y() + p.rows() <= pane_y + pane_rows) + }); + for pane in panes_to_push { + if !pushed_panes.contains(&pane.pid()) { + pane.push_right(increase_by); + pushed_panes.insert(pane.pid()); + } + } + self.increase_pane_width_right(&pane_id, increase_by); + } + } + fn reduce_pane_height_up(&mut self, id: &PaneId, count: usize) { + let pane = self.panes.get_mut(id).unwrap(); + pane.reduce_height_up(count); + if let PaneId::Terminal(pid) = id { + self.os_api + .set_terminal_size_using_fd(*pid, pane.columns() as u16, pane.rows() as u16); + } + } + fn increase_pane_height_down(&mut self, id: &PaneId, count: usize) { + let pane = self.panes.get_mut(id).unwrap(); + pane.increase_height_down(count); + if let PaneId::Terminal(pid) = pane.pid() { + self.os_api + .set_terminal_size_using_fd(pid, pane.columns() as u16, pane.rows() as u16); + } + } + fn increase_pane_width_right(&mut self, id: &PaneId, count: usize) { + let pane = self.panes.get_mut(id).unwrap(); + pane.increase_width_right(count); + if let PaneId::Terminal(pid) = pane.pid() { + self.os_api + .set_terminal_size_using_fd(pid, pane.columns() as u16, pane.rows() as u16); + } + } + fn reduce_pane_width_left(&mut self, id: &PaneId, count: usize) { + let pane = self.panes.get_mut(id).unwrap(); + pane.reduce_width_left(count); + if let PaneId::Terminal(pid) = pane.pid() { + self.os_api + .set_terminal_size_using_fd(pid, pane.columns() as u16, pane.rows() as u16); + } + } +} + +fn find_next_increasable_horizontal_pane( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + right_of: &Box<dyn Pane>, + increase_by: usize, +) -> Option<PaneId> { + let next_pane_candidates = panes.values().filter( + |p| { + p.x() == right_of.x() + right_of.columns() + 1 + && p.horizontally_overlaps_with(right_of.as_ref()) + }, // TODO: the name here is wrong, it should be vertically_overlaps_with + ); + let resizable_candidates = + next_pane_candidates.filter(|p| p.can_increase_height_by(increase_by)); + resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { + Some(next_pane) => { + let next_pane = panes.get(&next_pane).unwrap(); + if next_pane.y() < p.y() { + next_pane_id + } else { + Some(p.pid()) + } + } + None => Some(p.pid()), + }) +} + +fn find_next_increasable_vertical_pane( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + below: &Box<dyn Pane>, + increase_by: usize, +) -> Option<PaneId> { + let next_pane_candidates = panes.values().filter( + |p| p.y() == below.y() + below.rows() + 1 && p.vertically_overlaps_with(below.as_ref()), // TODO: the name here is wrong, it should be horizontally_overlaps_with + ); + let resizable_candidates = + next_pane_candidates.filter(|p| p.can_increase_width_by(increase_by)); + resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { + Some(next_pane) => { + let next_pane = panes.get(&next_pane).unwrap(); + if next_pane.x() < p.x() { + next_pane_id + } else { + Some(p.pid()) + } + } + None => Some(p.pid()), + }) +} + +fn find_next_reducible_vertical_pane( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + below: &Box<dyn Pane>, + reduce_by: usize, +) -> Option<PaneId> { + let next_pane_candidates = panes.values().filter( + |p| p.y() == below.y() + below.rows() + 1 && p.vertically_overlaps_with(below.as_ref()), // TODO: the name here is wrong, it should be horizontally_overlaps_with + ); + let resizable_candidates = next_pane_candidates.filter(|p| p.can_reduce_width_by(reduce_by)); + resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { + Some(next_pane) => { + let next_pane = panes.get(&next_pane).unwrap(); + if next_pane.x() < p.x() { + next_pane_id + } else { + Some(p.pid()) + } + } + None => Some(p.pid()), + }) +} + +fn find_next_reducible_horizontal_pane( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + right_of: &Box<dyn Pane>, + reduce_by: usize, +) -> Option<PaneId> { + let next_pane_candidates = panes.values().filter( + |p| { + p.x() == right_of.x() + right_of.columns() + 1 + && p.horizontally_overlaps_with(right_of.as_ref()) + }, // TODO: the name here is wrong, it should be vertically_overlaps_with + ); + let resizable_candidates = next_pane_candidates.filter(|p| p.can_reduce_height_by(reduce_by)); + resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { + Some(next_pane) => { + let next_pane = panes.get(&next_pane).unwrap(); + if next_pane.y() < p.y() { + next_pane_id + } else { + Some(p.pid()) + } + } + None => Some(p.pid()), + }) +} + +fn find_increasable_horizontal_chain( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + increase_by: usize, + screen_width: usize, + screen_height: usize, // TODO: this is the previous size (make this clearer) +) -> Option<Vec<PaneId>> { + let mut horizontal_coordinate = 0; + loop { + if horizontal_coordinate == screen_height { + return None; + } + + match panes + .values() + .find(|p| p.x() == 0 && p.y() == horizontal_coordinate) + { + Some(leftmost_pane) => { + if !leftmost_pane.can_increase_height_by(increase_by) { + horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows() + 1; + continue; + } + let mut panes_to_resize = vec![]; + let mut current_pane = leftmost_pane; + loop { + panes_to_resize.push(current_pane.pid()); + if current_pane.x() + current_pane.columns() == screen_width { + return Some(panes_to_resize); + } + match find_next_increasable_horizontal_pane(panes, ¤t_pane, increase_by) { + Some(next_pane_id) => { + current_pane = panes.get(&next_pane_id).unwrap(); + } + None => { + horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows() + 1; + break; + } + }; + } + } + None => { + return None; + } + } + } +} + +fn find_increasable_vertical_chain( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + increase_by: usize, + screen_width: usize, + screen_height: usize, // TODO: this is the previous size (make this clearer) +) -> Option<Vec<PaneId>> { + let mut vertical_coordinate = 0; + loop { + if vertical_coordinate == screen_width { + return None; + } + + match panes + .values() + .find(|p| p.y() == 0 && p.x() == vertical_coordinate) + { + Some(topmost_pane) => { + if !topmost_pane.can_increase_width_by(increase_by) { + vertical_coordinate = topmost_pane.x() + topmost_pane.columns() + 1; + continue; + } + let mut panes_to_resize = vec![]; + let mut current_pane = topmost_pane; + loop { + panes_to_resize.push(current_pane.pid()); + if current_pane.y() + current_pane.rows() == screen_height { + return Some(panes_to_resize); + } + match find_next_increasable_vertical_pane(panes, ¤t_pane, increase_by) { + Some(next_pane_id) => { + current_pane = panes.get(&next_pane_id).unwrap(); + } + None => { + vertical_coordinate = topmost_pane.x() + topmost_pane.columns() + 1; + break; + } + }; + } + } + None => { + return None; + } + } + } +} + +fn find_reducible_horizontal_chain( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + reduce_by: usize, + screen_width: usize, + screen_height: usize, // TODO: this is the previous size (make this clearer) +) -> Option<Vec<PaneId>> { + let mut horizontal_coordinate = 0; + loop { + if horizontal_coordinate == screen_height { + return None; + } + + match panes + .values() + .find(|p| p.x() == 0 && p.y() == horizontal_coordinate) + { + Some(leftmost_pane) => { + if !leftmost_pane.can_reduce_height_by(reduce_by) { + horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows() + 1; + continue; + } + let mut panes_to_resize = vec![]; + let mut current_pane = leftmost_pane; + loop { + panes_to_resize.push(current_pane.pid()); + if current_pane.x() + current_pane.columns() == screen_width { + return Some(panes_to_resize); + } + match find_next_reducible_horizontal_pane(panes, ¤t_pane, reduce_by) { + Some(next_pane_id) => { + current_pane = panes.get(&next_pane_id).unwrap(); + } + None => { + horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows() + 1; + break; + } + }; + } + } + None => { + return None; + } + } + } +} + +fn find_reducible_vertical_chain( + panes: &BTreeMap<PaneId, Box<dyn Pane>>, + increase_by: usize, + screen_width: usize, + screen_height: usize, // TODO: this is the previous size (make this clearer) +) -> Option<Vec<PaneId>> { + let mut vertical_coordinate = 0; + loop { + if vertical_coordinate == screen_width { + return None; + } + + match panes + .values() + .find(|p| p.y() == 0 && p.x() == vertical_coordinate) + { + Some(topmost_pane) => { + if !topmost_pane.can_reduce_width_by(increase_by) { + vertical_coordinate = topmost_pane.x() + topmost_pane.columns() + 1; + continue; + } + let mut panes_to_resize = vec![]; + let mut current_pane = topmost_pane; + loop { + panes_to_resize.push(current_pane.pid()); + if current_pane.y() + current_pane.rows() == screen_height { + return Some(panes_to_resize); + } + match find_next_reducible_vertical_pane(panes, ¤t_pane, increase_by) { + Some(next_pane_id) => { + current_pane = panes.get(&next_pane_id).unwrap(); + } + None => { + vertical_coordinate = topmost_pane.x() + topmost_pane.columns() + 1; + break; + } + }; + } + } + None => { + return None; + } + } + } +} diff --git a/src/client/panes/plugin_pane.rs b/src/client/panes/plugin_pane.rs index 4cffff5f..caf49acc 100644 --- a/src/client/panes/plugin_pane.rs +++ b/src/client/panes/plugin_pane.rs @@ -173,6 +173,18 @@ impl Pane for PluginPane { self.position_and_size.columns += count; self.should_render = true; } + fn push_down(&mut self, count: usize) { + self.position_and_size.y += count; + } + fn push_right(&mut self, count: usize) { + self.position_and_size.x += count; + } + fn pull_left(&mut self, count: usize) { + self.position_and_size.x -= count; + } + fn pull_up(&mut self, count: usize) { + self.position_and_size.y -= count; + } fn scroll_up(&mut self, _count: usize) { unimplemented!() } diff --git a/src/client/panes/terminal_pane.rs b/src/client/panes/terminal_pane.rs index f0b15e50..463a33e3 100644 --- a/src/client/panes/terminal_pane.rs +++ b/src/client/panes/terminal_pane.rs @@ -282,6 +282,18 @@ impl Pane for TerminalPane { self.position_and_size.columns += count; self.reflow_lines(); } + fn push_down(&mut self, count: usize) { + self.position_and_size.y += count; + } + fn push_right(&mut self, count: usize) { + self.position_and_size.x += count; + } + fn pull_left(&mut self, count: usize) { + self.position_and_size.x -= count; + } + fn pull_up(&mut self, count: usize) { + self.position_and_size.y -= count; + } fn scroll_up(&mut self, count: usize) { self.grid.move_viewport_up(count); self.mark_for_rerender(); diff --git a/src/client/tab.rs b/src/client/tab.rs index 1e56fd8b..695d42cb 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -2,20 +2,23 @@ //! as well as how they should be resized use crate::boundaries::colors; +use crate::client::pane_resizer::PaneResizer; use crate::common::{input::handler::parse_keys, AppInstruction, SenderWithContext}; use crate::layout::Layout; +use crate::os_input_output::OsApi; use crate::panes::{PaneId, PositionAndSize, TerminalPane}; use crate::pty_bus::{PtyInstruction, VteEvent}; +use crate::utils::shared::adjust_to_size; use crate::wasm_vm::PluginInstruction; use crate::{boundaries::Boundaries, panes::PluginPane}; -use crate::{os_input_output::OsApi, utils::shared::pad_to_size}; +use serde::{Deserialize, Serialize}; use std::os::unix::io::RawFd; use std::{ cmp::Reverse, collections::{BTreeMap, HashSet}, }; use std::{io::Write, sync::mpsc::channel}; -use zellij_tile::data::{Event, InputMode}; +use zellij_tile::data::{Event, ModeInfo}; 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; @@ -66,7 +69,17 @@ pub struct Tab { pub send_plugin_instructions: SenderWithContext<PluginInstruction>, pub send_app_instructions: SenderWithContext<AppInstruction>, expansion_boundary: Option<PositionAndSize>, - pub input_mode: InputMode, + should_clear_display_before_rendering: bool, + pub mode_info: ModeInfo, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct TabData { + /* subset of fields to publish to plugins */ + pub position: usize, + pub name: String, + pub active: bool, + pub mode_info: ModeInfo, } // FIXME: Use a struct that has a pane_type enum, to reduce all of the duplication @@ -99,6 +112,10 @@ pub trait Pane { fn reduce_width_right(&mut self, count: usize); fn reduce_width_left(&mut self, count: usize); fn increase_width_left(&mut self, count: usize); + fn push_down(&mut self, count: usize); + fn push_right(&mut self, count: usize); + fn pull_left(&mut self, count: usize); + fn pull_up(&mut self, count: usize); fn scroll_up(&mut self, count: usize); fn scroll_down(&mut self, count: usize); fn clear_scroll(&mut self); @@ -153,6 +170,22 @@ pub trait Pane { rows: self.rows(), } } + fn can_increase_height_by(&self, increase_by: usize) -> bool { + self.max_height() + .map(|max_height| self.rows() + increase_by <= max_height) + .unwrap_or(true) + } + fn can_increase_width_by(&self, increase_by: usize) -> bool { + self.max_width() + .map(|max_width| self.columns() + increase_by <= max_width) + .unwrap_or(true) + } + fn can_reduce_height_by(&self, reduce_by: usize) -> bool { + self.rows() > reduce_by && self.rows() - reduce_by >= self.min_height() + } + fn can_reduce_width_by(&self, reduce_by: usize) -> bool { + self.columns() > reduce_by && self.columns() - reduce_by >= self.min_width() + } fn min_width(&self) -> usize { MIN_TERMINAL_WIDTH } @@ -183,7 +216,7 @@ impl Tab { send_app_instructions: SenderWithContext<AppInstruction>, max_panes: Option<usize>, pane_id: Option<PaneId>, - input_mode: InputMode, + mode_info: ModeInfo, ) -> Self { let panes = if let Some(PaneId::Terminal(pid)) = pane_id { let new_terminal = TerminalPane::new(pid, *full_screen_ws); @@ -213,7 +246,8 @@ impl Tab { send_pty_instructions, send_plugin_instructions, expansion_boundary: None, - input_mode, + should_clear_display_before_rendering: false, + mode_info, } } @@ -267,6 +301,13 @@ impl Tab { self.send_plugin_instructions.clone(), ); self.panes.insert(PaneId::Plugin(pid), Box::new(new_plugin)); + // Send an initial mode update to the newly loaded plugin only! + self.send_plugin_instructions + .send(PluginInstruction::Update( + Some(pid), + Event::ModeUpdate(self.mode_info.clone()), + )) + .unwrap(); } else { // there are still panes left to fill, use the pids we received in this method let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout @@ -623,26 +664,33 @@ impl Tab { stdout .write_all(&hide_cursor.as_bytes()) .expect("cannot write to stdout"); - for (kind, terminal) in self.panes.iter_mut() { - if !self.panes_to_hide.contains(&terminal.pid()) { - match self.active_terminal.unwrap() == terminal.pid() { + if self.should_clear_display_before_rendering { + let clear_display = "\u{1b}[2J"; + stdout + .write_all(&clear_display.as_bytes()) + .expect("cannot write to stdout"); + self.should_clear_display_before_rendering = false; + } + for (kind, pane) in self.panes.iter_mut() { + if !self.panes_to_hide.contains(&pane.pid()) { + match self.active_terminal.unwrap() == pane.pid() { true => { - boundaries.add_rect(terminal.as_ref(), self.input_mode, Some(colors::GREEN)) + boundaries.add_rect(pane.as_ref(), self.mode_info.mode, Some(colors::GREEN)) } - false => boundaries.add_rect(terminal.as_ref(), self.input_mode, None), + false => boundaries.add_rect(pane.as_ref(), self.mode_info.mode, None), } - if let Some(vte_output) = terminal.render() { + if let Some(vte_output) = pane.render() { let vte_output = if let PaneId::Terminal(_) = kind { vte_output } else { - pad_to_size(&vte_output, terminal.rows(), terminal.columns()) + adjust_to_size(&vte_output, pane.rows(), pane.columns()) }; // FIXME: Use Termion for cursor and style clearing? write!( stdout, "\u{1b}[{};{}H\u{1b}[m{}", - terminal.y() + 1, - terminal.x() + 1, + pane.y() + 1, + pane.x() + 1, vte_output ) .expect("cannot write to stdout"); @@ -1655,17 +1703,30 @@ impl Tab { 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.can_increase_pane_and_surroundings_right(&active_pane_id, count) { - self.increase_pane_and_surroundings_right(&active_pane_id, count); - } else if self.can_reduce_pane_and_surroundings_right(&active_pane_id, count) { - self.reduce_pane_and_surroundings_right(&active_pane_id, count); - } + pub fn resize_whole_tab(&mut self, new_screen_size: PositionAndSize) { + if self.fullscreen_is_active { + // this is not ideal but until we get rid of expansion_boundary, it's a necessity + self.toggle_active_pane_fullscreen(); } - self.render(); + match PaneResizer::new(&mut self.panes, &mut self.os_api) + .resize(self.full_screen_ws, new_screen_size) + { + Some((column_difference, row_difference)) => { + self.should_clear_display_before_rendering = true; + self.expansion_boundary.as_mut().map(|expansion_boundary| { + // TODO: this is not always accurate + expansion_boundary.columns = + (expansion_boundary.columns as isize + column_difference) as usize; + expansion_boundary.rows = + (expansion_boundary.rows as isize + row_difference) as usize; + }); + self.full_screen_ws.columns = + (self.full_screen_ws.columns as isize + column_difference) as usize; + self.full_screen_ws.rows = + (self.full_screen_ws.rows as isize + row_difference) as usize; + } + None => {} + }; } pub fn resize_left(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much @@ -1679,6 +1740,18 @@ impl Tab { } self.render(); } + 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.can_increase_pane_and_surroundings_right(&active_pane_id, count) { + self.increase_pane_and_surroundings_right(&active_pane_id, count); + } 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(); + } pub fn resize_down(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much let count = 2; |
