add RenderThunk, LayoutThunk, Map::new, fold some components into arranger methods

This commit is contained in:
🪞👃🪞 2025-01-07 17:38:28 +01:00
parent 38e2e64751
commit b2fb71b405
8 changed files with 268 additions and 178 deletions

View file

@ -1,10 +1,28 @@
use crate::*; use crate::*;
use std::marker::PhantomData; use std::marker::PhantomData;
/// Lazily-evaluated [Render]able. /// Lazily-evaluated [Render]able.
pub struct Thunk<E: Output, T: Render<E>, F: Fn()->T + Send + Sync>(F, PhantomData<E>); pub struct Thunk<E: Output, T: Render<E>, F: Fn()->T + Send + Sync>(PhantomData<E>, F);
impl<E: Output, T: Render<E>, F: Fn()->T + Send + Sync> Thunk<E, T, F> { impl<E: Output, T: Render<E>, F: Fn()->T + Send + Sync> Thunk<E, T, F> {
pub fn new (thunk: F) -> Self { Self(thunk, Default::default()) } pub fn new (thunk: F) -> Self { Self(Default::default(), thunk) }
} }
impl<E: Output, T: Render<E>, F: Fn()->T + Send + Sync> Content<E> for Thunk<E, T, F> { impl<E: Output, T: Render<E>, F: Fn()->T + Send + Sync> Content<E> for Thunk<E, T, F> {
fn content (&self) -> impl Render<E> { (self.0)() } fn content (&self) -> impl Render<E> { (self.1)() }
}
pub struct RenderThunk<E: Output, F: Fn(&mut E) + Send + Sync>(PhantomData<E>, F);
impl<E: Output, F: Fn(&mut E) + Send + Sync> RenderThunk<E, F> {
pub fn new (render: F) -> Self { Self(Default::default(), render) }
}
impl<E: Output, F: Fn(&mut E) + Send + Sync> Content<E> for RenderThunk<E, F> {
fn render (&self, to: &mut E) { (self.1)(to) }
}
pub struct LayoutThunk<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync>(PhantomData<E>, F1, F2);
impl<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> LayoutThunk<E, F1, F2> {
pub fn new (layout: F1, render: F2) -> Self { Self(Default::default(), layout, render) }
}
impl<E: Output, F1: Fn(E::Area)->E::Area + Send + Sync, F2: Fn(&mut E) + Send + Sync> Content<E> for LayoutThunk<E, F1, F2> {
fn layout (&self, to: E::Area) -> E::Area { (self.1)(to) }
fn render (&self, to: &mut E) { (self.2)(to) }
} }

View file

