use std::{
fmt::{Debug, Display},
path::Path,
slice::{Iter, IterMut},
};
use eframe::egui;
pub trait DocumentTrait {
fn name(&self) -> impl Display {
let filename = self
.path()
.file_name()
.unwrap_or_else(|| self.path().as_os_str());
filename.display()
}
fn path(&self) -> &Path;
}
#[derive(serde::Deserialize, serde::Serialize, Debug, Default)]
pub struct Documents<D> {
pub(crate) current_idx: usize,
inner: Vec<D>,
}
impl<D> Documents<D> {
#[must_use]
pub fn get_current_index(&self) -> usize {
self.current_idx
}
#[must_use]
pub fn get(&self, index: usize) -> Option<&D> {
self.inner.get(index)
}
#[must_use]
pub fn get_mut(&mut self, index: usize) -> Option<&mut D> {
self.inner.get_mut(index)
}
pub fn set_current_index(&mut self, idx: usize) -> Result<(), String> {
if idx >= self.inner.len() {
return Err("Not enough documents".to_string());
}
Ok(())
}
#[must_use]
pub fn get_current_doc(&self) -> Option<&D> {
if self.inner.is_empty() {
return None;
}
let idx = self.current_idx % self.inner.len();
Some(&self.inner[idx])
}
pub fn get_current_doc_mut(&mut self) -> Option<&mut D> {
if self.inner.is_empty() {
return None;
}
let idx = self.current_idx % self.inner.len();
Some(&mut self.inner[idx])
}
pub fn push(&mut self, document: D) {
self.inner.push(document);
self.current_idx = self.inner.len() - 1;
}
pub fn iter_mut(&mut self) -> IterMut<'_, D> {
self.inner.iter_mut()
}
pub fn iter(&self) -> Iter<'_, D> {
self.inner.iter()
}
pub fn remove(&mut self, index: usize) {
self.inner.remove(index);
self.current_idx = self.current_idx.saturating_sub(1);
}
#[must_use]
pub fn is_some(&self) -> bool {
!self.inner.is_empty()
}
pub fn clear(&mut self) {
self.current_idx = 0;
self.inner.clear();
}
}
impl<'a, D> IntoIterator for &'a Documents<D> {
type Item = &'a D;
type IntoIter = std::slice::Iter<'a, D>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, D> IntoIterator for &'a mut Documents<D> {
type Item = &'a mut D;
type IntoIter = std::slice::IterMut<'a, D>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<D> Documents<D>
where
D: DocumentTrait + Debug + Default,
{
pub fn show_file_list(&mut self, ui: &mut egui::Ui) {
let mut current_idx = self.current_idx;
let mut to_remove = None;
for (idx, one_doc) in self.inner.iter().enumerate() {
ui.horizontal(|ui| {
ui.selectable_value(&mut current_idx, idx, format!("{}", one_doc.name()));
if ui.button("x").clicked() {
to_remove = Some(idx);
}
});
ui.separator();
}
self.current_idx = current_idx;
if let Some(index) = to_remove {
self.remove(index);
}
}
}