summaryrefslogtreecommitdiffstats
path: root/zellij-server/src/ui
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2021-08-12 14:50:00 +0200
committerGitHub <noreply@github.com>2021-08-12 14:50:00 +0200
commita37d3e5889476bbac209d20f89886daa3e9d3992 (patch)
treec02fbf779dda57b615a852fd6a43818b20722b19 /zellij-server/src/ui
parent426cee728a3b8c84edbc2d02cbc22f4840fc6a28 (diff)
feat(ui): pane frames (new pane UI) (#643)
* work * resize working * move focus working * close pane working * selection and fullscreen working * pane title line * titles and conditional scroll title * whole tab resize working * plugin frames working * plugin splitting working * truncate pane frame titles * cleanup * panes always draw their own borders - also fix gap * toggle pane frames * move toggle to screen and fix some bugs * fix plugin frame toggle * fix terminal window resize * fix scrolling and fullscreen bugs * unit tests passing * e2e tests passing and new test for new frames added * refactor: TerminalPane and PluginPane * refactor: Tab * refactor: moar Tab * refactor: Boundaries * only render and calculate boundaries when there are no pane frames * refactor: Layout * fix(grid): properly resize when coming back from alternative viewport * style: remove commented code * style: fmt * style: fmt * style: fmt + clippy * docs(changelog): update change
Diffstat (limited to 'zellij-server/src/ui')
-rw-r--r--zellij-server/src/ui/boundaries.rs159
-rw-r--r--zellij-server/src/ui/mod.rs1
-rw-r--r--zellij-server/src/ui/pane_boundaries_frame.rs277
-rw-r--r--zellij-server/src/ui/pane_resizer.rs64
-rw-r--r--zellij-server/src/ui/title_telescope.rs0
5 files changed, 372 insertions, 129 deletions
diff --git a/zellij-server/src/ui/boundaries.rs b/zellij-server/src/ui/boundaries.rs
index 42a80ace1..b25f1cc08 100644
--- a/zellij-server/src/ui/boundaries.rs
+++ b/zellij-server/src/ui/boundaries.rs
@@ -1,3 +1,4 @@
+use zellij_utils::pane_size::PositionAndSize;
use zellij_utils::zellij_tile;
use crate::tab::Pane;
@@ -405,73 +406,22 @@ impl Coordinates {
}
}
-pub(crate) trait Rect {
- fn x(&self) -> usize;
- fn y(&self) -> usize;
- fn rows(&self) -> usize;
- fn columns(&self) -> usize;
- fn right_boundary_x_coords(&self) -> usize {
- self.x() + self.columns()
- }
- fn bottom_boundary_y_coords(&self) -> usize {
- self.y() + self.rows()
- }
- fn is_directly_right_of(&self, other: &Self) -> bool {
- self.x() == other.x() + other.columns() + 1
- }
- fn is_directly_left_of(&self, other: &Self) -> bool {
- self.x() + self.columns() + 1 == other.x()
- }
- fn is_directly_below(&self, other: &Self) -> bool {
- self.y() == other.y() + other.rows() + 1
- }
- fn is_directly_above(&self, other: &Self) -> bool {
- self.y() + self.rows() + 1 == other.y()
- }
- fn horizontally_overlaps_with(&self, other: &Self) -> bool {
- (self.y() >= other.y() && self.y() <= (other.y() + other.rows()))
- || ((self.y() + self.rows()) <= (other.y() + other.rows())
- && (self.y() + self.rows()) > other.y())
- || (self.y() <= other.y() && (self.y() + self.rows() >= (other.y() + other.rows())))
- || (other.y() <= self.y() && (other.y() + other.rows() >= (self.y() + self.rows())))
- }
- fn get_horizontal_overlap_with(&self, other: &Self) -> usize {
- std::cmp::min(self.y() + self.rows(), other.y() + other.rows())
- - std::cmp::max(self.y(), other.y())
- }
- fn vertically_overlaps_with(&self, other: &Self) -> bool {
- (self.x() >= other.x() && self.x() <= (other.x() + other.columns()))
- || ((self.x() + self.columns()) <= (other.x() + other.columns())
- && (self.x() + self.columns()) > other.x())
- || (self.x() <= other.x()
- && (self.x() + self.columns() >= (other.x() + other.columns())))
- || (other.x() <= self.x()
- && (other.x() + other.columns() >= (self.x() + self.columns())))
- }
- fn get_vertical_overlap_with(&self, other: &Self) -> usize {
- std::cmp::min(self.x() + self.columns(), other.x() + other.columns())
- - std::cmp::max(self.x(), other.x())
- }
-}
-
pub struct Boundaries {
- columns: usize,
- rows: usize,
- // boundary_characters: HashMap<Coordinates, BoundaryType>,
+ position_and_size: PositionAndSize,
boundary_characters: HashMap<Coordinates, BoundarySymbol>,
}
impl Boundaries {
- pub fn new(columns: u16, rows: u16) -> Self {
- let columns = columns as usize;
- let rows = rows as usize;
+ pub fn new(position_and_size: &PositionAndSize) -> Self {
Boundaries {
- columns,
- rows,
+ position_and_size: *position_and_size,
boundary_characters: HashMap::new(),
}
}
pub fn add_rect(&mut self, rect: &dyn Pane, input_mode: InputMode, palette: Option<Palette>) {
+ if !self.is_fully_inside_screen(rect) {
+ return;
+ }
let color = match palette.is_some() {
true => match input_mode {
InputMode::Normal | InputMode::Locked => Some(palette.unwrap().green),
@@ -479,19 +429,23 @@ impl Boundaries {
},
false => None,
};
- if rect.x() > 0 {
+ if rect.x() > self.position_and_size.x {
+ // left boundary
let boundary_x_coords = rect.x() - 1;
let first_row_coordinates = self.rect_right_boundary_row_start(rect);
let last_row_coordinates = self.rect_right_boundary_row_end(rect);
for row in first_row_coordinates..last_row_coordinates {
let coordinates = Coordinates::new(boundary_x_coords, row);
- let mut symbol_to_add = if row == first_row_coordinates && row != 0 {
- BoundarySymbol::new(boundary_type::TOP_LEFT).color(color)
- } else if row == last_row_coordinates - 1 && row != self.rows - 1 {
- BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color)
- } else {
- BoundarySymbol::new(boundary_type::VERTICAL).color(color)
- };
+ let mut symbol_to_add =
+ if row == first_row_coordinates && row != self.position_and_size.y {
+ BoundarySymbol::new(boundary_type::TOP_LEFT).color(color)
+ } else if row == last_row_coordinates - 1
+ && row != self.position_and_size.y + self.position_and_size.rows - 1
+ {
+ BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color)
+ } else {
+ BoundarySymbol::new(boundary_type::VERTICAL).color(color)
+ };
if rect.invisible_borders() {
symbol_to_add = symbol_to_add.invisible();
}
@@ -503,15 +457,19 @@ impl Boundaries {
self.boundary_characters.insert(coordinates, next_symbol);
}
}
- if rect.y() > 0 {
+ if rect.y() > self.position_and_size.y {
+ // top boundary
let boundary_y_coords = rect.y() - 1;
let first_col_coordinates = self.rect_bottom_boundary_col_start(rect);
let last_col_coordinates = self.rect_bottom_boundary_col_end(rect);
for col in first_col_coordinates..last_col_coordinates {
let coordinates = Coordinates::new(col, boundary_y_coords);
- let mut symbol_to_add = if col == first_col_coordinates && col != 0 {
+ let mut symbol_to_add = if col == first_col_coordinates
+ && col != self.position_and_size.x
+ {
BoundarySymbol::new(boundary_type::TOP_LEFT).color(color)
- } else if col == last_col_coordinates - 1 && col != self.columns - 1 {
+ } else if col == last_col_coordinates - 1 && col != self.position_and_size.cols - 1
+ {
BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color)
} else {
BoundarySymbol::new(boundary_type::HORIZONTAL).color(color)
@@ -528,19 +486,22 @@ impl Boundaries {
}
}
if self.rect_right_boundary_is_before_screen_edge(rect) {
- // let boundary_x_coords = self.rect_right_boundary_x_coords(rect);
- let boundary_x_coords = rect.right_boundary_x_coords();
+ // right boundary
+ let boundary_x_coords = rect.right_boundary_x_coords() - 1;
let first_row_coordinates = self.rect_right_boundary_row_start(rect);
let last_row_coordinates = self.rect_right_boundary_row_end(rect);
for row in first_row_coordinates..last_row_coordinates {
let coordinates = Coordinates::new(boundary_x_coords, row);
- let mut symbol_to_add = if row == first_row_coordinates && row != 0 {
- BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color)
- } else if row == last_row_coordinates - 1 && row != self.rows - 1 {
- BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color)
- } else {
- BoundarySymbol::new(boundary_type::VERTICAL).color(color)
- };
+ let mut symbol_to_add =
+ if row == first_row_coordinates && row != self.position_and_size.y {
+ BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color)
+ } else if row == last_row_coordinates - 1
+ && row != self.position_and_size.y + self.position_and_size.rows - 1
+ {
+ BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color)
+ } else {
+ BoundarySymbol::new(boundary_type::VERTICAL).color(color)
+ };
if rect.invisible_borders() {
symbol_to_add = symbol_to_add.invisible();
}
@@ -553,14 +514,18 @@ impl Boundaries {
}
}
if self.rect_bottom_boundary_is_before_screen_edge(rect) {
- let boundary_y_coords = rect.bottom_boundary_y_coords();
+ // bottom boundary
+ let boundary_y_coords = rect.bottom_boundary_y_coords() - 1;
let first_col_coordinates = self.rect_bottom_boundary_col_start(rect);
let last_col_coordinates = self.rect_bottom_boundary_col_end(rect);
for col in first_col_coordinates..last_col_coordinates {
let coordinates = Coordinates::new(col, boundary_y_coords);
- let mut symbol_to_add = if col == first_col_coordinates && col != 0 {
+ let mut symbol_to_add = if col == first_col_coordinates
+ && col != self.position_and_size.x
+ {
BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color)
- } else if col == last_col_coordinates - 1 && col != self.columns - 1 {
+ } else if col == last_col_coordinates - 1 && col != self.position_and_size.cols - 1
+ {
BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color)
} else {
BoundarySymbol::new(boundary_type::HORIZONTAL).color(color)
@@ -590,27 +555,20 @@ impl Boundaries {
vte_output
}
fn rect_right_boundary_is_before_screen_edge(&self, rect: &dyn Pane) -> bool {
- rect.x() + rect.columns() < self.columns
+ rect.x() + rect.columns() < self.position_and_size.cols
}
fn rect_bottom_boundary_is_before_screen_edge(&self, rect: &dyn Pane) -> bool {
- rect.y() + rect.rows() < self.rows
+ rect.y() + rect.rows() < self.position_and_size.y + self.position_and_size.rows
}
fn rect_right_boundary_row_start(&self, rect: &dyn Pane) -> usize {
- if rect.y() == 0 {
- 0
- } else {
+ if rect.y() > self.position_and_size.y {
rect.y() - 1
+ } else {
+ self.position_and_size.y
}
}
fn rect_right_boundary_row_end(&self, rect: &dyn Pane) -> usize {
- let rect_bottom_row = rect.y() + rect.rows();
- // we do this because unless we're on the screen edge, we'd like to go one extra row to
- // connect to whatever boundary is beneath us
- if rect_bottom_row == self.rows {
- rect_bottom_row
- } else {
- rect_bottom_row + 1
- }
+ rect.y() + rect.rows()
}
fn rect_bottom_boundary_col_start(&self, rect: &dyn Pane) -> usize {
if rect.x() == 0 {
@@ -620,13 +578,12 @@ impl Boundaries {
}
}
fn rect_bottom_boundary_col_end(&self, rect: &dyn Pane) -> usize {
- let rect_right_col = rect.x() + rect.columns();
- // we do this because unless we're on the screen edge, we'd like to go one extra column to
- // connect to whatever boundary is right of us
- if rect_right_col == self.columns {
- rect_right_col
- } else {
- rect_right_col + 1
- }
+ rect.x() + rect.columns()
+ }
+ fn is_fully_inside_screen(&self, rect: &dyn Pane) -> bool {
+ rect.x() >= self.position_and_size.x
+ && rect.x() + rect.columns() <= self.position_and_size.x + self.position_and_size.cols
+ && rect.y() >= self.position_and_size.y
+ && rect.y() + rect.rows() <= self.position_and_size.y + self.position_and_size.rows
}
}
diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs
index 0087e54e8..beb70bf04 100644
--- a/zellij-server/src/ui/mod.rs
+++ b/zellij-server/src/ui/mod.rs
@@ -1,3 +1,4 @@
pub mod boundaries;
+pub mod pane_boundaries_frame;
pub mod pane_resizer;
pub mod pane_resizer_beta;
diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs
new file mode 100644
index 000000000..0ae454d96
--- /dev/null
+++ b/zellij-server/src/ui/pane_boundaries_frame.rs
@@ -0,0 +1,277 @@
+use crate::ui::boundaries::boundary_type;
+use ansi_term::Colour::{Fixed, RGB};
+use ansi_term::Style;
+use zellij_utils::pane_size::PositionAndSize;
+use zellij_utils::zellij_tile::prelude::PaletteColor;
+
+fn color_string(character: &str, color: Option<PaletteColor>) -> String {
+ match color {
+ Some(color) => match color {
+ PaletteColor::Rgb((r, g, b)) => {
+ format!("{}", RGB(r, g, b).bold().paint(character))
+ }
+ PaletteColor::EightBit(color) => {
+ format!("{}", Fixed(color).bold().paint(character))
+ }
+ },
+ None => format!("{}", Style::new().bold().paint(character)),
+ }
+}
+
+pub struct PaneBoundariesFrame {
+ pub position_and_size: PositionAndSize,
+ base_title: String,
+ title: String,
+ scroll_position: (usize, usize), // (position, length)
+ pub color: Option<PaletteColor>,
+ draw_title_only: bool,
+ should_render: bool,
+}
+
+impl PaneBoundariesFrame {
+ pub fn new(position_and_size: PositionAndSize, title: String) -> Self {
+ PaneBoundariesFrame {
+ position_and_size,
+ color: None,
+ base_title: title.clone(),
+ title,
+ scroll_position: (0, 0),
+ draw_title_only: false,
+ should_render: true,
+ }
+ }
+ pub fn frame_title_only(mut self) -> Self {
+ // TODO: remove this?
+ self.draw_title_only = true;
+ self.should_render = true;
+ self
+ }
+ pub fn render_only_title(&mut self, should_render_only_title: bool) {
+ if should_render_only_title != self.draw_title_only {
+ self.should_render = true;
+ self.draw_title_only = should_render_only_title;
+ }
+ }
+ pub fn change_pos_and_size(&mut self, position_and_size: PositionAndSize) {
+ if position_and_size != self.position_and_size {
+ self.position_and_size = position_and_size;
+ self.should_render = true;
+ }
+ }
+ pub fn set_color(&mut self, color: Option<PaletteColor>) {
+ if color != self.color {
+ self.color = color;
+ self.should_render = true;
+ }
+ }
+ pub fn update_scroll(&mut self, scroll_position: (usize, usize)) {
+ if scroll_position != self.scroll_position {
+ self.scroll_position = scroll_position;
+ self.should_render = true;
+ }
+ }
+ pub fn update_title(&mut self, title: Option<&String>) {
+ match title {
+ Some(title) => {
+ if title != &self.title {
+ self.title = title.clone();
+ self.should_render = true;
+ }
+ }
+ None => {
+ self.title = self.base_title.clone();
+ self.should_render = true;
+ }
+ }
+ }
+ pub fn content_position_and_size(&self) -> PositionAndSize {
+ if self.draw_title_only {
+ self.position_and_size.reduce_top_line()
+ } else {
+ self.position_and_size.reduce_outer_frame(1)
+ }
+ }
+ pub fn content_offset(&self) -> (usize, usize) {
+ // (column_difference, row_difference)
+ let content_position_and_size = self.content_position_and_size();
+ let column_difference = content_position_and_size
+ .x
+ .saturating_sub(self.position_and_size.x);
+ let row_difference = content_position_and_size
+ .y
+ .saturating_sub(self.position_and_size.y);
+ (column_difference, row_difference)
+ }
+ pub fn set_should_render(&mut self, should_render: bool) {
+ self.should_render = should_render;
+ }
+ fn render_title_right_side(&self, max_length: usize) -> Option<String> {
+ if self.scroll_position.0 > 0 || self.scroll_position.1 > 0 {
+ let prefix = " SCROLL: ";
+ let full_indication =
+ format!(" {}/{} ", self.scroll_position.0, self.scroll_position.1);
+ let short_indication = format!(" {} ", self.scroll_position.0);
+ if prefix.chars().count() + full_indication.chars().count() <= max_length {
+ Some(format!("{}{}", prefix, full_indication))
+ } else if full_indication.chars().count() <= max_length {
+ Some(full_indication)
+ } else if short_indication.chars().count() <= max_length {
+ Some(short_indication)
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ }
+ fn render_title_left_side(&self, max_length: usize) -> Option<String> {
+ let middle_truncated_sign = "[..]";
+ let middle_truncated_sign_long = "[...]";
+ let full_text = format!(" {} ", &self.title);
+ if max_length <= 6 {
+ None
+ } else if full_text.chars().count() <= max_length {
+ Some(full_text)
+ } else {
+ let length_of_each_half = (max_length - middle_truncated_sign.chars().count()) / 2;
+ let first_part: String = full_text.chars().take(length_of_each_half).collect();
+ let second_part: String = full_text
+ .chars()
+ .skip(full_text.chars().count() - length_of_each_half)
+ .collect();
+ let title_left_side = if first_part.chars().count()
+ + middle_truncated_sign.chars().count()
+ + second_part.chars().count()
+ < max_length
+ {
+ // this means we lost 1 character when dividing the total length into halves
+ format!(
+ "{}{}{}",
+ first_part, middle_truncated_sign_long, second_part
+ )
+ } else {
+ format!("{}{}{}", first_part, middle_truncated_sign, second_part)
+ };
+ Some(title_left_side)
+ }
+ }
+ fn render_title(&self, vte_output: &mut String) {
+ let total_title_length = self.position_and_size.cols - 2; // 2 for the left and right corners
+ let left_boundary = if self.draw_title_only {
+ boundary_type::HORIZONTAL
+ } else {
+ boundary_type::TOP_LEFT
+ };
+ let right_boundary = if self.draw_title_only {
+ boundary_type::HORIZONTAL
+ } else {
+ boundary_type::TOP_RIGHT
+ };
+ let left_side = self.render_title_left_side(total_title_length);
+ let right_side = left_side.as_ref().and_then(|left_side| {
+ let space_left = total_title_length.saturating_sub(left_side.chars().count() + 1); // 1 for a middle separator
+ self.render_title_right_side(space_left)
+ });
+ let title_text = match (left_side, right_side) {
+ (Some(left_side), Some(right_side)) => {
+ let mut middle = String::new();
+ for _ in
+ (left_side.chars().count() + right_side.chars().count())..total_title_length
+ {
+ middle.push_str(boundary_type::HORIZONTAL);
+ }
+ format!(
+ "{}{}{}{}{}",
+ left_boundary, left_side, middle, right_side, right_boundary
+ )
+ }
+ (Some(left_side), None) => {
+ let mut middle_padding = String::new();
+ for _ in left_side.chars().count()..total_title_length {
+ middle_padding.push_str(boundary_type::HORIZONTAL);
+ }
+ format!(
+ "{}{}{}{}",
+ left_boundary, left_side, middle_padding, right_boundary
+ )
+ }
+ _ => {
+ let mut middle_padding = String::new();
+ for _ in 0..total_title_length {
+ middle_padding.push_str(boundary_type::HORIZONTAL);
+ }
+ format!("{}{}{}", left_boundary, middle_padding, right_boundary)
+ }
+ };
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m{}",
+ self.position_and_size.y + 1, // +1 because goto is 1 indexed
+ self.position_and_size.x + 1, // +1 because goto is 1 indexed
+ color_string(&title_text, self.color),
+ )); // goto row/col + boundary character
+ }
+ pub fn render(&mut self) -> Option<String> {
+ if !self.should_render {
+ return None;
+ }
+ let mut vte_output = String::new();
+ if self.draw_title_only {
+ self.render_title(&mut vte_output);
+ } else {
+ for row in
+ self.position_and_size.y..(self.position_and_size.y + self.position_and_size.rows)
+ {
+ if row == self.position_and_size.y {
+ // top row
+ self.render_title(&mut vte_output);
+ } else if row == self.position_and_size.y + self.position_and_size.rows - 1 {
+ // bottom row
+ for col in self.position_and_size.x
+ ..(self.position_and_size.x + self.position_and_size.cols)
+ {
+ if col == self.position_and_size.x {
+ // bottom left corner
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m{}",
+ row + 1, // +1 because goto is 1 indexed
+ col + 1,
+ color_string(boundary_type::BOTTOM_LEFT, self.color),
+ )); // goto row/col + boundary character
+ } else if col == self.position_and_size.x + self.position_and_size.cols - 1
+ {
+ // bottom right corner
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m{}",
+ row + 1, // +1 because goto is 1 indexed
+ col + 1,
+ color_string(boundary_type::BOTTOM_RIGHT, self.color),
+ )); // goto row/col + boundary character
+ } else {
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m{}",
+ row + 1, // +1 because goto is 1 indexed
+ col + 1,
+ color_string(boundary_type::HORIZONTAL, self.color),
+ )); // goto row/col + boundary character
+ }
+ }
+ } else {
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m{}",
+ row + 1, // +1 because goto is 1 indexed
+ self.position_and_size.x + 1,
+ color_string(boundary_type::VERTICAL, self.color),
+ )); // goto row/col + boundary character
+ vte_output.push_str(&format!(
+ "\u{1b}[{};{}H\u{1b}[m{}",
+ row + 1, // +1 because goto is 1 indexed
+ self.position_and_size.x + self.position_and_size.cols,
+ color_string(boundary_type::VERTICAL, self.color),
+ )); // goto row/col + boundary character
+ }
+ }
+ }
+ self.should_render = false;
+ Some(vte_output)
+ }
+}
diff --git a/zellij-server/src/ui/pane_resizer.rs b/zellij-server/src/ui/pane_resizer.rs
index 39f2d40c6..1b5ddabf3 100644
--- a/zellij-server/src/ui/pane_resizer.rs
+++ b/zellij-server/src/ui/pane_resizer.rs
@@ -112,7 +112,7 @@ impl<'a> PaneResizer<'a> {
(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.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)
});
@@ -137,7 +137,7 @@ impl<'a> PaneResizer<'a> {
(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.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)
});
@@ -162,7 +162,7 @@ impl<'a> PaneResizer<'a> {
(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.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)
});
@@ -187,7 +187,7 @@ impl<'a> PaneResizer<'a> {
(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.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)
});
@@ -204,32 +204,44 @@ impl<'a> PaneResizer<'a> {
let pane = sel