hefesto_widgets/popups/file_browser/
mod.rs1use ratatui::{
2 buffer::Buffer,
3 layout::Rect,
4 style::{Color, Style},
5 widgets::StatefulWidget,
6};
7
8use crate::popups::FileBrowserState;
9use crate::scroll_list::ScrollList;
10use crate::DEFAULT_HIGHLIGHT;
11
12#[derive(Clone)]
25pub struct FileBrowser {
26 dir_style: Style,
27 file_style: Style,
28 highlight_style: Style,
29 highlight_symbol: String,
30 dir_icon: String,
31 file_icon: String,
32 max_selected: Option<usize>,
33}
34
35impl FileBrowser {
36 pub fn new() -> Self {
37 Self {
38 dir_style: Style::new().fg(Color::Cyan),
39 file_style: Style::new().fg(Color::White),
40 highlight_style: DEFAULT_HIGHLIGHT,
41 highlight_symbol: crate::HIGHLIGHT_SYMBOL.to_string(),
42 dir_icon: "📁 ".to_string(),
43 file_icon: "📄 ".to_string(),
44 max_selected: None,
45 }
46 }
47
48 pub fn dir_style(mut self, style: Style) -> Self {
49 self.dir_style = style;
50 self
51 }
52
53 pub fn file_style(mut self, style: Style) -> Self {
54 self.file_style = style;
55 self
56 }
57
58 pub fn highlight_style(mut self, style: Style) -> Self {
59 self.highlight_style = style;
60 self
61 }
62
63 pub fn highlight_symbol(mut self, symbol: &str) -> Self {
64 self.highlight_symbol = symbol.to_string();
65 self
66 }
67
68 pub fn dir_icon(mut self, icon: &str) -> Self {
69 self.dir_icon = icon.to_string();
70 self
71 }
72
73 pub fn file_icon(mut self, icon: &str) -> Self {
74 self.file_icon = icon.to_string();
75 self
76 }
77
78 pub fn max_selected(mut self, max: usize) -> Self {
79 self.max_selected = Some(max);
80 self
81 }
82
83 pub fn no_max_selected(mut self) -> Self {
84 self.max_selected = None;
85 self
86 }
87}
88
89impl Default for FileBrowser {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95impl StatefulWidget for FileBrowser {
96 type State = FileBrowserState;
97
98 fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
99 let items: Vec<(String, Style)> = state
100 .items
101 .iter()
102 .enumerate()
103 .map(|(i, (text, _))| {
104 let is_dir = state.entries.get(i).map(|e| e.is_dir).unwrap_or(false);
105 let style = if is_dir { self.dir_style } else { self.file_style };
106 (text.clone(), style)
107 })
108 .collect();
109
110 state.choose_popup_state.scroll_list_state.follow = false;
111 state.choose_popup_state.scroll_list_state.select(Some(state.choose_popup_state.cursor));
112
113 let list = ScrollList::new_styled(items)
114 .highlight_style(self.highlight_style)
115 .highlight_symbol(&self.highlight_symbol);
116 list.render(area, buf, &mut state.choose_popup_state.scroll_list_state);
117
118 if let Some(idx) = state.choose_popup_state.scroll_list_state.list_state.selected() {
119 state.choose_popup_state.cursor = idx;
120 }
121 }
122}