use ratatui::{
Frame,
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
};
use super::save_dialog::{SaveDialog, SaveDialogFocus};
pub fn draw_save_dialog(f: &mut Frame, area: Rect, dialog: &SaveDialog) {
let modal_width = 60.min(area.width - 4);
let modal_height = 20.min(area.height - 4);
let modal_area = Rect {
x: (area.width - modal_width) / 2,
y: (area.height - modal_height) / 2,
width: modal_width,
height: modal_height,
};
f.render_widget(Clear, modal_area);
let block = Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(Color::White))
.title(if dialog.has_selection {
" Save Selection As "
} else {
" Save As "
})
.title_style(
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
);
f.render_widget(block, modal_area);
let inner_area = modal_area.inner(ratatui::layout::Margin {
horizontal: 1,
vertical: 1,
});
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(2), Constraint::Min(5), Constraint::Length(3), Constraint::Length(2), ])
.split(inner_area);
let path_display = format!("📁 {}", dialog.current_path.display());
let path_widget = Paragraph::new(path_display)
.style(Style::default().fg(Color::Blue))
.block(Block::default().borders(Borders::BOTTOM));
f.render_widget(path_widget, chunks[0]);
let dirs: Vec<ListItem> = dialog
.directories
.iter()
.map(|dir| {
let prefix = if dir == ".." { "↑ " } else { "📁 " };
ListItem::new(format!("{prefix}{dir}"))
})
.collect();
let dirs_list = List::new(dirs)
.block(Block::default().borders(Borders::NONE))
.highlight_style(if dialog.focus == SaveDialogFocus::DirectoryList {
Style::default()
.bg(Color::DarkGray)
.fg(Color::White)
.add_modifier(Modifier::BOLD)
} else {
Style::default().bg(Color::Gray).fg(Color::Black)
});
let mut list_state = dialog.list_state;
f.render_stateful_widget(dirs_list, chunks[1], &mut list_state);
let filename_block = Block::default()
.borders(Borders::ALL)
.border_style(if dialog.focus == SaveDialogFocus::FilenameField {
Style::default().fg(Color::Cyan)
} else {
Style::default().fg(Color::DarkGray)
})
.title(" Filename ");
let filename_widget = Paragraph::new(dialog.filename.as_str())
.style(Style::default().fg(Color::White))
.block(filename_block);
f.render_widget(filename_widget, chunks[2]);
if dialog.focus == SaveDialogFocus::FilenameField {
let cursor_x = chunks[2].x + 1 + dialog.filename.len() as u16;
let cursor_y = chunks[2].y + 1;
if cursor_x < chunks[2].x + chunks[2].width - 1 {
f.set_cursor_position((cursor_x, cursor_y));
}
}
let controls = vec![
Span::styled("[Tab]", Style::default().fg(Color::Yellow)),
Span::raw(" switch "),
Span::styled("[Enter]", Style::default().fg(Color::Green)),
Span::raw(" save "),
Span::styled("[Esc]", Style::default().fg(Color::Red)),
Span::raw(" cancel"),
];
let controls_widget = Paragraph::new(Line::from(controls)).alignment(Alignment::Center);
f.render_widget(controls_widget, chunks[3]);
}