vtcode_tui/core_tui/widgets/
panel.rs1use ratatui::{
2 buffer::Buffer,
3 layout::Rect,
4 style::{Modifier, Style},
5 widgets::{Block, BorderType, Widget},
6};
7
8use super::layout_mode::LayoutMode;
9use crate::ui::tui::session::styling::SessionStyles;
10use crate::ui::tui::session::terminal_capabilities;
11
12pub struct Panel<'a> {
27 styles: &'a SessionStyles,
28 title: Option<&'a str>,
29 active: bool,
30 mode: LayoutMode,
31 border_type: Option<BorderType>,
32}
33
34impl<'a> Panel<'a> {
35 pub fn new(styles: &'a SessionStyles) -> Self {
37 Self {
38 styles,
39 title: None,
40 active: false,
41 mode: LayoutMode::Standard,
42 border_type: None,
43 }
44 }
45
46 #[must_use]
48 pub fn title(mut self, title: &'a str) -> Self {
49 self.title = Some(title);
50 self
51 }
52
53 #[must_use]
55 pub fn active(mut self, active: bool) -> Self {
56 self.active = active;
57 self
58 }
59
60 #[must_use]
62 pub fn mode(mut self, mode: LayoutMode) -> Self {
63 self.mode = mode;
64 self
65 }
66
67 #[must_use]
69 pub fn border_type(mut self, border_type: BorderType) -> Self {
70 self.border_type = Some(border_type);
71 self
72 }
73
74 pub fn render_and_get_inner(self, area: Rect, buf: &mut Buffer) -> Rect {
76 if !self.mode.show_borders() {
77 return area;
78 }
79
80 let border_style = if self.active {
81 self.styles.accent_style()
82 } else {
83 self.styles.border_style()
84 };
85
86 let border_type = self
87 .border_type
88 .unwrap_or_else(terminal_capabilities::get_border_type);
89
90 let mut block = Block::bordered()
91 .border_type(border_type)
92 .style(self.styles.default_style())
93 .border_style(border_style);
94
95 if self.mode.show_titles()
96 && let Some(title) = self.title
97 {
98 let title_style = if self.active {
99 self.styles.accent_style().add_modifier(Modifier::BOLD)
100 } else {
101 self.styles.default_style().add_modifier(Modifier::BOLD)
102 };
103 block = block.title(title).title_style(title_style);
104 }
105
106 let inner = block.inner(area);
107 block.render(area, buf);
108 inner
109 }
110}
111
112pub trait PanelStyles {
114 fn muted_style(&self) -> Style;
116
117 fn title_style(&self) -> Style;
119
120 fn border_active_style(&self) -> Style;
122
123 fn divider_style(&self) -> Style;
125}
126
127impl PanelStyles for SessionStyles {
128 fn muted_style(&self) -> Style {
129 self.default_style().add_modifier(Modifier::DIM)
130 }
131
132 fn title_style(&self) -> Style {
133 self.accent_style().add_modifier(Modifier::BOLD)
134 }
135
136 fn border_active_style(&self) -> Style {
137 self.border_style()
138 .remove_modifier(Modifier::DIM)
139 .add_modifier(Modifier::BOLD)
140 }
141
142 fn divider_style(&self) -> Style {
143 self.border_style().add_modifier(Modifier::DIM)
144 }
145}