From e57415aac97a004c3ecfd625466cf38d0bbb87f7 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 16 Dec 2024 18:10:26 +0100 Subject: [PATCH] wip: structure PianoHorizontal render sanely --- crates/tek/src/tui/app_sequencer.rs | 16 +++--- crates/tek/src/tui/app_transport.rs | 26 +++++----- crates/tek/src/tui/phrase_editor.rs | 37 ++++++++----- crates/tek/src/tui/piano_horizontal.rs | 72 +++++++++++++------------- 4 files changed, 81 insertions(+), 70 deletions(-) diff --git a/crates/tek/src/tui/app_sequencer.rs b/crates/tek/src/tui/app_sequencer.rs index 7703d467..7d29202e 100644 --- a/crates/tek/src/tui/app_sequencer.rs +++ b/crates/tek/src/tui/app_sequencer.rs @@ -184,10 +184,10 @@ pub struct PhraseSelector { // TODO: Display phrases always in order of appearance render!(|self: PhraseSelector|Tui::fixed_xy(24, 1, row!([ Tui::fg(self.color.lighter.rgb, Tui::bold(true, &self.title)), - Tui::bg(self.color.base.rgb, Tui::fg(self.color.lighter.rgb, row!([ + Tui::fg_bg(self.color.lighter.rgb, self.color.base.rgb, row!([ format!("{:8}", &self.name[0..8.min(self.name.len())]), Tui::bg(self.color.dark.rgb, &self.time), - ]))), + ])), ]))); impl PhraseSelector { @@ -311,19 +311,19 @@ render!(|self: SequencerStatusBar|Tui::fixed_y(2, lay!([ row!([" ", Tui::fg(TuiTheme::yellow(), b1), " ", c1,]), row!([" ", Tui::fg(TuiTheme::yellow(), b2), " ", c2,]), ]); - Tui::bg(TuiTheme::g(50), Tui::fg(TuiTheme::g(255), row!([ + Tui::fg_bg(TuiTheme::g(255), TuiTheme::g(50), row!([ single("SPACE", "play/pause"), double((" ✣", "cursor"), ("C-✣", "scroll"), ), double((",.", "note"), ("<>", "triplet"),), double(("[]", "phrase"), ("{}", "order"), ), double(("q", "enqueue"), ("e", "edit"), ), - ]))) + ])) }, Tui::fill_xy(Tui::at_se({ - Tui::bg(TuiTheme::g(25), row!([ - Tui::fg(TuiTheme::orange(), &self.cpu), - Tui::fg(TuiTheme::orange(), &self.res), - Tui::fg(TuiTheme::orange(), &self.size), + Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), row!([ + &self.cpu, + &self.res, + &self.size, ])) })), ]))); diff --git a/crates/tek/src/tui/app_transport.rs b/crates/tek/src/tui/app_transport.rs index af4660d7..fe8a4316 100644 --- a/crates/tek/src/tui/app_transport.rs +++ b/crates/tek/src/tui/app_transport.rs @@ -102,21 +102,21 @@ render!(|self: TransportView|{ struct Field<'a>(&'a str, &'a str, &'a ItemPalette); render!(|self: Field<'a>|row!([ - Tui::bg(Color::Reset, Tui::bold(true, - Tui::fg(self.2.lighter.rgb, self.0))), - Tui::fg(self.2.lighter.rgb, format!("{:>10}", self.1)), + Tui::fg_bg(self.2.lightest.rgb, self.2.darkest.rgb, Tui::bold(true, self.0)), + Tui::fg_bg(self.2.lighter.rgb, self.2.darkest.rgb, "│"), + Tui::fg_bg(self.2.lighter.rgb, self.2.base.rgb, format!("{:>10}", self.1)), ])); Tui::bg(color.base.rgb, Tui::fill_x(row!([ //PlayPause(self.started), " ", col!([ - Field(" Beat|", self.beat.as_str(), &color), - Field(" BPM|", self.bpm.as_str(), &color), + Field(" Beat", self.beat.as_str(), &color), + Field(" BPM", self.bpm.as_str(), &color), ]), " ", col!([ - Field(" Time|", format!("{:.1}s", self.current_second).as_str(), &color), - Field(" Smpl|", format!("{:.1}k", self.current_sample).as_str(), &color), + Field(" Time", format!("{:.1}s", self.current_second).as_str(), &color), + Field(" Smpl", format!("{:.1}k", self.current_sample).as_str(), &color), ]), ]))) @@ -128,12 +128,12 @@ render!(|self: PlayPause|Tui::bg( Tui::fixed_x(5, col!(|add|if self.0 { add(&Tui::fg(Color::Rgb(0, 255, 0), col!([ " 🭍🭑🬽 ", - " 🭞🭜🭘 " + " 🭞🭜🭘 ", ]))) } else { add(&Tui::fg(Color::Rgb(255, 128, 0), col!([ " ▗▄▖ ", - " ▝▀▘ " + " ▝▀▘ ", ]))) })) )); @@ -168,8 +168,8 @@ impl FocusWrap for TransportFocus { fn wrap <'a, W: Render> (self, focus: TransportFocus, content: &'a W) -> impl Render + 'a { - let focused = focus == self; - let corners = focused.then_some(CORNERS); + let focused = focus == self; + let corners = focused.then_some(CORNERS); //let highlight = focused.then_some(Tui::bg(Color::Rgb(60, 70, 50))); lay!([corners, /*highlight,*/ *content]) } @@ -179,8 +179,8 @@ impl FocusWrap for Option { fn wrap <'a, W: Render> (self, focus: TransportFocus, content: &'a W) -> impl Render + 'a { - let focused = Some(focus) == self; - let corners = focused.then_some(CORNERS); + let focused = Some(focus) == self; + let corners = focused.then_some(CORNERS); //let highlight = focused.then_some(Background(Color::Rgb(60, 70, 50))); lay!([corners, /*highlight,*/ *content]) } diff --git a/crates/tek/src/tui/phrase_editor.rs b/crates/tek/src/tui/phrase_editor.rs index 17f146b4..cbd11c60 100644 --- a/crates/tek/src/tui/phrase_editor.rs +++ b/crates/tek/src/tui/phrase_editor.rs @@ -231,34 +231,43 @@ impl std::fmt::Debug for PhraseEditorModel { pub struct PhraseEditStatus<'a>(pub &'a PhraseEditorModel); render!(|self:PhraseEditStatus<'a>|row!(|add|{ - let (color, name, length) = if let Some(phrase) = self.0.phrase().as_ref().map(|p|p.read().unwrap()) { - (phrase.color, phrase.name.clone(), phrase.length) + let (color, name, length, looped) = if let Some(phrase) = self.0.phrase().as_ref().map(|p|p.read().unwrap()) { + (phrase.color, phrase.name.clone(), phrase.length, phrase.loop_on) } else { - (ItemPalette::from(TuiTheme::g(64)), String::new(), 0) + (ItemPalette::from(TuiTheme::g(64)), String::new(), 0, false) }; let bg = color.base.rgb; let fg = color.lightest.rgb; - add(&Tui::fill_x(Tui::bg(bg, row!(|add|{ + let field = move|x, y|row!([ + Tui::fg_bg(color.lightest.rgb, Color::Reset, Tui::bold(true, x)), + Tui::fg_bg(color.lighter.rgb, Color::Reset, Tui::bold(true, "│")), + &y + ]); + add(&Tui::fill_x(Tui::fg_bg(fg, bg, row!(|add|{ add(&Tui::fixed_xy(26, 3, col!(![ - row!(![" Edit ", Tui::bold(true, format!("{name}"))]), - row!(![" Length ", Tui::bold(true, format!("{length}"))]), - row!(![" Loop ", Tui::bold(true, format!("on"))])])))?; + field(" Edit", format!("{name}")), + field(" Length", format!("{length}")), + field(" Loop", format!("{looped}")), + ])))?; add(&Tui::fixed_xy(25, 3, col!(![ - row!(!["Time ", Tui::bold(true, format!("{}", self.0.time_point()))]), - row!(!["View ", Tui::bold(true, format!("{}-{} ({}*{})", + field(" Time", format!("{}", + self.0.time_point())), + field(" View", format!("{}-{} ({}*{})", self.0.time_start(), self.0.time_end(), self.0.time_axis(), - self.0.time_zoom()))])])))?; + self.0.time_zoom())) + ])))?; add(&Tui::fixed_xy(25, 3, col!(![ - row!(!["Note ", Tui::bold(true, format!("{:4} ({:3}) {:4}", + field(" Note", format!("{:4} ({:3}) {:4}", to_note_name(self.0.note_point()), self.0.note_point(), - self.0.note_len()))]), - row!(!["View ", Tui::bold(true, format!("{}-{} ({})", + self.0.note_len())), + field(" View", format!("{}-{} ({})", to_note_name(self.0.note_lo()), to_note_name(self.0.note_hi()), - self.0.note_axis()))])])))?; + self.0.note_axis())) + ])))?; add(&Tui::fixed_xy(16, 3, col!(![ row!(!["TimeLock ", Tui::bold(true, format!("{}", self.0.time_lock()))])])))?; Ok(()) diff --git a/crates/tek/src/tui/piano_horizontal.rs b/crates/tek/src/tui/piano_horizontal.rs index 49d66a2d..78fdb539 100644 --- a/crates/tek/src/tui/piano_horizontal.rs +++ b/crates/tek/src/tui/piano_horizontal.rs @@ -6,7 +6,7 @@ pub struct PianoHorizontal { phrase: Option>>, /// Buffer where the whole phrase is rerendered on change buffer: BigBuffer, - /// Width and height of notes area at last render + /// Size of actual notes area size: Measure, /// The display window range: MidiRangeModel, @@ -39,7 +39,7 @@ impl PianoHorizontal { render!(|self: PianoHorizontal|{ let bg = TuiTheme::g(32); - let fg = self.color; + let color = self.color; let note_lo = self.range.note_lo(); let note_hi = self.range.note_hi(); let time_lock = self.range.time_lock(); @@ -48,45 +48,47 @@ render!(|self: PianoHorizontal|{ let time_point = self.point.time_point(); let note_point = self.point.note_point(); let note_len = self.point.note_len(); - lay!([ - &self.size, - Tui::fill_xy(Tui::bg(bg, Tui::split_s(false, 1, - Tui::fill_x(Tui::push_x(5, Tui::bg(fg.darkest.rgb, Tui::fg(fg.lightest.rgb, - PianoHorizontalTimeline { - time_start, - time_zoom, - } - )))), - Tui::split_e(true, 5, Tui::debug(lay!([ - PianoHorizontalNotes { - source: &self.buffer, - time_start, - note_hi, - }, - PianoHorizontalCursor { - time_zoom, - time_point, - time_start, - note_point: note_point, - note_len: note_len, - note_hi: note_hi, - note_lo: note_lo, - }, - ])), PianoHorizontalKeys { - color: self.color, - note_lo, - note_hi, - note_point: Some(note_point), - }), - ))) - ]) + let timeline = move||PianoHorizontalTimeline { + color, + time_start, + time_zoom, + }; + let notes = move||PianoHorizontalNotes { + source: &self.buffer, + time_start, + note_hi, + }; + let cursor = move||PianoHorizontalCursor { + time_zoom, + time_point, + time_start, + note_point: note_point, + note_len: note_len, + note_hi: note_hi, + note_lo: note_lo, + }; + let keys = move||PianoHorizontalKeys { + color: self.color, + note_lo, + note_hi, + note_point: Some(note_point), + }; + Tui::fill_xy(Tui::bg(bg, Tui::split_s(false, 1, + Tui::fill_x(Tui::push_x(5, timeline())), + Tui::split_e(true, 5, Tui::debug(lay!([&self.size, notes(), cursor()])), keys()), + ))) }); pub struct PianoHorizontalTimeline { + color: ItemPalette, time_start: usize, time_zoom: usize, } -render!(|self: PianoHorizontalTimeline|format!("{}*{}", self.time_start, self.time_zoom).as_str()); +render!(|self: PianoHorizontalTimeline|Tui::fg_bg( + self.color.lightest.rgb, + self.color.darkest.rgb, + format!("{}*{}", self.time_start, self.time_zoom).as_str() +)); pub struct PianoHorizontalKeys { color: ItemPalette,