summaryrefslogtreecommitdiffstats
path: root/zellij-server/src/ui
diff options
context:
space:
mode:
authora-kenji <aks.kenji@protonmail.com>2021-05-31 21:47:32 +0200
committera-kenji <aks.kenji@protonmail.com>2021-06-14 21:55:17 +0200
commitcafcca0c57696968b609c4f4a8c7a6fe7f2909a8 (patch)
tree46adb670807caa3c715962cf50022004de00dd65 /zellij-server/src/ui
parent9cbe4107403e94b3545257c7b13acd7fdd2cf04c (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.rs235
-rw-r--r--zellij-server/src/ui/mod.rs1
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;