aboutsummaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authora-kenji <aks.kenji@protonmail.com>2021-04-03 21:19:39 +0200
committera-kenji <aks.kenji@protonmail.com>2021-04-03 21:19:39 +0200
commit4f5f189373603d29fc8b042b72aae375efbd0a1c (patch)
treed63b769a0c218d4956316fd3128f96ed33c2d9cf /src/client
parentMerge branch 'main' of https://github.com/zellij-org/zellij into config-file (diff)
parentAdd Kyle to governance.md (diff)
downloadsl0ppij-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.rs1
-rw-r--r--src/client/pane_resizer.rs508
-rw-r--r--src/client/panes/plugin_pane.rs12
-rw-r--r--src/client/panes/terminal_pane.rs12
-rw-r--r--src/client/tab.rs121
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, &current_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, &current_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, &current_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, &current_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;