From f9d1456897caeac049f9fa99f86bb52c1507717e Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 9 Dec 2024 20:37:15 +0100 Subject: [PATCH] wip9 (15e) --- crates/tek/src/layout/layers.rs | 11 +- crates/tek/src/layout/stack.rs | 43 ++-- crates/tek/src/tui/app_transport.rs | 4 +- crates/tek/src/tui/engine_output.rs | 9 + crates/tek/src/tui/view_arranger.rs | 240 +++++++++++++-------- crates/tek/src/tui/view_phrase_editor.rs | 53 +++-- crates/tek/src/tui/view_phrase_length.rs | 42 +--- crates/tek/src/tui/view_phrase_list.rs | 14 +- crates/tek/src/tui/view_phrase_selector.rs | 2 +- crates/tek/src/tui/view_sequencer.rs | 41 ++-- crates/tek/src/tui/view_status_bar.rs | 2 +- 11 files changed, 252 insertions(+), 209 deletions(-) diff --git a/crates/tek/src/layout/layers.rs b/crates/tek/src/layout/layers.rs index d9eef72d..353198ab 100644 --- a/crates/tek/src/layout/layers.rs +++ b/crates/tek/src/layout/layers.rs @@ -1,8 +1,15 @@ use crate::*; #[macro_export] macro_rules! lay { - ($(move)*|$add:ident|$expr:expr) => { Layers::new($(move)*|$add|$expr) }; - ($($expr:expr),* $(,)?) => { Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) } + ([$($expr:expr),* $(,)?]) => { + Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + (![$($expr:expr),* $(,)?]) => { + Layers::new(|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + ($expr:expr) => { + Layers::new($expr) + }; } pub struct Layers< diff --git a/crates/tek/src/layout/stack.rs b/crates/tek/src/layout/stack.rs index 2bae0d1b..be309c77 100644 --- a/crates/tek/src/layout/stack.rs +++ b/crates/tek/src/layout/stack.rs @@ -1,21 +1,22 @@ use crate::*; #[macro_export] macro_rules! col { - ($($move:ident)?|$add:ident|$expr:expr) => { - Stack::down($(move)?|$add|$expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::down(move |add|{ - for $pat in $collection { add(&$item)?; } - Ok(()) - }) - }; - ($($expr:expr),* $(,)?) => { + ([$($expr:expr),* $(,)?]) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; + (![$($expr:expr),* $(,)?]) => { + Stack::down(|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + ($expr:expr) => { + Stack::down($expr) + }; + ($pat:pat in $collection:expr => $item:expr) => { + Stack::down(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) + }; } + #[macro_export] macro_rules! col_up { - ($($move:ident)?|$add:ident|$expr:expr) => { + ($(move)?|$add:ident|$expr:expr) => { Stack::up($(move)?|$add|$expr) }; ($pat:pat in $collection:expr => $item:expr) => { @@ -24,17 +25,23 @@ use crate::*; Ok(()) }) }; - ($($expr:expr),* $(,)?) => { Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) }; + ($($expr:expr),* $(,)?) => { + Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; } + #[macro_export] macro_rules! row { - ($($move:ident)?|$add:ident|$expr:expr) => { - Stack::right($(move)?|$add|$expr) + ([$($expr:expr),* $(,)?]) => { + Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + (![$($expr:expr),* $(,)?]) => { + Stack::right(|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + ($expr:expr) => { + Stack::right($expr) }; ($pat:pat in $collection:expr => $item:expr) => { - Stack::right(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; - ($($expr:expr),* $(,)?) => { - Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) + Stack::right(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) }; } diff --git a/crates/tek/src/tui/app_transport.rs b/crates/tek/src/tui/app_transport.rs index 8d9e8adf..0413de2c 100644 --- a/crates/tek/src/tui/app_transport.rs +++ b/crates/tek/src/tui/app_transport.rs @@ -56,7 +56,7 @@ impl FocusWrap for TransportFocus { 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) + lay!([corners, /*highlight,*/ *content]) } } @@ -67,7 +67,7 @@ impl FocusWrap for Option { 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) + lay!([corners, /*highlight,*/ *content]) } } diff --git a/crates/tek/src/tui/engine_output.rs b/crates/tek/src/tui/engine_output.rs index 025c3bfb..5fac2e11 100644 --- a/crates/tek/src/tui/engine_output.rs +++ b/crates/tek/src/tui/engine_output.rs @@ -138,6 +138,15 @@ pub fn buffer_update (buf: &mut Buffer, area: [u16;4], callback: &impl Fn(&mut C } } +impl Render for () { + fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { + Ok(None) + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + Ok(()) + } +} + impl Render for &str { fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { // TODO: line breaks diff --git a/crates/tek/src/tui/view_arranger.rs b/crates/tek/src/tui/view_arranger.rs index d129b369..89b8d25b 100644 --- a/crates/tek/src/tui/view_arranger.rs +++ b/crates/tek/src/tui/view_arranger.rs @@ -8,7 +8,7 @@ render!(|self: ArrangerTui|{ Tui::to_south( self.splits[0], Tui::to_south( - lay!( + lay!([ Layers::new(move |add|{ match self.mode { ArrangerMode::Horizontal => @@ -30,7 +30,7 @@ render!(|self: ArrangerTui|{ })) .fg(TuiTheme::title_fg(arranger_focused)) .push_x(1), - ), + ]), Split::right( self.splits[1], PhraseListView::from(self), @@ -85,6 +85,14 @@ fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> { widths } +fn any_size (_: E::Size) -> Perhaps{ + Ok(Some([0.into(),0.into()].into())) +} + +fn custom_render Usually<()>+Send+Sync> (render: F) -> impl Render { + Widget::new(|_|Ok(Some([0u16,0u16].into())), render) +} + pub fn arranger_content_vertical ( view: &ArrangerTui, factor: usize @@ -100,9 +108,8 @@ pub fn arranger_content_vertical ( let sep_fg = TuiTheme::separator_fg(false); let header_h = 3u16;//5u16; let scenes_w = 3 + ArrangerScene::longest_name(scenes) as u16; // x of 1st track - let rows: &[(usize, usize)] = rows.as_ref(); - let cols: &[(usize, usize)] = cols.as_ref(); - let any_size = |_|Ok(Some([0,0])); + //let rows: &[(usize, usize)] = rows_.as_ref(); + //let cols: &[(usize, usize)] = cols_.as_ref(); // track titles let header = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0)) => { @@ -135,12 +142,12 @@ pub fn arranger_content_vertical ( }).unwrap_or(String::from("▎")); let timer = Tui::to_south(until_next, elapsed); // name of active MIDI input - let input = format!("▎>{}", track.player.midi_ins().get(0) + let _input = format!("▎>{}", track.player.midi_ins().get(0) .map(|port|port.short_name()) .transpose()? .unwrap_or("(none)".into())); // name of active MIDI output - let output = format!("▎<{}", track.player.midi_outs().get(0) + let _output = format!("▎<{}", track.player.midi_outs().get(0) .map(|port|port.short_name()) .transpose()? .unwrap_or("(none)".into())); @@ -189,93 +196,144 @@ pub fn arranger_content_vertical ( ) })); - let arrangement = Tui::bg(bg.rgb, lay!(move|add|{ - // column separators - add(&Widget::new(any_size, move|to: &mut TuiOutput|{ - let style = Some(Style::default().fg(sep_fg)); - Ok(for x in cols.iter().map(|col|col.1) { - let x = scenes_w + to.area().x() + x as u16; - for y in to.area().y()..to.area().y2() { to.blit(&"▎", x, y, style); } - }) - }))?; - // row separators - add(&Widget::new(any_size, move|to: &mut TuiOutput|{ - Ok(for y in rows.iter().map(|row|row.1) { - let y = to.area().y() + (y / PPQ) as u16 + 1; - if y >= to.buffer.area.height { break } - for x in to.area().x()..to.area().x2().saturating_sub(2) { - if x < to.buffer.area.x && y < to.buffer.area.y { - let cell = to.buffer.get_mut(x, y); - cell.modifier = Modifier::UNDERLINED; - cell.underline_color = sep_fg; - } - } - }) - }))?; - // full grid with header and footer - add(&Tui::to_south(header, content))?; - // cursor - add(&Widget::new(any_size, move|to: &mut TuiOutput|{ - let area = to.area(); - let focused = view.arranger_focused(); - let selected = view.selected; - let get_track_area = |t: usize| [ - scenes_w + area.x() + cols[t].1 as u16, area.y(), - cols[t].0 as u16, area.h(), - ]; - let get_scene_area = |s: usize| [ - area.x(), header_h + area.y() + (rows[s].1 / PPQ) as u16, - area.w(), (rows[s].0 / PPQ) as u16 - ]; - let get_clip_area = |t: usize, s: usize| [ - scenes_w + area.x() + cols[t].1 as u16, - header_h + area.y() + (rows[s].1/PPQ) as u16, - cols[t].0 as u16, - (rows[s].0 / PPQ) as u16 - ]; - let mut track_area: Option<[u16;4]> = None; - let mut scene_area: Option<[u16;4]> = None; - let mut clip_area: Option<[u16;4]> = None; - let area = match selected { - ArrangerSelection::Mix => area, - ArrangerSelection::Track(t) => { - track_area = Some(get_track_area(t)); - area - }, - ArrangerSelection::Scene(s) => { - scene_area = Some(get_scene_area(s)); - area - }, - ArrangerSelection::Clip(t, s) => { - track_area = Some(get_track_area(t)); - scene_area = Some(get_scene_area(s)); - clip_area = Some(get_clip_area(t, s)); - area - }, - }; - let bg = TuiTheme::border_bg(); - if let Some([x, y, width, height]) = track_area { - to.fill_fg([x, y, 1, height], bg); - to.fill_fg([x + width, y, 1, height], bg); - } - if let Some([_, y, _, height]) = scene_area { - to.fill_ul([area.x(), y - 1, area.w(), 1], bg); - to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg); - } - Ok(if focused { - to.render_in(if let Some(clip_area) = clip_area { clip_area } - else if let Some(track_area) = track_area { track_area.clip_h(header_h) } - else if let Some(scene_area) = scene_area { scene_area.clip_w(scenes_w) } - else { area.clip_w(scenes_w).clip_h(header_h) }, &CORNERS)? - }) - })) - })); let color = TuiTheme::title_fg(view.arranger_focused()); - let size = format!("{}x{}", view.size.w(), view.size.h()); - let lower_right = Tui::at_se(Tui::fill_xy(Tui::pull_x(1, Tui::fg(color, size)))); - lay!(arrangement, lower_right) + lay!([ + Tui::bg(bg.rgb, lay!(![ + ArrangerVerticalColumnSeparator::from(view), + ArrangerVerticalRowSeparator::from((view, factor)), + col!(![header, content]), + ArrangerCursor::from((view, factor)), + ])), + Tui::at_se(Tui::fill_xy(Tui::pull_x(1, Tui::fg(color, format!("{}x{}", view.size.w(), view.size.h()))))), + ]) } +struct ArrangerVerticalColumnSeparator { + cols: Vec<(usize, usize)>, + scenes_w: u16, + sep_fg: Color, +} +impl From<&ArrangerTui> for ArrangerVerticalColumnSeparator { + fn from (state: &ArrangerTui) -> Self { + Self { + cols: track_widths(state.tracks()), + scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, + sep_fg: TuiTheme::separator_fg(false), + } + } +} +render!(|self: ArrangerVerticalColumnSeparator|custom_render(move|to: &mut TuiOutput|{ + let style = Some(Style::default().fg(self.sep_fg)); + Ok(for x in self.cols.iter().map(|col|col.1) { + let x = self.scenes_w + to.area().x() + x as u16; + for y in to.area().y()..to.area().y2() { + to.blit(&"▎", x, y, style); + } + }) +})); + +struct ArrangerVerticalRowSeparator { + rows: Vec<(usize, usize)>, + sep_fg: Color, +} +impl From<(&ArrangerTui, usize)> for ArrangerVerticalRowSeparator { + fn from ((state, factor): (&ArrangerTui, usize)) -> Self { + Self { + rows: ArrangerScene::ppqs(state.scenes(), factor), + sep_fg: TuiTheme::separator_fg(false), + } + } +} + +render!(|self: ArrangerVerticalRowSeparator|custom_render(move|to: &mut TuiOutput|{ + Ok(for y in self.rows.iter().map(|row|row.1) { + let y = to.area().y() + (y / PPQ) as u16 + 1; + if y >= to.buffer.area.height { break } + for x in to.area().x()..to.area().x2().saturating_sub(2) { + if x < to.buffer.area.x && y < to.buffer.area.y { + let cell = to.buffer.get_mut(x, y); + cell.modifier = Modifier::UNDERLINED; + cell.underline_color = self.sep_fg; + } + } + }) +})); + +struct ArrangerCursor { + cols: Vec<(usize, usize)>, + rows: Vec<(usize, usize)>, + focused: bool, + selected: ArrangerSelection, + scenes_w: u16, + header_h: u16, +} +impl From<(&ArrangerTui, usize)> for ArrangerCursor { + fn from ((state, factor): (&ArrangerTui, usize)) -> Self { + Self { + cols: track_widths(state.tracks()), + rows: ArrangerScene::ppqs(state.scenes(), factor), + focused: state.arranger_focused(), + selected: state.selected, + scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, + header_h: 3, + } + } +} +render!(|self: ArrangerCursor|custom_render(move|to: &mut TuiOutput|{ + let area = to.area(); + let focused = self.focused; + let selected = self.selected; + let get_track_area = |t: usize| [ + self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(), + self.cols[t].0 as u16, area.h(), + ]; + let get_scene_area = |s: usize| [ + area.x(), self.header_h + area.y() + (self.rows[s].1 / PPQ) as u16, + area.w(), (self.rows[s].0 / PPQ) as u16 + ]; + let get_clip_area = |t: usize, s: usize| [ + self.scenes_w + area.x() + self.cols[t].1 as u16, + self.header_h + area.y() + (self.rows[s].1/PPQ) as u16, + self.cols[t].0 as u16, + (self.rows[s].0 / PPQ) as u16 + ]; + let mut track_area: Option<[u16;4]> = None; + let mut scene_area: Option<[u16;4]> = None; + let mut clip_area: Option<[u16;4]> = None; + let area = match selected { + ArrangerSelection::Mix => area, + ArrangerSelection::Track(t) => { + track_area = Some(get_track_area(t)); + area + }, + ArrangerSelection::Scene(s) => { + scene_area = Some(get_scene_area(s)); + area + }, + ArrangerSelection::Clip(t, s) => { + track_area = Some(get_track_area(t)); + scene_area = Some(get_scene_area(s)); + clip_area = Some(get_clip_area(t, s)); + area + }, + }; + let bg = TuiTheme::border_bg(); + if let Some([x, y, width, height]) = track_area { + to.fill_fg([x, y, 1, height], bg); + to.fill_fg([x + width, y, 1, height], bg); + } + if let Some([_, y, _, height]) = scene_area { + to.fill_ul([area.x(), y - 1, area.w(), 1], bg); + to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg); + } + Ok(if focused { + to.render_in(if let Some(clip_area) = clip_area { clip_area } + else if let Some(track_area) = track_area { track_area.clip_h(self.header_h) } + else if let Some(scene_area) = scene_area { scene_area.clip_w(self.scenes_w) } + else { area.clip_w(self.scenes_w).clip_h(self.header_h) }, &CORNERS)? + }) +})); + pub fn arranger_content_horizontal ( view: &ArrangerTui, ) -> impl Render + use<'_> { diff --git a/crates/tek/src/tui/view_phrase_editor.rs b/crates/tek/src/tui/view_phrase_editor.rs index b651e67d..7de495b2 100644 --- a/crates/tek/src/tui/view_phrase_editor.rs +++ b/crates/tek/src/tui/view_phrase_editor.rs @@ -63,31 +63,6 @@ render!(|self: PhraseView<'a>|{ //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 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) }) @@ -124,7 +99,24 @@ render!(|self: PhraseView<'a>|{ ////} //Ok(()) //}; - let indicators = lay!(|add|{ + let indicators = lay!(move|add|{ + let title_color = if *focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)}; + 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 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()), + ) + }; 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)))))?; @@ -133,12 +125,15 @@ render!(|self: PhraseView<'a>|{ }); let content = 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::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)) - )), + ])), ))); - lay!(indicators, content) + lay!([ + indicators, + content + ]) }); #[derive(Copy, Clone, Debug)] diff --git a/crates/tek/src/tui/view_phrase_length.rs b/crates/tek/src/tui/view_phrase_length.rs index 79e0bee1..c20423d3 100644 --- a/crates/tek/src/tui/view_phrase_length.rs +++ b/crates/tek/src/tui/view_phrase_length.rs @@ -1,45 +1,17 @@ use crate::*; -render!(|self:PhraseLength|{ +render!(|self: PhraseLength|{ let bars = ||self.bars_string(); let beats = ||self.beats_string(); let ticks = ||self.ticks_string(); - row!(|add|(match self.focus { + row!(move|add|match self.focus { None => - add(&row!(" ", bars(), "B", beats(), "b", ticks(), "T")), + add(&row!([" ", bars(), "B", beats(), "b", ticks(), "T"])), Some(PhraseLengthFocus::Bar) => - add(&row!("[", bars(), "]", beats(), "b", ticks(), "T")), + add(&row!(["[", bars(), "]", beats(), "b", ticks(), "T"])), Some(PhraseLengthFocus::Beat) => - add(&row!(" ", bars(), "[", beats(), "]", ticks(), "T")), + add(&row!([" ", bars(), "[", beats(), "]", ticks(), "T"])), Some(PhraseLengthFocus::Tick) => - add(&row!(" ", bars(), "B", beats(), "[", ticks(), "]")), - })) - //Layers::new(move|add|{ - //match self.focus { - //None => add(&row!( - //" ", self.bars_string(), - //".", self.beats_string(), - //".", self.ticks_string(), - //" " - //)), - //Some(PhraseLengthFocus::Bar) => add(&row!( - //"[", self.bars_string(), - //"]", self.beats_string(), - //".", self.ticks_string(), - //" " - //)), - //Some(PhraseLengthFocus::Beat) => add(&row!( - //" ", self.bars_string(), - //"[", self.beats_string(), - //"]", self.ticks_string(), - //" " - //)), - //Some(PhraseLengthFocus::Tick) => add(&row!( - //" ", self.bars_string(), - //".", self.beats_string(), - //"[", self.ticks_string(), - //"]" - //)), - //} - //}) + add(&row!([" ", bars(), "B", beats(), "[", ticks(), "]"])), + }) }); diff --git a/crates/tek/src/tui/view_phrase_list.rs b/crates/tek/src/tui/view_phrase_list.rs index bda7f5f5..a9a6a0f2 100644 --- a/crates/tek/src/tui/view_phrase_list.rs +++ b/crates/tek/src/tui/view_phrase_list.rs @@ -25,7 +25,7 @@ impl<'a, T: HasPhraseList> From<&'a T> for PhraseListView<'a> { // TODO: Display phrases always in order of appearance render!(|self: PhraseListView<'a>|{ let Self { title, focused, entered, phrases, index, mode } = self; - let content = Stack::down(move|add|match mode { + let content = col!(|add|match mode { Some(PhrasesMode::Import(_, ref browser)) => { add(browser) }, @@ -34,7 +34,7 @@ render!(|self: PhraseListView<'a>|{ }, _ => { for (i, phrase) in phrases.iter().enumerate() { - add(&Layers::new(|add|{ + add(&lay!(|add|{ let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); let mut length = PhraseLength::new(length, None); if let Some(PhrasesMode::Length(phrase, new_length, focus)) = mode { @@ -44,7 +44,7 @@ render!(|self: PhraseListView<'a>|{ } } let length = Tui::fill_x(Tui::at_e(length)); - let row1 = Tui::fill_x(lay!(Tui::fill_x(Tui::at_w(format!(" {i}"))), length)); + let row1 = Tui::fill_x(lay!([Tui::fill_x(Tui::at_w(format!(" {i}"))), length])); let mut row2 = format!(" {name}"); if let Some(PhrasesMode::Rename(phrase, _)) = mode { if *focused && i == *phrase { @@ -63,13 +63,13 @@ render!(|self: PhraseListView<'a>|{ } }); let border_color = if *focused {Color::Rgb(100, 110, 40)} else {Color::Rgb(70, 80, 50)}; - 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!( - Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)).wrap(content), + lay!([ + Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color)) + .wrap(Tui::bg(Color::Rgb(28, 35, 25), Tui::fill_xy(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 1eb1ff72..248c3979 100644 --- a/crates/tek/src/tui/view_phrase_selector.rs +++ b/crates/tek/src/tui/view_phrase_selector.rs @@ -42,7 +42,7 @@ render!(|self:PhraseSelector<'a>|{ 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 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))))?; diff --git a/crates/tek/src/tui/view_sequencer.rs b/crates/tek/src/tui/view_sequencer.rs index 80b16050..5b67aa20 100644 --- a/crates/tek/src/tui/view_sequencer.rs +++ b/crates/tek/src/tui/view_sequencer.rs @@ -2,16 +2,6 @@ use crate::*; render!(|self: SequencerTui|{ - let play = PhraseSelector::play_phrase( - &self.player, - self.focused() == SequencerFocus::PhrasePlay, - self.entered() - ); - let next = PhraseSelector::next_phrase( - &self.player, - self.focused() == SequencerFocus::PhraseNext, - self.entered() - ); Tui::to_north( SequencerStatusBar::from(self), Tui::to_south( @@ -19,14 +9,19 @@ render!(|self: SequencerTui|{ Tui::min_y( 20, Tui::to_east( - 20, - Tui::to_south( - Tui::fixed_y(4, play), - Tui::to_south( - Tui::fixed_y(4, next), - PhraseListView::from(self) - ) - ), + Tui::min_x(20, col!([ + Tui::fixed_y(4, PhraseSelector::play_phrase( + &self.player, + self.focused() == SequencerFocus::PhrasePlay, + self.entered() + )), + Tui::fixed_y(4, PhraseSelector::next_phrase( + &self.player, + self.focused() == SequencerFocus::PhraseNext, + self.entered() + )), + PhraseListView::from(self) + ])), PhraseView::from(self) ) ) @@ -45,7 +40,7 @@ render!(|self: SequencerStatusBar|{ Tui::to_east( Tui::bg(orange, Tui::fg(black, Tui::bold(true, self.mode))), Tui::bg(light, row!((prefix, hotkey, suffix) in self.help.iter() => { - row!(" ", prefix, Tui::fg(yellow, *hotkey), suffix) + row!([" ", prefix, Tui::fg(yellow, *hotkey), suffix]) })) ) }; @@ -55,17 +50,17 @@ render!(|self: SequencerStatusBar|{ let cpu = &self.cpu; let res = &self.res; let size = &self.size; - Tui::bg(dark, row!( + Tui::bg(dark, row!([ Tui::fg(orange, cpu), Tui::fg(orange, res), Tui::fg(orange, size), - )) + ])) }; lay!(|add|if self.width > 60 { - add(&row!(modeline, statusbar)) + add(&row!(![modeline, statusbar])) } else if self.width > 0 { - add(&col!(modeline, statusbar)) + add(&col!(![modeline, statusbar])) } else { Ok(()) }) diff --git a/crates/tek/src/tui/view_status_bar.rs b/crates/tek/src/tui/view_status_bar.rs index 5b919be9..b3af3c5b 100644 --- a/crates/tek/src/tui/view_status_bar.rs +++ b/crates/tek/src/tui/view_status_bar.rs @@ -11,7 +11,7 @@ pub trait StatusBar: Render { { let hotkey_fg = Self::hotkey_fg(); row!([a, b, c] in commands.iter() => { - row!(a, Tui::fg(hotkey_fg, Tui::bold(true, b)), c) + row!([a, Tui::fg(hotkey_fg, Tui::bold(true, b)), c]) }) //Tui::reduce(commands.iter(), |prev, [a, b, c]| //Tui::to_east(prev,