diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index c8ac670b..2fc6223c 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -342,7 +342,7 @@ impl PhraseLength { self.pulses / (self.bpb * self.ppq) } pub fn beats (&self) -> usize { - self.pulses % (self.bpb * self.ppq) + (self.pulses % (self.bpb * self.ppq)) / self.ppq } pub fn ticks (&self) -> usize { self.pulses % self.ppq @@ -359,3 +359,19 @@ impl PhraseLength { } #[derive(Copy,Clone)] pub enum PhraseLengthFocus { Bar, Beat, 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, + } + } +} diff --git a/crates/tek_sequencer/src/sequencer_cmd.rs b/crates/tek_sequencer/src/sequencer_cmd.rs index e8a19b4d..dfcd45d4 100644 --- a/crates/tek_sequencer/src/sequencer_cmd.rs +++ b/crates/tek_sequencer/src/sequencer_cmd.rs @@ -40,19 +40,39 @@ impl Handle for PhrasePool { key!(Shift-KeyCode::Char(c)) => { phrase.name.push(*c); }, key!(KeyCode::Esc) => { phrase.name = old_name.clone(); self.mode = None; }, key!(KeyCode::Enter) => { self.mode = None; }, - _ => return Ok(None) + _ => return Ok(Some(true)) } }, - Some(PhrasePoolMode::Length(phrase, length, focus)) => { - todo!("edit phrase length"); + Some(PhrasePoolMode::Length(phrase, ref mut length, ref mut focus)) => { let mut phrase = self.phrases[phrase].write().unwrap(); match from.event() { - key!(KeyCode::Backspace) => { phrase.name.pop(); }, - key!(KeyCode::Char(c)) => { phrase.name.push(*c); }, - key!(Shift-KeyCode::Char(c)) => { phrase.name.push(*c); }, - //key!(KeyCode::Esc) => { phrase.name = old_name.clone(); self.mode = None; }, + key!(KeyCode::Left) => { focus.prev() }, + key!(KeyCode::Right) => { focus.next() }, + key!(KeyCode::Esc) => { self.mode = None; }, key!(KeyCode::Enter) => { self.mode = None; }, - _ => return Ok(None) + key!(KeyCode::Up) => match focus { + PhraseLengthFocus::Bar => { + *length += 4 * PPQ + }, + PhraseLengthFocus::Beat => { + *length += PPQ + }, + PhraseLengthFocus::Tick => { + *length += 1 + }, + }, + key!(KeyCode::Down) => match focus { + PhraseLengthFocus::Bar => { + *length = length.saturating_sub(4 * PPQ) + }, + PhraseLengthFocus::Beat => { + *length = length.saturating_sub(PPQ) + }, + PhraseLengthFocus::Tick => { + *length = length.saturating_sub(1) + }, + }, + _ => return Ok(Some(true)) } }, None => match from.event() { diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index 23b2b7bf..b788c0f8 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -16,17 +16,21 @@ impl Content for PhrasePool { fn content (&self) -> impl Widget { let content = col!( (i, phrase) in self.phrases.iter().enumerate() => Layers::new(|add|{ + let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); - let ticks = length % PPQ; - let beats = length % (4 * PPQ); - let bars = length / (4 * PPQ); + let row1 = lay!(format!(" {i}").align_w().fill_x(), if let Some(PhrasePoolMode::Length(phrase, length, focus)) = self.mode { - PhraseLength::new(length, Some(focus)) + if self.focused && i == phrase { + PhraseLength::new(length, Some(focus)) + } else { + PhraseLength::new(length, None) + } } else { PhraseLength::new(length, None) }.align_e().fill_x() ).fill_x(); + let row2 = if let Some(PhrasePoolMode::Rename(phrase, _)) = self.mode { if self.focused && i == phrase { format!(" {}▄", name) @@ -36,12 +40,15 @@ impl Content for PhrasePool { } else { format!(" {}", name) }; + add(&col!(row1, row2).fill_x().bg(if i == self.phrase { color //Color::Rgb(40, 50, 30) } else { color //Color::Rgb(28, 35, 25) }))?; + if self.focused && i == self.phrase { add(&CORNERS)?; } + Ok(()) }) )