use crate::*; use super::note_y_iter; pub struct PianoHorizontalKeys<'a>(pub(crate) &'a PianoHorizontal); render!(|self: PianoHorizontalKeys<'a>|render(|to|Ok(render_keys_v(to, self)))); has_color!(|self: PianoHorizontalKeys<'a>|self.0.color.base); impl<'a> NoteRange for PianoHorizontalKeys<'a> { fn note_lo (&self) -> &AtomicUsize { &self.0.note_lo() } fn note_axis (&self) -> &AtomicUsize { &self.0.note_axis() } } impl<'a> NotePoint for PianoHorizontalKeys<'a> { fn note_len (&self) -> usize { self.0.note_len() } fn set_note_len (&self, x: usize) { self.0.set_note_len(x) } fn note_point (&self) -> usize { self.0.note_point() } fn set_note_point (&self, x: usize) { self.0.set_note_point(x) } } pub fn render_keys_v (to: &mut TuiOutput, state: &T) { let color = state.color(); let note_lo = state.note_lo().get(); let note_hi = state.note_hi(); let note_point = state.note_point(); let [x, y0, w, h] = to.area().xywh(); let key_style = Some(Style::default().fg(Color::Rgb(192, 192, 192)).bg(Color::Rgb(0, 0, 0))); let off_style = Some(Style::default().fg(TuiTheme::g(160))); let on_style = Some(Style::default().fg(TuiTheme::g(255)).bg(color.rgb).bold()); 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 { continue } if note == note_point { to.blit(&format!("{:<5}", to_note_name(note)), x, screen_y, on_style) } else { to.blit(&to_note_name(note), x, screen_y, off_style) }; } } fn to_key (note: usize) -> &'static str { match note % 12 { 11 => "████▌", 10 => " ", 9 => "████▌", 8 => " ", 7 => "████▌", 6 => " ", 5 => "████▌", 4 => "████▌", 3 => " ", 2 => "████▌", 1 => " ", 0 => "████▌", _ => unreachable!(), } }