From 0f6c09cf2be2806d7d2cdd84fd936241084f732e Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 19 Oct 2024 01:07:24 +0300 Subject: [PATCH] fix track title and corners overlap --- crates/tek_sequencer/src/arranger.rs | 21 +++-- crates/tek_sequencer/src/arranger_cmd.rs | 3 +- crates/tek_sequencer/src/arranger_tui.rs | 109 ++++++++++++----------- crates/tek_sequencer/src/lib.rs | 15 ++-- 4 files changed, 80 insertions(+), 68 deletions(-) diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index 499e9fdc..3f250639 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -158,6 +158,20 @@ impl Arranger { }, } } + /// Update status bar + pub fn update_status (&mut self) { + self.status = match self.focused() { + ArrangerFocus::Transport => ArrangerStatusBar::Transport, + ArrangerFocus::Arrangement => match self.arrangement.selected { + ArrangementFocus::Mix => ArrangerStatusBar::ArrangementMix, + ArrangementFocus::Track(_) => ArrangerStatusBar::ArrangementTrack, + ArrangementFocus::Scene(_) => ArrangerStatusBar::ArrangementScene, + ArrangementFocus::Clip(_, _) => ArrangerStatusBar::ArrangementClip, + }, + ArrangerFocus::PhrasePool => ArrangerStatusBar::PhrasePool, + ArrangerFocus::PhraseEditor => ArrangerStatusBar::PhraseEditor, + } + } } /// Focus layout of arranger app impl FocusGrid for Arranger { @@ -180,12 +194,7 @@ impl FocusGrid for Arranger { focused == ArrangerFocus::PhrasePool; self.editor.focused = focused == ArrangerFocus::PhraseEditor; - self.status = match focused { - ArrangerFocus::Transport => ArrangerStatusBar::Transport, - ArrangerFocus::Arrangement => ArrangerStatusBar::ArrangementMix, - ArrangerFocus::PhrasePool => ArrangerStatusBar::PhrasePool, - ArrangerFocus::PhraseEditor => ArrangerStatusBar::PhraseEditor, - } + self.update_status(); } } /// General methods for arrangement diff --git a/crates/tek_sequencer/src/arranger_cmd.rs b/crates/tek_sequencer/src/arranger_cmd.rs index dcd17aa6..ae5e3b97 100644 --- a/crates/tek_sequencer/src/arranger_cmd.rs +++ b/crates/tek_sequencer/src/arranger_cmd.rs @@ -18,6 +18,7 @@ impl Handle for Arranger { _ => return Ok(None) } }; + self.update_status(); Ok(Some(true)) } } @@ -40,7 +41,7 @@ impl Arranger { key!(KeyCode::Char('>')) => { self.phrases_split = self.phrases_split + 1; }, - _ => return self.arrangement.handle(from) + _ => return self.phrases.handle(from) } Ok(Some(true)) } diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 74ee90fc..5726dd44 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -1,5 +1,5 @@ use crate::*; -/// The standalone arranger consists of transport, clip grid, and sequencer. +/// Layout for standalone arranger app. impl Content for Arranger { type Engine = Tui; fn content (&self) -> impl Widget { @@ -19,7 +19,7 @@ impl Content for Arranger { ) ) ) - ).fill_xy() + ) } } impl Content for ArrangerStatusBar { @@ -38,8 +38,8 @@ impl Content for ArrangerStatusBar { .fg(Color::Rgb(0, 0, 0)) .bold(true); row!(label, " ", match self { - Self::ArrangementMix => - "[G]et [S]et [A]dd [I]nsert [D]uplicate [E]dit [C]olor", + Self::ArrangementClip => + "[G]et [S]et [A]dd [I]nsert [D]uplicate [E]dit [C]olor [,.]Choose", Self::PhrasePool => "[A]ppend [I]nsert [D]uplicate [C]olor re[N]ame leng[T]h [,.]Move [<>]Resize", _ => "" @@ -120,6 +120,55 @@ impl<'a> Content for VerticalArranger<'a, Tui> { Ok(()) }))?; + // track titles + let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{ + let name = track.name.read().unwrap(); + let max_w = w.saturating_sub(1).min(name.len()); + (&format!("▎{}", &name[0..max_w]).as_str()) + .min_xy(w as u16, 2) + .bg(track.color) + .push_x(offset - 1) + }); + + // scene titles + let scene_name = |scene, playing: bool, height|row!( + if playing { "▶ " } else { " " }, + (scene as &Scene).name.read().unwrap().as_str(), + ).fixed_xy(offset.saturating_sub(1), height); + + // scene clips + let scene_clip = |scene, track: usize, w: u16, h: u16|Layers::new(move |add|{ + let mut color = clip_bg; + match (tracks.get(track), (scene as &Scene).clips.get(track)) { + (Some(_), Some(Some(phrase))) => { + let name = &(phrase as &Arc>).read().unwrap().name; + let name = format!("{}", name); + let max_w = name.len().min((w as usize).saturating_sub(2)); + add(&name.as_str()[0..max_w].push_x(1).fixed_x(w))?; + color = (phrase as &Arc>).read().unwrap().color; + }, + _ => {} + }; + add(&Background(color)) + }).fixed_xy(w, h); + + add(&col!(track_titles, col!( + // scenes: + (scene, pulses) in scenes.iter().zip(rows.iter().map(|row|row.0)) => { + let height = 1.max((pulses / PPQ) as u16); + let playing = scene.is_playing(tracks); + Stack::right(move |add| { + // scene title: + add(&scene_name(scene, playing, height).bg(scene.color))?; + // clip per track: + for (track, w) in cols.iter().map(|col|col.0).enumerate() { + add(&scene_clip(scene, track, w as u16, height))?; + } + Ok(()) + }).fixed_y(height) + } + )))?; + // cursor add(&CustomWidget::new(|_|Ok(Some([0,0])), move|to: &mut TuiOutput|{ let area = to.area(); @@ -165,63 +214,19 @@ impl<'a> Content for VerticalArranger<'a, Tui> { if focused { if let Some(clip_area) = clip_area { to.render_in(clip_area, &CORNERS)?; - to.fill_bg(clip_area, Color::Rgb(40, 50, 30)); + //to.fill_bg(clip_area, Color::Rgb(40, 50, 30)); } else if let Some(track_area) = track_area { to.render_in(track_area.clip_h(2), &CORNERS)?; - to.fill_bg(track_area, Color::Rgb(40, 50, 30)); + //to.fill_bg(track_area, Color::Rgb(40, 50, 30)); } else if let Some(scene_area) = scene_area { to.render_in(scene_area.clip_w(offset-1), &CORNERS)?; - to.fill_bg(scene_area, Color::Rgb(40, 50, 30)); + //to.fill_bg(scene_area, Color::Rgb(40, 50, 30)); } } Ok(()) }))?; - let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{ - let name = track.name.read().unwrap(); - let max_w = w.min(name.len()); - (&format!("▎{}", &name[0..max_w]).as_str()) - .min_xy(w as u16, 2) - .bg(track.color) - .push_x(offset - 1) - }); - - let scene_name = |scene, playing: bool, height|row!( - if playing { "▶ " } else { " " }, - (scene as &Scene).name.read().unwrap().as_str(), - ).fixed_xy(offset.saturating_sub(1), height); - - let scene_clip = |scene, track: usize, w: u16, h: u16|Layers::new(move |add|{ - let mut color = clip_bg; - match (tracks.get(track), (scene as &Scene).clips.get(track)) { - (Some(_), Some(Some(phrase))) => { - let name = &(phrase as &Arc>).read().unwrap().name; - let name = format!("{}", name); - let max_w = name.len().min((w as usize).saturating_sub(2)); - add(&name.as_str()[0..max_w].push_x(1).fixed_x(w))?; - color = (phrase as &Arc>).read().unwrap().color; - }, - _ => {} - }; - add(&Background(color)) - }).fixed_xy(w, h); - - add(&col!(track_titles, col!( - // scenes: - (scene, pulses) in scenes.iter().zip(rows.iter().map(|row|row.0)) => { - let height = 1.max((pulses / PPQ) as u16); - let playing = scene.is_playing(tracks); - Stack::right(move |add| { - // scene title: - add(&scene_name(scene, playing, height).bg(scene.color))?; - // clip per track: - for (track, w) in cols.iter().map(|col|col.0).enumerate() { - add(&scene_clip(scene, track, w as u16, height))?; - } - Ok(()) - }).fixed_y(height) - } - ))) + Ok(()) }).bg(bg).border(border) } } diff --git a/crates/tek_sequencer/src/lib.rs b/crates/tek_sequencer/src/lib.rs index 279b137f..8f000956 100644 --- a/crates/tek_sequencer/src/lib.rs +++ b/crates/tek_sequencer/src/lib.rs @@ -17,21 +17,18 @@ submod! { pub const PPQ: usize = 96; -pub const CORNERS: CornersTall = CornersTall(NOT_DIM_GREEN); +pub const CORNERS: CornersTall = CornersTall(CORNERS_STYLE); +tui_style!(CORNERS_STYLE = + Some(Color::Rgb(96, 255, 32)), None, None, Modifier::empty(), Modifier::DIM); /// Octave number (from -1 to 9) pub const NTH_OCTAVE: [&'static str;11] = [ "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]; -tui_style!(GRAY_DIM = - Some(Color::Gray), None, None, Modifier::DIM, Modifier::empty()); -tui_style!(GRAY_NOT_DIM_BOLD = - Some(Color::Gray), None, None, Modifier::BOLD, Modifier::DIM); -tui_style!(NOT_DIM_GREEN = - Some(Color::Rgb(96, 255, 32)), Some(COLOR_BG1), None, Modifier::empty(), Modifier::DIM); -tui_style!(WHITE_NOT_DIM_BOLD = - Some(Color::White), None, None, Modifier::BOLD, Modifier::DIM); +tui_style!(GRAY_DIM = Some(Color::Gray), None, None, Modifier::DIM, Modifier::empty()); +tui_style!(GRAY_NOT_DIM_BOLD = Some(Color::Gray), None, None, Modifier::BOLD, Modifier::DIM); +tui_style!(WHITE_NOT_DIM_BOLD = Some(Color::White), None, None, Modifier::BOLD, Modifier::DIM); pub fn random_okhsl () -> Okhsl { let mut rng = thread_rng();