use crate::*; /// Sections in the arranger app that may be focused #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ArrangerViewFocus { /// The transport (toolbar) is focused Transport, /// The arrangement (grid) is focused Arrangement, /// The phrase list (pool) is focused PhrasePool, /// The phrase editor (sequencer) is focused PhraseEditor, } /// Focus layout of arranger app impl FocusGrid for ArrangerView { type Item = ArrangerViewFocus; fn cursor (&self) -> (usize, usize) { self.focus_cursor } fn cursor_mut (&mut self) -> &mut (usize, usize) { &mut self.focus_cursor } fn focus_enter (&mut self) { let focused = self.focused(); if !self.entered { self.entered = true; use ArrangerViewFocus::*; if let Some(transport) = self.transport.as_ref() { //transport.write().unwrap().entered = focused == Transport } self.arrangement.entered = focused == Arrangement; self.phrases.write().unwrap().entered = focused == PhrasePool; self.editor.entered = focused == PhraseEditor; } } fn focus_exit (&mut self) { if self.entered { self.entered = false; self.arrangement.entered = false; self.editor.entered = false; self.phrases.write().unwrap().entered = false; } } fn entered (&self) -> Option { if self.entered { Some(self.focused()) } else { None } } fn layout (&self) -> &[&[ArrangerViewFocus]] { use ArrangerViewFocus::*; &[ &[Transport, Transport], &[Arrangement, Arrangement], &[PhrasePool, PhraseEditor], ] } fn update_focus (&mut self) { use ArrangerViewFocus::*; let focused = self.focused(); self.arrangement.focused = focused == Arrangement; self.sequencer.transport.focused = focused == Transport; self.sequencer.phrases.focused = focused == PhrasePool; self.sequencer.editor.focused = focused == PhraseEditor; //self.update_status(); } } #[derive(PartialEq, Clone, Copy)] /// Represents the current user selection in the arranger pub enum ArrangementEditorFocus { /// The whole mix is selected Mix, /// A track is selected. Track(usize), /// A scene is selected. Scene(usize), /// A clip (track × scene) is selected. Clip(usize, usize), } /// Focus identification methods impl ArrangementEditorFocus { pub fn description ( &self, tracks: &Vec, scenes: &Vec, ) -> String { format!("Selected: {}", match self { Self::Mix => format!("Everything"), Self::Track(t) => match tracks.get(*t) { Some(track) => format!("T{t}: {}", &track.name.read().unwrap()), None => format!("T??"), }, Self::Scene(s) => match scenes.get(*s) { Some(scene) => format!("S{s}: {}", &scene.name.read().unwrap()), None => format!("S??"), }, Self::Clip(t, s) => match (tracks.get(*t), scenes.get(*s)) { (Some(_), Some(scene)) => match scene.clip(*t) { Some(clip) => format!("T{t} S{s} C{}", &clip.read().unwrap().name), None => format!("T{t} S{s}: Empty") }, _ => format!("T{t} S{s}: Empty"), } }) } pub fn is_mix (&self) -> bool { match self { Self::Mix => true, _ => false } } pub fn is_track (&self) -> bool { match self { Self::Track(_) => true, _ => false } } pub fn is_scene (&self) -> bool { match self { Self::Scene(_) => true, _ => false } } pub fn is_clip (&self) -> bool { match self { Self::Clip(_, _) => true, _ => false } } pub fn track (&self) -> Option { use ArrangementEditorFocus::*; match self { Clip(t, _) => Some(*t), Track(t) => Some(*t), _ => None } } pub fn scene (&self) -> Option { use ArrangementEditorFocus::*; match self { Clip(_, s) => Some(*s), Scene(s) => Some(*s), _ => None } } } //pub fn track_next (&mut self, last_track: usize) { //use ArrangementEditorFocus::*; //*self = match self { //Mix => Track(0), //Track(t) => Track(last_track.min(*t + 1)), //Scene(s) => Clip(0, *s), //Clip(t, s) => Clip(last_track.min(*t + 1), *s), //} //} //pub fn track_prev (&mut self) { //use ArrangementEditorFocus::*; //*self = match self { //Mix => Mix, //Scene(s) => Scene(*s), //Track(t) => if *t == 0 { Mix } else { Track(*t - 1) }, //Clip(t, s) => if *t == 0 { Scene(*s) } else { Clip(t.saturating_sub(1), *s) } //} //} //pub fn scene_next (&mut self, last_scene: usize) { //use ArrangementEditorFocus::*; //*self = match self { //Mix => Scene(0), //Track(t) => Clip(*t, 0), //Scene(s) => Scene(last_scene.min(*s + 1)), //Clip(t, s) => Clip(*t, last_scene.min(*s + 1)), //} //} //pub fn scene_prev (&mut self) { //use ArrangementEditorFocus::*; //*self = match self { //Mix => Mix, //Track(t) => Track(*t), //Scene(s) => if *s == 0 { Mix } else { Scene(*s - 1) }, //Clip(t, s) => if *s == 0 { Track(*t) } else { Clip(*t, s.saturating_sub(1)) } //} //}