move widths and with_widths to ArrangerTrack

This commit is contained in:
🪞👃🪞 2024-12-21 03:37:23 +01:00
parent 958885686e
commit 8a2f7da8b3
2 changed files with 67 additions and 56 deletions

View file

@ -1,16 +1,8 @@
use crate::*; use crate::*;
const HEADER_H: u16 = 3;
fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> { const HEADER_H: u16 = 3;
let mut widths = vec![]; const SCENES_W_OFFSET: u16 = 3;
let mut total = 0;
for track in tracks.iter() {
let width = track.width;
widths.push((width, total));
total += width;
}
widths.push((0, total));
widths
}
fn tracks_with_widths (tracks: &[ArrangerTrack]) fn tracks_with_widths (tracks: &[ArrangerTrack])
-> impl Iterator<Item = (usize, &ArrangerTrack, usize, usize)> -> impl Iterator<Item = (usize, &ArrangerTrack, usize, usize)>
{ {
@ -21,6 +13,7 @@ fn tracks_with_widths (tracks: &[ArrangerTrack])
data data
}) })
} }
pub struct ArrangerVHead<'a> { pub struct ArrangerVHead<'a> {
scenes_w: u16, scenes_w: u16,
timebase: &'a Arc<Timebase>, timebase: &'a Arc<Timebase>,
@ -31,10 +24,10 @@ from!(<'a>|state: &'a ArrangerTui|ArrangerVHead<'a> = Self { // A
tracks: state.tracks(), tracks: state.tracks(),
timebase: state.clock().timebase(), timebase: state.clock().timebase(),
current: &state.clock().playhead, current: &state.clock().playhead,
scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(state.scenes()) as u16,
}); });
render!(<Tui>|self: ArrangerVHead<'a>|Tui::push_x(self.scenes_w, row!( render!(<Tui>|self: ArrangerVHead<'a>|Tui::push_x(self.scenes_w, row!(
(_, track, x1, x2) in tracks_with_widths(self.tracks) => { (_, track, x1, x2) in ArrangerTrack::with_widths(self.tracks) => {
let (w, h) = (x2 - x1, HEADER_H); let (w, h) = (x2 - x1, HEADER_H);
let color = track.color(); let color = track.color();
Tui::bg(color.base.rgb, Tui::min_xy(w as u16, h, Fixed::wh(w as u16, 5, col!([ Tui::bg(color.base.rgb, Tui::min_xy(w as u16, h, Fixed::wh(w as u16, 5, col!([
@ -100,8 +93,8 @@ pub struct ArrangerVColSep {
sep_fg: Color, sep_fg: Color,
} }
from!(|state:&ArrangerTui|ArrangerVColSep = Self { from!(|state:&ArrangerTui|ArrangerVColSep = Self {
cols: track_widths(state.tracks()), cols: ArrangerTrack::widths(state.tracks()),
scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(state.scenes()) as u16,
sep_fg: TuiTheme::separator_fg(false), sep_fg: TuiTheme::separator_fg(false),
}); });
render!(<Tui>|self: ArrangerVColSep|render(move|to: &mut TuiOutput|{ render!(<Tui>|self: ArrangerVColSep|render(move|to: &mut TuiOutput|{
@ -141,26 +134,22 @@ pub struct ArrangerVCursor {
scenes_w: u16, scenes_w: u16,
} }
from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self { from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self {
cols: track_widths(args.0.tracks()), cols: ArrangerTrack::widths(args.0.tracks()),
rows: ArrangerScene::ppqs(args.0.scenes(), args.1), rows: ArrangerScene::ppqs(args.0.scenes(), args.1),
selected: args.0.selected(), selected: args.0.selected(),
scenes_w: 3 + ArrangerScene::longest_name(args.0.scenes()) as u16, scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(args.0.scenes()) as u16,
}); });
render!(<Tui>|self: ArrangerVCursor|render(move|to: &mut TuiOutput|{ render!(<Tui>|self: ArrangerVCursor|render(move|to: &mut TuiOutput|{
let area = to.area(); let area = to.area();
let focused = true; let focused = true;
let selected = self.selected; let selected = self.selected;
let get_track_area = |t: usize| [ let get_track_area = |t: usize| [
self.scenes_w + area.x() + self.cols[t].1 as u16, self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(),
area.y(), self.cols[t].0 as u16, area.h(),
self.cols[t].0 as u16,
area.h(),
]; ];
let get_scene_area = |s: usize| [ let get_scene_area = |s: usize| [
area.x(), area.x(), HEADER_H + area.y() + (self.rows[s].1 / PPQ) as u16,
HEADER_H + area.y() + (self.rows[s].1 / PPQ) as u16, area.w(), (self.rows[s].0 / PPQ) as u16
area.w(),
(self.rows[s].0 / PPQ) as u16
]; ];
let get_clip_area = |t: usize, s: usize| [ let get_clip_area = |t: usize, s: usize| [
self.scenes_w + area.x() + self.cols[t].1 as u16, self.scenes_w + area.x() + self.cols[t].1 as u16,
@ -220,42 +209,41 @@ from!(<'a>|args:(&'a ArrangerTui, usize)|ArrangerVBody<'a> = Self {
render!(<Tui>|self: ArrangerVBody<'a>|Fixed::h( render!(<Tui>|self: ArrangerVBody<'a>|Fixed::h(
(self.size.h() as u16).saturating_sub(HEADER_H), (self.size.h() as u16).saturating_sub(HEADER_H),
col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => { col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => {
let height = 1.max((pulses / PPQ) as u16); Self::format_scene(&self.tracks, scene, pulses)
let playing = scene.is_playing(self.tracks);
Fixed::h(height, row!([
Self::format_play(playing),
Tui::bold(true, scene.name.read().unwrap().as_str()),
row!((index, _, x1, x2) in tracks_with_widths(self.tracks) => {
Self::format_clip(&self.tracks, &scene, index, (x2 - x1) as u16, height)
})])
)
}) })
)); ));
impl<'a> ArrangerVBody<'a> { impl<'a> ArrangerVBody<'a> {
fn format_play (playing: bool) -> &'static str { fn format_scene (
if playing { "" } else { " " } tracks: &'a [ArrangerTrack], scene: &'a ArrangerScene, pulses: usize
) -> impl Render<Tui> + use<'a> {
let height = 1.max((pulses / PPQ) as u16);
let playing = scene.is_playing(tracks);
Fixed::h(height, row!([
if playing { "" } else { " " },
Tui::bold(true, scene.name.read().unwrap().as_str()),
row!((index, track, x1, x2) in ArrangerTrack::with_widths(tracks) => {
Self::format_clip(scene, index, track, (x2 - x1) as u16, height)
})])
)
} }
fn format_clip (tracks: &'a [ArrangerTrack], scene: &'a ArrangerScene, i: usize, w: u16, h: u16) fn format_clip (
-> impl Render<Tui> + use<'a> scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16
{ ) -> impl Render<Tui> + use<'a> {
Fixed::wh(w, h, Layers::new(move |add|{ Fixed::wh(w, h, Layers::new(move |add|{
let mut bg = TuiTheme::border_bg(); let mut bg = TuiTheme::border_bg();
match (tracks.get(i), scene.clips.get(i)) { if let Some(Some(phrase)) = scene.clips.get(index) {
(Some(track), Some(Some(phrase))) => { let name = &(phrase as &Arc<RwLock<Phrase>>).read().unwrap().name;
let name = &(phrase as &Arc<RwLock<Phrase>>).read().unwrap().name; let name = format!("{}", name);
let name = format!("{}", name); let max_w = name.len().min((w as usize).saturating_sub(2));
let max_w = name.len().min((w as usize).saturating_sub(2)); let color = phrase.read().unwrap().color;
let color = phrase.read().unwrap().color; bg = color.dark.rgb;
bg = color.dark.rgb; if let Some((_, Some(ref playing))) = track.player.play_phrase() {
if let Some((_, Some(ref playing))) = track.player.play_phrase() { if *playing.read().unwrap() == *phrase.read().unwrap() {
if *playing.read().unwrap() == *phrase.read().unwrap() { bg = color.light.rgb
bg = color.light.rgb }
} };
}; add(&Fixed::w(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?;
add(&Fixed::w(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?; }
},
_ => {}
};
//add(&Background(bg)) //add(&Background(bg))
Ok(()) Ok(())
})) }))

View file

@ -13,6 +13,29 @@ use KeyCode::{Char, Delete};
} }
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 {
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
})
}
}
impl ArrangerTrackApi for ArrangerTrack { impl ArrangerTrackApi for ArrangerTrack {
/// Name of track /// Name of track
fn name (&self) -> &Arc<RwLock<String>> { fn name (&self) -> &Arc<RwLock<String>> {