use phosphor_core::transport::Transport;
const TICKS_PER_BAR: i64 = Transport::PPQ * 4;
#[derive(Debug)]
pub struct LoopEditor {
pub active: bool,
pub enabled: bool,
pub start_bar: u32,
pub end_bar: u32,
}
impl Default for LoopEditor {
fn default() -> Self { Self::new() }
}
impl LoopEditor {
pub fn new() -> Self {
Self {
active: false,
enabled: false,
start_bar: 1,
end_bar: 5,
}
}
pub fn focus(&mut self) {
self.active = true;
}
pub fn unfocus(&mut self) {
self.active = false;
}
pub fn toggle_enabled(&mut self) {
self.enabled = !self.enabled;
}
pub fn move_start_left(&mut self) {
if self.start_bar > 1 {
self.start_bar -= 1;
}
}
pub fn move_start_right(&mut self) {
if self.start_bar + 1 < self.end_bar {
self.start_bar += 1;
}
}
pub fn move_end_left(&mut self) {
if self.end_bar > self.start_bar + 1 {
self.end_bar -= 1;
}
}
pub fn move_end_right(&mut self) {
self.end_bar += 1;
}
pub fn start_ticks(&self) -> i64 {
(self.start_bar as i64 - 1) * TICKS_PER_BAR
}
pub fn end_ticks(&self) -> i64 {
(self.end_bar as i64 - 1) * TICKS_PER_BAR
}
pub fn bar_count(&self) -> u32 {
self.end_bar - self.start_bar
}
pub fn display(&self) -> String {
format!("{}-{}", self.start_bar, self.end_bar - 1)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_4_bars() {
let le = LoopEditor::new();
assert_eq!(le.start_bar, 1);
assert_eq!(le.end_bar, 5);
assert_eq!(le.bar_count(), 4);
assert_eq!(le.display(), "1-4");
}
#[test]
fn start_cant_go_below_1() {
let mut le = LoopEditor::new();
le.move_start_left();
le.move_start_left();
le.move_start_left();
assert_eq!(le.start_bar, 1);
}
#[test]
fn start_cant_pass_end() {
let mut le = LoopEditor::new();
for _ in 0..10 {
le.move_start_right();
}
assert_eq!(le.start_bar, 4);
assert!(le.start_bar < le.end_bar);
}
#[test]
fn end_cant_pass_start() {
let mut le = LoopEditor::new();
for _ in 0..10 {
le.move_end_left();
}
assert_eq!(le.end_bar, 2);
assert!(le.end_bar > le.start_bar);
}
#[test]
fn end_can_grow() {
let mut le = LoopEditor::new();
le.move_end_right();
le.move_end_right();
assert_eq!(le.end_bar, 7);
assert_eq!(le.display(), "1-6");
}
#[test]
fn ticks_correct() {
let le = LoopEditor::new();
assert_eq!(le.start_ticks(), 0);
assert_eq!(le.end_ticks(), 4 * TICKS_PER_BAR); }
#[test]
fn ticks_for_two_bars() {
let mut le = LoopEditor::new();
le.end_bar = 3;
assert_eq!(le.display(), "1-2");
assert_eq!(le.start_ticks(), 0);
assert_eq!(le.end_ticks(), 2 * TICKS_PER_BAR); }
#[test]
fn focus_unfocus() {
let mut le = LoopEditor::new();
assert!(!le.active);
le.focus();
assert!(le.active);
le.unfocus();
assert!(!le.active);
}
#[test]
fn enabled_toggle() {
let mut le = LoopEditor::new();
assert!(!le.enabled);
le.toggle_enabled();
assert!(le.enabled);
le.toggle_enabled();
assert!(!le.enabled);
}
#[test]
fn focus_does_not_enable() {
let mut le = LoopEditor::new();
le.focus();
assert!(le.active);
assert!(!le.enabled);
}
}