rust_kanban/ui/rendering/view/
new_board_form.rs1use 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}