diff options
author | Aram Drevekenin <aram@poor.dev> | 2023-03-16 17:31:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-16 17:31:40 +0100 |
commit | 5cb1cea10c43f0835ac2a114742c1a7eb282788c (patch) | |
tree | 00e5368a01627b688095492f4af892e483e0b6be /zellij-server/src/panes | |
parent | 2f0b4d048e3b854ece88cd927fda89bd227289c0 (diff) |
fix(panes): adding panes to lone stack (#2298)
Diffstat (limited to 'zellij-server/src/panes')
-rw-r--r-- | zellij-server/src/panes/floating_panes/mod.rs | 2 | ||||
-rw-r--r-- | zellij-server/src/panes/tiled_panes/mod.rs | 45 | ||||
-rw-r--r-- | zellij-server/src/panes/tiled_panes/stacked_panes.rs | 52 | ||||
-rw-r--r-- | zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs | 15 |
4 files changed, 99 insertions, 15 deletions
diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs index 84e85431f..a85cf80fd 100644 --- a/zellij-server/src/panes/floating_panes/mod.rs +++ b/zellij-server/src/panes/floating_panes/mod.rs @@ -532,7 +532,7 @@ impl FloatingPanes { pub fn focus_pane_on_edge(&mut self, direction: Direction, client_id: ClientId) { let display_area = *self.display_area.borrow(); let viewport = *self.viewport.borrow(); - let mut floating_pane_grid = FloatingPaneGrid::new( + let floating_pane_grid = FloatingPaneGrid::new( &mut self.panes, &mut self.desired_pane_positions, display_area, diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs index d4eb66b22..89a329bb4 100644 --- a/zellij-server/src/panes/tiled_panes/mod.rs +++ b/zellij-server/src/panes/tiled_panes/mod.rs @@ -176,13 +176,14 @@ impl TiledPanes { *self.display_area.borrow(), *self.viewport.borrow(), ); - pane_grid + let has_room_for_new_pane = pane_grid .find_room_for_new_pane(cursor_height_width_ratio) - .is_some() + .is_some(); + has_room_for_new_pane || pane_grid.has_room_for_new_stacked_pane() } fn add_pane(&mut self, pane_id: PaneId, mut pane: Box<dyn Pane>, should_relayout: bool) { let cursor_height_width_ratio = self.cursor_height_width_ratio(); - let pane_grid = TiledPaneGrid::new( + let mut pane_grid = TiledPaneGrid::new( &mut self.panes, &self.panes_to_hide, *self.display_area.borrow(), @@ -190,18 +191,34 @@ impl TiledPanes { ); let pane_id_and_split_direction = pane_grid.find_room_for_new_pane(cursor_height_width_ratio); - if let Some((pane_id_to_split, split_direction)) = pane_id_and_split_direction { - // this unwrap is safe because floating panes should not be visible if there are no floating panes - let pane_to_split = self.panes.get_mut(&pane_id_to_split).unwrap(); - let size_of_both_panes = pane_to_split.position_and_size(); - if let Some((first_geom, second_geom)) = split(split_direction, &size_of_both_panes) { - pane_to_split.set_geom(first_geom); - pane.set_geom(second_geom); - self.panes.insert(pane_id, pane); - if should_relayout { - self.relayout(!split_direction); + match pane_id_and_split_direction { + Some((pane_id_to_split, split_direction)) => { + // this unwrap is safe because floating panes should not be visible if there are no floating panes + let pane_to_split = self.panes.get_mut(&pane_id_to_split).unwrap(); + let size_of_both_panes = pane_to_split.position_and_size(); + if let Some((first_geom, second_geom)) = split(split_direction, &size_of_both_panes) + { + pane_to_split.set_geom(first_geom); + pane.set_geom(second_geom); + self.panes.insert(pane_id, pane); + if should_relayout { + self.relayout(!split_direction); + } } - } + }, + None => { + // we couldn't add the pane normally, let's see if there's room in one of the + // stacks... + match pane_grid.make_room_in_stack_for_pane() { + Ok(new_pane_geom) => { + pane.set_geom(new_pane_geom); + self.panes.insert(pane_id, pane); // TODO: is set_geom the right one? + }, + Err(e) => { + log::error!("Failed to add pane to stack: {:?}", e); + }, + } + }, } } pub fn fixed_pane_geoms(&self) -> Vec<Viewport> { diff --git a/zellij-server/src/panes/tiled_panes/stacked_panes.rs b/zellij-server/src/panes/tiled_panes/stacked_panes.rs index 00b193f69..cc0b0f151 100644 --- a/zellij-server/src/panes/tiled_panes/stacked_panes.rs +++ b/zellij-server/src/panes/tiled_panes/stacked_panes.rs @@ -430,6 +430,58 @@ impl<'a> StackedPanes<'a> { stacked_pane_ids_over_flexible_panes, )) } + pub fn make_room_for_new_pane(&mut self) -> Result<PaneGeom> { + let err_context = || format!("Failed to add pane to stack"); + let all_stacks = self.get_all_stacks()?; + for stack in all_stacks { + if let Some((id_of_flexible_pane_in_stack, _flexible_pane_in_stack)) = stack + .iter() + .find(|(_p_id, p)| !p.rows.is_fixed() && p.rows.as_usize() > 1) + { + self.make_lowest_pane_in_stack_flexible(id_of_flexible_pane_in_stack)?; + let all_stacked_pane_positions = + self.positions_in_stack(id_of_flexible_pane_in_stack)?; + let position_of_flexible_pane = + self.position_of_flexible_pane(&all_stacked_pane_positions)?; + let (flexible_pane_id, mut flexible_pane_geom) = *all_stacked_pane_positions + .iter() + .nth(position_of_flexible_pane) + .with_context(err_context)?; + let mut position_for_new_pane = flexible_pane_geom.clone(); + position_for_new_pane + .rows + .set_inner(position_for_new_pane.rows.as_usize() - 1); + position_for_new_pane.y = position_for_new_pane.y + 1; + flexible_pane_geom.rows = Dimension::fixed(1); + self.panes + .borrow_mut() + .get_mut(&flexible_pane_id) + .with_context(err_context)? + .set_geom(flexible_pane_geom); + return Ok(position_for_new_pane); + } + } + Err(anyhow!("Not enough room for another pane!")) + } + fn get_all_stacks(&self) -> Result<Vec<Vec<(PaneId, PaneGeom)>>> { + let err_context = || "Failed to get positions in stack"; + let panes = self.panes.borrow(); + let all_flexible_panes_in_stack: Vec<PaneId> = panes + .iter() + .filter(|(_pid, p)| { + p.position_and_size().is_stacked && !p.position_and_size().rows.is_fixed() + }) + .map(|(pid, _p)| *pid) + .collect(); + let mut stacks = vec![]; + for pane_id in all_flexible_panes_in_stack { + stacks.push( + self.positions_in_stack(&pane_id) + .with_context(err_context)?, + ); + } + Ok(stacks) + } fn fill_space_over_one_liner_pane(&mut self, id: &PaneId) -> Result<bool> { let (position_of_current_pane, position_of_flexible_pane) = self.position_of_current_and_flexible_pane(id)?; diff --git a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs index 5ee5cf3ca..7da65d712 100644 --- a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs +++ b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs @@ -1366,6 +1366,21 @@ impl<'a> TiledPaneGrid<'a> { direction.map(|direction| (*t_id_to_split, direction)) }) } + pub fn has_room_for_new_stacked_pane(&self) -> bool { + let panes = self.panes.borrow(); + let flexible_pane_in_stack: Vec<(&PaneId, &&mut Box<dyn Pane>)> = panes + .iter() + .filter(|(_, p)| { + p.selectable() && p.current_geom().is_stacked && !p.current_geom().rows.is_fixed() + }) + .collect(); + flexible_pane_in_stack + .iter() + .any(|(_p_id, p)| p.current_geom().rows.as_usize() > 1) + } + pub fn make_room_in_stack_for_pane(&mut self) -> Result<PaneGeom> { + StackedPanes::new(self.panes.clone()).make_room_for_new_pane() + } } pub fn split(direction: SplitDirection, rect: &PaneGeom) -> Option<(PaneGeom, PaneGeom)> { |