LineBuffer

This commit is contained in:
🪞👃🪞 2024-07-06 22:07:23 +03:00
parent 61af72c281
commit d75600188e
3 changed files with 92 additions and 3 deletions

View file

@ -13,7 +13,6 @@ pub(crate) use std::sync::{
// Non-stdlib dependencies:
pub(crate) use microxdg::XdgApp;
pub(crate) use ratatui::prelude::*;
pub(crate) use midly::{MidiMessage, live::LiveEvent, num::u7};
pub(crate) use crossterm::{ExecutableCommand};
pub(crate) use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};

View file

@ -1,4 +1,6 @@
use crate::core::*;
pub(crate) use ratatui::prelude::*;
use ratatui::buffer::Cell;
use ratatui::widgets::WidgetRef;
pub trait Blit {
@ -80,3 +82,92 @@ impl WidgetRef for dyn Render {
Render::render(self, buf, area).expect("Failed to render device.");
}
}
pub struct LineBuffer {
width: usize,
cells: Vec<Cell>,
style: Option<Style>,
bg: Cell,
}
impl LineBuffer {
pub fn new (bg: Cell, width: usize, height: usize) -> Self {
Self {
style: None,
width: width,
cells: vec![bg.clone();width*height],
bg,
}
}
pub fn height (&self) -> usize {
self.cells.len() / self.width
}
pub fn style (&mut self, style: Style) -> &mut Self {
self.style = Some(style);
self
}
pub fn no_style (&mut self) -> &mut Self {
self.style = None;
self
}
pub fn put (&mut self, data: &str, x: usize, y: usize) -> &mut Self {
if x < self.width {
for (i, c) in data.chars().enumerate() {
if x + i >= self.width {
break;
}
let index = y * self.width + x + i;
while index >= self.cells.len() {
self.cells.extend_from_slice(&vec![self.bg.clone();self.width]);
}
self.cells[index].set_char(c);
if let Some(s) = self.style {
self.cells[index].set_style(s);
}
}
}
self
}
pub fn show (&self, buf: &mut Buffer, area: Rect, offset: isize) -> Usually<Rect> {
let Rect { x, mut y, width, height } = area;
for row in offset..self.height() as isize {
let length = self.cells.len();
let start = ((row.max(0) as usize)*self.width).min(length);
let end = (((row + 1).max(0) as usize)*self.width).min(length);
for (column, cell) in self.cells[start..end].iter().enumerate() {
if column >= width as usize {
break
}
*buf.get_mut(x + column as u16, y + row as u16) = cell.clone();
}
y = y + 1;
if y > height {
break
}
}
Ok(area)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_line_buffer () {
let mut buffer = LineBuffer::new(Cell::default(), 12, 0);
assert_eq!(buffer.cells.len(), 0);
buffer.put("FOO", 0, 0);
assert_eq!(buffer.cells.len(), 12);
buffer.put("FOO", 6, 0);
assert_eq!(buffer.cells.len(), 12);
buffer.put("FOO", 11, 0);
assert_eq!(buffer.cells.len(), 12);
buffer.put("FOO", 12, 0);
assert_eq!(buffer.cells.len(), 12);
buffer.put("FOO", 24, 0);
assert_eq!(buffer.cells.len(), 12);
buffer.put("FOO", 0, 1);
assert_eq!(buffer.cells.len(), 24);
}
}

View file

@ -13,8 +13,8 @@ pub struct TransportView<'a> {
impl<'a> Render for TransportView<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let Rect { x, y, width, .. } = area;
draw_play_stop(buf, x + 1, y, &self.playing);
if width > 100 {
draw_play_stop(buf, x + 1, y, &self.playing);
draw_rec(buf, x + 12, y, self.record);
draw_dub(buf, x + 19, y, self.overdub);
draw_mon(buf, x + 26, y, self.monitor);
@ -26,7 +26,6 @@ impl<'a> Render for TransportView<'a> {
);
Ok(Rect { x, y, width, height: 1 })
} else {
draw_play_stop(buf, x + 1, y, &self.playing);
draw_bpm(buf, x + 12, y, self.timebase.bpm() as usize, self.quant);
draw_timer(buf, x + width - 1, y,
self.timebase.ppq() as usize,