rust_kanban/ui/rendering/view/
new_board_form.rs

1use crate::{
2    app::{
3        state::{AppStatus, Focus, KeyBindingEnum},
4        App,
5    },
6    ui::{
7        rendering::{
8            common::render_close_button,
9            utils::{
10                calculate_viewport_corrected_cursor_position, check_if_active_and_get_style,
11                get_mouse_focusable_field_style,
12            },
13            view::NewBoardForm,
14        },
15        Renderable,
16    },
17};
18use ratatui::{
19    layout::{Alignment, Constraint, Direction, Layout},
20    text::{Line, Span},
21    widgets::{Block, BorderType, Borders, Paragraph},
22    Frame,
23};
24
25impl Renderable for NewBoardForm {
26    fn render(rect: &mut Frame, app: &mut App, is_active: bool) {
27        let chunks = Layout::default()
28            .direction(Direction::Vertical)
29            .constraints(
30                [
31                    Constraint::Length(3),
32                    Constraint::Length(5),
33                    Constraint::Fill(1),
34                    Constraint::Length(4),
35                    Constraint::Length(3),
36                ]
37                .as_ref(),
38            )
39            .split(rect.area());
40
41        let general_style = check_if_active_and_get_style(
42            is_active,
43            app.current_theme.inactive_text_style,
44            app.current_theme.general_style,
45        );
46        let help_key_style = check_if_active_and_get_style(
47            is_active,
48            app.current_theme.inactive_text_style,
49            app.current_theme.help_key_style,
50        );
51        let help_text_style = check_if_active_and_get_style(
52            is_active,
53            app.current_theme.inactive_text_style,
54            app.current_theme.help_text_style,
55        );
56        let name_style =
57            get_mouse_focusable_field_style(app, Focus::NewBoardName, &chunks[1], is_active, false);
58        let description_style = get_mouse_focusable_field_style(
59            app,
60            Focus::NewBoardDescription,
61            &chunks[2],
62            is_active,
63            false,
64        );
65        let submit_style =
66            get_mouse_focusable_field_style(app, Focus::SubmitButton, &chunks[4], is_active, false);
67
68        let title_paragraph = Paragraph::new("Create a new Board")
69            .alignment(Alignment::Center)
70            .block(
71                Block::default()
72                    .borders(Borders::ALL)
73                    .border_type(BorderType::Rounded)
74                    .style(general_style),
75            );
76        rect.render_widget(title_paragraph, chunks[0]);
77
78        let board_name_block = Block::default()
79            .borders(Borders::ALL)
80            .style(name_style)
81            .border_type(BorderType::Rounded)
82            .title("Board Name (required)");
83        app.state
84            .text_buffers
85            .board_name
86            .set_block(board_name_block);
87        rect.render_widget(app.state.text_buffers.board_name.widget(), chunks[1]);
88
89        let board_description_block = Block::default()
90            .borders(Borders::ALL)
91            .style(description_style)
92            .border_type(BorderType::Rounded)
93            .title("Board Description");
94        app.state
95            .text_buffers
96            .board_description
97            .set_block(board_description_block);
98        if app.config.show_line_numbers {
99            app.state
100                .text_buffers
101                .board_description
102                .set_line_number_style(general_style)
103        } else {
104            app.state
105                .text_buffers
106                .board_description
107                .remove_line_number()
108        }
109        rect.render_widget(app.state.text_buffers.board_description.widget(), chunks[2]);
110
111        let input_mode_key = app
112            .get_first_keybinding(KeyBindingEnum::TakeUserInput)
113            .unwrap_or("".to_string());
114        let next_focus_key = app
115            .get_first_keybinding(KeyBindingEnum::NextFocus)
116            .unwrap_or("".to_string());
117        let prv_focus_key = app
118            .get_first_keybinding(KeyBindingEnum::PrvFocus)
119            .unwrap_or("".to_string());
120        let accept_key = app
121            .get_first_keybinding(KeyBindingEnum::Accept)
122            .unwrap_or("".to_string());
123        let cancel_key = app
124            .get_first_keybinding(KeyBindingEnum::GoToPreviousViewOrCancel)
125            .unwrap_or("".to_string());
126        let stop_user_input_key = app
127            .get_first_keybinding(KeyBindingEnum::StopUserInput)
128            .unwrap_or("".to_string());
129
130        let help_text = Line::from(vec![
131            Span::styled("Press ", help_text_style),
132            Span::styled(input_mode_key, help_key_style),
133            Span::styled(" or ", help_text_style),
134            Span::styled(accept_key.clone(), help_key_style),
135            Span::styled("to start typing. Press ", help_text_style),
136            Span::styled(stop_user_input_key, help_key_style),
137            Span::styled(" to stop typing. Press ", help_text_style),
138            Span::styled(next_focus_key, help_key_style),
139            Span::styled(" or ", help_text_style),
140            Span::styled(prv_focus_key, help_key_style),
141            Span::styled(" to switch focus. Press ", help_text_style),
142            Span::styled(accept_key, help_key_style),
143            Span::styled(" to submit. Press ", help_text_style),
144            Span::styled(cancel_key, help_key_style),
145            Span::styled(" to cancel", help_text_style),
146        ]);
147        let help_paragraph = Paragraph::new(help_text)
148            .alignment(Alignment::Center)
149            .block(
150                Block::default()
151                    .borders(Borders::ALL)
152                    .border_type(BorderType::Rounded)
153                    .border_style(general_style),
154            )
155            .wrap(ratatui::widgets::Wrap { trim: true });
156        rect.render_widget(help_paragraph, chunks[3]);
157
158        let submit_button = Paragraph::new("Submit").alignment(Alignment::Center).block(
159            Block::default()
160                .borders(Borders::ALL)
161                .style(submit_style)
162                .border_type(BorderType::Rounded),
163        );
164        rect.render_widget(submit_button, chunks[4]);
165
166        if app.state.app_status == AppStatus::UserInput {
167            match app.state.focus {
168                Focus::NewBoardName => {
169                    let (x_pos, y_pos) = calculate_viewport_corrected_cursor_position(
170                        &app.state.text_buffers.board_name,
171                        &app.config.show_line_numbers,
172                        &chunks[1],
173                    );
174                    rect.set_cursor_position((x_pos, y_pos));
175                }
176                Focus::NewBoardDescription => {
177                    let (x_pos, y_pos) = calculate_viewport_corrected_cursor_position(
178                        &app.state.text_buffers.board_description,
179                        &app.config.show_line_numbers,
180                        &chunks[2],
181                    );
182                    rect.set_cursor_position((x_pos, y_pos));
183                }
184                _ => {}
185            }
186        }
187
188        if app.config.enable_mouse_support {
189            render_close_button(rect, app, is_active);
190        }
191    }
192}