From 7d78811f6869fc0acd53b77198c2162017b4b158 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 9 Dec 2024 17:53:08 +0100 Subject: [PATCH] wip5 (66e): kk --- crates/tek/src/tui/engine_style.rs | 3 + crates/tek/src/tui/view_phrase_editor.rs | 174 ++++++++++----------- crates/tek/src/tui/view_phrase_list.rs | 9 +- crates/tek/src/tui/view_phrase_selector.rs | 49 +++--- 4 files changed, 117 insertions(+), 118 deletions(-) diff --git a/crates/tek/src/tui/engine_style.rs b/crates/tek/src/tui/engine_style.rs index e1c1c61e..bbc04e39 100644 --- a/crates/tek/src/tui/engine_style.rs +++ b/crates/tek/src/tui/engine_style.rs @@ -112,6 +112,9 @@ impl Render for Styled<&str> { } pub trait BorderStyle: Send + Sync + Copy { + fn wrap > (self, w: W) -> Bordered { + Bordered(self, w) + } const NW: &'static str = ""; const N: &'static str = ""; const NE: &'static str = ""; diff --git a/crates/tek/src/tui/view_phrase_editor.rs b/crates/tek/src/tui/view_phrase_editor.rs index 58041b97..026f18d9 100644 --- a/crates/tek/src/tui/view_phrase_editor.rs +++ b/crates/tek/src/tui/view_phrase_editor.rs @@ -52,96 +52,94 @@ impl<'a, T: HasEditor> From<&'a T> for PhraseView<'a> { } } -impl<'a> Content for PhraseView<'a> { - fn content (&self) -> impl Render { - let Self { - focused, entered, size, - phrase, view_mode, buffer, - note_point, note_len, - note_range: (note_lo, note_hi), - note_names: (note_lo_name, note_hi_name), - time_start, time_point, - //now: _, - .. - } = self; - let upper_left = format!( - "╭{note_hi} {note_hi_name} {}", - phrase.as_ref().map(|p|p.read().unwrap().name.clone()).unwrap_or(String::new()) +render!(|self: PhraseView<'a>|{ + let Self { + focused, entered, size, + phrase, view_mode, buffer, + note_point, note_len, + note_range: (note_lo, note_hi), + note_names: (note_lo_name, note_hi_name), + time_start, time_point, + //now: _, + .. + } = self; + let upper_left = format!( + "╭{note_hi} {note_hi_name} {}", + phrase.as_ref().map(|p|p.read().unwrap().name.clone()).unwrap_or(String::new()) + ); + let lower_left = format!( + "╰{note_lo} {note_lo_name}" + ); + let mut lower_right = format!( + " {} ", size.format() + ); + if *focused && *entered { + lower_right = format!("Note: {} ({}) {} {lower_right}", + note_point, to_note_name(*note_point), pulses_to_name(*note_len) ); - let lower_left = format!( - "╰{note_lo} {note_lo_name}" - ); - let mut lower_right = format!( - " {} ", size.format() - ); - if *focused && *entered { - lower_right = format!("Note: {} ({}) {} {lower_right}", - note_point, to_note_name(*note_point), pulses_to_name(*note_len) - ); - } - let mut upper_right = format!( - "[{}]", - if *entered {"■"} else {" "} - ); - if let Some(phrase) = phrase { - upper_right = format!("Time: {}/{} {} {upper_right}", - time_point, phrase.read().unwrap().length, pulses_to_name(view_mode.time_zoom()), - ) - }; - let title_color = if *focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)}; - // is it r6d that `to` is the receiver? - let keys = move|to: &mut TuiOutput|{ - Ok(if to.area().h() >= 2 { view_mode.render_keys(to, *note_hi, *note_lo) }) - }; - let notes = |to: &mut TuiOutput|{ - size.set_wh(to.area.w(), to.area.h() as usize - 1); - let draw = to.area().h() >= 2; - Ok(if draw { view_mode.render_notes(to, buffer, *time_start, *note_hi) }) - }; - let cursor = move|to: &mut TuiOutput|{ - Ok(if *focused && *entered { - view_mode.render_cursor( - to, - *time_point, *time_start, view_mode.time_zoom(), - *note_point, *note_len, *note_hi, *note_lo, - ) - }) - }; - //let playhead = move|_: &mut TuiOutput|{ // will this live or die? - ////let playhead_inactive = Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(40,50,30)); - ////let playhead_active = playhead_inactive.clone().yellow().bold().not_dim(); - ////if let Some(_) = phrase { - ////let now = now.get() as usize; // TODO FIXME: self.now % phrase.read().unwrap().length; - ////let time_clamp = time_clamp; - ////for x in 0..(time_clamp/time_zoom).saturating_sub(*time_start) { - ////let this_step = time_start + (x + 0) * time_zoom; - ////let next_step = time_start + (x + 1) * time_zoom; - ////let x = to.area().x() + x as u16; - ////let active = this_step <= now && now < next_step; - ////let character = if active { "|" } else { "·" }; - ////let style = if active { playhead_active } else { playhead_inactive }; - ////to.blit(&character, x, to.area.y(), Some(style)); - ////} - ////} - //Ok(()) - //}; - Tui::layers() - .add(Tui::layers() - .add(Tui::at_nw(Tui::fg(title_color, upper_left))) - .add(Tui::at_sw(Tui::fg(title_color, lower_left))) - .add(Tui::fill_xy(Tui::at_ne(Tui::pull_x(1, Tui::fg(title_color, upper_right))))) - .add(Tui::fill_xy(Tui::at_se(Tui::pull_x(1, Tui::fg(title_color, lower_right)))))) - .add(Tui::bg( - Color::Rgb(40, 50, 30), - Tui::fill_x(Tui::to_east( - Tui::push_y(1, Tui::fill_y(Widget::new(|to:[u16;2]|Ok(Some(to.clip_w(2))), keys))), - Tui::fill_x(lay!( - Tui::push_y(1, Tui::fill_x(Widget::new(|to|Ok(Some(to)), notes))), - Tui::push_y(1, Widget::new(|to|Ok(Some(to)), cursor)) - )), - )))) } -} + let mut upper_right = format!( + "[{}]", + if *entered {"■"} else {" "} + ); + if let Some(phrase) = phrase { + upper_right = format!("Time: {}/{} {} {upper_right}", + time_point, phrase.read().unwrap().length, pulses_to_name(view_mode.time_zoom()), + ) + }; + let title_color = if *focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)}; + // is it r6d that `to` is the receiver? + let keys = move|to: &mut TuiOutput|{ + Ok(if to.area().h() >= 2 { view_mode.render_keys(to, *note_hi, *note_lo) }) + }; + let notes = |to: &mut TuiOutput|{ + size.set_wh(to.area.w(), to.area.h() as usize - 1); + let draw = to.area().h() >= 2; + Ok(if draw { view_mode.render_notes(to, buffer, *time_start, *note_hi) }) + }; + let cursor = move|to: &mut TuiOutput|{ + Ok(if *focused && *entered { + view_mode.render_cursor( + to, + *time_point, *time_start, view_mode.time_zoom(), + *note_point, *note_len, *note_hi, *note_lo, + ) + }) + }; + //let playhead = move|_: &mut TuiOutput|{ // will this live or die? + ////let playhead_inactive = Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(40,50,30)); + ////let playhead_active = playhead_inactive.clone().yellow().bold().not_dim(); + ////if let Some(_) = phrase { + ////let now = now.get() as usize; // TODO FIXME: self.now % phrase.read().unwrap().length; + ////let time_clamp = time_clamp; + ////for x in 0..(time_clamp/time_zoom).saturating_sub(*time_start) { + ////let this_step = time_start + (x + 0) * time_zoom; + ////let next_step = time_start + (x + 1) * time_zoom; + ////let x = to.area().x() + x as u16; + ////let active = this_step <= now && now < next_step; + ////let character = if active { "|" } else { "·" }; + ////let style = if active { playhead_active } else { playhead_inactive }; + ////to.blit(&character, x, to.area.y(), Some(style)); + ////} + ////} + //Ok(()) + //}; + Tui::layers() + .add(Tui::layers() + .add(Tui::at_nw(Tui::fg(title_color, upper_left))) + .add(Tui::at_sw(Tui::fg(title_color, lower_left))) + .add(Tui::fill_xy(Tui::at_ne(Tui::pull_x(1, Tui::fg(title_color, upper_right))))) + .add(Tui::fill_xy(Tui::at_se(Tui::pull_x(1, Tui::fg(title_color, lower_right)))))) + .add(Tui::bg( + Color::Rgb(40, 50, 30), + Tui::fill_x(Tui::to_east( + Tui::push_y(1, Tui::fill_y(Widget::new(|to:[u16;2]|Ok(Some(to.clip_w(2))), keys))), + Tui::fill_x(lay!( + Tui::push_y(1, Tui::fill_x(Widget::new(|to|Ok(Some(to)), notes))), + Tui::push_y(1, Widget::new(|to|Ok(Some(to)), cursor)) + )), + )))) +}); #[derive(Copy, Clone, Debug)] pub enum PhraseViewMode { diff --git a/crates/tek/src/tui/view_phrase_list.rs b/crates/tek/src/tui/view_phrase_list.rs index ecdc21ca..d213e642 100644 --- a/crates/tek/src/tui/view_phrase_list.rs +++ b/crates/tek/src/tui/view_phrase_list.rs @@ -63,14 +63,13 @@ render!(|self: PhraseListView<'a>|{ } }); let border_color = if *focused {Color::Rgb(100, 110, 40)} else {Color::Rgb(70, 80, 50)}; - let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)); - let content = content.fill_xy().bg(Color::Rgb(28, 35, 25)).border(border); + let content = Tui::bg(Color::Rgb(28, 35, 25), Tui::fill_xy(content)); let title_color = if *focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)}; let upper_left = format!("[{}] {title}", if *entered {"■"} else {" "}); let upper_right = format!("({})", phrases.len()); lay!( - content, - Tui::fg(title_color, upper_left.to_string()).push_x(1).align_nw().fill_xy(), - Tui::fg(title_color, upper_right.to_string()).pull_x(1).align_ne().fill_xy(), + Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)).wrap(content), + Tui::fill_xy(Tui::at_nw(Tui::push_x(1, Tui::fg(title_color, upper_left.to_string())))), + Tui::fill_xy(Tui::at_ne(Tui::pull_x(1, Tui::fg(title_color, upper_right.to_string())))), ) }); diff --git a/crates/tek/src/tui/view_phrase_selector.rs b/crates/tek/src/tui/view_phrase_selector.rs index 7636a8af..1eb1ff72 100644 --- a/crates/tek/src/tui/view_phrase_selector.rs +++ b/crates/tek/src/tui/view_phrase_selector.rs @@ -35,28 +35,27 @@ impl<'a> PhraseSelector<'a> { } // TODO: Display phrases always in order of appearance -impl<'a> Content for PhraseSelector<'a> { - fn content (&self) -> impl Render { - let Self { title, phrase, focused, entered } = self; - let content = Layers::new(move|add|{ - if let Some((instant, Some(phrase))) = phrase { - let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); - let length = PhraseLength::new(length, None); - let length = length.align_e().fill_x(); - let row1 = lay!(format!(" ").align_w().fill_x(), length).fill_x(); - let row2 = format!(" {name}"); - let row2 = TuiStyle::bold(row2, true); - add(&Tui::bg(color.base.rgb, Tui::fill_x(Tui::to_south(row1, row2))))?; - } - Ok(()) - }); - let border_color = if *focused {Color::Rgb(100, 110, 40)} else {Color::Rgb(70, 80, 50)}; - let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)); - let content = content.fill_xy().bg(Color::Rgb(28, 35, 25)).border(border); - let title_color = if *focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)}; - lay!( - content, - TuiStyle::fg(*title, title_color).push_x(1).align_nw().fill_xy(), - ) - } -} +render!(|self:PhraseSelector<'a>|{ + let Self { title, phrase, focused, entered } = self; + let content = Layers::new(move|add|{ + if let Some((instant, Some(phrase))) = phrase { + let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); + let length = PhraseLength::new(length, None); + let length = Tui::fill_x(Tui::at_e(length)); + let row1 = Tui::fill_x(lay!(Tui::fill_x(Tui::at_w(format!(" "))), length)); + let row2 = format!(" {name}"); + let row2 = Tui::bold(true, row2); + add(&Tui::bg(color.base.rgb, Tui::fill_x(Tui::to_south(row1, row2))))?; + } + Ok(()) + }); + let border_color = if *focused {Color::Rgb(100, 110, 40)} else {Color::Rgb(70, 80, 50)}; + let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)); + //let content = Tui::bg(Color::Rgb(28, 35, 25), Tui::fill_xy(content)).border(border); + let content = Tui::bg(Color::Rgb(28, 35, 25), Tui::fill_xy(content)); + let title_color = if *focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)}; + Tui::over( + border.wrap(content), + Tui::fill_xy(Tui::at_nw(Tui::push_x(1, Tui::fg(title_color, *title)))), + ) +});