mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
fold in Notes and Cursor into PianoHorizontal
This commit is contained in:
parent
2401dc8fcd
commit
709391ff0a
4 changed files with 68 additions and 77 deletions
|
|
@ -13,9 +13,7 @@ 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::*;
|
||||
|
||||
pub(crate) use ::tek_time::*;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue