//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")
        //}
    //}