//! Clip launcher and arrangement editor. use crate::*; use tek_core::Direction; /// Represents the tracks and scenes of the composition. pub struct Arranger { /// Name of arranger pub name: String, /// Display mode of arranger pub mode: ArrangerViewMode, /// Currently selected element. pub selected: ArrangerFocus, /// Collection of tracks. pub tracks: Vec, /// Collection of scenes. pub scenes: Vec, pub focused: bool, pub entered: bool, pub transport: Option>>, pub show_sequencer: Option } render!(Arranger |self, buf, area| { let arrangement = |buf, area| match self.mode { ArrangerViewMode::Horizontal => super::arranger_view_h::draw(self, buf, area), ArrangerViewMode::VerticalCompact1 => super::arranger_view_v::draw_compact_1(self, buf, area), ArrangerViewMode::VerticalCompact2 => super::arranger_view_v::draw_compact_2(self, buf, area), ArrangerViewMode::VerticalExpanded => super::arranger_view_v::draw_expanded(self, buf, area), }; if let Some(direction) = self.show_sequencer { let used = arrangement(buf, area)?; match direction { Direction::Down => { let area = Rect { y: area.y + used.height, height: area.height - used.height, ..area }; self.sequencer().map(|sequencer|sequencer.render(buf, area)); }, _ => unimplemented!() } Ok(area) } else { arrangement(buf, area) } }); impl Arranger { pub fn new (name: &str) -> Self { Self { name: name.into(), mode: ArrangerViewMode::VerticalCompact2, selected: ArrangerFocus::Clip(0, 0), scenes: vec![], tracks: vec![], entered: true, focused: true, transport: None, show_sequencer: Some(Direction::Down), } } pub fn activate (&mut self) { match self.selected { ArrangerFocus::Scene(s) => { for (track_index, track) in self.tracks.iter_mut().enumerate() { track.sequence = self.scenes[s].clips[track_index]; track.reset = true; } }, ArrangerFocus::Clip(t, s) => { self.tracks[t].sequence = self.scenes[s].clips[t]; self.tracks[t].reset = true; }, _ => {} } } pub fn sequencer (&self) -> Option<&Sequencer> { self.selected.track() .map(|track|self.tracks.get(track)) .flatten() } pub fn sequencer_mut (&mut self) -> Option<&mut Sequencer> { self.selected.track() .map(|track|self.tracks.get_mut(track)) .flatten() } pub fn show_phrase (&mut self) -> Usually<()> { //unimplemented!() //let phrase = self.phrase(); //self.sequencer.show(phrase) Ok(()) } pub fn phrase (&self) -> Option<&Arc>> { let track_id = self.selected.track()?; self.tracks.get(track_id)?.phrases.get((*self.scene()?.clips.get(track_id)?)?) } pub fn phrase_next (&mut self) { let track_index = self.selected.track(); let scene_index = self.selected.scene(); track_index .and_then(|index|self.tracks.get_mut(index).map(|track|(index, track))) .and_then(|(track_index, track)|{ let phrases = track.phrases.len(); scene_index .and_then(|index|self.scenes.get_mut(index)) .and_then(|scene|{ if let Some(phrase_index) = scene.clips[track_index] { if phrase_index >= phrases - 1 { scene.clips[track_index] = None; } else { scene.clips[track_index] = Some(phrase_index + 1); } } else if phrases > 0 { scene.clips[track_index] = Some(0); } Some(()) }) }); } pub fn phrase_prev (&mut self) { let track_index = self.selected.track(); let scene_index = self.selected.scene(); track_index .and_then(|index|self.tracks.get_mut(index).map(|track|(index, track))) .and_then(|(track_index, track)|{ let phrases = track.phrases.len(); scene_index .and_then(|index|self.scenes.get_mut(index)) .and_then(|scene|{ if let Some(phrase_index) = scene.clips[track_index] { scene.clips[track_index] = if phrase_index == 0 { None } else { Some(phrase_index - 1) }; } else if phrases > 0 { scene.clips[track_index] = Some(phrases - 1); } Some(()) }) }); } pub fn scene (&self) -> Option<&Scene> { self.selected.scene().map(|s|self.scenes.get(s)).flatten() } pub fn scene_mut (&mut self) -> Option<&mut Scene> { self.selected.scene().map(|s|self.scenes.get_mut(s)).flatten() } pub fn scene_next (&mut self) { self.selected.scene_next(self.scenes.len() - 1) } pub fn scene_prev (&mut self) { self.selected.scene_prev() } pub fn scene_add (&mut self, name: Option<&str>) -> Usually<&mut Scene> { let clips = vec![None;self.tracks.len()]; self.scenes.push(match name { Some(name) => Scene::new(name, clips), None => Scene::new(&self.scene_default_name(), clips), }); let index = self.scenes.len() - 1; Ok(&mut self.scenes[index]) } pub fn scene_del (&mut self) { unimplemented!("Arranger::scene_del"); } pub fn scene_default_name (&self) -> String { format!("Scene {}", self.scenes.len() + 1) } }