124 lines
3.4 KiB
Rust
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(),
|
|
}
|
|
}
|
|
}
|