perch/src/model/column.rs

120 lines
3.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::*;
use crate::ratatui::style::Style;
pub struct Column<G, S, U> {
pub title: Arc<str>,
pub width: usize,
pub collapsed: bool,
pub getter: G,
pub setter: Option<S>,
pub styler: Option<U>,
}
type Getter<T> = fn(&T)->Option<Arc<str>>;
type Setter<T> = fn(&mut T, usize, &str);
type Styler<T> = fn(&T)->Option<Style>;
impl<G, S, U> Column<Getter<G>, Setter<S>, Styler<U>> {
pub fn new (
title: &impl AsRef<str>,
width: usize,
getter: Getter<G>,
) -> Self {
Self {
width,
title: title.as_ref().into(),
getter,
setter: None,
styler: None,
collapsed: false,
}
}
fn setter (mut self, setter: Setter<S>) -> Self {
self.setter = Some(setter);
self
}
fn styler (mut self, styler: Styler<U>) -> Self {
self.styler = Some(styler);
self
}
}
pub(crate) fn entries_under (
entries: &mut [Entry],
index: usize
) -> Option<Vec<(Arc<PathBuf>, Arc<RwLock<Metadata>>)>> {
let path = if let Some(Entry { path, info, .. }) = entries.get(index)
&& let Metadata::Directory { .. } = &*info.read().unwrap()
{
Some(path.clone())
} else {
None
};
if let Some(path) = path {
let mut others = vec![];
for other in entries.iter_mut() {
if other.path.starts_with(path.as_ref()) && !other.is_directory() {
others.push((other.path.clone(), other.info.clone()));
}
}
Some(others)
} else {
None
}
}
pub struct Columns<G, S, U>(pub Vec<Column<G, S, U>>);
macro_rules! setter {
($set:ident) => {{
fn $set (state: &mut Taggart, index: usize, value: &str) {
if let Some(entries) = entries_under(&mut state.entries, index) {
for (_path, entry) in entries.into_iter() {
if entry.write().unwrap().$set(&value) {
state.count_changes();
//state.tasks.retain(|t|{(t.path != p) || (t.item.key() != item.key())});
//state.tasks.push(Task { path: p, item, });
};
}
} else if let Some(entry) = state.entries.get_mut(index) {
//let p = entry.path.clone();
if entry.$set(&value) {
state.count_changes();
//state.tasks.retain(|t|{(t.path != p) || (t.item.key() != item.key())});
//state.tasks.push(Task { path: p, item, });
};
}
}
$set
}}
}
impl Default for Columns<
fn(&Entry)->Option<Arc<str>>,
fn(&mut Taggart, usize, &str),
fn(&Entry)->Option<Style>,
> {
fn default () -> Self {
Self(vec![
// Computed file hash
Column::new(&"Hash", 8, |entry: &Entry|entry.hash()),
// File size
Column::new(&"Size", 8, |entry: &Entry|entry.size()),
// Selected?
Column::new(&"", 1, |entry: &Entry|Some(" ".into())),
// File name
Column::new(&"File", 40, |entry: &Entry|entry.name()),
// Modified tags?
Column::new(&"~", 1, |entry: &Entry|if entry.is_modified() {
Some("~".into())
} else {
None
}),
Column::new(&"Artist", 15, |entry: &Entry|entry.artist()).setter(setter!(set_artist)),
Column::new(&"Year", 4, |entry: &Entry|entry.year()).setter(setter!(set_year)),
Column::new(&"Release", 15, |entry: &Entry|entry.album()).setter(setter!(set_album)),
Column::new(&"Track", 5, |entry: &Entry|entry.track()).setter(setter!(set_track)),
Column::new(&"Title", 40, |entry: &Entry|entry.title()).setter(setter!(set_title)),
])
}
}