use serde::{Deserialize, Serialize}; use crate::position::Position; /// Contains the position and size of a [`Pane`], or more generally of any terminal, measured /// in character rows and columns. #[derive(Clone, Copy, Default, PartialEq, Debug, Serialize, Deserialize)] pub struct PaneGeom { pub x: usize, pub y: usize, pub rows: Dimension, pub cols: Dimension, } #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] pub struct Viewport { pub x: usize, pub y: usize, pub rows: usize, pub cols: usize, } #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] pub struct Offset { pub top: usize, pub bottom: usize, pub right: usize, pub left: usize, } #[derive(Clone, Copy, Default, PartialEq, Debug, Serialize, Deserialize)] pub struct Size { pub rows: usize, pub cols: usize, } #[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] pub struct Dimension { pub constraint: Constraint, inner: usize, } impl Default for Dimension { fn default() -> Self { Self::percent(100.0) } } impl Dimension { pub fn fixed(size: usize) -> Dimension { Self { constraint: Constraint::Fixed(size), inner: 1, } } pub fn percent(percent: f64) -> Dimension { Self { constraint: Constraint::Percent(percent), inner: 1, } } pub fn as_usize(&self) -> usize { self.inner } pub fn as_percent(&self) -> Option { if let Constraint::Percent(p) = self.constraint { Some(p) } else { None } } pub fn set_inner(&mut self, inner: usize) { self.inner = inner; } pub fn is_fixed(&self) -> bool { matches!(self.constraint, Constraint::Fixed(_)) } } #[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] pub enum Constraint { /// Constrains the dimension to a fixed, integer number of rows / columns Fixed(usize), /// Constrains the dimension to a flexible percent size of the total screen Percent(f64), } impl PaneGeom { pub fn contains(&self, point: &Position) -> bool { let col = point.column.0 as usize; let row = point.line.0 as usize; self.x <= col && col < self.x + self.cols.as_usize() && self.y <= row && row < self.y + self.rows.as_usize() } } impl Offset { pub fn frame(size: usize) -> Self { Self { top: size, bottom: size, right: size, left: size, } } // FIXME: This should be top and left, not bottom and right, but `boundaries.rs` would need // some changing pub fn shift(bottom: usize, right: usize) -> Self { Self { bottom, right, ..Default::default() } } } impl From for Viewport { fn from(pane: PaneGeom) -> Self { Self { x: pane.x, y: pane.y, rows: pane.rows.as_usize(), cols: pane.cols.as_usize(), } } } impl From for Viewport { fn from(size: Size) -> Self { Self { rows: size.rows, cols: size.cols, ..Default::default() } } }