rust_kanban/ui/rendering/popup/
change_theme.rs1use crate::{
2 app::{
3 state::{Focus, KeyBindingEnum},
4 App,
5 },
6 constants::LIST_SELECTED_SYMBOL,
7 ui::{
8 rendering::{
9 common::{render_blank_styled_canvas, render_close_button},
10 popup::ChangeTheme,
11 utils::{
12 centered_rect_with_percentage, check_if_active_and_get_style,
13 check_if_mouse_is_in_area,
14 },
15 },
16 Renderable,
17 },
18};
19use ratatui::{
20 layout::{Alignment, Constraint, Direction, Layout},
21 text::{Line, Span},
22 widgets::{Block, BorderType, Borders, List, ListItem, Paragraph},
23 Frame,
24};
25
26impl Renderable for ChangeTheme {
27 fn render(rect: &mut Frame, app: &mut App, is_active: bool) {
28 let general_style = check_if_active_and_get_style(
29 is_active,
30 app.current_theme.inactive_text_style,
31 app.current_theme.general_style,
32 );
33 let list_select_style = check_if_active_and_get_style(
34 is_active,
35 app.current_theme.inactive_text_style,
36 app.current_theme.list_select_style,
37 );
38 let keyboard_focus_style = check_if_active_and_get_style(
39 is_active,
40 app.current_theme.inactive_text_style,
41 app.current_theme.keyboard_focus_style,
42 );
43 let help_key_style = check_if_active_and_get_style(
44 is_active,
45 app.current_theme.inactive_text_style,
46 app.current_theme.help_key_style,
47 );
48 let help_text_style = check_if_active_and_get_style(
49 is_active,
50 app.current_theme.inactive_text_style,
51 app.current_theme.help_text_style,
52 );
53 let render_area = centered_rect_with_percentage(70, 70, rect.area());
54 let clear_area = centered_rect_with_percentage(80, 80, rect.area());
55 let clear_area_border = Block::default()
56 .title("Change Theme")
57 .style(general_style)
58 .borders(Borders::ALL)
59 .border_style(keyboard_focus_style)
60 .border_type(BorderType::Rounded);
61
62 let chunks = Layout::default()
63 .direction(Direction::Vertical)
64 .constraints([Constraint::Fill(1), Constraint::Length(5)].as_ref())
65 .split(render_area);
66
67 let theme_list = app
68 .all_themes
69 .iter()
70 .map(|t| ListItem::new(vec![Line::from(t.name.clone())]))
71 .collect::<Vec<ListItem>>();
72
73 if check_if_mouse_is_in_area(&app.state.current_mouse_coordinates, &chunks[0]) {
74 app.state.mouse_focus = Some(Focus::ThemeSelector);
75 app.state.set_focus(Focus::ThemeSelector);
76 let top_of_list = chunks[0].y + 1;
77 let mut bottom_of_list = chunks[0].y + theme_list.len() as u16;
78 if bottom_of_list > chunks[0].bottom() {
79 bottom_of_list = chunks[0].bottom();
80 }
81 let mouse_y = app.state.current_mouse_coordinates.1;
82 if mouse_y >= top_of_list && mouse_y <= bottom_of_list {
83 app.state
84 .app_list_states
85 .theme_selector
86 .select(Some((mouse_y - top_of_list) as usize));
87 let selected_theme = app
88 .all_themes
89 .get(app.state.app_list_states.theme_selector.selected().unwrap())
90 .unwrap();
91 app.current_theme = selected_theme.clone();
92 } else {
93 app.state.app_list_states.theme_selector.select(None);
94 }
95 };
96 let themes = List::new(theme_list)
97 .block(
98 Block::default()
99 .style(general_style)
100 .borders(Borders::ALL)
101 .border_type(BorderType::Rounded),
102 )
103 .highlight_style(list_select_style)
104 .highlight_symbol(LIST_SELECTED_SYMBOL);
105
106 let up_key = app
107 .get_first_keybinding(KeyBindingEnum::Up)
108 .unwrap_or("".to_string());
109 let down_key = app
110 .get_first_keybinding(KeyBindingEnum::Down)
111 .unwrap_or("".to_string());
112 let accept_key = app
113 .get_first_keybinding(KeyBindingEnum::Accept)
114 .unwrap_or("".to_string());
115 let cancel_key = app
116 .get_first_keybinding(KeyBindingEnum::GoToPreviousViewOrCancel)
117 .unwrap_or("".to_string());
118
119 let help_spans = Line::from(vec![
120 Span::styled("Use ", help_text_style),
121 Span::styled(up_key, help_key_style),
122 Span::styled(" or ", help_text_style),
123 Span::styled(down_key, help_key_style),
124 Span::styled(
125 " to navigate or use the mouse cursor. Press ",
126 help_text_style,
127 ),
128 Span::styled(accept_key, help_key_style),
129 Span::styled(" or ", help_text_style),
130 Span::styled("<Mouse Left Click>", help_key_style),
131 Span::styled(" To select a Theme. Press ", help_text_style),
132 Span::styled(cancel_key, help_key_style),
133 Span::styled(" to cancel", help_text_style),
134 ]);
135
136 let change_theme_help = Paragraph::new(help_spans)
137 .alignment(Alignment::Left)
138 .block(
139 Block::default()
140 .title("Help")
141 .borders(Borders::ALL)
142 .style(general_style)
143 .border_type(BorderType::Rounded),
144 )
145 .alignment(Alignment::Center)
146 .wrap(ratatui::widgets::Wrap { trim: true });
147
148 render_blank_styled_canvas(rect, &app.current_theme, clear_area, is_active);
149 rect.render_widget(clear_area_border, clear_area);
150 rect.render_stateful_widget(
151 themes,
152 chunks[0],
153 &mut app.state.app_list_states.theme_selector,
154 );
155 rect.render_widget(change_theme_help, chunks[1]);
156 if app.config.enable_mouse_support {
157 render_close_button(rect, app, is_active)
158 }
159 }
160}