1use crossterm::{
2 cursor, execute,
3 style::{Color, Print, PrintStyledContent, Stylize},
4 terminal::{Clear, ClearType},
5};
6use std::io::{stdout, Write};
7use textwrap::fill;
8
9pub struct InfoBox {
10 pub title: String,
11 pub message: String,
12 pub width: usize,
13 pub padding: usize,
14 pub title_color: Color,
15 pub border_color: Color,
16 pub message_color: Color,
17}
18
19impl InfoBox {
20 pub fn new(
21 title: String,
22 message: String,
23 width: usize,
24 title_color: Option<Color>,
25 border_color: Option<Color>,
26 message_color: Option<Color>,
27 ) -> Self {
28 Self {
29 title,
30 message,
31 width,
32 padding: 2,
33 title_color: title_color.unwrap_or(Color::White), border_color: border_color.unwrap_or(Color::Blue),
35 message_color: message_color.unwrap_or(Color::Reset),
36 }
37 }
38
39 pub fn with_padding(mut self, padding: usize) -> Self {
40 self.padding = padding;
41 self
42 }
43
44 pub fn render(&self) -> Result<(), Box<dyn std::error::Error>> {
45 let mut stdout = stdout();
46 let total_width = self.width + 2 * self.padding + 2;
47
48 execute!(stdout, cursor::MoveToColumn(0))?;
49 execute!(stdout, Clear(ClearType::UntilNewLine))?;
50
51 execute!(
52 stdout,
53 PrintStyledContent(
54 format!("{: <width$}", self.title, width = total_width as usize)
55 .with(self.title_color)
56 )
57 )?;
58 execute!(stdout, Print("\n"))?;
59
60 execute!(stdout, PrintStyledContent("┌".with(self.border_color)))?;
61 for _ in 0..total_width - 2 {
62 execute!(stdout, PrintStyledContent("─".with(self.border_color)))?;
63 }
64 execute!(stdout, PrintStyledContent("┐\n".with(self.border_color)))?;
65
66 let wrapped_message = fill(&self.message, self.width);
67 for line in wrapped_message.lines() {
68 execute!(stdout, PrintStyledContent("│".with(self.border_color)))?;
69 for _ in 0..self.padding {
70 execute!(stdout, Print(" "))?;
71 }
72 execute!(stdout, PrintStyledContent(line.with(self.message_color)))?;
73 for _ in 0..self.padding + (self.width - line.len()) {
74 execute!(stdout, Print(" "))?;
75 }
76 execute!(stdout, PrintStyledContent("│\n".with(self.border_color)))?;
77 }
78
79 execute!(stdout, PrintStyledContent("└".with(self.border_color)))?;
80 for _ in 0..total_width - 2 {
81 execute!(stdout, PrintStyledContent("─".with(self.border_color)))?;
82 }
83 execute!(stdout, PrintStyledContent("┘\n".with(self.border_color)))?;
84
85 stdout.flush()?;
86
87 Ok(())
88 }
89}