rust_kanban/ui/rendering/view/
edit_keybindings.rs1use crate::{
2 app::{
3 state::{Focus, KeyBindingEnum},
4 App,
5 },
6 constants::{SCROLLBAR_BEGIN_SYMBOL, SCROLLBAR_END_SYMBOL, SCROLLBAR_TRACK_SYMBOL},
7 ui::{
8 rendering::{
9 common::{draw_title, render_close_button},
10 utils::{
11 check_if_active_and_get_style, get_button_style, get_mouse_focusable_field_style,
12 },
13 view::EditKeybindings,
14 },
15 Renderable,
16 },
17};
18use ratatui::{
19 layout::{Alignment, Constraint, Layout, Margin},
20 text::{Line, Span},
21 widgets::{
22 Block, BorderType, Borders, Cell, Paragraph, Row, Scrollbar, ScrollbarOrientation,
23 ScrollbarState, Table,
24 },
25 Frame,
26};
27
28impl Renderable for EditKeybindings {
29 fn render(rect: &mut Frame, app: &mut App, is_active: bool) {
30 let chunks = Layout::default()
31 .constraints(
32 [
33 Constraint::Length(3),
34 Constraint::Fill(1),
35 Constraint::Length(5),
36 Constraint::Length(3),
37 ]
38 .as_ref(),
39 )
40 .split(rect.area());
41
42 let default_style = check_if_active_and_get_style(
43 is_active,
44 app.current_theme.inactive_text_style,
45 app.current_theme.general_style,
46 );
47 let scrollbar_style = check_if_active_and_get_style(
48 is_active,
49 app.current_theme.inactive_text_style,
50 app.current_theme.progress_bar_style,
51 );
52 let reset_style =
53 get_button_style(app, Focus::SubmitButton, Some(&chunks[3]), is_active, true);
54 let current_element_style = check_if_active_and_get_style(
55 is_active,
56 app.current_theme.inactive_text_style,
57 app.current_theme.list_select_style,
58 );
59 let table_border_style = get_mouse_focusable_field_style(
60 app,
61 Focus::EditKeybindingsTable,
62 &chunks[1],
63 is_active,
64 false,
65 );
66 let help_key_style = check_if_active_and_get_style(
67 is_active,
68 app.current_theme.inactive_text_style,
69 app.current_theme.help_key_style,
70 );
71 let help_text_style = check_if_active_and_get_style(
72 is_active,
73 app.current_theme.inactive_text_style,
74 app.current_theme.help_text_style,
75 );
76
77 let up_key = app
78 .get_first_keybinding(KeyBindingEnum::Up)
79 .unwrap_or("".to_string());
80 let down_key = app
81 .get_first_keybinding(KeyBindingEnum::Down)
82 .unwrap_or("".to_string());
83 let next_focus_key = app
84 .get_first_keybinding(KeyBindingEnum::NextFocus)
85 .unwrap_or("".to_string());
86 let prv_focus_key = app
87 .get_first_keybinding(KeyBindingEnum::PrvFocus)
88 .unwrap_or("".to_string());
89 let accept_key = app
90 .get_first_keybinding(KeyBindingEnum::Accept)
91 .unwrap_or("".to_string());
92 let cancel_key = app
93 .get_first_keybinding(KeyBindingEnum::GoToPreviousViewOrCancel)
94 .unwrap_or("".to_string());
95
96 let edit_keybinding_help_spans = Line::from(vec![
97 Span::styled("Use ", help_text_style),
98 Span::styled(up_key, help_key_style),
99 Span::styled(" and ", help_text_style),
100 Span::styled(down_key, help_key_style),
101 Span::styled(" or scroll with the mouse", help_text_style),
102 Span::styled(" to select a keybinding, Press ", help_text_style),
103 Span::styled(accept_key.clone(), help_key_style),
104 Span::styled(" or ", help_text_style),
105 Span::styled("<Mouse Left Click>", help_key_style),
106 Span::styled(" to edit, ", help_text_style),
107 Span::styled(cancel_key, help_key_style),
108 Span::styled(
109 " to cancel, To Reset Keybindings to Default Press ",
110 help_text_style,
111 ),
112 Span::styled(next_focus_key, help_key_style),
113 Span::styled(" or ", help_text_style),
114 Span::styled(prv_focus_key, help_key_style),
115 Span::styled(" to highlight Reset Button and Press ", help_text_style),
116 Span::styled(accept_key, help_key_style),
117 Span::styled(" on the Reset Keybindings Button", help_text_style),
118 ]);
119
120 let mut table_items: Vec<Vec<String>> = Vec::new();
121 let keybindings = app.config.keybindings.clone();
122 for (key, value) in keybindings.iter() {
123 let mut row: Vec<String> = Vec::new();
124 row.push(keybindings.keybinding_enum_to_action(key).to_string());
125 let mut row_value = String::new();
126 for v in value.iter() {
127 row_value.push_str(&v.to_string());
128 if value.iter().last().unwrap() != v {
130 row_value.push_str(", ");
131 }
132 }
133 row.push(row_value);
134 table_items.push(row);
135 }
136 table_items.sort_by(|a, b| a[0].cmp(&b[0]));
138
139 let rows = table_items.iter().map(|item| {
140 let height = item
141 .iter()
142 .map(|content| content.chars().filter(|c| *c == '\n').count())
143 .max()
144 .unwrap_or(0)
145 + 1;
146 let cells = item.iter().map(|c| Cell::from(c.to_string()));
147 Row::new(cells).height(height as u16)
148 });
149
150 let current_index = app
151 .state
152 .app_table_states
153 .edit_keybindings
154 .selected()
155 .unwrap_or(0);
156 let scrollbar = Scrollbar::new(ScrollbarOrientation::VerticalRight)
157 .begin_symbol(SCROLLBAR_BEGIN_SYMBOL)
158 .style(scrollbar_style)
159 .end_symbol(SCROLLBAR_END_SYMBOL)
160 .track_symbol(SCROLLBAR_TRACK_SYMBOL)
161 .track_style(app.current_theme.inactive_text_style);
162 let mut scrollbar_state = ScrollbarState::new(table_items.len()).position(current_index);
163 let scrollbar_area = chunks[1].inner(Margin {
164 vertical: 1,
165 horizontal: 0,
166 });
167
168 let t = Table::new(rows, [Constraint::Fill(1), Constraint::Fill(1)])
169 .block(
170 Block::default()
171 .title("Edit Keybindings")
172 .style(default_style)
173 .border_style(table_border_style)
174 .borders(Borders::ALL)
175 .border_type(BorderType::Rounded),
176 )
177 .row_highlight_style(current_element_style)
178 .highlight_symbol(">> ");
179
180 let edit_keybinding_help = Paragraph::new(edit_keybinding_help_spans)
181 .block(
182 Block::default()
183 .title("Help")
184 .borders(Borders::ALL)
185 .border_type(BorderType::Rounded),
186 )
187 .style(default_style)
188 .alignment(Alignment::Center)
189 .wrap(ratatui::widgets::Wrap { trim: true });
190
191 let reset_button = Paragraph::new("Reset Keybindings to Default")
192 .block(
193 Block::default()
194 .title("Reset")
195 .borders(Borders::ALL)
196 .border_type(BorderType::Rounded),
197 )
198 .style(reset_style)
199 .alignment(Alignment::Center);
200
201 rect.render_widget(draw_title(app, chunks[0], is_active), chunks[0]);
202 rect.render_stateful_widget(
203 t,
204 chunks[1],
205 &mut app.state.app_table_states.edit_keybindings,
206 );
207 rect.render_stateful_widget(scrollbar, scrollbar_area, &mut scrollbar_state);
208 rect.render_widget(edit_keybinding_help, chunks[2]);
209 rect.render_widget(reset_button, chunks[3]);
210 if app.config.enable_mouse_support {
211 render_close_button(rect, app, is_active)
212 }
213 }
214}