Files
Cagire/src/state/patterns_nav.rs

124 lines
3.4 KiB
Rust

use std::ops::RangeInclusive;
use crate::model::{MAX_BANKS, MAX_PATTERNS};
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum PatternsColumn {
#[default]
Banks,
Patterns,
}
#[derive(Clone, Copy, Default)]
pub struct PatternsNav {
pub column: PatternsColumn,
pub bank_cursor: usize,
pub pattern_cursor: usize,
pub bank_anchor: Option<usize>,
pub pattern_anchor: Option<usize>,
}
impl PatternsNav {
pub fn move_left(&mut self) {
self.clear_selection();
self.column = PatternsColumn::Banks;
}
pub fn move_right(&mut self) {
self.clear_selection();
self.column = PatternsColumn::Patterns;
}
pub fn move_up(&mut self) {
match self.column {
PatternsColumn::Banks => {
self.bank_cursor = (self.bank_cursor + MAX_BANKS - 1) % MAX_BANKS;
}
PatternsColumn::Patterns => {
self.pattern_cursor = (self.pattern_cursor + MAX_PATTERNS - 1) % MAX_PATTERNS;
}
}
}
pub fn move_down(&mut self) {
match self.column {
PatternsColumn::Banks => {
self.bank_cursor = (self.bank_cursor + 1) % MAX_BANKS;
}
PatternsColumn::Patterns => {
self.pattern_cursor = (self.pattern_cursor + 1) % MAX_PATTERNS;
}
}
}
pub fn move_up_clamped(&mut self) {
match self.column {
PatternsColumn::Banks => {
self.bank_cursor = self.bank_cursor.saturating_sub(1);
}
PatternsColumn::Patterns => {
self.pattern_cursor = self.pattern_cursor.saturating_sub(1);
}
}
}
pub fn move_down_clamped(&mut self) {
match self.column {
PatternsColumn::Banks => {
self.bank_cursor = (self.bank_cursor + 1).min(MAX_BANKS - 1);
}
PatternsColumn::Patterns => {
self.pattern_cursor = (self.pattern_cursor + 1).min(MAX_PATTERNS - 1);
}
}
}
pub fn selected_bank(&self) -> usize {
self.bank_cursor
}
pub fn selected_pattern(&self) -> usize {
self.pattern_cursor
}
pub fn bank_selection_range(&self) -> Option<RangeInclusive<usize>> {
let anchor = self.bank_anchor?;
let a = anchor.min(self.bank_cursor);
let b = anchor.max(self.bank_cursor);
Some(a..=b)
}
pub fn pattern_selection_range(&self) -> Option<RangeInclusive<usize>> {
let anchor = self.pattern_anchor?;
let a = anchor.min(self.pattern_cursor);
let b = anchor.max(self.pattern_cursor);
Some(a..=b)
}
pub fn selected_banks(&self) -> Vec<usize> {
match self.bank_selection_range() {
Some(range) => range.collect(),
None => vec![self.bank_cursor],
}
}
pub fn selected_patterns(&self) -> Vec<usize> {
match self.pattern_selection_range() {
Some(range) => range.collect(),
None => vec![self.pattern_cursor],
}
}
pub fn clear_selection(&mut self) {
self.bank_anchor = None;
self.pattern_anchor = None;
}
pub fn has_selection(&self) -> bool {
match self.column {
PatternsColumn::Banks => self.bank_anchor.is_some(),
PatternsColumn::Patterns => self.pattern_anchor.is_some(),
}
}
}