fold in Notes and Cursor into PianoHorizontal

This commit is contained in:
🪞👃🪞 2025-01-10 01:59:54 +01:00
parent 2401dc8fcd
commit 709391ff0a
4 changed files with 68 additions and 77 deletions

View file

@ -12,11 +12,9 @@ mod midi_view; pub use midi_view::*;
mod midi_editor; pub use midi_editor::*;
mod midi_select; pub use midi_select::*;
mod piano_h; pub use self::piano_h::*;
mod piano_h_cursor; pub use self::piano_h_cursor::*;
mod piano_h_keys; pub use self::piano_h_keys::*;
mod piano_h_notes; pub use self::piano_h_notes::*;
mod piano_h_time; pub use self::piano_h_time::*;
mod piano_h; pub use self::piano_h::*;
mod piano_h_keys; pub use self::piano_h_keys::*;
mod piano_h_time; pub use self::piano_h_time::*;
pub(crate) use ::tek_time::*;
pub(crate) use ::tek_jack::{*, jack::*};

View file

@ -10,10 +10,7 @@ render!(TuiOut: (self: PianoHorizontal) => Bsp::s( // the freeze is in the piano
)),
Fill::xy(Bsp::e(
Fixed::x(self.keys_width, PianoHorizontalKeys(self)),
Fill::xy(self.size.of(lay!(
Fill::xy(PianoHorizontalNotes(self)),
Fill::xy(PianoHorizontalCursor(self)),
))),
Fill::xy(self.size.of(lay!(self.notes(), self.cursor()))),
)),
));
impl PianoHorizontal {
@ -76,6 +73,70 @@ impl PianoHorizontal {
}
}
fn notes (&self) -> impl Content<TuiOut> {
let time_start = self.time_start().get();
let note_axis = self.note_axis().get();
let note_lo = self.note_lo().get();
let note_hi = self.note_hi();
let note_point = self.note_point();
let buffer = self.buffer.clone();
RenderThunk::new(move|render: &mut TuiOut|{
let source = buffer.read().unwrap();
let [x0, y0, w, h] = render.area().xywh();
if h as usize != note_axis {
panic!("area height mismatch: {h} <> {note_axis}");
}
for (area_x, screen_x) in (x0..x0+w).enumerate() {
for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
let source_x = time_start + area_x;
let source_y = note_hi - area_y;
// TODO: enable loop rollover:
//let source_x = (time_start + area_x) % source.width.max(1);
//let source_y = (note_hi - area_y) % source.height.max(1);
let is_in_x = source_x < source.width;
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) = render.buffer.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) {
*cell = source_cell.clone();
}
}
}
}
}
})
}
fn cursor (&self) -> impl Content<TuiOut> {
let style = Some(Style::default().fg(self.color.lightest.rgb));
let note_hi = self.note_hi();
let note_len = self.note_len();
let note_lo = self.note_lo().get();
let note_point = self.note_point();
let time_point = self.time_point();
let time_start = self.time_start().get();
let time_zoom = self.time_zoom().get();
RenderThunk::new(move|render: &mut TuiOut|{
let [x0, y0, w, _] = render.area().xywh();
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
if note == note_point {
for x in 0..w {
let screen_x = x0 + x;
let time_1 = time_start + x as usize * time_zoom;
let time_2 = time_1 + time_zoom;
if time_1 <= time_point && time_point < time_2 {
render.blit(&"", screen_x, screen_y, style);
let tail = note_len as u16 / time_zoom as u16;
for x_tail in (screen_x + 1)..(screen_x + tail) {
render.blit(&"", x_tail, screen_y, style);
}
break
}
}
break
}
}
})
}
}
has_size!(<TuiOut>|self:PianoHorizontal|&self.size);

View file

@ -1,33 +0,0 @@
use crate::*;
use super::*;
pub struct PianoHorizontalCursor<'a>(pub(crate) &'a PianoHorizontal);
render!(TuiOut: |self: PianoHorizontalCursor<'a>, render|{
let style = Some(Style::default().fg(self.0.color.lightest.rgb));
let note_hi = self.0.note_hi();
let note_len = self.0.note_len();
let note_lo = self.0.note_lo().get();
let note_point = self.0.note_point();
let time_point = self.0.time_point();
let time_start = self.0.time_start().get();
let time_zoom = self.0.time_zoom().get();
let [x0, y0, w, _] = render.area().xywh();
for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
if note == note_point {
for x in 0..w {
let screen_x = x0 + x;
let time_1 = time_start + x as usize * time_zoom;
let time_2 = time_1 + time_zoom;
if time_1 <= time_point && time_point < time_2 {
render.blit(&"", screen_x, screen_y, style);
let tail = note_len as u16 / time_zoom as u16;
for x_tail in (screen_x + 1)..(screen_x + tail) {
render.blit(&"", x_tail, screen_y, style);
}
break
}
}
break
}
}
});

View file

@ -1,35 +0,0 @@
use crate::*;
use super::*;
pub struct PianoHorizontalNotes<'a>(pub(crate) &'a PianoHorizontal);
render!(TuiOut: |self: PianoHorizontalNotes<'a>, render|{
let time_start = self.0.time_start().get();
let note_axis = self.0.note_axis().get();
let note_lo = self.0.note_lo().get();
let note_hi = self.0.note_hi();
let note_point = self.0.note_point();
let source = self.0.buffer.read().unwrap();
let [x0, y0, w, h] = render.area().xywh();
if h as usize != note_axis {
panic!("area height mismatch: {h} <> {note_axis}");
}
for (area_x, screen_x) in (x0..x0+w).enumerate() {
for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
let source_x = time_start + area_x;
let source_y = note_hi - area_y;
// TODO: enable loop rollover:
//let source_x = (time_start + area_x) % source.width.max(1);
//let source_y = (note_hi - area_y) % source.height.max(1);
let is_in_x = source_x < source.width;
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) = render.buffer.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) {
*cell = source_cell.clone();
}
}
}
}
}
});