@ -10,20 +10,30 @@ pub fn map_south<O: Output>(
Fill::x(item)))) Fill::x(item))))
} }
pub struct Map<A, B, I, F, G>(pub F, pub G) where pub struct Map<'a, A, B, I, F, G>(pub PhantomData<&'a()>, pub F, pub G) where
I: Iterator<Item = A> + Send + Sync, I: Iterator<Item = A> + Send + Sync,
F: Fn() -> I + Send + Sync, F: Fn() -> I + Send + Sync + 'a,
G: Fn(A, usize)->B + Send + Sync; G: Fn(A, usize)->B + Send + Sync;
impl<E, A, B, I, F, G> Content<E> for Map<A, B, I, F, G> where impl<'a, A, B, I, F, G> Map<'a, A, B, I, F, G> where
I: Iterator<Item = A> + Send + Sync,
F: Fn() -> I + Send + Sync + 'a,
G: Fn(A, usize)->B + Send + Sync
{
pub fn new (f: F, g: G) -> Self {
Self(Default::default(), f, g)
}
}
impl<'a, E, A, B, I, F, G> Content<E> for Map<'a, A, B, I, F, G> where
E: Output, E: Output,
B: Render<E>, B: Render<E>,
I: Iterator<Item = A> + Send + Sync, I: Iterator<Item = A> + Send + Sync,
F: Fn() -> I + Send + Sync, F: Fn() -> I + Send + Sync + 'a,
G: Fn(A, usize)->B + Send + Sync G: Fn(A, usize)->B + Send + Sync
{ {
fn layout (&self, area: E::Area) -> E::Area { fn layout (&self, area: E::Area) -> E::Area {
let Self(get_iterator, callback) = self; let Self(_, get_iterator, callback) = self;
let mut index = 0; let mut index = 0;
let [mut min_x, mut min_y] = area.center(); let [mut min_x, mut min_y] = area.center();
let [mut max_x, mut max_y] = area.center(); let [mut max_x, mut max_y] = area.center();
@ -42,7 +52,7 @@ impl<E, A, B, I, F, G> Content<E> for Map<A, B, I, F, G> where
area.center_xy([w.into(), h.into()].into()).into() area.center_xy([w.into(), h.into()].into()).into()
} }
fn render (&self, to: &mut E) { fn render (&self, to: &mut E) {
let Self(get_iterator, callback) = self; let Self(_, get_iterator, callback) = self;
let mut index = 0; let mut index = 0;
//let area = self.layout(to.area()); //let area = self.layout(to.area());
for item in get_iterator() { for item in get_iterator() {

View file

@ -37,27 +37,6 @@ impl Arranger {
has_clock!(|self:ArrangerTrack|self.player.clock()); has_clock!(|self:ArrangerTrack|self.player.clock());
has_player!(|self:ArrangerTrack|self.player); has_player!(|self:ArrangerTrack|self.player);
impl ArrangerTrack { impl ArrangerTrack {
pub fn widths (tracks: &[Self]) -> Vec<(usize, usize)> {
let mut widths = vec![];
let mut total = 0;
for track in tracks.iter() {
let width = track.width;
widths.push((width, total));
total += width;
}
widths.push((0, total));
widths
}
pub fn with_widths (tracks: &[ArrangerTrack])
-> impl Iterator<Item = (usize, &ArrangerTrack, usize, usize)>
{
let mut x = 0;
tracks.iter().enumerate().map(move |(index, track)|{
let data = (index, track, x, x + track.width);
x += track.width;
data
})
}
/// Name of track /// Name of track
pub fn name (&self) -> &Arc<RwLock<String>> { pub fn name (&self) -> &Arc<RwLock<String>> {
&self.name &self.name

View file

@ -23,23 +23,32 @@ use crate::*;
//}); //});
render!(TuiOut: (self: Arranger) => { render!(TuiOut: (self: Arranger) => {
let scenes = &self.scenes; let scenes = &self.scenes;
let ppqs = Arranger::ppqs(scenes, 1); let scene_heights = Arranger::scene_heights(scenes, 1);
Fill::xy(self.size.of( Fill::xy(self.size.of(
Bsp::s(self.toolbar_view(), Bsp::s(self.toolbar_view(),
Bsp::n(self.status_view(), Bsp::n(self.status_view(),
Bsp::n(self.selector_view(),
Bsp::w(self.pool_view(), Bsp::w(self.pool_view(),
Bsp::s(Align::n(Fill::x(Fixed::y(3, self.header()))), Bsp::n(self.selector_view(),
Bsp::s(Align::n(Fill::x(Fixed::y(1, self.ins()))), Bsp::n(Fixed::y(20, &self.editor),
Bsp::s(Align::n(Fill::x(Fixed::y(1, self.outs()))), Bsp::s(
Fill::xy( Align::w(Fill::x(
Bsp::a(Fill::xy(Fill::xy(Map( Bsp::s(Fixed::y(3, Align::w(self.header())),
move||scenes.iter(),//.zip(ppqs.iter().map(|row|row.0)), Bsp::s(Fixed::y(1, self.ins()), Fill::x(Fixed::y(1, self.outs()))))
move|scene, i|Arranger::format_scene(&self.tracks, scene, ppqs[i].0)))), )),
Bsp::a(
Bsp::a( Bsp::a(
Fill::xy(ArrangerVRowSep::from((self, 1))), Map::new(
Fill::xy(ArrangerVColSep::from(self)))))))))))))) move||scenes.iter(),//.zip(scene_heights.iter().map(|row|row.0)),
}); move|scene, i|Arranger::format_scene(&self.tracks, scene, scene_heights[i].0)
),
self.cursor(),
),
Bsp::a(
Fill::xy(self.scene_row_sep()),
""
//Fill::xy(ArrangerVColSep::from(self))
)
)))))))))});
//Align::n(Fill::xy(lay!( //Align::n(Fill::xy(lay!(
//Align::n(Fill::xy(Tui::bg(self.color.darkest.rgb, " "))), //Align::n(Fill::xy(Tui::bg(self.color.darkest.rgb, " "))),
//Align::n(Fill::xy(ArrangerVRowSep::from((self, 1)))), //Align::n(Fill::xy(ArrangerVRowSep::from((self, 1)))),
@ -71,7 +80,7 @@ impl<'a> ArrangerVClips<'a> {
size: &state.size, size: &state.size,
tracks: &state.tracks, tracks: &state.tracks,
scenes: &state.scenes, scenes: &state.scenes,
rows: Arranger::ppqs(&state.scenes, zoom), rows: Arranger::scene_heights(&state.scenes, zoom),
} }
} }
} }
@ -81,7 +90,7 @@ fn row <T: Content<TuiOut>> (color: ItemPalette, field: T) -> impl Content<TuiOu
impl Arranger { impl Arranger {
fn header (&self) -> impl Content<TuiOut> + use<'_> { fn header (&self) -> impl Content<TuiOut> + use<'_> {
let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16; let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
Push::x(scenes_w, Map(||ArrangerTrack::with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| { Push::x(scenes_w, Map::new(||Arranger::tracks_with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| {
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H); let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
let color = track.color(); let color = track.color();
let title = format!("{} {} {}", track.name.read().unwrap(), x1, x2); let title = format!("{} {} {}", track.name.read().unwrap(), x1, x2);
@ -92,7 +101,7 @@ impl Arranger {
} }
fn ins (&self) -> impl Content<TuiOut> + use<'_> { fn ins (&self) -> impl Content<TuiOut> + use<'_> {
let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16; let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
Push::x(scenes_w, Map(||ArrangerTrack::with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| { Push::x(scenes_w, Map::new(||Arranger::tracks_with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| {
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H); let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
let color = track.color(); let color = track.color();
let input = Self::format_input(track); let input = Self::format_input(track);
@ -102,14 +111,14 @@ impl Arranger {
} }
fn outs (&self) -> impl Content<TuiOut> + use<'_> { fn outs (&self) -> impl Content<TuiOut> + use<'_> {
let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16; let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
Push::x(scenes_w, Map(||ArrangerTrack::with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| { Push::x(scenes_w, Map::new(||Arranger::tracks_with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| {
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H); let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
let color = track.color(); let color = track.color();
Fill::xy(Align::n(Push::x(x2 as u16, Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fill::xy(Align::n(Push::x(x2 as u16, Tui::bg(color.base.rgb, Min::xy(w as u16, h,
Fixed::xy(w as u16, 5, row(color, Self::format_output(track).ok()))))))) Fixed::xy(w as u16, 5, row(color, Self::format_output(track).ok())))))))
})) }))
} }
pub fn ppqs (scenes: &[ArrangerScene], factor: usize) -> Vec<(usize, usize)> { pub fn scene_heights (scenes: &[ArrangerScene], factor: usize) -> Vec<(usize, usize)> {
let mut total = 0; let mut total = 0;
if factor == 0 { if factor == 0 {
scenes.iter().map(|scene|{ scenes.iter().map(|scene|{
@ -135,7 +144,7 @@ impl Arranger {
let name = Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb, let name = Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb,
Expand::x(1, Tui::bold(true, scene.name.read().unwrap().clone())) Expand::x(1, Tui::bold(true, scene.name.read().unwrap().clone()))
); );
let clips = Map(||ArrangerTrack::with_widths(tracks), move|(index, track, x1, x2), _| let clips = Map::new(||Arranger::tracks_with_widths(tracks), move|(index, track, x1, x2), _|
Push::x((x2 - x1) as u16, Self::format_clip(scene, index, track, (x2 - x1) as u16, height)) Push::x((x2 - x1) as u16, Self::format_clip(scene, index, track, (x2 - x1) as u16, height))
); );
Fixed::y(height, Bsp::e(icon, Bsp::e(name, clips))) Fixed::y(height, Bsp::e(icon, Bsp::e(name, clips)))
@ -226,129 +235,209 @@ impl Arranger {
Ok(format!("<{}", track.player.midi_outs().first().map(|port|port.short_name()) Ok(format!("<{}", track.player.midi_outs().first().map(|port|port.short_name())
.transpose()?.unwrap_or("?".into()))) .transpose()?.unwrap_or("?".into())))
} }
}
pub struct ArrangerVColSep { fn track_col_sep <'a> (&'a self) -> impl Content<TuiOut> + 'a {
fg: Color, let fg = TuiTheme::separator_fg(false);
cols: Vec<(usize, usize)>, let x = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
scenes_w: u16 Map::new(
} move||Self::tracks_with_widths(self.tracks.as_slice()),
from!(|state:&Arranger|ArrangerVColSep = Self { move|(_n, _track, x1, _x2), _i|Push::x(x + x1 as u16, Fill::y(Tui::fg(fg, "")))
fg: TuiTheme::separator_fg(false), )
cols: ArrangerTrack::widths(&state.tracks), }
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16, pub fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> {
}); let mut widths = vec![];
render!(TuiOut: |self: ArrangerVColSep, to| { let mut total = 0;
let style = Some(Style::default().fg(self.fg)); for track in tracks.iter() {
for x in self.cols.iter().map(|col|col.1) { let width = track.width;
let x = self.scenes_w + to.area().x() + x as u16; widths.push((width, total));
for y in to.area().y()..to.area().y2() { total += width;
to.blit(&"", x, y, style);
} }
widths.push((0, total));
widths
} }
}); pub fn tracks_with_widths (tracks: &[ArrangerTrack])
-> impl Iterator<Item = (usize, &ArrangerTrack, usize, usize)>
pub struct ArrangerVRowSep { {
fg: Color, let mut x = 0;
rows: Vec<(usize, usize)>, tracks.iter().enumerate().map(move |(index, track)|{
} let data = (index, track, x, x + track.width);
from!(|args:(&Arranger, usize)|ArrangerVRowSep = Self { x += track.width;
fg: Color::Rgb(255,255,255,), data
rows: Arranger::ppqs(&args.0.scenes, args.1), })
});
render!(TuiOut: |self: ArrangerVRowSep, to|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 {
if let Some(cell) = to.buffer.cell_mut(ratatui::prelude::Position::from((x, y))) {
cell.modifier = Modifier::UNDERLINED;
cell.underline_color = self.fg;
}
//}
} }
});
pub struct ArrangerVCursor { fn scene_row_sep <'a> (&'a self) -> impl Content<TuiOut> + 'a {
cols: Vec<(usize, usize)>, let fg = Color::Rgb(255,255,255);
rows: Vec<(usize, usize)>, Map::new(move||self.scenes_with_heights(), |_, _|"")
color: ItemPalette, //Map(||rows.iter(), |(_n, _scene, y1, _y2), _i| {
reticle: Reticle, //let y = to.area().y() + (y / PPQ) as u16 + 1;
selected: ArrangerSelection, //if y >= to.buffer.area.height { break }
scenes_w: u16, //for x in to.area().x()..to.area().x2().saturating_sub(2) {
} ////if x < to.buffer.area.x && y < to.buffer.area.y {
//if let Some(cell) = to.buffer.cell_mut(ratatui::prelude::Position::from((x, y))) {
//cell.modifier = Modifier::UNDERLINED;
//cell.underline_color = fg;
//}
////}
//}
//})
}
pub fn scenes_with_heights (&self)
-> impl Iterator<Item = (usize, &ArrangerScene, usize, usize)>
{
let mut y = 0;
self.scenes.iter().enumerate().map(move|(index, scene)|{
let data = (index, scene, y, y + 1);
y += 1;
data
})
}
from!(|args:(&Arranger, usize)|ArrangerVCursor = Self { fn cursor (&self) -> impl Content<TuiOut> + '_ {
cols: ArrangerTrack::widths(&args.0.tracks), let color = self.color;
rows: Arranger::ppqs(&args.0.scenes, args.1), let bg = color.lighter.rgb;//Color::Rgb(0, 255, 0);
selected: args.0.selected(), let selected = self.selected();
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&args.0.scenes) as u16, let cols = Arranger::track_widths(&self.tracks);
color: args.0.color, let rows = Arranger::scene_heights(&self.scenes, 1);
reticle: Reticle(Style { let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
fg: Some(args.0.color.lighter.rgb),
bg: None,
underline_color: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::DIM
}),
});
impl Content<TuiOut> for ArrangerVCursor {
fn render (&self, to: &mut TuiOut) {
let area = to.area();
let focused = true; let focused = true;
let selected = self.selected; let reticle = Reticle(Style {
let get_track_area = |t: usize| [ fg: Some(self.color.lighter.rgb),
self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(), bg: None,
self.cols[t].0 as u16, area.h(), underline_color: None,
]; add_modifier: Modifier::empty(),
let get_scene_area = |s: usize| [ sub_modifier: Modifier::DIM
area.x(), HEADER_H + area.y() + (self.rows[s].1 / PPQ) as u16, });
area.w(), (self.rows[s].0 / PPQ) as u16 RenderThunk::new(move|to: &mut TuiOut|{
]; let area = to.area();
let get_clip_area = |t: usize, s: usize| [ let [x, y, w, h] = area.xywh();
(self.scenes_w + area.x() + self.cols[t].1 as u16).saturating_sub(1), let mut track_area: Option<[u16;4]> = match selected {
HEADER_H + area.y() + (self.rows[s].1/PPQ) as u16, ArrangerSelection::Track(t) | ArrangerSelection::Clip(t, _) => Some([
self.cols[t].0 as u16 + 2, x + scenes_w + cols[t].1 as u16, y,
(self.rows[s].0 / PPQ) as u16 cols[t].0 as u16, h,
]; ]),
let mut track_area: Option<[u16;4]> = None; _ => None
let mut scene_area: Option<[u16;4]> = None; };
let mut clip_area: Option<[u16;4]> = None; let mut scene_area: Option<[u16;4]> = match selected {
let area = match selected { ArrangerSelection::Scene(s) | ArrangerSelection::Clip(_, s) => Some([
ArrangerSelection::Mix => area, x, y + HEADER_H + (rows[s].1 / PPQ) as u16,
ArrangerSelection::Track(t) => { w, (rows[s].0 / PPQ) as u16
track_area = Some(get_track_area(t)); ]),
area _ => None
}, };
ArrangerSelection::Scene(s) => { let mut clip_area: Option<[u16;4]> = match selected {
scene_area = Some(get_scene_area(s)); ArrangerSelection::Clip(t, s) => Some([
area (scenes_w + x + cols[t].1 as u16).saturating_sub(1),
}, HEADER_H + y + (rows[s].1/PPQ) as u16,
ArrangerSelection::Clip(t, s) => { cols[t].0 as u16 + 2,
track_area = Some(get_track_area(t)); (rows[s].0 / PPQ) as u16
scene_area = Some(get_scene_area(s)); ]),
clip_area = Some(get_clip_area(t, s)); _ => None
area };
}, if let Some([x, y, width, height]) = track_area {
}; to.fill_fg([x, y, 1, height], bg);
let bg = self.color.lighter.rgb;//Color::Rgb(0, 255, 0); to.fill_fg([x + width, y, 1, height], bg);
if let Some([x, y, width, height]) = track_area { }
to.fill_fg([x, y, 1, height], bg); if let Some([_, y, _, height]) = scene_area {
to.fill_fg([x + width, y, 1, height], bg); to.fill_ul([x, y - 1, w, 1], bg);
} to.fill_ul([x, y + height - 1, w, 1], bg);
if let Some([_, y, _, height]) = scene_area { }
to.fill_ul([area.x(), y - 1, area.w(), 1], bg); if focused {
to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg); to.place(if let Some(clip_area) = clip_area {
} clip_area
if focused { } else if let Some(track_area) = track_area {
to.place(if let Some(clip_area) = clip_area { track_area.clip_h(HEADER_H)
clip_area } else if let Some(scene_area) = scene_area {
} else if let Some(track_area) = track_area { scene_area.clip_w(scenes_w)
track_area.clip_h(HEADER_H) } else {
} else if let Some(scene_area) = scene_area { area.clip_w(scenes_w).clip_h(HEADER_H)
scene_area.clip_w(self.scenes_w) }, &reticle)
} else { };
area.clip_w(self.scenes_w).clip_h(HEADER_H) })
}, &self.reticle)
};
} }
} }
//pub struct ArrangerVCursor {
//cols: Vec<(usize, usize)>,
//rows: Vec<(usize, usize)>,
//color: ItemPalette,
//reticle: Reticle,
//selected: ArrangerSelection,
//scenes_w: u16,
//}
//from!(|args:(&Arranger, usize)|ArrangerVCursor = Self {
//cols: Arranger::track_widths(&args.0.tracks),
//rows: Arranger::scene_heights(&args.0.scenes, args.1),
//selected: args.0.selected(),
//scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&args.0.scenes) as u16,
//color: args.0.color,
//reticle: Reticle(Style {
//fg: Some(args.0.color.lighter.rgb),
//bg: None,
//underline_color: None,
//add_modifier: Modifier::empty(),
//sub_modifier: Modifier::DIM
//}),
//});
//impl Content<TuiOut> for ArrangerVCursor {
//fn render (&self, to: &mut TuiOut) {
//let area = to.area();
//let focused = true;
//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(), 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).saturating_sub(1),
//HEADER_H + area.y() + (self.rows[s].1/PPQ) as u16,
//self.cols[t].0 as u16 + 2,
//(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 = self.color.lighter.rgb;//Color::Rgb(0, 255, 0);
//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);
//}
//if focused {
//to.place(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(self.scenes_w)
//} else {
//area.clip_w(self.scenes_w).clip_h(HEADER_H)
//}, &self.reticle)
//};
//}
//}

View file

@ -10,15 +10,7 @@ pub(crate) use ::tek_tui::{
*, *,
tek_edn::*, tek_edn::*,
tek_layout::*, tek_layout::*,
tek_engine::{ tek_engine::*,
from,
Usually, Perhaps,
Output, Content, Render, RenderBox, Thunk, render, Engine, Size, Area,
Input, handle, Handle, command, Command, input_to_command, InputToCommand, keymap, EventMap,
},
Tui,
TuiIn, key, ctrl, shift, alt, kexp, kpat,
TuiOut,
crossterm::{ crossterm::{
self, self,
event::{ event::{

View file

@ -25,7 +25,9 @@ render!(TuiOut: |self: PianoHorizontalNotes<'a>, render|{
let is_in_y = source_y < source.height; let is_in_y = source_y < source.height;
if is_in_x && is_in_y { if is_in_x && is_in_y {
if let Some(source_cell) = source.get(source_x, source_y) { if let Some(source_cell) = source.get(source_x, source_y) {
*render.buffer.get_mut(screen_x, screen_y) = source_cell.clone(); if let Some(cell) = render.buffer.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) {
*cell = source_cell.clone();
}
} }
} }
} }

View file

@ -7,7 +7,7 @@ render!(TuiOut: (self: PoolView<'a>) => {
let color = self.1.phrase().read().unwrap().color; let color = self.1.phrase().read().unwrap().color;
Outer( Outer(
Style::default().fg(color.dark.rgb).bg(color.darkest.rgb) Style::default().fg(color.dark.rgb).bg(color.darkest.rgb)
).enclose(Map(||model.phrases().iter(), |clip, i|{ ).enclose(Map::new(||model.phrases().iter(), |clip, i|{
let item_height = 1; let item_height = 1;
let item_offset = i as u16 * item_height; let item_offset = i as u16 * item_height;
let selected = i == model.phrase_index(); let selected = i == model.phrase_index();

View file

@ -17,7 +17,7 @@ render!(TuiOut: (self: SampleList<'a>) => {
let note_lo = editor.note_lo().load(Relaxed); let note_lo = editor.note_lo().load(Relaxed);
let note_pt = editor.note_point(); let note_pt = editor.note_point();
let note_hi = editor.note_hi(); let note_hi = editor.note_hi();
Outer(Style::default().fg(TuiTheme::g(96))).enclose(Map(move||(note_lo..=note_hi).rev(), move|note, i| { Outer(Style::default().fg(TuiTheme::g(96))).enclose(Map::new(move||(note_lo..=note_hi).rev(), move|note, i| {
let offset = |a|Push::y(i as u16, Align::n(Fixed::y(1, Fill::x(a)))); let offset = |a|Push::y(i as u16, Align::n(Fixed::y(1, Fill::x(a))));