1use ratatui::style::{Color, Style};
22use ratatui::widgets::{Block, BorderType, Borders};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum EnhancedBorderStyle {
27 Rounded,
29 Double,
31 Thick,
33 Square,
35}
36
37pub struct EnhancedBorder {
39 style: EnhancedBorderStyle,
40 focused: bool,
41 title: Option<String>,
42 focused_color: Color,
43 unfocused_color: Color,
44}
45
46impl EnhancedBorder {
47 pub fn new(style: EnhancedBorderStyle) -> Self {
49 Self {
50 style,
51 focused: false,
52 title: None,
53 focused_color: Color::Cyan,
54 unfocused_color: Color::Gray,
55 }
56 }
57
58 pub fn focused(mut self, focused: bool) -> Self {
60 self.focused = focused;
61 self
62 }
63
64 pub fn title<S: Into<String>>(mut self, title: S) -> Self {
66 self.title = Some(title.into());
67 self
68 }
69
70 pub fn focused_color(mut self, color: Color) -> Self {
72 self.focused_color = color;
73 self
74 }
75
76 pub fn unfocused_color(mut self, color: Color) -> Self {
78 self.unfocused_color = color;
79 self
80 }
81
82 pub fn build(self) -> Block<'static> {
84 let border_color = if self.focused { self.focused_color } else { self.unfocused_color };
85
86 let border_type = match self.style {
87 EnhancedBorderStyle::Rounded => BorderType::Rounded,
88 EnhancedBorderStyle::Double => BorderType::Double,
89 EnhancedBorderStyle::Thick => BorderType::Thick,
90 EnhancedBorderStyle::Square => BorderType::Plain,
91 };
92
93 let mut block = Block::default()
94 .borders(Borders::ALL)
95 .border_type(border_type)
96 .border_style(self.get_border_style(border_color));
97
98 if let Some(title) = self.title {
99 let title_with_indicator = if self.focused {
101 match self.style {
102 EnhancedBorderStyle::Rounded => format!("╭─ {title} ─╮"),
103 EnhancedBorderStyle::Double => format!("╔═ {title} ═╗"),
104 EnhancedBorderStyle::Thick => format!("┏━ {title} ━┓"),
105 EnhancedBorderStyle::Square => format!("┌─ {title} ─┐"),
106 }
107 } else {
108 title
109 };
110 block = block.title(title_with_indicator);
111 }
112
113 block
114 }
115
116 fn get_border_style(&self, base_color: Color) -> Style {
118 if self.focused {
119 Style::default().fg(base_color)
121 } else {
122 Style::default().fg(base_color)
123 }
124 }
125}
126
127impl EnhancedBorder {
129 pub fn rounded() -> Self {
131 Self::new(EnhancedBorderStyle::Rounded)
132 }
133
134 pub fn double() -> Self {
136 Self::new(EnhancedBorderStyle::Double)
137 }
138
139 pub fn thick() -> Self {
141 Self::new(EnhancedBorderStyle::Thick)
142 }
143
144 pub fn square() -> Self {
146 Self::new(EnhancedBorderStyle::Square)
147 }
148}
149
150pub struct BorderPresets;
152
153impl BorderPresets {
154 pub fn terminal(
156 focused: bool,
157 title: String,
158 focused_color: Color,
159 unfocused_color: Color,
160 ) -> Block<'static> {
161 EnhancedBorder::rounded()
162 .focused(focused)
163 .title(title)
164 .focused_color(focused_color)
165 .unfocused_color(unfocused_color)
166 .build()
167 }
168
169 pub fn code(
171 focused: bool,
172 title: String,
173 focused_color: Color,
174 unfocused_color: Color,
175 ) -> Block<'static> {
176 EnhancedBorder::double()
177 .focused(focused)
178 .title(title)
179 .focused_color(focused_color)
180 .unfocused_color(unfocused_color)
181 .build()
182 }
183
184 pub fn trace(
186 focused: bool,
187 title: String,
188 focused_color: Color,
189 unfocused_color: Color,
190 ) -> Block<'static> {
191 EnhancedBorder::thick()
192 .focused(focused)
193 .title(title)
194 .focused_color(focused_color)
195 .unfocused_color(unfocused_color)
196 .build()
197 }
198
199 pub fn display(
201 focused: bool,
202 title: String,
203 focused_color: Color,
204 unfocused_color: Color,
205 ) -> Block<'static> {
206 EnhancedBorder::rounded()
207 .focused(focused)
208 .title(title)
209 .focused_color(focused_color)
210 .unfocused_color(unfocused_color)
211 .build()
212 }
213}