rust_kanban/ui/rendering/view/
main_menu_view.rs

1use crate::{
2    app::App,
3    constants::LIST_SELECTED_SYMBOL,
4    ui::{
5        rendering::{
6            common::{draw_help, draw_title, render_close_button, render_logs},
7            utils::{
8                check_if_active_and_get_style,
9                get_mouse_focusable_field_style_with_vertical_list_selection,
10            },
11            view::MainMenuView,
12        },
13        Renderable,
14    },
15};
16use ratatui::{
17    layout::{Alignment, Constraint, Direction, Layout, Rect},
18    style::Modifier,
19    widgets::{Block, BorderType, Borders, List, ListItem, Paragraph},
20    Frame,
21};
22
23impl Renderable for MainMenuView {
24    fn render(rect: &mut Frame, app: &mut App, is_active: bool) {
25        let chunks = Layout::default()
26            .direction(Direction::Vertical)
27            .constraints(
28                [
29                    Constraint::Length(3),
30                    Constraint::Length(10),
31                    Constraint::Fill(1),
32                    Constraint::Fill(2),
33                ]
34                .as_ref(),
35            )
36            .split(rect.area());
37
38        let help_chunks = Layout::default()
39            .direction(Direction::Horizontal)
40            .constraints(
41                [
42                    Constraint::Fill(1),
43                    Constraint::Length(1),
44                    Constraint::Fill(1),
45                ]
46                .as_ref(),
47            )
48            .margin(1)
49            .split(chunks[2]);
50
51        let general_style = check_if_active_and_get_style(
52            is_active,
53            app.current_theme.inactive_text_style,
54            app.current_theme.general_style,
55        );
56        let rapid_blink_general_style = if is_active {
57            general_style.add_modifier(Modifier::RAPID_BLINK)
58        } else {
59            general_style
60        };
61
62        let main_menu_help = draw_help(app, chunks[2], is_active);
63        let help_separator = Block::default()
64            .borders(Borders::LEFT)
65            .border_style(general_style);
66
67        rect.render_widget(draw_title(app, chunks[0], is_active), chunks[0]);
68
69        if let Some(email_id) = &app.state.user_login_data.email_id {
70            let email_id = email_id.to_string();
71            let email_id_len = email_id.len() as u16 + 4;
72            let sub_main_menu_chunks = Layout::default()
73                .direction(Direction::Horizontal)
74                .constraints(
75                    [
76                        Constraint::Length(chunks[1].width - email_id_len),
77                        Constraint::Length(email_id_len),
78                    ]
79                    .as_ref(),
80                )
81                .split(chunks[1]);
82
83            let border_block = Block::default()
84                .borders(Borders::ALL)
85                .border_style(rapid_blink_general_style)
86                .border_type(BorderType::Rounded);
87
88            let email_chunks = Layout::default()
89                .direction(Direction::Vertical)
90                .constraints(
91                    [
92                        Constraint::Length((sub_main_menu_chunks[1].height - 4) / 2),
93                        Constraint::Length(1),
94                        Constraint::Length(1),
95                        Constraint::Length(1),
96                        Constraint::Length((sub_main_menu_chunks[1].height - 4) / 2),
97                    ]
98                    .as_ref(),
99                )
100                .split(sub_main_menu_chunks[1]);
101
102            let heading_text = Paragraph::new("Logged in as:")
103                .block(Block::default().style(rapid_blink_general_style))
104                .alignment(Alignment::Center)
105                .wrap(ratatui::widgets::Wrap { trim: true });
106
107            let email_id_text = Paragraph::new(email_id)
108                .block(Block::default().style(rapid_blink_general_style))
109                .alignment(Alignment::Center)
110                .wrap(ratatui::widgets::Wrap { trim: true });
111
112            draw_main_menu(app, sub_main_menu_chunks[0], rect, is_active);
113            rect.render_widget(border_block, sub_main_menu_chunks[1]);
114            rect.render_widget(heading_text, email_chunks[1]);
115            rect.render_widget(email_id_text, email_chunks[3]);
116        } else {
117            draw_main_menu(app, chunks[1], rect, is_active);
118        }
119
120        rect.render_widget(main_menu_help.0, chunks[2]);
121        rect.render_stateful_widget(
122            main_menu_help.1,
123            help_chunks[0],
124            &mut app.state.app_table_states.help,
125        );
126        rect.render_widget(help_separator, help_chunks[1]);
127        rect.render_stateful_widget(
128            main_menu_help.2,
129            help_chunks[2],
130            &mut app.state.app_table_states.help,
131        );
132        render_logs(app, true, chunks[3], rect, is_active);
133        if app.config.enable_mouse_support {
134            render_close_button(rect, app, is_active);
135        }
136    }
137}
138
139fn draw_main_menu(app: &mut App, render_area: Rect, rect: &mut Frame, is_active: bool) {
140    let main_menu_items = app.main_menu.all();
141    let menu_style = get_mouse_focusable_field_style_with_vertical_list_selection(
142        app,
143        &main_menu_items,
144        render_area,
145        is_active,
146    );
147    let default_style = check_if_active_and_get_style(
148        is_active,
149        app.current_theme.inactive_text_style,
150        app.current_theme.general_style,
151    );
152    let highlight_style = check_if_active_and_get_style(
153        is_active,
154        app.current_theme.inactive_text_style,
155        app.current_theme.list_select_style,
156    );
157    let list_items = main_menu_items
158        .iter()
159        .map(|i| ListItem::new(i.to_string()))
160        .collect::<Vec<ListItem>>();
161    let main_menu = List::new(list_items)
162        .block(
163            Block::default()
164                .title("Main menu")
165                .style(default_style)
166                .borders(Borders::ALL)
167                .border_style(menu_style)
168                .border_type(BorderType::Rounded),
169        )
170        .highlight_style(highlight_style)
171        .highlight_symbol(LIST_SELECTED_SYMBOL);
172
173    rect.render_stateful_widget(
174        main_menu,
175        render_area,
176        &mut app.state.app_list_states.main_menu,
177    );
178}