use super::types::TreeNode;
use super::Tree;
use crate::utils::{fuzzy_match, FuzzyMatch};
impl Tree {
pub fn query(&self) -> &str {
&self.query
}
pub fn set_query(&mut self, query: impl Into<String>) {
self.query = query.into();
self.update_matches();
}
pub fn clear_query(&mut self) {
self.query.clear();
self.matches.clear();
self.current_match = 0;
}
pub fn is_searchable(&self) -> bool {
self.searchable
}
pub fn match_count(&self) -> usize {
self.matches.len()
}
pub fn current_match_index(&self) -> usize {
if self.matches.is_empty() {
0
} else {
self.current_match + 1
}
}
pub fn update_matches(&mut self) {
self.matches.clear();
self.current_match = 0;
if self.query.is_empty() {
return;
}
fn find_matches(
nodes: &[TreeNode],
query: &str,
visible_index: &mut usize,
matches: &mut Vec<usize>,
) {
for node in nodes {
if fuzzy_match(query, &node.label).is_some() {
matches.push(*visible_index);
}
*visible_index += 1;
if node.expanded && !node.children.is_empty() {
find_matches(&node.children, query, visible_index, matches);
}
}
}
let mut visible_index = 0;
find_matches(
&self.root,
&self.query,
&mut visible_index,
&mut self.matches,
);
if let Some(&first) = self.matches.first() {
self.selection.set(first);
}
}
pub fn next_match(&mut self) -> bool {
if self.matches.is_empty() {
return false;
}
self.current_match = (self.current_match + 1) % self.matches.len();
self.selection.set(self.matches[self.current_match]);
true
}
pub fn prev_match(&mut self) -> bool {
if self.matches.is_empty() {
return false;
}
self.current_match = self
.current_match
.checked_sub(1)
.unwrap_or(self.matches.len() - 1);
self.selection.set(self.matches[self.current_match]);
true
}
pub fn get_match(&self, label: &str) -> Option<FuzzyMatch> {
if self.query.is_empty() {
None
} else {
fuzzy_match(&self.query, label)
}
}
pub fn is_match(&self, visible_index: usize) -> bool {
self.matches.contains(&visible_index)
}
}