use std::{
cmp::min,
path::{Path, PathBuf},
};
use ratatui::{
layout::Rect,
style::Color,
text::Line,
widgets::{Paragraph, Widget},
Frame,
};
use crate::config::{ColorG, Gradient, MENU_STYLES};
use crate::io::Offseted;
use crate::log_info;
use crate::modes::ContentWindow;
use crate::{colored_skip_take, impl_content, impl_selectable};
pub struct TempMarks {
content: Vec<Option<PathBuf>>,
pub index: usize,
}
impl Default for TempMarks {
fn default() -> Self {
let content = vec![None; Self::NB_TEMP_MARKS];
let index = 0;
Self { content, index }
}
}
impl TempMarks {
const NB_TEMP_MARKS: usize = 10;
fn log_index_error(index: usize) {
log_info!(
"index {index} is too big for a temp mark. Should be between 0 and {NB_TEMP_MARKS} excluded",
NB_TEMP_MARKS=Self::NB_TEMP_MARKS
);
}
pub fn set_mark(&mut self, index: usize, path: PathBuf) {
self.remove_path(&path);
if index >= Self::NB_TEMP_MARKS {
Self::log_index_error(index);
return;
}
self.content[index] = Some(path);
}
pub fn erase_current_mark(&mut self) {
self.content[self.index] = None;
}
pub fn get_mark(&self, index: usize) -> &Option<PathBuf> {
if index >= Self::NB_TEMP_MARKS {
Self::log_index_error(index);
return &None;
}
&self.content[index]
}
pub fn draw_menu(&self, f: &mut Frame, rect: &Rect, window: &ContentWindow) {
let mut p_rect = rect.offseted(2, 3);
p_rect.height = p_rect.height.saturating_sub(2);
let content = self.content();
let lines: Vec<_> = colored_skip_take!(content, window)
.filter(|(index, _, _)| {
(*index) as u16 + ContentWindow::WINDOW_MARGIN_TOP_U16 + 1 - window.top as u16 + 2
<= rect.height
})
.map(|(index, opt_path, style)| {
let content = if let Some(path) = opt_path {
format!("{index} {p}", p = path.display())
} else {
format!("{index} ")
};
Line::styled(content, self.style(index, &style))
})
.collect();
Paragraph::new(lines).render(p_rect, f.buffer_mut());
}
pub fn digit_for(&self, path: &Path) -> Option<usize> {
for (index, marked_path) in self.content.iter().enumerate() {
match marked_path {
Some(p) if p == path => return Some(index),
_ => (),
}
}
None
}
pub fn move_path(&mut self, old_path: &Path, new_path: &Path) {
let Some(index) = self.digit_for(old_path) else {
return;
};
self.set_mark(index, new_path.to_path_buf());
}
pub fn remove_path(&mut self, old_path: &Path) {
for index in 0..Self::NB_TEMP_MARKS {
match &self.content[index] {
Some(path) if path == old_path => self.content[index] = None,
_ => (),
}
}
}
}
type Opb = Option<PathBuf>;
impl_content!(TempMarks, Opb);