diff --git a/src/groovebox.rs b/src/groovebox.rs index 97ed72fd..9b5c5d9c 100644 --- a/src/groovebox.rs +++ b/src/groovebox.rs @@ -87,53 +87,63 @@ audio!(|self: Groovebox, client, scope|{ self.perf.update(t0, scope); Control::Continue }); -render!(Tui: (self: Groovebox) => { - let w = self.size.w(); - let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 }; - let pool_w = if !self.compact { phrase_w } else { 5 }; - let sampler_w = if !self.compact { 11 } else { 4 }; - let sample_h = if !self.compact { 5 } else { 0 }; - let note_pt = self.editor.note_point(); - let color = self.player.play_phrase().as_ref() - .and_then(|(_,p)|p.as_ref().map(|p|p.read().unwrap().color)) - .clone(); - let sampler = Fixed::x(sampler_w, Push::y(if self.compact { 1 } else { 0 }, - Align::w(Fill::y(SampleList::new(self.compact, &self.sampler, &self.editor))))); - let selectors = - Bsp::e(ClipSelected::play_phrase(&self.player), ClipSelected::next_phrase(&self.player)); - let edit_clip = - MidiEditClip(&self.editor); - self.size.of(Bsp::s( +render!(Tui: (self: Groovebox) => self.size.of(Bsp::s( + self.toolbar_view(), + Bsp::s( + self.selector_view(), + Bsp::n(self.sample_view(), + Bsp::n(self.status_view(), + Bsp::w( + self.pool_view(), + Fill::xy(Bsp::e( + self.sampler_view(), + &self.editor + ))))))))); + +impl Groovebox { + fn toolbar_view (&self) -> impl Content + use<'_> { Fill::x(Fixed::y(2, lay!( Align::w(Meter("L/", self.sampler.input_meter[0])), Align::e(Meter("R/", self.sampler.input_meter[1])), Align::x(Tui::bg(TuiTheme::g(32), TransportView::new(true, &self.player.clock))), - ))), - Bsp::s( - lay!(Align::w(edit_clip), Align::e(selectors)), - Bsp::n( - Max::y(sample_h, Fill::xy(if let Some((_, sample)) = &self.sampler.recording { - SampleViewer(Some(sample.clone())) - } else if let Some(sample) = &self.sampler.mapped[note_pt] { - SampleViewer(Some(sample.clone())) - } else { - SampleViewer(None) - })), - Bsp::n( - lay!( - Align::w(Fixed::y(1, SamplerStatus(&self.sampler, note_pt))), - Align::x(Fixed::y(1, MidiEditStatus(&self.editor))), - ), - Bsp::w( - Fixed::x(pool_w, PoolView(self.compact, &self.pool)), - Fill::xy(Bsp::e(sampler, &self.editor)), - ), - ) - ) + ))) + } + fn status_view (&self) -> impl Content + use<'_> { + let note_pt = self.editor.note_point(); + lay!( + Align::w(Fixed::y(1, SamplerStatus(&self.sampler, note_pt))), + Align::x(Fixed::y(1, MidiEditStatus(&self.editor))), ) - )) -}); + } + fn sampler_view (&self) -> impl Content + use<'_> { + let sampler_w = if !self.compact { 11 } else { 4 }; + let sampler_y = if self.compact { 1 } else { 0 }; + Fixed::x(sampler_w, Push::y(sampler_y, Fill::y( + SampleList::new(self.compact, &self.sampler, &self.editor)))) + } + fn sample_view (&self) -> impl Content + use<'_> { + let note_pt = self.editor.note_point(); + let sample_h = if self.compact { 0 } else { 5 }; + Max::y(sample_h, Fill::xy( + SampleViewer::from_sampler(&self.sampler, note_pt))) + } + fn pool_view (&self) -> impl Content + use<'_> { + let w = self.size.w(); + let pool_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 }; + Fixed::x(if self.compact { 5 } else { pool_w }, + PoolView(self.compact, &self.pool)) + } + fn selector_view (&self) -> impl Content + use<'_> { + lay!( + Align::w(MidiEditClip(&self.editor)), + Align::e(Bsp::e( + ClipSelected::play_phrase(&self.player), + ClipSelected::next_phrase(&self.player) + )) + ) + } +} pub enum GrooveboxCommand { Compact(bool), diff --git a/src/sampler/sample_viewer.rs b/src/sampler/sample_viewer.rs index f555a37d..29f75e01 100644 --- a/src/sampler/sample_viewer.rs +++ b/src/sampler/sample_viewer.rs @@ -5,6 +5,19 @@ use ratatui::{prelude::Rect, widgets::{Widget, canvas::{Canvas, Points, Line}}}; const EMPTY: &[(f64, f64)] = &[(0., 0.), (1., 1.), (2., 2.), (0., 2.), (2., 0.)]; pub struct SampleViewer(pub Option>>); + +impl SampleViewer { + pub fn from_sampler (sampler: &Sampler, note_pt: usize) -> Self { + if let Some((_, sample)) = &sampler.recording { + SampleViewer(Some(sample.clone())) + } else if let Some(sample) = &sampler.mapped[note_pt] { + SampleViewer(Some(sample.clone())) + } else { + SampleViewer(None) + } + } +} + render!(Tui: |self: SampleViewer, to|{ let [x, y, width, height] = to.area();