#![allow(dead_code)]
use std::{
collections::VecDeque,
fmt,
ops::{Index, IndexMut},
};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Direction {
Forward,
Backward,
}
impl Direction {
pub fn reverse(&self) -> Direction {
match self {
Direction::Forward => Direction::Backward,
Direction::Backward => Direction::Forward,
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum InsertPoint {
Index(usize),
Focused,
AfterFocused,
First,
Last,
}
#[derive(Clone, Copy)]
pub enum Selector<'a, T> {
Focused,
Index(usize),
Condition(&'a dyn Fn(&T) -> bool),
}
impl<'a, T> fmt::Debug for Selector<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Focused => f.debug_struct("Selector::Focused").finish(),
Self::Index(i) => f.debug_struct("Selector::Index").field("index", i).finish(),
Self::Condition(_func) => f
.debug_struct("Selector::Condition")
.field("condition", &stringify!(_func))
.finish(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Ring<T> {
elements: VecDeque<T>,
focused: usize,
}
impl<T> Ring<T> {
pub fn new(elements: Vec<T>) -> Ring<T> {
Ring {
elements: elements.into(),
focused: 0,
}
}
pub fn would_wrap(&self, dir: Direction) -> bool {
let wrap_back = self.focused == 0 && dir == Direction::Backward;
let wrap_forward = self.focused == self.elements.len() - 1 && dir == Direction::Forward;
wrap_back || wrap_forward
}
pub fn focused_index(&self) -> usize {
self.focused
}
pub fn focused(&self) -> Option<&T> {
self.elements.get(self.focused)
}
pub fn focused_mut(&mut self) -> Option<&mut T> {
self.elements.get_mut(self.focused)
}
pub fn rotate(&mut self, direction: Direction) {
if self.elements.is_empty() {
return;
}
match direction {
Direction::Forward => self.elements.rotate_right(1),
Direction::Backward => self.elements.rotate_left(1),
}
}
fn next_index(&self, direction: Direction) -> usize {
let max = self.elements.len() - 1;
match direction {
Direction::Forward => {
if self.focused == max {
0
} else {
self.focused + 1
}
}
Direction::Backward => {
if self.focused == 0 {
max
} else {
self.focused - 1
}
}
}
}
pub fn cycle_focus(&mut self, direction: Direction) -> Option<&T> {
self.focused = self.next_index(direction);
self.focused()
}
pub fn drag_focused(&mut self, direction: Direction) -> Option<&T> {
match (self.focused, self.next_index(direction), direction) {
(0, _, Direction::Backward) => self.rotate(direction),
(_, 0, Direction::Forward) => self.rotate(direction),
(focused, other, _) => self.elements.swap(focused, other),
}
self.cycle_focus(direction)
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn insert_at(&mut self, insert_point: &InsertPoint, element: T) {
match insert_point {
InsertPoint::Index(ix) => self.elements.insert(*ix, element),
InsertPoint::Focused => self.elements.insert(self.focused_index(), element),
InsertPoint::First => self.elements.push_front(element),
InsertPoint::Last => self.elements.push_back(element),
InsertPoint::AfterFocused => {
let ix = self.focused_index() + 1;
if ix > self.elements.len() {
self.elements.push_back(element)
} else {
self.elements.insert(ix, element)
}
}
}
}
pub fn insert(&mut self, index: usize, element: T) {
self.elements.insert(index, element);
}
pub fn push(&mut self, element: T) {
self.elements.push_back(element);
}
pub fn iter(&self) -> std::collections::vec_deque::Iter<'_, T> {
self.elements.iter()
}
pub fn iter_mut(&mut self) -> std::collections::vec_deque::IterMut<'_, T> {
self.elements.iter_mut()
}
pub fn get(&self, index: usize) -> Option<&T> {
self.elements.get(index)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.elements.get_mut(index)
}
fn clamp_focus(&mut self) {
if self.focused > 0 && self.focused >= self.elements.len() - 1 {
self.focused -= 1;
}
}
fn element_by(&self, cond: impl Fn(&T) -> bool) -> Option<(usize, &T)> {
self.elements.iter().enumerate().find(|(_, e)| cond(*e))
}
fn element_by_mut(&mut self, cond: impl Fn(&T) -> bool) -> Option<(usize, &mut T)> {
self.elements.iter_mut().enumerate().find(|(_, e)| cond(*e))
}
pub fn index(&self, s: &Selector<'_, T>) -> Option<usize> {
match s {
Selector::Focused => Some(self.focused_index()),
Selector::Index(i) => {
if *i < self.len() {
Some(*i)
} else {
None
}
}
Selector::Condition(f) => self.element_by(f).map(|(i, _)| i),
}
}
pub fn element(&self, s: &Selector<'_, T>) -> Option<&T> {
match s {
Selector::Focused => self.focused(),
Selector::Index(i) => self.elements.get(*i),
Selector::Condition(f) => self.element_by(f).map(|(_, e)| e),
}
}
pub fn element_mut(&mut self, s: &Selector<'_, T>) -> Option<&mut T> {
match s {
Selector::Focused => self.focused_mut(),
Selector::Index(i) => self.elements.get_mut(*i),
Selector::Condition(f) => self.element_by_mut(f).map(|(_, e)| e),
}
}
pub fn all_elements(&self, s: &Selector<'_, T>) -> Vec<&T> {
match s {
Selector::Focused => self.focused().into_iter().collect(),
Selector::Index(i) => self.elements.get(*i).into_iter().collect(),
Selector::Condition(f) => self.elements.iter().filter(|e| f(*e)).collect(),
}
}
pub fn all_elements_mut(&mut self, s: &Selector<'_, T>) -> Vec<&mut T> {
match s {
Selector::Focused => self.focused_mut().into_iter().collect(),
Selector::Index(i) => self.elements.get_mut(*i).into_iter().collect(),
Selector::Condition(f) => self.elements.iter_mut().filter(|e| f(*e)).collect(),
}
}
pub fn focus(&mut self, s: &Selector<'_, T>) -> Option<&T> {
match s {
Selector::Focused => self.focused(),
Selector::Index(i) => {
self.focused = *i;
self.focused()
}
Selector::Condition(f) => {
if let Some((i, _)) = self.element_by(f) {
self.focused = i;
Some(&self.elements[self.focused])
} else {
None
}
}
}
}
pub fn remove(&mut self, s: &Selector<'_, T>) -> Option<T> {
match s {
Selector::Focused => {
let c = self.elements.remove(self.focused);
self.clamp_focus();
c
}
Selector::Index(i) => {
let c = self.elements.remove(*i);
self.clamp_focus();
c
}
Selector::Condition(f) => {
if let Some((i, _)) = self.element_by(f) {
let c = self.elements.remove(i);
self.clamp_focus();
c
} else {
None
}
}
}
}
}
impl<T: PartialEq> Ring<T> {
pub fn equivalent_selectors(&self, s: &Selector<'_, T>, t: &Selector<'_, T>) -> bool {
match (self.element(&s), self.element(&t)) {
(Some(e), Some(f)) => e == f,
_ => false,
}
}
}
impl<T: Clone> Ring<T> {
#[allow(dead_code)]
pub fn as_vec(&self) -> Vec<T> {
self.iter().cloned().collect()
}
}
impl<T> Index<usize> for Ring<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.elements[index]
}
}
impl<T> IndexMut<usize> for Ring<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.elements[index]
}
}