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}