diff --git a/crates/tek_layout/src/bsp.rs b/crates/tek_layout/src/bsp.rs index d916ae33..3ab5093b 100644 --- a/crates/tek_layout/src/bsp.rs +++ b/crates/tek_layout/src/bsp.rs @@ -46,7 +46,7 @@ pub struct ToNorth, B: Render>(Option, A, B) pub struct ToSouth, B: Render>(Option, A, B); -pub struct ToEast, B: Render>(Option, A, B); +pub struct ToEast(Option, A, B); pub struct ToWest, B: Render>(Option, A, B); @@ -68,6 +68,15 @@ impl, B: Render> Render for ToSouth { } } +impl, B: Render> Render for ToWest { + fn min_size (&self, _: E::Size) -> Perhaps { + todo!(); + } + fn render (&self, _: &mut E::Output) -> Usually<()> { + Ok(()) + } +} + impl, B: Render> Render for ToEast { fn min_size (&self, _: E::Size) -> Perhaps { todo!(); diff --git a/crates/tek_layout/src/fixed.rs b/crates/tek_layout/src/fixed.rs index 67b01e24..e82cbf7c 100644 --- a/crates/tek_layout/src/fixed.rs +++ b/crates/tek_layout/src/fixed.rs @@ -2,15 +2,15 @@ use crate::*; impl> LayoutFixed for W {} -pub trait LayoutFixed: Render + Sized { - fn fixed_x (self, x: E::Unit) -> Fixed { - Fixed::X(x, self) +pub trait LayoutFixed { + fn fixed_x > (x: E::Unit, w: W) -> Fixed { + Fixed::X(x, w) } - fn fixed_y (self, y: E::Unit) -> Fixed { - Fixed::Y(y, self) + fn fixed_y > (y: E::Unit, w: W) -> Fixed { + Fixed::Y(y, w) } - fn fixed_xy (self, x: E::Unit, y: E::Unit) -> Fixed { - Fixed::XY(x, y, self) + fn fixed_xy > (x: E::Unit, y: E::Unit, w: W) -> Fixed { + Fixed::XY(x, y, w) } } diff --git a/crates/tek_layout/src/map_reduce.rs b/crates/tek_layout/src/map_reduce.rs index e407603f..3afa1fc8 100644 --- a/crates/tek_layout/src/map_reduce.rs +++ b/crates/tek_layout/src/map_reduce.rs @@ -1,20 +1,16 @@ use crate::*; -impl LayoutMapReduce for E {} +impl, T, R: Render> LayoutMapReduce for E {} -pub trait LayoutMapReduce { - fn map (iterator: I, callback: F) -> Map +pub trait LayoutMapReduce, T, R: Render> { + fn map (iterator: I, callback: F) -> Map where - I: Iterator, - R: Render, F: Fn(T)->R { Map(Default::default(), iterator, callback) } - fn reduce (iterator: I, callback: F) -> Reduce + fn reduce (iterator: I, callback: F) -> Reduce where - I: Iterator, - R: Render, F: Fn(R, T)->R { Reduce(Default::default(), iterator, callback) diff --git a/crates/tek_tui/src/tui_view_arranger.rs b/crates/tek_tui/src/tui_view_arranger.rs index 1d713133..48ca0cd6 100644 --- a/crates/tek_tui/src/tui_view_arranger.rs +++ b/crates/tek_tui/src/tui_view_arranger.rs @@ -103,34 +103,11 @@ pub fn arranger_content_vertical ( let rows: &[(usize, usize)] = rows.as_ref(); let cols: &[(usize, usize)] = cols.as_ref(); let any_size = |_|Ok(Some([0,0])); - let arrangement = Layers::new(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; - } - } - }) - }))?; - - // track titles - let header = Tui::reduce(tracks.iter().zip(cols.iter().map(|col|col.0)), |prev, (track, w)|{ + // track titles + let header = Tui::reduce( + tracks.iter().zip(cols.iter().map(|col|col.0)), + |prev, (track, w)|{ // name and width of track let name = track.name().read().unwrap(); let max_w = w.saturating_sub(1).min(name.len()).max(2); @@ -158,6 +135,7 @@ pub fn arranger_content_vertical ( String::new() } }).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) .map(|port|port.short_name()) @@ -168,55 +146,77 @@ pub fn arranger_content_vertical ( .map(|port|port.short_name()) .transpose()? .unwrap_or("(none)".into())); - let current = - Tui::push_x(scenes_w, - Tui::bg(track.color().rgb, - Tui::min_xy(w as u16, header_h, - Tui::to_south(name, Tui::to_south(until_next, elapsed))))); - Tui::to_east(prev, current) - }); + //Tui::to_east(prev, Tui::push_x(scenes_w, + //Tui::bg(track.color().rgb, + //Tui::min_xy(w as u16, header_h, + //Tui::to_south(name, timer))))) + prev + } + ); - // tracks and scenes - let content = Tui::fixed_y((view.size.h() as u16).saturating_sub(header_h), Tui::reduce( - scenes.iter().zip(rows.iter().map(|row|row.0)), - |(scene, pulses)| { - let height = 1.max((pulses / PPQ) as u16); - let playing = scene.is_playing(tracks); - Tui::fixed_y( - height, + let content = Tui::fixed_y((view.size.h() as u16).saturating_sub(header_h), Tui::reduce( + scenes.iter().zip(rows.iter().map(|row|row.0)), + |(scene, pulses)| { + let height = 1.max((pulses / PPQ) as u16); + let playing = scene.is_playing(tracks); + Tui::fixed_y( + height, + Tui::to_east( Tui::to_east( - Tui::to_east( - if playing { "▶ " } else { " " }, - Tui::bold(true, scene.name.read().unwrap().as_str()) - ), - Tui::iter( - cols.iter().map(|col|col.0).enumerate(), - |(track, w)|Tui::fixed_xy(w as u16, height, Layers::new(move |add|{ - let mut bg = clip_bg; - match (tracks.get(track), scene.clips.get(track)) { - (Some(track), 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)); - let color = phrase.read().unwrap().color; - add(&name.as_str()[0..max_w].push_x(1).fixed_x(w as u16))?; - bg = color.dark.rgb; - if let Some((_, Some(ref playing))) = track.player.play_phrase() { - if *playing.read().unwrap() == *phrase.read().unwrap() { - bg = color.light.rgb - } - }; - }, - _ => {} - }; - add(&Background(bg)) - })) - ) + if playing { "▶ " } else { " " }, + Tui::bold(true, scene.name.read().unwrap().as_str()) + ), + Tui::iter( + cols.iter().map(|col|col.0).enumerate(), + |(track, w)|Tui::fixed_xy(w as u16, height, Layers::new(move |add|{ + let mut bg = clip_bg; + match (tracks.get(track), scene.clips.get(track)) { + (Some(track), 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)); + let color = phrase.read().unwrap().color; + add(&name.as_str()[0..max_w].push_x(1).fixed_x(w as u16))?; + bg = color.dark.rgb; + if let Some((_, Some(ref playing))) = track.player.play_phrase() { + if *playing.read().unwrap() == *phrase.read().unwrap() { + bg = color.light.rgb + } + }; + }, + _ => {} + }; + add(&Background(bg)) + })) ) ) - } - )); + ) + } + )); + let arrangement = Layers::new(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