use crate::selection_state::ItemCollection;
use super::Item;
#[derive(Debug, Clone)]
pub struct HistoricalSelection {
pub index: usize,
pub selection: ItemCollection,
}
impl From<(usize, ItemCollection)> for HistoricalSelection {
fn from((index, selection): (usize, ItemCollection)) -> Self {
Self { index, selection }
}
}
const MAX_SELECTION_HISTORY_LENGTH: usize = 100;
#[derive(Clone, Default, Debug)]
pub struct SelectionHistory {
pub current: usize,
pub stack: Vec<ItemCollection>,
}
impl SelectionHistory {
pub fn retain(&mut self, f: &impl Fn(&Item) -> bool) {
re_tracing::profile_function!();
let mut i = 0;
self.stack.retain_mut(|selection| {
selection.retain(|item, _| f(item));
let retain = !selection.is_empty();
if !retain && i <= self.current {
self.current = self.current.saturating_sub(1);
}
i += 1;
retain
});
self.current = self.current.min(self.stack.len().saturating_sub(1));
}
pub fn current(&self) -> Option<HistoricalSelection> {
self.stack
.get(self.current)
.cloned()
.map(|s| (self.current, s).into())
}
pub fn previous(&self) -> Option<HistoricalSelection> {
let prev_index = self.current.checked_sub(1)?;
let prev = self.stack.get(prev_index)?;
Some((prev_index, prev.clone()).into())
}
pub fn next(&self) -> Option<HistoricalSelection> {
self.stack
.get(self.current + 1)
.map(|sel| (self.current + 1, sel.clone()).into())
}
#[must_use]
pub fn select_previous(&mut self) -> Option<ItemCollection> {
if let Some(previous) = self.previous() {
if previous.index != self.current {
self.current = previous.index;
return self.current().map(|s| s.selection);
}
}
None
}
#[must_use]
pub fn select_next(&mut self) -> Option<ItemCollection> {
if let Some(next) = self.next() {
if next.index != self.current {
self.current = next.index;
return self.current().map(|s| s.selection);
}
}
None
}
pub fn update_selection(&mut self, selection: &ItemCollection) {
if selection.is_empty() {
return;
}
if self.current().as_ref().map(|c| &c.selection) == Some(selection) {
return;
}
self.stack.truncate(self.current + 1);
self.stack.push(selection.clone());
if self.stack.len() > MAX_SELECTION_HISTORY_LENGTH {
self.stack
.drain((self.stack.len() - MAX_SELECTION_HISTORY_LENGTH)..self.stack.len());
}
self.current = self.stack.len() - 1;
}
}