wip: refactor pt.9, 403 errors

This commit is contained in:
🪞👃🪞 2024-11-10 18:38:22 +01:00
parent a784f7a6f2
commit 8aa1ba8d0f
29 changed files with 1008 additions and 902 deletions

View file

@ -0,0 +1,176 @@
use crate::*;
/// Displays and edits phrase length.
pub struct PhraseLength<E: Engine> {
_engine: PhantomData<E>,
/// Pulses per beat (quaver)
pub ppq: usize,
/// Beats per bar
pub bpb: usize,
/// Length of phrase in pulses
pub pulses: usize,
/// Selected subdivision
pub focus: Option<PhraseLengthFocus>,
}
impl<E: Engine> PhraseLength<E> {
pub fn new (pulses: usize, focus: Option<PhraseLengthFocus>) -> Self {
Self { _engine: Default::default(), ppq: PPQ, bpb: 4, pulses, focus }
}
pub fn bars (&self) -> usize {
self.pulses / (self.bpb * self.ppq)
}
pub fn beats (&self) -> usize {
(self.pulses % (self.bpb * self.ppq)) / self.ppq
}
pub fn ticks (&self) -> usize {
self.pulses % self.ppq
}
pub fn bars_string (&self) -> String {
format!("{}", self.bars())
}
pub fn beats_string (&self) -> String {
format!("{}", self.beats())
}
pub fn ticks_string (&self) -> String {
format!("{:>02}", self.ticks())
}
}
impl Content for PhraseLength<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Layers::new(move|add|{
match self.focus {
None => add(&row!(
" ", self.bars_string(),
".", self.beats_string(),
".", self.ticks_string(),
" "
)),
Some(PhraseLengthFocus::Bar) => add(&row!(
"[", self.bars_string(),
"]", self.beats_string(),
".", self.ticks_string(),
" "
)),
Some(PhraseLengthFocus::Beat) => add(&row!(
" ", self.bars_string(),
"[", self.beats_string(),
"]", self.ticks_string(),
" "
)),
Some(PhraseLengthFocus::Tick) => add(&row!(
" ", self.bars_string(),
".", self.beats_string(),
"[", self.ticks_string(),
"]"
)),
}
})
}
}
/// Focused field of `PhraseLength`
#[derive(Copy, Clone)]
pub enum PhraseLengthFocus {
/// Editing the number of bars
Bar,
/// Editing the number of beats
Beat,
/// Editing the number of ticks
Tick,
}
impl PhraseLengthFocus {
pub fn next (&mut self) {
*self = match self {
Self::Bar => Self::Beat,
Self::Beat => Self::Tick,
Self::Tick => Self::Bar,
}
}
pub fn prev (&mut self) {
*self = match self {
Self::Bar => Self::Tick,
Self::Beat => Self::Bar,
Self::Tick => Self::Beat,
}
}
}
#[derive(Clone, PartialEq)]
pub enum PhraseLengthCommand {
Begin,
Next,
Prev,
Inc,
Dec,
Set(usize),
Confirm,
Cancel,
}
impl InputToCommand<Tui, PhrasePoolView<Tui>> for PhraseLengthCommand {
fn input_to_command (_: &PhrasePoolView<Tui>, from: &TuiInput) -> Option<Self> {
match from.event() {
key!(KeyCode::Up) => Some(Self::Inc),
key!(KeyCode::Down) => Some(Self::Dec),
key!(KeyCode::Right) => Some(Self::Next),
key!(KeyCode::Left) => Some(Self::Prev),
key!(KeyCode::Enter) => Some(Self::Confirm),
key!(KeyCode::Esc) => Some(Self::Cancel),
_ => None
}
}
}
impl<E: Engine> Command<PhrasePoolView<E>> for PhraseLengthCommand {
fn translate (self, state: &PhrasePoolView<E>) -> Self {
use PhraseLengthCommand::*;
if let Some(PhrasePoolMode::Length(_, length, _)) = state.mode {
match self {
Confirm => { return Self::Set(length) },
_ => self
}
} else if self == Begin {
todo!()
} else {
unreachable!()
}
}
fn execute (self, state: &mut PhrasePoolView<E>) -> Perhaps<Self> {
use PhraseLengthFocus::*;
use PhraseLengthCommand::*;
if let Some(PhrasePoolMode::Length(phrase, ref mut length, ref mut focus)) = state.mode {
match self {
Cancel => { state.mode = None; },
Prev => { focus.prev() },
Next => { focus.next() },
Inc => match focus {
Bar => { *length += 4 * PPQ },
Beat => { *length += PPQ },
Tick => { *length += 1 },
},
Dec => match focus {
Bar => { *length = length.saturating_sub(4 * PPQ) },
Beat => { *length = length.saturating_sub(PPQ) },
Tick => { *length = length.saturating_sub(1) },
},
Set(length) => {
let mut phrase = state.phrases[phrase].write().unwrap();
let old_length = phrase.length;
phrase.length = length;
state.mode = None;
return Ok(Some(Self::Set(old_length)))
},
_ => unreachable!()
}
Ok(None)
} else if self == Begin {
todo!()
} else {
unreachable!()
}
}
}