1use crate::{
2 app::{
3 App, INDEX_SOURCE_FORMAT, INDEX_SOURCE_NEW_FORMAT_ALIAS, INDEX_SOURCE_NEW_FORMAT_REGEX,
4 INDEX_SOURCE_OK_BUTTON, INDEX_SOURCE_PATH, INDEX_SOURCE_TYPE,
5 },
6 styles::selected_style,
7};
8use tui::{
9 backend::{Backend},
10 layout::{Alignment, Constraint, Direction, Layout, Rect},
11 style::{Color, Style},
12 text::{Span, Spans},
13 widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Tabs},
14 Frame,
15};
16
17use super::{ui_popup::centered_rect, ui_shared::display_cursor};
18
19fn draw_source_type_selector<B>(f: &mut Frame<B>, app: &App, area: Rect)
20where
21 B: Backend,
22{
23 let titles = ["FILE", "WS"]
24 .iter()
25 .map(|t| Spans::from(vec![Span::styled(*t, Style::default().fg(Color::White))]))
26 .collect();
27
28 let source_type_widget = Tabs::new(titles)
29 .block(Block::default().borders(Borders::ALL).title("Source type"))
30 .select(app.source_type)
31 .style(match INDEX_SOURCE_TYPE == app.input_buffer_index {
32 false => Style::default(),
33 true => selected_style(app.color),
34 })
35 .highlight_style(selected_style(app.color));
36
37 f.render_widget(source_type_widget, area);
38}
39
40fn draw_source_path<B>(f: &mut Frame<B>, app: &App, area: Rect)
41where
42 B: Backend,
43{
44 let source_path_widget = Paragraph::new(app.input_buffers[INDEX_SOURCE_PATH].value())
45 .style(match INDEX_SOURCE_PATH == app.input_buffer_index {
46 false => Style::default(),
47 true => selected_style(app.color),
48 })
49 .block(Block::default().borders(Borders::ALL).title("Path"));
50
51 f.render_widget(source_path_widget, area);
52 if INDEX_SOURCE_PATH == app.input_buffer_index {
53 display_cursor(f, area, app.input_buffers[INDEX_SOURCE_PATH].cursor())
54 }
55}
56
57fn draw_format_list<B>(f: &mut Frame<B>, app: &mut App, area: Rect)
58where
59 B: Backend,
60{
61 let formats: Vec<ListItem> = app
62 .formats
63 .items
64 .iter()
65 .map(|i| {
66 let lines = vec![Spans::from(i.clone())];
67 ListItem::new(lines).style(Style::default().fg(Color::White))
68 })
69 .collect();
70
71 let formats = List::new(formats)
73 .block(
74 Block::default()
75 .borders(Borders::ALL)
76 .title("Format")
77 .border_style(match INDEX_SOURCE_FORMAT == app.input_buffer_index {
78 false => Style::default(),
79 true => selected_style(app.color),
80 }),
81 )
82 .highlight_style(selected_style(app.color))
83 .highlight_symbol(">> ");
84
85 f.render_stateful_widget(formats, area, &mut app.formats.state);
86}
87
88fn draw_new_format_alias<B>(f: &mut Frame<B>, app: &App, area: Rect)
89where
90 B: Backend,
91{
92 let format_alias_widget =
93 Paragraph::new(app.input_buffers[INDEX_SOURCE_NEW_FORMAT_ALIAS].value())
94 .style(
95 match INDEX_SOURCE_NEW_FORMAT_ALIAS == app.input_buffer_index {
96 false => Style::default(),
97 true => selected_style(app.color),
98 },
99 )
100 .block(Block::default().borders(Borders::ALL).title("Alias"));
101
102 f.render_widget(format_alias_widget, area);
103 if INDEX_SOURCE_NEW_FORMAT_ALIAS == app.input_buffer_index {
104 display_cursor(f, area, app.input_buffers[INDEX_SOURCE_NEW_FORMAT_ALIAS].cursor())
105 }
106}
107
108fn draw_new_format_regex<B>(f: &mut Frame<B>, app: &App, area: Rect)
109where
110 B: Backend,
111{
112 let format_regex_widget =
113 Paragraph::new(app.input_buffers[INDEX_SOURCE_NEW_FORMAT_REGEX].value())
114 .style(
115 match INDEX_SOURCE_NEW_FORMAT_REGEX == app.input_buffer_index {
116 false => Style::default(),
117 true => selected_style(app.color),
118 },
119 )
120 .block(Block::default().borders(Borders::ALL).title("Regex"));
121
122 f.render_widget(format_regex_widget, area);
123 if INDEX_SOURCE_NEW_FORMAT_REGEX == app.input_buffer_index {
124 display_cursor(f, area, app.input_buffers[INDEX_SOURCE_NEW_FORMAT_REGEX].cursor())
125 }
126}
127
128fn draw_ok_button<B>(f: &mut Frame<B>, app: &App, area: Rect)
129where
130 B: Backend,
131{
132 let ok_button_widget = Paragraph::new("OK")
133 .style(match INDEX_SOURCE_OK_BUTTON == app.input_buffer_index {
134 false => Style::default(),
135 true => selected_style(app.color),
136 })
137 .alignment(Alignment::Center)
138 .block(Block::default().borders(Borders::ALL));
139 f.render_widget(ok_button_widget, area);
140}
141
142pub fn draw_source_popup<B>(f: &mut Frame<B>, app: &mut App)
143where
144 B: Backend,
145{
146 let block = Block::default()
147 .title("Add new source")
148 .borders(Borders::ALL)
149 .border_style(selected_style(app.color));
150
151 let area = centered_rect(60, 28, f.size());
152 f.render_widget(Clear, area); f.render_widget(block, area);
154
155 let popup_layout = Layout::default()
156 .direction(Direction::Horizontal)
157 .constraints([Constraint::Percentage(100)].as_ref())
158 .margin(1)
159 .split(area);
160 let popup_layout = Layout::default()
161 .direction(Direction::Vertical)
162 .constraints(
163 [
164 Constraint::Max(3),
165 Constraint::Max(3),
166 Constraint::Percentage(40),
167 Constraint::Max(3),
168 Constraint::Max(3),
169 Constraint::Max(1),
170 ]
171 .as_ref(),
172 )
173 .margin(1)
174 .split(popup_layout[0]);
175
176 draw_source_type_selector(f, app, popup_layout[INDEX_SOURCE_TYPE]);
177 draw_source_path(f, app, popup_layout[INDEX_SOURCE_PATH]);
178 draw_format_list(f, app, popup_layout[INDEX_SOURCE_FORMAT]);
179 draw_new_format_alias(f, app, popup_layout[INDEX_SOURCE_NEW_FORMAT_ALIAS]);
180 draw_new_format_regex(f, app, popup_layout[INDEX_SOURCE_NEW_FORMAT_REGEX]);
181 draw_ok_button(f, app, popup_layout[INDEX_SOURCE_OK_BUTTON]);
182}