1use ratatui::buffer::Buffer;
2use ratatui::layout::{Position, Rect};
3use ratatui::style::Style;
4use ratatui::symbols;
5use ratatui::widgets::{BorderType, Borders, Widget};
6
7pub struct HeaderBlock {
8 borders: Borders,
10 border_style: Style,
12 border_type: BorderType,
15 style: Style,
17}
18
19impl Default for HeaderBlock {
20 fn default() -> HeaderBlock {
21 HeaderBlock {
22 borders: Borders::NONE,
23 border_style: Default::default(),
24 border_type: BorderType::Rounded,
25 style: Default::default(),
26 }
27 }
28}
29
30impl HeaderBlock {
31 pub fn border_style(mut self, style: Style) -> HeaderBlock {
32 self.border_style = style;
33 self
34 }
35
36 pub fn style(mut self, style: Style) -> HeaderBlock {
37 self.style = style;
38 self
39 }
40
41 pub fn borders(mut self, flag: Borders) -> HeaderBlock {
42 self.borders = flag;
43 self
44 }
45
46 pub fn border_type(mut self, border_type: BorderType) -> HeaderBlock {
47 self.border_type = border_type;
48 self
49 }
50}
51
52impl Widget for HeaderBlock {
53 fn render(self, area: Rect, buf: &mut Buffer) {
54 if area.area() == 0 {
55 return;
56 }
57 buf.set_style(area, self.style);
58 let symbols = BorderType::to_border_set(self.border_type);
59
60 if self.borders.intersects(Borders::LEFT) {
62 for y in area.top()..area.bottom() {
63 if let Some(cell) = buf.cell_mut(Position::new(area.left(), y)) {
64 cell.set_symbol(symbols.vertical_left)
65 .set_style(self.border_style);
66 }
67 }
68 }
69 if self.borders.intersects(Borders::TOP) {
70 for x in area.left()..area.right() {
71 if let Some(cell) = buf.cell_mut(Position::new(x, area.top())) {
72 cell.set_symbol(symbols.horizontal_top)
73 .set_style(self.border_style);
74 }
75 }
76 }
77 if self.borders.intersects(Borders::RIGHT) {
78 let x = area.right() - 1;
79 for y in area.top()..area.bottom() {
80 if let Some(cell) = buf.cell_mut(Position::new(x, y)) {
81 cell.set_symbol(symbols.vertical_right)
82 .set_style(self.border_style);
83 }
84 }
85 }
86 if self.borders.intersects(Borders::BOTTOM) {
87 let y = area.bottom() - 1;
88 for x in area.left()..area.right() {
89 if let Some(cell) = buf.cell_mut(Position::new(x, y)) {
90 cell.set_symbol(symbols.horizontal_bottom)
91 .set_style(self.border_style);
92 }
93 }
94 }
95
96 if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) {
98 if let Some(cell) = buf.cell_mut(Position::new(area.right() - 1, area.bottom() - 1)) {
99 cell.set_symbol(symbols::line::VERTICAL_LEFT)
100 .set_style(self.border_style);
101 }
102 }
103 if self.borders.contains(Borders::RIGHT | Borders::TOP) {
104 if let Some(cell) = buf.cell_mut(Position::new(area.right() - 1, area.top())) {
105 cell.set_symbol(symbols.top_right)
106 .set_style(self.border_style);
107 }
108 }
109 if self.borders.contains(Borders::LEFT | Borders::BOTTOM) {
110 if let Some(cell) = buf.cell_mut(Position::new(area.left(), area.bottom() - 1)) {
111 cell.set_symbol(symbols::line::VERTICAL_RIGHT)
112 .set_style(self.border_style);
113 }
114 }
115 if self.borders.contains(Borders::LEFT | Borders::TOP) {
116 if let Some(cell) = buf.cell_mut(Position::new(area.left(), area.top())) {
117 cell.set_symbol(symbols.top_left)
118 .set_style(self.border_style);
119 }
120 }
121 }
122}
123
124#[derive(Clone)]
125pub enum FooterBlockType {
126 Single { top: bool },
127 Begin,
128 End,
129 Repeat,
130}
131
132pub struct FooterBlock {
133 borders: Borders,
135 border_style: Style,
137 border_type: BorderType,
140 block_type: FooterBlockType,
142 style: Style,
144}
145
146impl Default for FooterBlock {
147 fn default() -> Self {
148 Self {
149 block_type: FooterBlockType::Single { top: true },
150 borders: Self::borders(FooterBlockType::Single { top: true }),
151 border_style: Default::default(),
152 border_type: BorderType::Rounded,
153 style: Default::default(),
154 }
155 }
156}
157
158impl FooterBlock {
159 pub fn border_style(mut self, style: Style) -> Self {
160 self.border_style = style;
161 self
162 }
163
164 pub fn style(mut self, style: Style) -> Self {
165 self.style = style;
166 self
167 }
168
169 pub fn block_type(mut self, block_type: FooterBlockType) -> Self {
170 self.block_type = block_type.clone();
171 self.borders = Self::borders(block_type);
172 self
173 }
174
175 pub fn border_type(mut self, border_type: BorderType) -> Self {
176 self.border_type = border_type;
177 self
178 }
179
180 fn borders(block_type: FooterBlockType) -> Borders {
181 match block_type {
182 FooterBlockType::Single { top } => {
183 if top {
184 Borders::ALL
185 } else {
186 Borders::LEFT | Borders::RIGHT | Borders::BOTTOM
187 }
188 }
189 FooterBlockType::Begin => Borders::ALL,
190 FooterBlockType::End | FooterBlockType::Repeat => {
191 Borders::TOP | Borders::RIGHT | Borders::BOTTOM
192 }
193 }
194 }
195}
196
197impl Widget for FooterBlock {
198 fn render(self, area: Rect, buf: &mut Buffer) {
199 if area.area() == 0 {
200 return;
201 }
202 buf.set_style(area, self.style);
203 let symbols = BorderType::to_border_set(self.border_type);
204
205 if self.borders.intersects(Borders::LEFT) {
207 for y in area.top()..area.bottom() {
208 if let Some(cell) = buf.cell_mut(Position::new(area.left(), y)) {
209 cell.set_symbol(symbols.vertical_left)
210 .set_style(self.border_style);
211 }
212 }
213 }
214 if self.borders.intersects(Borders::TOP) {
215 for x in area.left()..area.right() {
216 if let Some(cell) = buf.cell_mut(Position::new(x, area.top())) {
217 cell.set_symbol(symbols.horizontal_top)
218 .set_style(self.border_style);
219 }
220 }
221 }
222 if self.borders.intersects(Borders::RIGHT) {
223 let x = area.right() - 1;
224 for y in area.top()..area.bottom() {
225 if let Some(cell) = buf.cell_mut(Position::new(x, y)) {
226 cell.set_symbol(symbols.vertical_right)
227 .set_style(self.border_style);
228 }
229 }
230 }
231 if self.borders.intersects(Borders::BOTTOM) {
232 let y = area.bottom() - 1;
233 for x in area.left()..area.right() {
234 if let Some(cell) = buf.cell_mut(Position::new(x, y)) {
235 cell.set_symbol(symbols.horizontal_bottom)
236 .set_style(self.border_style);
237 }
238 }
239 }
240
241 if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) {
243 let symbol = match self.block_type {
244 FooterBlockType::Begin | FooterBlockType::Repeat => symbols::line::HORIZONTAL_UP,
245 _ => symbols.bottom_right,
246 };
247 if let Some(cell) = buf.cell_mut(Position::new(area.right() - 1, area.bottom() - 1)) {
248 cell.set_symbol(symbol).set_style(self.border_style);
249 }
250 }
251 if self.borders.contains(Borders::RIGHT | Borders::TOP) {
252 let symbol = match self.block_type {
253 FooterBlockType::Begin | FooterBlockType::Repeat => symbols::line::HORIZONTAL_DOWN,
254 _ => symbols::line::VERTICAL_LEFT,
255 };
256 if let Some(cell) = buf.cell_mut(Position::new(area.right() - 1, area.top())) {
257 cell.set_symbol(symbol).set_style(self.border_style);
258 }
259 }
260 if self.borders.contains(Borders::LEFT | Borders::BOTTOM) {
261 if let Some(cell) = buf.cell_mut(Position::new(area.left(), area.bottom() - 1)) {
262 cell.set_symbol(symbols.bottom_left)
263 .set_style(self.border_style);
264 }
265 }
266 if self.borders.contains(Borders::LEFT | Borders::TOP) {
267 if let Some(cell) = buf.cell_mut(Position::new(area.left(), area.top())) {
268 cell.set_symbol(symbols::line::VERTICAL_RIGHT)
269 .set_style(self.border_style);
270 }
271 }
272 }
273}