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 padding: Option<usize>,
25 title_color: Option<Color>,
26 border_color: Option<Color>,
27 message_color: Option<Color>,
28 ) -> Self {
29 Self {
30 title,
31 message,
32 width,
33 padding: padding.unwrap_or(2),
34 title_color: title_color.unwrap_or(Color::White), border_color: border_color.unwrap_or(Color::Blue),
36 message_color: message_color.unwrap_or(Color::Reset),
37 }
38 }
39
40 pub fn render(&self) -> Result<(), Box<dyn std::error::Error>> {
41 let mut stdout = stdout();
42 let total_width = self.width + 2 * self.padding + 2;
43
44 execute!(stdout, cursor::MoveToColumn(0))?;
45 execute!(stdout, Clear(ClearType::UntilNewLine))?;
46
47 execute!(
48 stdout,
49 PrintStyledContent(
50 format!("{: <width$}", self.title, width = total_width as usize)
51 .with(self.title_color)
52 )
53 )?;
54 execute!(stdout, Print("\n"))?;
55
56 execute!(stdout, PrintStyledContent("┌".with(self.border_color)))?;
57 for _ in 0..total_width - 2 {
58 execute!(stdout, PrintStyledContent("─".with(self.border_color)))?;
59 }
60 execute!(stdout, PrintStyledContent("┐\n".with(self.border_color)))?;
61
62 let wrapped_message = fill(&self.message, self.width);
63 for line in wrapped_message.lines() {
64 execute!(stdout, PrintStyledContent("│".with(self.border_color)))?;
65 for _ in 0..self.padding {
66 execute!(stdout, Print(" "))?;
67 }
68 execute!(stdout, PrintStyledContent(line.with(self.message_color)))?;
69 for _ in 0..self.padding + (self.width - line.len()) {
70 execute!(stdout, Print(" "))?;
71 }
72 execute!(stdout, PrintStyledContent("│\n".with(self.border_color)))?;
73 }
74
75 execute!(stdout, PrintStyledContent("└".with(self.border_color)))?;
76 for _ in 0..total_width - 2 {
77 execute!(stdout, PrintStyledContent("─".with(self.border_color)))?;
78 }
79 execute!(stdout, PrintStyledContent("┘\n".with(self.border_color)))?;
80
81 stdout.flush()?;
82
83 Ok(())
84 }
85}