//impl Bar for ArrangerStatus { //type State = (ArrangerFocus, ArrangerSelection, bool); //fn hotkey_fg () -> Color where Self: Sized { //TuiTheme::HOTKEY_FG //} //fn update (&mut self, (focused, selected, entered): &Self::State) { //*self = match focused { ////ArrangerFocus::Menu => { todo!() }, //ArrangerFocus::Transport(_) => ArrangerStatus::Transport, //ArrangerFocus::Arranger => match selected { //ArrangerSelection::Mix => ArrangerStatus::ArrangerMix, //ArrangerSelection::Track(_) => ArrangerStatus::ArrangerTrack, //ArrangerSelection::Scene(_) => ArrangerStatus::ArrangerScene, //ArrangerSelection::Clip(_, _) => ArrangerStatus::ArrangerClip, //}, //ArrangerFocus::Phrases => ArrangerStatus::PhrasePool, //ArrangerFocus::PhraseEditor => match entered { //true => ArrangerStatus::PhraseEdit, //false => ArrangerStatus::PhraseView, //}, //} //} //} //render!(<Tui>|self: ArrangerStatus|{ //let label = match self { //Self::Transport => "TRANSPORT", //Self::ArrangerMix => "PROJECT", //Self::ArrangerTrack => "TRACK", //Self::ArrangerScene => "SCENE", //Self::ArrangerClip => "CLIP", //Self::PhrasePool => "SEQ LIST", //Self::PhraseView => "VIEW SEQ", //Self::PhraseEdit => "EDIT SEQ", //}; //let status_bar_bg = TuiTheme::status_bar_bg(); //let mode_bg = TuiTheme::mode_bg(); //let mode_fg = TuiTheme::mode_fg(); //let mode = Tui::fg(mode_fg, Tui::bg(mode_bg, Tui::bold(true, format!(" {label} ")))); //let commands = match self { //Self::ArrangerMix => Self::command(&[ //["", "c", "olor"], //["", "<>", "resize"], //["", "+-", "zoom"], //["", "n", "ame/number"], //["", "Enter", " stop all"], //]), //Self::ArrangerClip => Self::command(&[ //["", "g", "et"], //["", "s", "et"], //["", "a", "dd"], //["", "i", "ns"], //["", "d", "up"], //["", "e", "dit"], //["", "c", "olor"], //["re", "n", "ame"], //["", ",.", "select"], //["", "Enter", " launch"], //]), //Self::ArrangerTrack => Self::command(&[ //["re", "n", "ame"], //["", ",.", "resize"], //["", "<>", "move"], //["", "i", "nput"], //["", "o", "utput"], //["", "m", "ute"], //["", "s", "olo"], //["", "Del", "ete"], //["", "Enter", " stop"], //]), //Self::ArrangerScene => Self::command(&[ //["re", "n", "ame"], //["", "Del", "ete"], //["", "Enter", " launch"], //]), //Self::PhrasePool => Self::command(&[ //["", "a", "ppend"], //["", "i", "nsert"], //["", "d", "uplicate"], //["", "Del", "ete"], //["", "c", "olor"], //["re", "n", "ame"], //["leng", "t", "h"], //["", ",.", "move"], //["", "+-", "resize view"], //]), //Self::PhraseView => Self::command(&[ //["", "enter", " edit"], //["", "arrows/pgup/pgdn", " scroll"], //["", "+=", "zoom"], //]), //Self::PhraseEdit => Self::command(&[ //["", "esc", " exit"], //["", "a", "ppend"], //["", "s", "et"], //["", "][", "length"], //["", "+-", "zoom"], //]), //_ => Self::command(&[]) //}; ////let commands = commands.iter().reduce(String::new(), |s, (a, b, c)| format!("{s} {a}{b}{c}")); //Tui::bg(status_bar_bg, Fill::w(row!([mode, commands]))) //}); ///// Status bar for arranger app //#[derive(Copy, Clone, Debug)] //pub enum ArrangerStatus { //Transport, //ArrangerMix, //ArrangerTrack, //ArrangerScene, //ArrangerClip, //PhrasePool, //PhraseView, //PhraseEdit, //} //let focused = true; //let _tracks = view.tracks(); //lay!( //focused.then_some(Background(TuiTheme::border_bg())), //row!( //// name //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ //todo!() ////let Self(tracks, selected) = self; ////let yellow = Some(Style::default().yellow().bold().not_dim()); ////let white = Some(Style::default().white().bold().not_dim()); ////let area = to.area(); ////let area = [area.x(), area.y(), 3 + 5.max(track_name_max_len(tracks)) as u16, area.h()]; ////let offset = 0; // track scroll offset ////for y in 0..area.h() { ////if y == 0 { ////to.blit(&"Mixer", area.x() + 1, area.y() + y, Some(DIM))?; ////} else if y % 2 == 0 { ////let index = (y as usize - 2) / 2 + offset; ////if let Some(track) = tracks.get(index) { ////let selected = selected.track() == Some(index); ////let style = if selected { yellow } else { white }; ////to.blit(&format!(" {index:>02} "), area.x(), area.y() + y, style)?; ////to.blit(&*track.name.read().unwrap(), area.x() + 4, area.y() + y, style)?; ////} ////} ////} ////Ok(Some(area)) //}), //// monitor //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ //todo!() ////let Self(tracks) = self; ////let mut area = to.area(); ////let on = Some(Style::default().not_dim().green().bold()); ////let off = Some(DIM); ////area.x += 1; ////for y in 0..area.h() { ////if y == 0 { //////" MON ".blit(to.buffer, area.x, area.y + y, style2)?; ////} else if y % 2 == 0 { ////let index = (y as usize - 2) / 2; ////if let Some(track) = tracks.get(index) { ////let style = if track.monitoring { on } else { off }; ////to.blit(&" MON ", area.x(), area.y() + y, style)?; ////} else { ////area.height = y; ////break ////} ////} ////} ////area.width = 4; ////Ok(Some(area)) //}), //// record //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ //todo!() ////let Self(tracks) = self; ////let mut area = to.area(); ////let on = Some(Style::default().not_dim().red().bold()); ////let off = Some(Style::default().dim()); ////area.x += 1; ////for y in 0..area.h() { ////if y == 0 { //////" REC ".blit(to.buffer, area.x, area.y + y, style2)?; ////} else if y % 2 == 0 { ////let index = (y as usize - 2) / 2; ////if let Some(track) = tracks.get(index) { ////let style = if track.recording { on } else { off }; ////to.blit(&" REC ", area.x(), area.y() + y, style)?; ////} else { ////area.height = y; ////break ////} ////} ////} ////area.width = 4; ////Ok(Some(area)) //}), //// overdub //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ //todo!() ////let Self(tracks) = self; ////let mut area = to.area(); ////let on = Some(Style::default().not_dim().yellow().bold()); ////let off = Some(Style::default().dim()); ////area.x = area.x + 1; ////for y in 0..area.h() { ////if y == 0 { //////" OVR ".blit(to.buffer, area.x, area.y + y, style2)?; ////} else if y % 2 == 0 { ////let index = (y as usize - 2) / 2; ////if let Some(track) = tracks.get(index) { ////to.blit(&" OVR ", area.x(), area.y() + y, if track.overdub { ////on ////} else { ////off ////})?; ////} else { ////area.height = y; ////break ////} ////} ////} ////area.width = 4; ////Ok(Some(area)) //}), //// erase //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ //todo!() ////let Self(tracks) = self; ////let mut area = to.area(); ////let off = Some(Style::default().dim()); ////area.x = area.x + 1; ////for y in 0..area.h() { ////if y == 0 { //////" DEL ".blit(to.buffer, area.x, area.y + y, style2)?; ////} else if y % 2 == 0 { ////let index = (y as usize - 2) / 2; ////if let Some(_) = tracks.get(index) { ////to.blit(&" DEL ", area.x(), area.y() + y, off)?; ////} else { ////area.height = y; ////break ////} ////} ////} ////area.width = 4; ////Ok(Some(area)) //}), //// gain //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ //todo!() ////let Self(tracks) = self; ////let mut area = to.area(); ////let off = Some(Style::default().dim()); ////area.x = area.x() + 1; ////for y in 0..area.h() { ////if y == 0 { //////" GAIN ".blit(to.buffer, area.x, area.y + y, style2)?; ////} else if y % 2 == 0 { ////let index = (y as usize - 2) / 2; ////if let Some(_) = tracks.get(index) { ////to.blit(&" +0.0 ", area.x(), area.y() + y, off)?; ////} else { ////area.height = y; ////break ////} ////} ////} ////area.width = 7; ////Ok(Some(area)) //}), //// scenes //Widget::new(|_|{todo!()}, |to: &mut TuiOutput|{ //let [x, y, _, height] = to.area(); //let mut x2 = 0; //Ok(for (scene_index, scene) in view.scenes().iter().enumerate() { //let active_scene = view.selected.scene() == Some(scene_index); //let sep = Some(if active_scene { //Style::default().yellow().not_dim() //} else { //Style::default().dim() //}); //for y in y+1..y+height { //to.blit(&"│", x + x2, y, sep); //} //let name = scene.name.read().unwrap(); //let mut x3 = name.len() as u16; //to.blit(&*name, x + x2, y, sep); //for (i, clip) in scene.clips.iter().enumerate() { //let active_track = view.selected.track() == Some(i); //if let Some(clip) = clip { //let y2 = y + 2 + i as u16 * 2; //let label = format!("{}", clip.read().unwrap().name); //to.blit(&label, x + x2, y2, Some(if active_track && active_scene { //Style::default().not_dim().yellow().bold() //} else { //Style::default().not_dim() //})); //x3 = x3.max(label.len() as u16) //} //} //x2 = x2 + x3 + 1; //}) //}), //) //) //} //impl Command<ArrangerModel> for ArrangerSceneCommand { //} //Edit(phrase) => { state.state.phrase = phrase.clone() }, //ToggleViewMode => { state.state.mode.to_next(); }, //Delete => { state.state.delete(); }, //Activate => { state.state.activate(); }, //ZoomIn => { state.state.zoom_in(); }, //ZoomOut => { state.state.zoom_out(); }, //MoveBack => { state.state.move_back(); }, //MoveForward => { state.state.move_forward(); }, //RandomColor => { state.state.randomize_color(); }, //Put => { state.state.phrase_put(); }, //Get => { state.state.phrase_get(); }, //AddScene => { state.state.scene_add(None, None)?; }, //AddTrack => { state.state.track_add(None, None)?; }, //ToggleLoop => { state.state.toggle_loop() }, //pub fn zoom_in (&mut self) { //if let ArrangerEditorMode::V(factor) = self.mode { //self.mode = ArrangerEditorMode::V(factor + 1) //} //} //pub fn zoom_out (&mut self) { //if let ArrangerEditorMode::V(factor) = self.mode { //self.mode = ArrangerEditorMode::V(factor.saturating_sub(1)) //} //} //pub fn move_back (&mut self) { //match self.selected { //ArrangerEditorFocus::Scene(s) => { //if s > 0 { //self.scenes.swap(s, s - 1); //self.selected = ArrangerEditorFocus::Scene(s - 1); //} //}, //ArrangerEditorFocus::Track(t) => { //if t > 0 { //self.tracks.swap(t, t - 1); //self.selected = ArrangerEditorFocus::Track(t - 1); //// FIXME: also swap clip order in scenes //} //}, //_ => todo!("arrangement: move forward") //} //} //pub fn move_forward (&mut self) { //match self.selected { //ArrangerEditorFocus::Scene(s) => { //if s < self.scenes.len().saturating_sub(1) { //self.scenes.swap(s, s + 1); //self.selected = ArrangerEditorFocus::Scene(s + 1); //} //}, //ArrangerEditorFocus::Track(t) => { //if t < self.tracks.len().saturating_sub(1) { //self.tracks.swap(t, t + 1); //self.selected = ArrangerEditorFocus::Track(t + 1); //// FIXME: also swap clip order in scenes //} //}, //_ => todo!("arrangement: move forward") //} //}