diff options
author | a-kenji <aks.kenji@protonmail.com> | 2021-05-31 21:47:32 +0200 |
---|---|---|
committer | a-kenji <aks.kenji@protonmail.com> | 2021-06-14 21:55:17 +0200 |
commit | cafcca0c57696968b609c4f4a8c7a6fe7f2909a8 (patch) | |
tree | 46adb670807caa3c715962cf50022004de00dd65 /zellij-server/src/ui | |
parent | 9cbe4107403e94b3545257c7b13acd7fdd2cf04c (diff) |
Move `layout.rs` from `server` to `utils`
* give feedback on most errors in the layout-file
Diffstat (limited to 'zellij-server/src/ui')
-rw-r--r-- | zellij-server/src/ui/layout.rs | 235 | ||||
-rw-r--r-- | zellij-server/src/ui/mod.rs | 1 |
2 files changed, 0 insertions, 236 deletions
diff --git a/zellij-server/src/ui/layout.rs b/zellij-server/src/ui/layout.rs deleted file mode 100644 index a9af665fa..000000000 --- a/zellij-server/src/ui/layout.rs +++ /dev/null @@ -1,235 +0,0 @@ -use zellij_utils::{serde, serde_yaml}; - -use serde::{Deserialize, Serialize}; -use std::path::{Path, PathBuf}; -use std::{fs::File, io::prelude::*}; - -use zellij_utils::pane_size::PositionAndSize; - -fn split_space_to_parts_vertically( - space_to_split: &PositionAndSize, - sizes: Vec<Option<SplitSize>>, -) -> Vec<PositionAndSize> { - let mut split_parts = Vec::new(); - let mut current_x_position = space_to_split.x; - let mut current_width = 0; - let max_width = space_to_split.columns - (sizes.len() - 1); // minus space for gaps - - let mut parts_to_grow = Vec::new(); - - // First fit in the parameterized sizes - for size in sizes { - let (columns, max_columns) = match size { - Some(SplitSize::Percent(percent)) => { - ((max_width as f32 * (percent as f32 / 100.0)) as usize, None) - } // TODO: round properly - Some(SplitSize::Fixed(size)) => (size as usize, Some(size as usize)), - None => { - parts_to_grow.push(current_x_position); - ( - 1, // This is grown later on - None, - ) - } - }; - split_parts.push(PositionAndSize { - x: current_x_position, - y: space_to_split.y, - columns, - rows: space_to_split.rows, - max_columns, - ..Default::default() - }); - current_width += columns; - current_x_position += columns + 1; // 1 for gap - } - - if current_width > max_width { - panic!("Layout contained too many columns to fit onto the screen!"); - } - - let mut last_flexible_index = split_parts.len() - 1; - if let Some(new_columns) = (max_width - current_width).checked_div(parts_to_grow.len()) { - current_width = 0; - current_x_position = 0; - for (idx, part) in split_parts.iter_mut().enumerate() { - part.x = current_x_position; - if parts_to_grow.contains(&part.x) { - part.columns = new_columns; - last_flexible_index = idx; - } - current_width += part.columns; - current_x_position += part.columns + 1; // 1 for gap - } - } - - if current_width < max_width { - // we have some extra space left, let's add it to the last flexible part - let extra = max_width - current_width; - let mut last_part = split_parts.get_mut(last_flexible_index).unwrap(); - last_part.columns += extra; - for part in (&mut split_parts[last_flexible_index + 1..]).iter_mut() { - part.x += extra; - } - } - split_parts -} - -fn split_space_to_parts_horizontally( - space_to_split: &PositionAndSize, - sizes: Vec<Option<SplitSize>>, -) -> Vec<PositionAndSize> { - let mut split_parts = Vec::new(); - let mut current_y_position = space_to_split.y; - let mut current_height = 0; - let max_height = space_to_split.rows - (sizes.len() - 1); // minus space for gaps - - let mut parts_to_grow = Vec::new(); - - for size in sizes { - let (rows, max_rows) = match size { - Some(SplitSize::Percent(percent)) => ( - (max_height as f32 * (percent as f32 / 100.0)) as usize, - None, - ), // TODO: round properly - Some(SplitSize::Fixed(size)) => (size as usize, Some(size as usize)), - None => { - parts_to_grow.push(current_y_position); - ( - 1, // This is grown later on - None, - ) - } - }; - split_parts.push(PositionAndSize { - x: space_to_split.x, - y: current_y_position, - columns: space_to_split.columns, - rows, - max_rows, - ..Default::default() - }); - current_height += rows; - current_y_position += rows + 1; // 1 for gap - } - - if current_height > max_height { - panic!("Layout contained too many rows to fit onto the screen!"); - } - - let mut last_flexible_index = split_parts.len() - 1; - if let Some(new_rows) = (max_height - current_height).checked_div(parts_to_grow.len()) { - current_height = 0; - current_y_position = 0; - - for (idx, part) in split_parts.iter_mut().enumerate() { - part.y = current_y_position; - if parts_to_grow.contains(&part.y) { - part.rows = new_rows; - last_flexible_index = idx; - } - current_height += part.rows; - current_y_position += part.rows + 1; // 1 for gap - } - } - - if current_height < max_height { - // we have some extra space left, let's add it to the last flexible part - let extra = max_height - current_height; - let mut last_part = split_parts.get_mut(last_flexible_index).unwrap(); - last_part.rows += extra; - for part in (&mut split_parts[last_flexible_index + 1..]).iter_mut() { - part.y += extra; - } - } - split_parts -} - -fn split_space( - space_to_split: &PositionAndSize, - layout: &Layout, -) -> Vec<(Layout, PositionAndSize)> { - let mut pane_positions = Vec::new(); - let sizes: Vec<Option<SplitSize>> = layout.parts.iter().map(|part| part.split_size).collect(); - - let split_parts = match layout.direction { - Direction::Vertical => split_space_to_parts_vertically(space_to_split, sizes), - Direction::Horizontal => split_space_to_parts_horizontally(space_to_split, sizes), - }; - for (i, part) in layout.parts.iter().enumerate() { - let part_position_and_size = split_parts.get(i).unwrap(); - if !part.parts.is_empty() { - let mut part_positions = split_space(&part_position_and_size, part); - pane_positions.append(&mut part_positions); - } else { - pane_positions.push((part.clone(), *part_position_and_size)); - } - } - pane_positions -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(crate = "self::serde")] -pub(crate) enum Direction { - Horizontal, - Vertical, -} - -#[derive(Debug, Serialize, Deserialize, Clone, Copy)] -#[serde(crate = "self::serde")] -pub(crate) enum SplitSize { - Percent(u8), // 1 to 100 - Fixed(u16), // An absolute number of columns or rows -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(crate = "self::serde")] -pub(crate) struct Layout { - pub direction: Direction, - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub parts: Vec<Layout>, - #[serde(skip_serializing_if = "Option::is_none")] - pub split_size: Option<SplitSize>, - #[serde(skip_serializing_if = "Option::is_none")] - pub plugin: Option<PathBuf>, -} - -impl Layout { - pub fn new(layout_path: &Path) -> Self { - let mut layout_file = File::open(&layout_path) - .or_else(|_| File::open(&layout_path.with_extension("yaml"))) - .unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display())); - - let mut layout = String::new(); - layout_file - .read_to_string(&mut layout) - .unwrap_or_else(|_| panic!("could not read layout {}", &layout_path.display())); - let layout: Layout = serde_yaml::from_str(&layout) - .unwrap_or_else(|_| panic!("could not parse layout {}", &layout_path.display())); - layout - } - - // It wants to use Path here, but that doesn't compile. - #[allow(clippy::ptr_arg)] - pub fn from_dir(layout: &PathBuf, data_dir: &Path) -> Self { - Self::new(&data_dir.join("layouts/").join(layout)) - } - - pub fn total_terminal_panes(&self) -> usize { - let mut total_panes = 0; - total_panes += self.parts.len(); - for part in self.parts.iter() { - if part.plugin.is_none() { - total_panes += part.total_terminal_panes(); - } - } - total_panes - } - - pub fn position_panes_in_space( - &self, - space: &PositionAndSize, - ) -> Vec<(Layout, PositionAndSize)> { - split_space(space, &self) - } -} diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs index 1e4c85fd3..b2d94d164 100644 --- a/zellij-server/src/ui/mod.rs +++ b/zellij-server/src/ui/mod.rs @@ -1,3 +1,2 @@ pub mod boundaries; -pub mod layout; pub mod pane_resizer; |