diff --git a/src/ui.rs b/src/ui.rs index 60a9dac..468ea4e 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -44,99 +44,73 @@ pub fn ui(f: &mut Frame, app: &mut App) { // Popup for Adding Server if let InputMode::Adding(state) = &app.input_mode { - let block = Block::default().borders(Borders::ALL).title(" Add New Connection "); - let area = centered_rect(60, 40, size); - f.render_widget(Clear, area); // Clear the background - f.render_widget(block, area); - - let input_layout = Layout::default() - .direction(Direction::Vertical) - .margin(2) - .constraints( - [ - Constraint::Length(3), // Name - Constraint::Length(3), // User - Constraint::Length(3), // Host - Constraint::Length(3), // Port - Constraint::Min(1), - ] - .as_ref(), - ) - .split(area); - - let fields = [ - ("Name", &state.name), - ("User (default: root)", &state.user), - ("Host/IP", &state.host), - ("Port (default: 22)", &state.port), - ]; - - for (i, (label, value)) in fields.iter().enumerate() { - let mut style = Style::default(); - if state.field_idx == i { - style = style.fg(Color::Yellow); - } - let input = Paragraph::new(value.as_str()) - .style(style) - .block(Block::default().borders(Borders::ALL).title(*label)); - f.render_widget(input, input_layout[i]); - - // Show cursor in the active input field - if state.field_idx == i { - f.set_cursor( - input_layout[i].x + value.len() as u16 + 1, // Position after the text - input_layout[i].y + 1, // Middle of the input area - ); - } - } + render_connection_form( + f, + " Add New Connection ", + state.field_idx, + &[&state.name, &state.user, &state.host, &state.port], + ); } // Popup for Editing Server if let InputMode::Editing(state) = &app.input_mode { - let block = Block::default().borders(Borders::ALL).title(" Edit Connection "); - let area = centered_rect(60, 40, size); - f.render_widget(Clear, area); // Clear the background - f.render_widget(block, area); + render_connection_form( + f, + " Edit Connection ", + state.field_idx, + &[&state.name, &state.user, &state.host, &state.port], + ); + } +} - let input_layout = Layout::default() - .direction(Direction::Vertical) - .margin(2) - .constraints( - [ - Constraint::Length(3), // Name - Constraint::Length(3), // User - Constraint::Length(3), // Host - Constraint::Length(3), // Port - Constraint::Min(1), - ] - .as_ref(), - ) - .split(area); +fn render_connection_form(f: &mut Frame, title: &str, field_idx: usize, values: &[&String]) { + let size = f.size(); + // Use fixed height of 19 lines (enough for 4 fields * 3 lines + margins/borders) + let area = centered_fixed_rect(60, 19, size); + + let block = Block::default().borders(Borders::ALL).title(title); + f.render_widget(Clear, area); // Clear the background + f.render_widget(block, area); + + let input_layout = Layout::default() + .direction(Direction::Vertical) + .margin(2) + .constraints( + [ + Constraint::Length(3), // Name + Constraint::Length(3), // User + Constraint::Length(3), // Host + Constraint::Length(3), // Port + Constraint::Min(1), + ] + .as_ref(), + ) + .split(area); + + let fields_labels = [ + "Name", + "User (default: root)", + "Host/IP", + "Port (default: 22)", + ]; + + for (i, label) in fields_labels.iter().enumerate() { + let value = values[i]; + let mut style = Style::default(); + if field_idx == i { + style = style.fg(Color::Yellow); + } + let input = Paragraph::new(value.as_str()) + .style(style) + .block(Block::default().borders(Borders::ALL).title(*label)); + f.render_widget(input, input_layout[i]); - let fields = [ - ("Name", &state.name), - ("User (default: root)", &state.user), - ("Host/IP", &state.host), - ("Port (default: 22)", &state.port), - ]; - - for (i, (label, value)) in fields.iter().enumerate() { - let mut style = Style::default(); - if state.field_idx == i { - style = style.fg(Color::Yellow); - } - let input = Paragraph::new(value.as_str()) - .style(style) - .block(Block::default().borders(Borders::ALL).title(*label)); - f.render_widget(input, input_layout[i]); - - // Show cursor in the active input field - if state.field_idx == i { - f.set_cursor( - input_layout[i].x + value.len() as u16 + 1, // Position after the text - input_layout[i].y + 1, // Middle of the input area - ); - } + // Show cursor in the active input field + if field_idx == i { + f.set_cursor( + input_layout[i].x + value.len() as u16 + 1, // Position after the text + input_layout[i].y + 1, // Middle of the input area + ); } } } @@ -166,3 +140,29 @@ pub fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect { ) .split(popup_layout[1])[1] } + +fn centered_fixed_rect(width_percent: u16, height: u16, r: Rect) -> Rect { + let popup_layout = Layout::default() + .direction(Direction::Vertical) + .constraints( + [ + Constraint::Fill(1), + Constraint::Length(height), + Constraint::Fill(1), + ] + .as_ref(), + ) + .split(r); + + Layout::default() + .direction(Direction::Horizontal) + .constraints( + [ + Constraint::Fill(1), + Constraint::Percentage(width_percent), + Constraint::Fill(1), + ] + .as_ref(), + ) + .split(popup_layout[1])[1] +} \ No newline at end of file