diff options
| author | David Heinemeier Hansson <david@hey.com> | 2026-08-09 00:37:57 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-09 01:37:57 +0300 |
| commit | 36a8d36a7258e08b40c01bf521b1f4006525f143 (patch) | |
| tree | edaf35204db558c4d6b5a79ab78b6d6e5138c9dc /src/ui | |
| parent | 3a76fea2d858a7a5ef58615f1cc9aabaa30b80ee (diff) | |
feat: make outer pane borders configurable (#2535)
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/panes.rs | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/src/ui/panes.rs b/src/ui/panes.rs index b904ce00..22daddf8 100644 --- a/src/ui/panes.rs +++ b/src/ui/panes.rs @@ -91,8 +91,21 @@ pub(crate) fn apply_pane_chrome( panes: Vec<PaneInfo>, pane_borders: bool, pane_gaps: bool, + pane_outer_borders: bool, ) -> Vec<PaneInfo> { let multi_pane = panes.len() > 1; + let outer_left = panes.iter().map(|info| info.rect.x).min().unwrap_or(0); + let outer_top = panes.iter().map(|info| info.rect.y).min().unwrap_or(0); + let outer_right = panes + .iter() + .map(|info| info.rect.x.saturating_add(info.rect.width)) + .max() + .unwrap_or(0); + let outer_bottom = panes + .iter() + .map(|info| info.rect.y.saturating_add(info.rect.height)) + .max() + .unwrap_or(0); panes .iter() .cloned() @@ -121,6 +134,20 @@ pub(crate) fn apply_pane_chrome( borders.remove(Borders::BOTTOM); } } + if !pane_outer_borders { + if info.rect.x == outer_left { + borders.remove(Borders::LEFT); + } + if info.rect.y == outer_top { + borders.remove(Borders::TOP); + } + if info.rect.x.saturating_add(info.rect.width) == outer_right { + borders.remove(Borders::RIGHT); + } + if info.rect.y.saturating_add(info.rect.height) == outer_bottom { + borders.remove(Borders::BOTTOM); + } + } borders }; info @@ -179,7 +206,7 @@ pub(super) fn resize_tab_panes( if tab.zoomed { let focused_id = tab.layout.focused(); if let Some((terminal_id, rt)) = runtime_for_tab_pane(terminal_runtimes, tab, focused_id) { - let borders = if multi_pane && app.pane_borders { + let borders = if multi_pane && app.pane_borders && app.pane_outer_borders { Borders::ALL } else { Borders::NONE @@ -198,7 +225,12 @@ pub(super) fn resize_tab_panes( return; } - for info in apply_pane_chrome(tab.layout.panes(area), app.pane_borders, app.pane_gaps) { + for info in apply_pane_chrome( + tab.layout.panes(area), + app.pane_borders, + app.pane_gaps, + app.pane_outer_borders, + ) { let pane_inner = pane_inner_rect(info.rect, info.borders); if let Some((terminal_id, rt)) = runtime_for_tab_pane(terminal_runtimes, tab, info.id) { @@ -234,7 +266,7 @@ pub(super) fn compute_pane_infos( if ws.zoomed { let focused_id = ws.layout.focused(); - let borders = if multi_pane && app.pane_borders { + let borders = if multi_pane && app.pane_borders && app.pane_outer_borders { Borders::ALL } else { Borders::NONE @@ -268,7 +300,12 @@ pub(super) fn compute_pane_infos( }]; } - let mut pane_infos = apply_pane_chrome(ws.layout.panes(area), app.pane_borders, app.pane_gaps); + let mut pane_infos = apply_pane_chrome( + ws.layout.panes(area), + app.pane_borders, + app.pane_gaps, + app.pane_outer_borders, + ); for info in &mut pane_infos { let pane_inner = pane_inner_rect(info.rect, info.borders); @@ -1054,6 +1091,7 @@ mod tests { workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)), true, false, + true, ); let left = infos.iter().find(|info| info.id == root).unwrap(); let right = infos.iter().find(|info| info.id == right).unwrap(); @@ -1074,6 +1112,7 @@ mod tests { workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)), true, false, + true, ); let top = infos.iter().find(|info| info.id == root).unwrap(); let bottom = infos.iter().find(|info| info.id == bottom).unwrap(); @@ -1084,6 +1123,26 @@ mod tests { } #[test] + fn disabled_outer_borders_keep_only_shared_pane_dividers() { + let mut workspace = Workspace::test_new("test"); + let root = workspace.tabs[0].root_pane; + let right = workspace.test_split(ratatui::layout::Direction::Horizontal); + workspace.tabs[0].layout.focus_pane(root); + + let infos = apply_pane_chrome( + workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)), + true, + false, + false, + ); + let left = infos.iter().find(|info| info.id == root).unwrap(); + let right = infos.iter().find(|info| info.id == right).unwrap(); + + assert_eq!(left.borders, Borders::NONE); + assert_eq!(right.borders, Borders::LEFT); + } + + #[test] fn pane_gaps_keep_independent_bordered_panes() { let mut workspace = Workspace::test_new("test"); let root = workspace.tabs[0].root_pane; @@ -1094,6 +1153,7 @@ mod tests { workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)), true, true, + true, ); let left = infos.iter().find(|info| info.id == root).unwrap(); let right = infos.iter().find(|info| info.id == right).unwrap(); @@ -1114,6 +1174,7 @@ mod tests { workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)), false, true, + true, ); let left = infos.iter().find(|info| info.id == root).unwrap(); let right = infos.iter().find(|info| info.id == right).unwrap(); @@ -1133,6 +1194,7 @@ mod tests { workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)), false, false, + true, ); for info in infos { |
