From f1bd9e7e8897021e26989a4e7ab1c82a6e473906 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 11 Jan 2025 21:17:27 +0100 Subject: [PATCH] wip: unified app: still curiously empty --- tek/src/app.rs | 120 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/tek/src/app.rs b/tek/src/app.rs index a0b9e6f8..5103e8f5 100644 --- a/tek/src/app.rs +++ b/tek/src/app.rs @@ -103,7 +103,7 @@ impl EdnViewData for &App { Sym(":pool") => self.pool().boxed(), Sym(":sample") => self.sample().boxed(), Sym(":sampler") => self.sampler().boxed(), - Sym(":scenes") => self.scene_row(w).boxed(), + Sym(":scenes") => self.scene_row(w, self.size.h().saturating_sub(9) as u16).boxed(), Sym(":status") => self.status(0).boxed(), Sym(":toolbar") => self.toolbar().boxed(), Sym(":tracks") => self.track_row(w, 3).boxed(), @@ -180,7 +180,9 @@ impl App { fn output_row (&self, w: u16, h: u16) -> impl Content + '_ { self.row(w, h, output_header(&self), output_cells(&self)) } - fn scene_row (&self, w: u16) -> impl Content + '_ { "" } + fn scene_row (&self, w: u16, h: u16) -> impl Content + '_ { + self.row(w, h, output_header(&self), output_cells(&self)) + } pub fn tracks_with_sizes (&self) -> impl Iterator @@ -191,6 +193,11 @@ impl App { _ => None }, self.editor_w()) } + pub fn scenes_with_sizes (&self, h: usize) + -> impl Iterator + { + scenes_with_sizes(self.scenes.iter(), &self.selected, self.is_editing(), 2, 15) + } fn is_editing (&self) -> bool { self.editing.load(Relaxed) } @@ -207,6 +214,26 @@ impl App { w } } +pub fn scenes_with_sizes <'a>( + scenes: impl Iterator + 'a, + selected: &'a ArrangerSelection, + editing: bool, + scene_height: usize, + scene_larger: usize, +) -> impl Iterator + 'a { + let mut y = 0; + let (selected_track, selected_scene) = match selected { + ArrangerSelection::Clip(t, s) => (Some(t), Some(s)), + _ => (None, None) + }; + scenes.enumerate().map(move|(s, scene)|{ + let active = editing && selected_track.is_some() && selected_scene == Some(&s); + let height = if active { scene_larger } else { scene_height }; + let data = (s, scene, y, y + height); + y += height; + data + }) +} pub fn tracks_with_sizes <'a> ( tracks: impl Iterator, active: Option, @@ -310,3 +337,92 @@ fn mute_solo (bg: Color, mute: bool, solo: bool) -> impl Content { fn cell > (color: ItemPalette, field: T) -> impl Content { Tui::fg_bg(color.lightest.rgb, color.base.rgb, Fixed::y(1, field)) } + +fn scene_headers <'a> (state: &'a App) -> BoxThunk<'a, TuiOut> { + (||{ + let last_color = Arc::new(RwLock::new(ItemPalette::from(Color::Rgb(0, 0, 0)))); + let selected = state.selected.scene(); + Fill::y(Align::c(Map::new(||state.scenes_with_sizes(2), move|(_, scene, y1, y2), i| { + let h = (y2 - y1) as u16; + let name = format!("🭬{}", &scene.name); + let color = scene.color(); + let active = selected == Some(i); + let mid = if active { color.light } else { color.base }; + let top = Some(last_color.read().unwrap().base.rgb); + let cell = phat_sel_3( + active, + Tui::bold(true, name.clone()), + Tui::bold(true, name), + top, + mid.rgb, + Color::Rgb(0, 0, 0) + ); + *last_color.write().unwrap() = color; + map_south(y1 as u16, h + 1, Fixed::y(h + 1, cell)) + }))).boxed() + }).into() +} +fn scene_cells <'a> (state: &'a App) -> BoxThunk<'a, TuiOut> { + let editing = state.is_editing(); + let tracks = move||state.tracks_with_sizes(); + let scenes = ||state.scenes_with_sizes(2); + let selected_track = state.selected.track(); + let selected_scene = state.selected.scene(); + (move||Fill::y(Align::c(Map::new(tracks, move|(_, track, x1, x2), t| { + let w = (x2 - x1) as u16; + let color: ItemPalette = track.color().dark.into(); + let last_color = Arc::new(RwLock::new(ItemPalette::from(Color::Rgb(0, 0, 0)))); + let cells = Map::new(scenes, move|(_, scene, y1, y2), s| { + let h = (y2 - y1) as u16; + let color = scene.color(); + let (name, fg, bg) = if let Some(c) = &scene.clips[t] { + let c = c.read().unwrap(); + (c.name.to_string(), c.color.lightest.rgb, c.color.base.rgb) + } else { + ("⏹ ".to_string(), TuiTheme::g(64), TuiTheme::g(32)) + }; + let last = last_color.read().unwrap().clone(); + let active = editing && selected_scene == Some(s) && selected_track == Some(t); + let editor = Thunk::new(||&state.editor); + let cell = Thunk::new(move||phat_sel_3( + selected_track == Some(t) && selected_scene == Some(s), + Tui::fg(fg, Push::x(1, Tui::bold(true, name.to_string()))), + Tui::fg(fg, Push::x(1, Tui::bold(true, name.to_string()))), + if selected_track == Some(t) && selected_scene.map(|s|s+1) == Some(s) { + None + } else { + Some(bg.into()) + }, + bg.into(), + bg.into(), + )); + let cell = Either(active, editor, cell); + *last_color.write().unwrap() = bg.into(); + map_south( + y1 as u16, + h + 1, + Fill::x(Fixed::y(h + 1, cell)) + ) + }); + let column = Fixed::x(w, Tui::bg(Color::Reset, Align::y(cells)).boxed()); + Fixed::x(w, map_east(x1 as u16, w, column)) + }))).boxed()).into() +} +fn cell_clip <'a> ( + scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16 +) -> impl Content + use<'a> { + scene.clips.get(index).map(|clip|clip.as_ref().map(|clip|{ + let clip = clip.read().unwrap(); + let mut bg = TuiTheme::border_bg(); + let name = clip.name.to_string(); + let max_w = name.len().min((w as usize).saturating_sub(2)); + let color = clip.color; + bg = color.dark.rgb; + if let Some((_, Some(ref playing))) = track.player.play_clip() { + if *playing.read().unwrap() == *clip { + bg = color.light.rgb + } + }; + Fixed::xy(w, h, &Tui::bg(bg, Push::x(1, Fixed::x(w, &name.as_str()[0..max_w])))); + })) +}