diff --git a/src/arrange.rs b/src/arrange.rs index b6d80a71..33b3aeac 100644 --- a/src/arrange.rs +++ b/src/arrange.rs @@ -787,21 +787,22 @@ impl Arrangement { for track in self.tracks().iter() { h = h.max(track.devices.len() as u16 * 2); } + let tracks = ||self.tracks_with_sizes(); + let track = move|(_, track, _x1, _x2), index| wh_exact( + Some(track_width(index, track)), + Some(h + 1), + bg(track.color.dark.term, origin_nw(iter_south(move||0..h, + |_, _index|wh_exact(Some(track.width as u16), Some(2), + fg_bg( + ItemTheme::G[32].lightest.term, + ItemTheme::G[32].dark.term, + origin_nw(format!(" · {}", "--")) + ) + ))))); view_track_row_section(theme, button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false), button_2("D", "+", false), - iter(||self.tracks_with_sizes(), move|(_, track, _x1, _x2), index| { - wh_exact(Some(track_width(index, track)), Some(h + 1), - bg(track.color.dark.term, origin_nw(iter_south(move||0..h, - |_, _index|wh_exact(Some(track.width as u16), Some(2), - fg_bg( - ItemTheme::G[32].lightest.term, - ItemTheme::G[32].dark.term, - origin_nw(format!(" · {}", "--")) - ) - ))))); - todo!() - }) + iter(tracks, track) ) } diff --git a/src/browse.rs b/src/browse.rs index f539b17d..773bfd86 100644 --- a/src/browse.rs +++ b/src/browse.rs @@ -251,12 +251,12 @@ impl<'a> PoolView<'a> { let f = color.lightest.term; let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") }; let length = if false { String::default() } else { format!("{length} ") }; - h_exact(1, iter_south(item_offset, item_height, bg(b, below!( - w_full(origin_w(fg(fg, bold(selected, name)))), - w_full(origin_e(fg(fg, bold(selected, length)))), - w_full(origin_w(When::new(selected, bold(true, fg(g(255), "▶"))))), - w_full(origin_e(When::new(selected, bold(true, fg(g(255), "◀"))))), - )))) + h_exact(1, bg(b, below!( + w_full(origin_w(fg(f, bold(selected, name)))), + w_full(origin_e(fg(f, bold(selected, length)))), + w_full(origin_w(when(selected, bold(true, fg(g(255), "▶"))))), + w_full(origin_e(when(selected, bold(true, fg(g(255), "◀"))))), + ))) })))) } } @@ -312,12 +312,14 @@ impl Browse { } impl Browse { fn tui (&self) -> impl Draw { - iter_south(1, ||EntriesIterator { + let item = |entry, _index|w_full(origin_w(entry)); + let iterate = ||EntriesIterator { offset: 0, index: 0, length: self.dirs.len() + self.files.len(), browser: self, - }, |entry, _index|w_full(origin_w(entry))) + }; + iter_south_fixed(1, iterate, item) } } impl<'a> Iterator for EntriesIterator<'a> { diff --git a/src/editor.rs b/src/editor.rs index c792c39f..4720a409 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -525,6 +525,7 @@ impl PianoHorizontal { } impl PianoHorizontal { + /// Draw the piano roll background. /// /// This mode uses full blocks on note on and half blocks on legato: █▄ █▄ █▄ @@ -559,6 +560,7 @@ impl PianoHorizontal { } } } + /// Draw the piano roll foreground. /// /// This mode uses full blocks on note on and half blocks on legato: █▄ █▄ █▄ @@ -596,14 +598,16 @@ impl PianoHorizontal { } } + fn notes (&self) -> impl Draw { let time_start = self.get_time_start(); let note_lo = self.get_note_lo(); let note_hi = self.get_note_hi(); let buffer = self.buffer.clone(); - Thunk::new(move|to: &mut Tui|{ + thunk(move|to: &mut Tui|{ + let xywh = to.area().into(); + let XYWH(x0, y0, w, _h) = xywh; let source = buffer.read().unwrap(); - let XYWH(x0, y0, w, _h) = to.area(); //if h as usize != note_axis { //panic!("area height mismatch: {h} <> {note_axis}"); //} @@ -618,15 +622,17 @@ impl PianoHorizontal { let is_in_y = source_y < source.height; if is_in_x && is_in_y { if let Some(source_cell) = source.get(source_x, source_y) { - if let Some(cell) = to.buffer.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) { + if let Some(cell) = to.0.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) { *cell = source_cell.clone(); } } } } } + Ok(xywh) }) } + fn cursor (&self) -> impl Draw { let note_hi = self.get_note_hi(); let note_lo = self.get_note_lo(); @@ -636,8 +642,9 @@ impl PianoHorizontal { let time_start = self.get_time_start(); let time_zoom = self.get_time_zoom(); let style = Some(Style::default().fg(self.color.lightest.term)); - Thunk::new(move|to: &mut Tui|{ - let XYWH(x0, y0, w, _) = to.area(); + thunk(move|to: &mut Tui|{ + let xywh = to.area().into(); + let XYWH(x0, y0, w, _h) = xywh; for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { if note == note_pos { for x in 0..w { @@ -656,8 +663,10 @@ impl PianoHorizontal { break } } + Ok(xywh) }) } + fn keys (&self) -> impl Draw { let state = self; let color = state.color; @@ -667,8 +676,9 @@ impl PianoHorizontal { let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0))); let off_style = Some(Style::default().fg(g(255))); let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.term).bold()); - h_full(w_exact(self.keys_width, Thunk::new(move|to: &mut Tui|{ - let XYWH(x, y0, _w, _h) = to.area(); + h_full(w_exact(self.keys_width, thunk(move|to: &mut Tui|{ + let xywh = to.area().into(); + let XYWH(x, y0, _w, _h) = xywh; for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { to.blit(&to_key(note), x, screen_y, key_style); if note > 127 { @@ -680,11 +690,14 @@ impl PianoHorizontal { to.blit(¬e_pitch_to_name(note), x, screen_y, off_style) }; } + Ok(xywh) }))) } + fn timeline (&self) -> impl Draw + '_ { - w_full(h_exact(1, Thunk::new(move|to: &mut Tui|{ - let XYWH(x, y, w, _h) = to.area(); + w_full(h_exact(1, thunk(move|to: &mut Tui|{ + let xywh = to.area().into(); + let XYWH(x, y, w, _h) = xywh; let style = Some(Style::default().dim()); let length = self.clip.as_ref().map(|p|p.read().unwrap().length).unwrap_or(1); for (area_x, screen_x) in (0..w).map(|d|(d, d+x)) { @@ -693,6 +706,7 @@ impl PianoHorizontal { to.blit(&"|", screen_x, y, style); } } + Ok(xywh) }))) } } diff --git a/src/mix.rs b/src/mix.rs index 64afce51..74db8388 100644 --- a/src/mix.rs +++ b/src/mix.rs @@ -67,7 +67,7 @@ pub enum MixingMode { } fn draw_meters (meters: &[f32]) -> impl Draw + use<'_> { - Tui::bg(Black, w_exact(2, iter_east(1, ||meters.iter(), |value, _index|{ + bg(Black, w_exact(2, iter_east_fixed(1, ||meters.iter(), |value, _index|{ h_full(RmsMeter(*value)) }))) } diff --git a/src/sample.rs b/src/sample.rs index 43763aa3..6b6fa4a9 100644 --- a/src/sample.rs +++ b/src/sample.rs @@ -596,8 +596,9 @@ fn draw_list_item (sample: &Option>>) -> String { fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_> { let min_db = -64.0; - Thunk::new(move|to: &mut Tui|{ - let XYWH(x, y, width, height) = to.area(); + thunk(move|to: &mut Tui|{ + let xywh = to.area().into(); + let XYWH(x, y, width, height) = xywh; let area = Rect { x, y, width, height }; if let Some(sample) = &sample { let sample = sample.read().unwrap(); @@ -631,7 +632,8 @@ fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_ //height as f64 / 2.0, //text.red() //); - }).render(area, &mut to.1); + }) + .render(area, to.as_mut()); } else { Canvas::default() .x_bounds([0.0, width as f64]) @@ -644,8 +646,9 @@ fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_ //text.red() //); }) - .render(area, &mut to.1); + .render(area, to.as_mut()); } + Ok(xywh) }) } diff --git a/src/sequence.rs b/src/sequence.rs index fe15f60f..3e280965 100644 --- a/src/sequence.rs +++ b/src/sequence.rs @@ -118,12 +118,16 @@ pub trait HasPlayClip: HasClock { let MidiClip { ref name, color, .. } = *clip.read().unwrap(); (name.clone(), color) } else { - ("".into(), Tui::g(64).into()) + ("".into(), ItemTheme::G[64].into()) }; - let time: String = self.pulses_since_start_looped() + field_v(color, "Now:", format!("{} {}", self.play_status_time(), name)) + } + + fn play_status_time (&self) -> String { + self.pulses_since_start_looped() .map(|(times, time)|format!("{:>3}x {:>}", times+1.0, self.clock().timebase.format_beats_1(time))) - .unwrap_or_else(||String::from(" ")).into(); - field_v(color, "Now:", format!("{} {}", time, name)) + .unwrap_or_else(||String::from(" ")) + .into() } fn next_status (&self) -> impl Draw { diff --git a/src/tek.rs b/src/tek.rs index b0e709cf..7d786348 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -368,7 +368,7 @@ def_sizes_iter!(TracksSizes => Track); /// let _ = tek::view_logo(); /// ``` pub fn view_logo () -> impl Draw { - wh_exact(32, 7, bold(true, fg(Rgb(240,200,180), south!{ + wh_exact(Some(32), Some(7), bold(true, fg(Rgb(240, 200, 180), south!{ h_exact(1, ""), h_exact(1, ""), h_exact(1, "~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~"), @@ -384,9 +384,9 @@ pub fn view_logo () -> impl Draw { /// ``` pub fn view_transport ( play: bool, - bpm: Arc>, - beat: Arc>, - time: Arc>, + bpm: &Arc>, + beat: &Arc>, + time: &Arc>, ) -> impl Draw { let theme = ItemTheme::G[96]; bg(Black, east!(above( @@ -788,7 +788,7 @@ fn app_interpret_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usua Some(":templates") => { let modes = state.config.modes.clone(); let height = (modes.read().unwrap().len() * 2) as u16; - h_exact(height, w_min(30, thunk(move |to: &mut Tui|{ + h_exact(height, w_min(Some(30), thunk(move |to: &mut Tui|{ for (index, (id, profile)) in modes.read().unwrap().iter().enumerate() { let bg = if index == 0 { Rgb(70,70,70) } else { Rgb(50,50,50) }; let name = profile.name.get(0).map(|x|x.as_ref()).unwrap_or(""); @@ -804,7 +804,7 @@ fn app_interpret_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usua } }))) }.draw(to), - Some(":sessions") => h_exact(6, w_min(30, thunk(|to: &mut Tui|{ + Some(":sessions") => h_exact(Some(6), w_min(Some(30), thunk(|to: &mut Tui|{ let fg = Rgb(224, 192, 128); for (index, name) in ["session1", "session2", "session3"].iter().enumerate() { let bg = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) }; diff --git a/tengri b/tengri index 9c5bfafb..e0781571 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit 9c5bfafb7a4163022c5a96c3a25d0aca258a28d2 +Subproject commit e0781571c42cb72e7445a2adbdb7a99e37600562