use super::*;
pub struct PanelFilter {
pub dir: PathBuf,
pub text: String,
glob: crate::glob::Glob,
all: Vec<Item>,
}
impl PanelFilter {
fn keep(&self, items: &[Item]) -> Vec<Item> {
items.iter().filter(|item| item.is_parent() || self.glob.matches(&item.name_full, item.is_dir)).cloned().collect()
}
}
impl AppState {
pub fn filter(&self, is_left: bool) -> Option<&PanelFilter> {
if is_left { self.filter_left.as_ref() } else { self.filter_right.as_ref() }
}
fn filter_mut(&mut self, is_left: bool) -> &mut Option<PanelFilter> {
if is_left { &mut self.filter_left } else { &mut self.filter_right }
}
pub fn open_filter_prompt(&mut self) {
let text = self.filter(self.is_left_active).map(|filter| filter.text.clone()).unwrap_or_default();
let mut input = TextInput::new();
input.set(text.clone());
self.filter_before = text;
self.dialog = Some(Dialog::Prompt(PromptKind::Filter, input));
}
pub fn cancel_filter_prompt(&mut self) {
self.dialog = None;
let before = std::mem::take(&mut self.filter_before);
self.set_filter(self.is_left_active, &before);
}
pub fn set_filter(&mut self, is_left: bool, text: &str) {
let (dir, children, state) = if is_left {
(&self.dir_left, &self.children_left, &self.state_left)
} else {
(&self.dir_right, &self.children_right, &self.state_right)
};
let cursor = state.selected().and_then(|index| children.get(index)).map(|item| item.name_os.clone());
let dir = dir.clone();
let all = match self.filter_mut(is_left).take() {
Some(filter) => filter.all,
None => std::mem::take(if is_left { &mut self.children_left } else { &mut self.children_right }),
};
let items = match crate::glob::Glob::filter(text) {
Some(glob) => {
let filter = PanelFilter { dir, text: text.to_string(), glob, all };
let items = filter.keep(&filter.all);
*self.filter_mut(is_left) = Some(filter);
items
}
None => all,
};
let index = cursor.and_then(|name| items.iter().position(|item| item.name_os == name)).or_else(|| items.iter().position(|item| !item.is_parent())).unwrap_or(0);
let (children, state, selected) = if is_left {
(&mut self.children_left, &mut self.state_left, &mut self.selected_left)
} else {
(&mut self.children_right, &mut self.state_right, &mut self.selected_right)
};
*children = items;
state.select(Some(index));
prune_selection(selected, children);
self.search_clear();
self.preview = None;
self.cursor_detail = None;
}
pub(super) fn filter_listing(&mut self, is_left: bool, found: &Path, items: Vec<Item>) -> Vec<Item> {
let slot = self.filter_mut(is_left);
match slot {
Some(filter) if filter.dir == found => {
let kept = filter.keep(&items);
filter.all = items;
kept
}
_ => {
*slot = None;
items
}
}
}
pub fn filter_typed(&mut self) {
if let Some(Dialog::Prompt(PromptKind::Filter, input)) = &self.dialog {
let text = input.text.clone();
self.set_filter(self.is_left_active, &text);
}
}
}