use crate::*; use super::*; pub struct ArrangerVClips<'a> { size: &'a Measure, scenes: &'a Vec, tracks: &'a Vec, rows: Vec<(usize, usize)>, } impl<'a> ArrangerVClips<'a> { pub fn new (state: &'a ArrangerTui, zoom: usize) -> Self { Self { size: &state.size, tracks: &state.tracks, scenes: &state.scenes, rows: ArrangerScene::ppqs(&state.scenes, zoom), } } } impl<'a, E: Engine> Content for ArrangerVClips<'a> { fn content (&self) -> Option> { let iter = self.scenes.iter().zip(self.rows.iter().map(|row|row.0)); let col = Coll::map(self.scenes.iter().zip(self.rows.iter().map(|row|row.0)), |(scene, pulses), i| Self::format_scene(self.tracks, scene, pulses)); Some(Fill::xy(col)) } } impl<'a> ArrangerVClips<'a> { fn format_scene ( tracks: &'a [ArrangerTrack], scene: &'a ArrangerScene, pulses: usize ) -> impl Content + use<'a> { let height = 1.max((pulses / PPQ) as u16); let playing = scene.is_playing(tracks); Fixed::y(height, row!( Tui::bg(scene.color.base.rgb, if playing { "▶ " } else { " " }), Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb, Expand::x(1, Tui::bold(true, scene.name.read().unwrap().as_str()))), Coll::map(ArrangerTrack::with_widths(tracks), |(index, track, x1, x2), _| Push::x(Self::format_clip(scene, index, track, (x2 - x1) as u16, height)))))} fn format_clip ( scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16 ) -> impl Content + use<'a> { Fixed::xy(w, h, Layers::new(move |add|{ if let Some(Some(phrase)) = scene.clips.get(index) { let mut bg = TuiTheme::border_bg(); let name = &(phrase as &Arc>).read().unwrap().name.to_string(); let max_w = name.len().min((w as usize).saturating_sub(2)); let color = phrase.read().unwrap().color; bg = color.dark.rgb; if let Some((_, Some(ref playing))) = track.player.play_phrase() { if *playing.read().unwrap() == *phrase.read().unwrap() { bg = color.light.rgb } }; add(&Tui::bg(bg, Push::x(1, Fixed::x(w, &name.as_str()[0..max_w]))) )?; } Ok(()) })) } }