Skip to main content

pito_tui/
layout.rs

1use ratatui::layout::Rect;
2
3pub const TOP: u16 = 1;
4pub const SIDE: u16 = 1;
5pub const PAD: u16 = 2;
6pub const GAP: u16 = 1;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[non_exhaustive]
10pub enum Edge {
11    Start,
12    Third,
13    Middle,
14    End,
15}
16
17impl Edge {
18    const fn at(self, start: u16, room: u16, size: u16) -> u16 {
19        let spare = room.saturating_sub(size);
20        start.saturating_add(match self {
21            Edge::Start => 0,
22            Edge::Third => spare / 3,
23            Edge::Middle => spare / 2,
24            Edge::End => spare,
25        })
26    }
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30#[non_exhaustive]
31pub struct Spot {
32    pub x: Edge,
33    pub y: Edge,
34}
35
36impl Spot {
37    pub const TOP_LEFT: Spot = Spot::new(Edge::Start, Edge::Start);
38    pub const TOP: Spot = Spot::new(Edge::Middle, Edge::Start);
39    pub const TOP_RIGHT: Spot = Spot::new(Edge::End, Edge::Start);
40    pub const LEFT: Spot = Spot::new(Edge::Start, Edge::Middle);
41    pub const MIDDLE: Spot = Spot::new(Edge::Middle, Edge::Middle);
42    pub const RIGHT: Spot = Spot::new(Edge::End, Edge::Middle);
43    pub const BOTTOM_LEFT: Spot = Spot::new(Edge::Start, Edge::End);
44    pub const BOTTOM: Spot = Spot::new(Edge::Middle, Edge::End);
45    pub const BOTTOM_RIGHT: Spot = Spot::new(Edge::End, Edge::End);
46    pub const THIRD: Spot = Spot::new(Edge::Middle, Edge::Third);
47
48    pub const fn new(x: Edge, y: Edge) -> Self {
49        Spot { x, y }
50    }
51
52    pub fn place(self, area: Rect, width: u16, height: u16) -> Rect {
53        let width = width.min(area.width);
54        let height = height.min(area.height);
55        Rect::new(
56            self.x.at(area.x, area.width, width),
57            self.y.at(area.y, area.height, height),
58            width,
59            height,
60        )
61    }
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65#[non_exhaustive]
66pub struct Layout {
67    pub top: u16,
68    pub bottom: u16,
69    pub side: u16,
70    pub pad: u16,
71    pub head_gap: u16,
72    pub gap: u16,
73    pub small: Spot,
74}
75
76impl Layout {
77    pub const fn new() -> Self {
78        Layout {
79            top: TOP,
80            bottom: 0,
81            side: SIDE,
82            pad: PAD,
83            head_gap: 0,
84            gap: GAP,
85            small: Spot::THIRD,
86        }
87    }
88
89    pub const fn top(mut self, rows: u16) -> Self {
90        self.top = rows;
91        self
92    }
93
94    pub const fn bottom(mut self, rows: u16) -> Self {
95        self.bottom = rows;
96        self
97    }
98
99    pub const fn side(mut self, cells: u16) -> Self {
100        self.side = cells;
101        self
102    }
103
104    pub const fn pad(mut self, cells: u16) -> Self {
105        self.pad = cells;
106        self
107    }
108
109    pub const fn head_gap(mut self, rows: u16) -> Self {
110        self.head_gap = rows;
111        self
112    }
113
114    pub const fn gap(mut self, rows: u16) -> Self {
115        self.gap = rows;
116        self
117    }
118
119    pub const fn small(mut self, spot: Spot) -> Self {
120        self.small = spot;
121        self
122    }
123}
124
125impl Default for Layout {
126    fn default() -> Self {
127        Layout::new()
128    }
129}