From a57bb60ac913d133a1888bc9b59a8ad8131efe9a Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 12 Sep 2024 19:41:47 +0300 Subject: [PATCH] rewrite vertical arranger as components --- crates/tek_sequencer/src/arranger.rs | 127 +++++++++++---------------- 1 file changed, 53 insertions(+), 74 deletions(-) diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index fa420f7e..9498b83d 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -498,103 +498,77 @@ impl<'a> Widget for CursorFocus<'a> { struct TracksHeader<'a>(u16, &'a[(usize, usize)], &'a [Sequencer]); -impl<'a> Widget for TracksHeader<'a> { +impl<'a> Content for TracksHeader<'a> { type Engine = Tui; - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - let area = to.area(); - let Self(offset, track_cols, tracks) = *self; - let [x, y, width, _] = area; - for (track, (w, x)) in tracks.iter().zip(track_cols) { - let x = *x as u16; - if x > width { - break + fn content (&self) -> impl Widget { + let Self(_offset, columns, tracks) = *self; + Split::right(move |add|{ + for (track, (w, _)) in tracks.iter().zip(columns) { + add(&Min::W(*w as u16, Layers::new(|add|{ + add(&FillBg(COLOR_BG1))?; + add(&track.name.read().unwrap().as_str()) + })))?; } - let name = track.name.read().unwrap(); - to.fill_bg([offset + x, y, *w as u16, 2], COLOR_BG1); - to.blit(&*name, offset + x + 1, y, Some(Style::default().white()))?; - } - Ok(Some([x, y, width, 2])) + Ok(()) + }) } } struct SceneRows<'a>(u16, &'a[(usize, usize)], &'a[(usize, usize)], &'a[Sequencer], &'a[Scene]); -impl<'a> Widget for SceneRows<'a> { +impl<'a> Content for SceneRows<'a> { type Engine = Tui; - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - let area = to.area(); - let Self(offset, track_cols, scene_rows, tracks, scenes) = *self; - let black = Some(Style::default().fg(Nord::SEPARATOR)); - let [_, mut y, _, _height] = area; - for (_, x) in track_cols.iter() { - let x = *x as u16; - if x > 0 { - for y in area.y()-2..y-2 { - to.blit(&"▎", x - 1, y, black)?; - } + fn content (&self) -> impl Widget { + let Self(offset, columns, rows, tracks, scenes) = *self; + Split::down(move |add| { + for (scene, (_pulses, _)) in scenes.iter().zip(rows) { + add(&SceneRow(tracks, scene, columns, offset))?; } - } - for (scene, (pulses, _)) in scenes.iter().zip(scene_rows) { - //if y > height { - //break - //} - let h = 1.max((pulses / 96) as u16); - SceneRow(tracks, scene, track_cols, offset) - .render(to.with_area(area.x(), y, area.w(), h))?; - y = y + h - } - Ok(Some(area)) + Ok(()) + }) } } struct SceneRow<'a>(&'a[Sequencer], &'a Scene, &'a[(usize, usize)], u16); -impl<'a> Widget for SceneRow<'a> { +impl<'a> Content for SceneRow<'a> { type Engine = Tui; - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - let area = to.area(); - let Self(tracks, scene, track_cols, offset) = self; - let [x, y, width, _] = area; + fn content (&self) -> impl Widget { + let Self(tracks, scene, columns, _offset) = self; let playing = scene.is_playing(tracks); - to.blit(&if playing { "▶" } else { " " }, x, y, None)?; - to.blit(&*scene.name.read().unwrap(), x + 1, y, Some(Style::default().white()))?; - to.fill_bg([x, y, offset.saturating_sub(1), area.h()], COLOR_BG1); - for (track, (w, x)) in track_cols.iter().enumerate() { - let x = *x as u16 + offset; - if x > width { - break + Split::right(move |add| { + add(&Layers::new(|add|{ + add(&if playing { "▶" } else { " " })?; + add(&scene.name.read().unwrap().as_str())?; + add(&FillBg(COLOR_BG1)) + }))?; + for (track, (_w, _x)) in columns.iter().enumerate() { + add(&SceneClip(tracks.get(track), scene.clips.get(track)))?; } - if let (Some(track), Some(Some(clip))) = ( - tracks.get(track), scene.clips.get(track) - ) { - SceneClip(track, *clip).render(to.with_area(x, y, *w as u16, area.h()))?; - } - } - Ok(Some(area)) + Ok(()) + }) } } -struct SceneClip<'a>(&'a Sequencer, usize); +struct SceneClip<'a>(Option<&'a Sequencer>, Option<&'a Option>); -impl<'a> Widget for SceneClip<'a> { +impl<'a> Content for SceneClip<'a> { type Engine = Tui; - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - let area = to.area(); + fn content (&self) -> impl Widget { let Self(track, clip) = self; - let style = Some(Style::default().white()); - if let Some(phrase) = track.phrases.get(*clip) { - let phrase = phrase.read().unwrap(); - let name = phrase.name.read().unwrap(); - to.blit(&format!("{clip:02} {name}"), area.x() + 1, area.y(), style)?; - to.fill_bg(area, if track.sequence == Some(*clip) { - Nord::PLAYING - } else { - COLOR_BG1 - }); - } else { - to.fill_bg(area, COLOR_BG0) - } - Ok(Some(area)) + Layers::new(move |add|{ + let mut color = COLOR_BG0; + if let (Some(track), Some(Some(clip))) = (track, clip) { + if let Some(phrase) = track.phrases.get(*clip) { + add(&format!( + "{clip:02} {}", + phrase.read().unwrap().name.read().unwrap() + ).as_str())?; + color = if track.sequence == Some(*clip) { Nord::PLAYING } else { COLOR_BG1 }; + } + } + add(&FillBg(color)) + }) } } @@ -867,6 +841,7 @@ impl<'a> Widget for TrackScenesColumn<'a> { Ok(Some([x, y, x2, height])) } } + /// Appears on first run (i.e. if state dir is missing). pub struct ArrangerRenameModal { _engine: std::marker::PhantomData, @@ -876,6 +851,7 @@ pub struct ArrangerRenameModal { result: Arc>, cursor: usize } + impl ArrangerRenameModal { pub fn new (target: ArrangerFocus, value: &Arc>) -> Self { Self { @@ -888,6 +864,7 @@ impl ArrangerRenameModal { } } } + impl Widget for ArrangerRenameModal { type Engine = Tui; fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { @@ -914,6 +891,7 @@ impl Widget for ArrangerRenameModal { Ok(Some(area)) } } + impl Handle for ArrangerRenameModal { fn handle (&mut self, from: &Tui) -> Perhaps { match from.event() { @@ -952,6 +930,7 @@ impl Handle for ArrangerRenameModal { } } } + impl Exit for ArrangerRenameModal { fn exited (&self) -> bool { self.done