use crate::core::*; use super::*; pub fn draw ( s: &Sequencer, buf: &mut Buffer, mut area: Rect, ) -> Usually { area.x = area.x + 13; let Rect { x, y, width, height } = area; keys(buf, area, s.note_start)?; timer(buf, x+6, y-1, s.time_start, s.time_start + area.width as usize, 0); if let Some(phrase) = s.phrase() { lanes(buf, x, y, phrase, s.timebase.ppq() as usize, s.time_zoom, s.time_start, s.time_start + area.width as usize, s.note_start, s.note_start + area.height as usize, ); } cursor( buf, x, y, Style::default().green().not_dim(), s.time_cursor, s.note_cursor ); footer(s, buf, x, y, width, height); Ok(Rect { x: x - 13, y, width, height }) } pub fn timer ( buf: &mut Buffer, x: u16, y: u16, time0: usize, time1: usize, now: usize ) { for step in time0..time1 { buf.set_string(x + step as u16, y, &"-", if step == now { Style::default().yellow().bold().not_dim() } else { Style::default() }); } } pub fn keys ( buf: &mut Buffer, area: Rect, note_start: usize ) -> Usually { let bw = Style::default().dim(); let Rect { x, y, width, height } = area; let h = height.saturating_sub(2); for i in 0..h { let y = y + i; let key = KEYS_VERTICAL[(i % 6) as usize]; key.blit(buf, x + 1, y, Some(bw)); "█".blit(buf, x + 2, y, Some(bw)); "·".repeat(width.saturating_sub(6) as usize).blit(buf, x + 5, y, Some(bw.black())); //buf.set_string(x + 3, y, &format!("{i}"), Style::default()); if i % 6 == 0 { let octave = format!("C{}", ((note_start - i as usize) / 6) as i8 - 4); buf.set_string(x + 3, y, &octave, Style::default()); } } Ok(area) } pub fn lanes ( buf: &mut Buffer, x: u16, y: u16, phrase: &Phrase, ppq: usize, time_zoom: usize, time0: usize, time1: usize, note0: usize, note1: usize, ) { let bg = Style::default(); let (bw, wh) = (bg.dim(), bg.white()); for step in time0..time1 { let x = x as usize + 5 + step; let (a, b) = ((step + 0) * ppq / time_zoom, (step + 1) * ppq / time_zoom,); if step % 4 == 0 { "|".blit(buf, x as u16, y - 1, Some(Style::default().dim())); } if step % (time_zoom * 4) == 0 { format!("{}", step / time_zoom / 4 + 1) .blit(buf, x as u16, y - 1, Some(Style::default().bold().not_dim())); } let h = ((note1-note0)/2).saturating_sub(y as usize); for k in 0..h { let (character, style) = match ( contains_note_on(phrase, u7::from_int_lossy((note0 + k * 2 + 0) as u8), a, b), contains_note_on(phrase, u7::from_int_lossy((note0 + k * 2 + 1) as u8), a, b), ) { (true, true) => ("█", wh), (true, false) => ("▀", wh), (false, true) => ("▄", wh), (false, false) => ("·", bw), }; let y = y as usize + k; character.blit(buf, x as u16, y as u16, Some(style)); } } } pub fn cursor (buf: &mut Buffer, x: u16, y: u16, style: Style, time: usize, note: usize) { let x = x + 5 + time as u16; let y = y + note as u16 / 2; let c = if note % 2 == 0 { "▀" } else { "▄" }; c.blit(buf, x, y, Some(style)); } pub fn footer (s: &Sequencer, buf: &mut Buffer, mut x: u16, y: u16, width: u16, height: u16) { buf.set_string(x, y + height, format!("├{}┤", "-".repeat((width - 2).into())), Style::default().dim()); buf.set_string(x, y + height + 2, format!("├{}┤", "-".repeat((width - 2).into())), Style::default().dim()); x = x + 2; { for (_, [letter, title, value]) in [ ["S", &format!("ync"), &format!("<4/4>")], ["Q", &format!("uant"), &format!("<1/{}>", 4 * s.time_zoom)], ["N", &format!("ote"), &format!("{} ({}-{})", s.note_start + s.note_cursor, s.note_start, "X")], ["T", &format!("ime"), &format!("{} ({}-{})", s.time_start + s.time_cursor + 1, s.time_start + 1, "X")], ].iter().enumerate() { buf.set_string(x, y + height + 1, letter, Style::default().bold().yellow().dim()); x = x + 1; buf.set_string(x, y + height + 1, &title, Style::default().bold().dim()); x = x + title.len() as u16 + 1; buf.set_string(x, y + height + 1, &value, Style::default().not_dim()); x = x + value.len() as u16; buf.set_string(x, y + height + 1, " ", Style::default().dim()); x = x + 2; } } }