wip: layout

This commit is contained in:
🪞👃🪞 2024-06-12 23:21:56 +03:00
parent ac865824cc
commit d627d257ad
13 changed files with 220 additions and 131 deletions

View file

@ -36,7 +36,7 @@ pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box<dyn E
if event::poll(poll).is_ok() { if event::poll(poll).is_ok() {
let event = event::read().unwrap(); let event = event::read().unwrap();
match event { match event {
crossterm::event::Event::Key(KeyEvent { Event::Key(KeyEvent {
code: KeyCode::Char('c'), code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL, modifiers: KeyModifiers::CONTROL,
.. ..
@ -53,7 +53,6 @@ pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box<dyn E
stdout().execute(EnterAlternateScreen)?; stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?; enable_raw_mode()?;
let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout()))?; let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout()))?;
let sleep = std::time::Duration::from_millis(16);
//better_panic::install(); //better_panic::install();
let better_panic_handler = better_panic::Settings::auto() let better_panic_handler = better_panic::Settings::auto()
.verbosity(better_panic::Verbosity::Full) .verbosity(better_panic::Verbosity::Full)
@ -70,6 +69,7 @@ pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box<dyn E
//writeln!(std::io::stderr(), "{:?}", ::backtrace::Backtrace::new()) //writeln!(std::io::stderr(), "{:?}", ::backtrace::Backtrace::new())
//.unwrap(); //.unwrap();
})); }));
let sleep = std::time::Duration::from_millis(16);
loop { loop {
terminal.draw(|frame|{ terminal.draw(|frame|{
let area = frame.size(); let area = frame.size();
@ -93,15 +93,15 @@ pub trait Device: Send + Sync {
fn handle (&mut self, _event: &EngineEvent) -> Usually<()> { fn handle (&mut self, _event: &EngineEvent) -> Usually<()> {
Ok(()) Ok(())
} }
fn render (&self, _buffer: &mut Buffer, _area: Rect) -> Usually<(u16, u16)> { fn render (&self, _buffer: &mut Buffer, _area: Rect) -> Usually<Rect> {
Ok((0,0)) Ok(Rect { x: 0, y: 0, width: 0, height: 0 })
} }
fn process (&mut self, _client: Client, _scope: ProcessScope) {} fn process (&mut self, _client: Client, _scope: ProcessScope) {}
} }
pub struct DynamicDevice<T> { pub struct DynamicDevice<T> {
pub state: Mutex<T>, pub state: Mutex<T>,
pub render: Mutex<Box<dyn FnMut(&T, &mut Buffer, Rect)->Usually<(u16, u16)> + Send>>, pub render: Mutex<Box<dyn FnMut(&T, &mut Buffer, Rect)->Usually<Rect> + Send>>,
pub handle: Mutex<Box<dyn FnMut(&mut T, &EngineEvent)->Usually<()> + Send>>, pub handle: Mutex<Box<dyn FnMut(&mut T, &EngineEvent)->Usually<()> + Send>>,
pub process: Mutex<Box<dyn FnMut(&mut T) + Send>> pub process: Mutex<Box<dyn FnMut(&mut T) + Send>>
} }
@ -113,7 +113,7 @@ impl<T> DynamicDevice<T> {
process: P, process: P,
state: T state: T
) -> Self where ) -> Self where
R: FnMut(&T, &mut Buffer, Rect)->Usually<(u16, u16)> + Send + 'static, R: FnMut(&T, &mut Buffer, Rect)->Usually<Rect> + Send + 'static,
H: FnMut(&mut T, &EngineEvent) -> Result<(), Box<dyn Error>> + Send + 'static, H: FnMut(&mut T, &EngineEvent) -> Result<(), Box<dyn Error>> + Send + 'static,
P: FnMut(&mut T) + Send + 'static P: FnMut(&mut T) + Send + 'static
{ {
@ -133,7 +133,7 @@ impl<T: Send + Sync> Device for DynamicDevice<T> {
fn handle (&mut self, event: &EngineEvent) -> Usually<()> { fn handle (&mut self, event: &EngineEvent) -> Usually<()> {
self.handle.lock().unwrap()(&mut *self.state.lock().unwrap(), event) self.handle.lock().unwrap()(&mut *self.state.lock().unwrap(), event)
} }
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<(u16, u16)> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
self.render.lock().unwrap()(&*self.state.lock().unwrap(), buf, area) self.render.lock().unwrap()(&*self.state.lock().unwrap(), buf, area)
} }
} }

View file

@ -15,7 +15,7 @@ impl Chain {
} }
pub fn render (state: &Chain, buf: &mut Buffer, area: Rect) pub fn render (state: &Chain, buf: &mut Buffer, area: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
let Rect { x, y, width, height } = area; let Rect { x, y, width, height } = area;
let area = Rect { x, y, width: 40, height: 30 }; let area = Rect { x, y, width: 40, height: 30 };
@ -26,25 +26,25 @@ pub fn render (state: &Chain, buf: &mut Buffer, area: Rect)
let mut x = 0u16; let mut x = 0u16;
y = y + 1; y = y + 1;
for device in state.devices.iter() { for device in state.devices.iter() {
let (w, h) = device.render(buf, Rect { let result = device.render(buf, Rect {
x: area.x, x: area.x,
y: area.y + y, y: area.y + y,
width: area.width, width: area.width,
height: area.height - y height: area.height.saturating_sub(y)
})?; })?;
//buf.set_string(area.x, y, format!("{y}---TOP---+{h}"), Style::default().red()); //buf.set_string(area.x, y, format!("{y}---TOP---+{h}"), Style::default().red());
x = x.max(w); x = x.max(result.width);
y = y + h; y = y + result.height;
y = y + 1; y = y + 1;
buf.set_string(area.x, y, "", Style::default().black()); buf.set_string(area.x, y, "", Style::default().black());
buf.set_string(area.x + area.width - 1, y, "", Style::default().black()); buf.set_string(area.x + area.width - 1, y, "", Style::default().black());
buf.set_string(area.x + 2, y, "Patch in... │ Patch out...", Style::default().dim()); buf.set_string(area.x + 2, y, " Patch in Patch out", Style::default().dim());
y = y + 1; y = y + 1;
//buf.set_string(area.x, y, format!("{y}---BOT---"), Style::default().red()); //buf.set_string(area.x, y, format!("{y}---BOT---"), Style::default().red());
//buf.set_string(area.x + area.width - 1, area.y + 1, "│", Style::default().black()); //buf.set_string(area.x + area.width - 1, area.y + 1, "│", Style::default().black());
//buf.set_string(area.x + 2, y, "Patch...", Style::default().dim()); //buf.set_string(area.x + 2, y, "Patch...", Style::default().dim());
} }
Ok((x, y)) Ok(Rect { x: area.x, y: area.y, width: x, height: y })
} }
pub fn handle (state: &mut Chain, event: &EngineEvent) -> Result<(), Box<dyn Error>> { pub fn handle (state: &mut Chain, event: &EngineEvent) -> Result<(), Box<dyn Error>> {

View file

@ -12,7 +12,9 @@ impl Launcher {
} }
} }
pub fn render (state: &Launcher, buf: &mut Buffer, area: Rect) {} pub fn render (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
Ok(Rect::default())
}
pub fn handle (state: &mut Launcher, event: &Event) -> Result<(), Box<dyn Error>> { pub fn handle (state: &mut Launcher, event: &Event) -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())

View file

@ -13,7 +13,7 @@ impl Looper {
} }
pub fn render (state: &Looper, buf: &mut Buffer, area: Rect) pub fn render (state: &Looper, buf: &mut Buffer, area: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
//let move_to = |col, row| MoveTo(offset.0 + col, offset.1 + row); //let move_to = |col, row| MoveTo(offset.0 + col, offset.1 + row);
//stdout //stdout
@ -22,7 +22,7 @@ pub fn render (state: &Looper, buf: &mut Buffer, area: Rect)
//.queue(move_to(0, 2))?.queue(PrintStyledContent(" Loop 1 [ ] ████ Track 1".bold()))? //.queue(move_to(0, 2))?.queue(PrintStyledContent(" Loop 1 [ ] ████ Track 1".bold()))?
//.queue(move_to(0, 3))?.queue(PrintStyledContent(" Loop 2 [ ] ████████ Track 2".bold()))? //.queue(move_to(0, 3))?.queue(PrintStyledContent(" Loop 2 [ ] ████████ Track 2".bold()))?
//.queue(move_to(0, 4))?.queue(PrintStyledContent(" Loop 3 [ ] ████████ Track 3".bold()))?; //.queue(move_to(0, 4))?.queue(PrintStyledContent(" Loop 3 [ ] ████████ Track 3".bold()))?;
Ok((20, 10)) Ok(Rect::default())
} }
pub fn handle (state: &mut Looper, event: &EngineEvent) -> Result<(), Box<dyn Error>> { pub fn handle (state: &mut Looper, event: &EngineEvent) -> Result<(), Box<dyn Error>> {

View file

@ -42,10 +42,10 @@ impl Mixer {
} }
pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect) pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
if area.height < 2 { if area.height < 2 {
return Ok((0, 0)) return Ok(area)
} }
area.x = area.width.saturating_sub(80) / 2; area.x = area.width.saturating_sub(80) / 2;
area.width = area.width.min(80); area.width = area.width.min(80);
@ -87,7 +87,7 @@ pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect)
//fn render_meters ( //fn render_meters (
//state: &mut Mixer, //state: &mut Mixer,
//stdout: &mut Stdout, //stdout: &mut Stdout,
//offset: (u16, u16) //offset: Rect
//) -> Result<(), Box<dyn Error>> { //) -> Result<(), Box<dyn Error>> {
//let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); //let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
//for (i, track) in state.tracks.iter().enumerate() { //for (i, track) in state.tracks.iter().enumerate() {
@ -102,7 +102,7 @@ pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect)
//} //}
} }
} }
Ok((20,10)) Ok(area)
} }
pub fn handle (state: &mut Mixer, event: &EngineEvent) -> Result<(), Box<dyn Error>> { pub fn handle (state: &mut Mixer, event: &EngineEvent) -> Result<(), Box<dyn Error>> {

View file

@ -13,10 +13,10 @@ impl Plugin {
} }
pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, width, height }: Rect) pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, width, height }: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
let style = Style::default().gray(); let style = Style::default().gray();
draw_box(buf, Rect { x, y: y, width: 40, height: 8 }); draw_box(buf, Rect { x, y, width: 40, height: 8 });
buf.set_string(x + 1, y + 1, &format!(" {}", state.name), style.white().bold()); buf.set_string(x + 1, y + 1, &format!(" {}", state.name), style.white().bold());
buf.set_string(x + 13, y + 1, &format!("│ Plugin Name"), style.not_dim()); buf.set_string(x + 13, y + 1, &format!("│ Plugin Name"), style.not_dim());
buf.set_string(x + 0, y + 2, &format!("├--------------------------------------┤"), style.dim()); buf.set_string(x + 0, y + 2, &format!("├--------------------------------------┤"), style.dim());
@ -24,7 +24,7 @@ pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, width, height }: R
buf.set_string(x + 1, y + 4, &format!(" Parameter 2 0.0"), style); buf.set_string(x + 1, y + 4, &format!(" Parameter 2 0.0"), style);
buf.set_string(x + 1, y + 5, &format!(" Parameter 3 0.0"), style); buf.set_string(x + 1, y + 5, &format!(" Parameter 3 0.0"), style);
buf.set_string(x + 1, y + 6, &format!(" Parameter 4 0.0"), style); buf.set_string(x + 1, y + 6, &format!(" Parameter 4 0.0"), style);
Ok((40, 7)) Ok(Rect { x, y, width: 40, height: 7 })
} }
pub fn handle (state: &mut Plugin, event: &EngineEvent) -> Result<(), Box<dyn Error>> { pub fn handle (state: &mut Plugin, event: &EngineEvent) -> Result<(), Box<dyn Error>> {

View file

@ -107,28 +107,28 @@ impl Sample {
} }
pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, width, height }: Rect) pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, width, height }: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
let style = Style::default().gray(); let style = Style::default().gray();
draw_box(buf, Rect { x, y: y, width: 40, height: 12 }); draw_box(buf, Rect { x, y: y, width: 40, height: 12 });
buf.set_string(x + 1, y + 1, &format!(" {}", state.name), style.white().bold()); buf.set_string(x + 1, y + 1, &format!(" {}", state.name), style.white().bold());
buf.set_string(x + 0, y + 2, &format!("├--------------------------------------┤"), style.dim()); buf.set_string(x + 0, y + 2, &format!("├--------------------------------------┤"), style.dim());
buf.set_string(x + 2, y + 3, &format!("C0 Sample#000"), style.bold()); buf.set_string(x + 2, y + 3, &format!("C4 Sample#000"), style.bold());
buf.set_string(x + 2, y + 4, &format!(" {:.03}s", buf.set_string(x + 2, y + 4, &format!(" {:.03}s",
100000.0/44100.0), style); 100000.0/44100.0), style);
buf.set_string(x + 2, y + 5, &format!("C#0 Sample#001"), style.bold()); buf.set_string(x + 2, y + 5, &format!("C#4 Sample#001"), style.bold());
buf.set_string(x + 2, y + 6, &format!(" {:.03}-{:.03}s", buf.set_string(x + 2, y + 6, &format!(" {:.03}-{:.03}s",
50000.0/44100.0, 100000.0/44100.0), style); 50000.0/44100.0, 100000.0/44100.0), style);
buf.set_string(x + 2, y + 7, &format!("D0 Sample#002"), style.bold()); buf.set_string(x + 2, y + 7, &format!("D4 Sample#002"), style.bold());
buf.set_string(x + 2, y + 8, &format!(" {:.03}-{:.03}/{:.03}s", buf.set_string(x + 2, y + 8, &format!(" {:.03}-{:.03}/{:.03}s",
0.0, 50000.0/44100.0, 100000.0/44100.0), style); 0.0, 50000.0/44100.0, 100000.0/44100.0), style);
buf.set_string(x + 2, y + 9, &format!("D#0 Sample#003"), style.bold()); buf.set_string(x + 2, y + 9, &format!("D#4 Sample#003"), style.bold());
buf.set_string(x + 2, y + 10, &format!(" {:.03}-[{:.03}-{:.03}]/{:.03}s ", buf.set_string(x + 2, y + 10, &format!(" {:.03}-[{:.03}-{:.03}]/{:.03}s ",
10000.0/44100.0, 25000.0/44100.0, 50000.0/44100.0, 100000.0/44100.0), style); 10000.0/44100.0, 25000.0/44100.0, 50000.0/44100.0, 100000.0/44100.0), style);
//buf.set_string(x + 1, y + 7 + 6, &format!(" Inputs... │ Outputs... "), style.dim()); //buf.set_string(x + 1, y + 7 + 6, &format!(" Inputs... │ Outputs... "), style.dim());
//render_table(state, stdout, offset)?; //render_table(state, stdout, offset)?;
//render_meters(state, stdout, offset)?; //render_meters(state, stdout, offset)?;
Ok((40, 11)) Ok(Rect { x, y, width: 40, height: 11 })
} }
//fn render_table ( //fn render_table (

View file

@ -206,52 +206,65 @@ const KEYS_VERTICAL: [&'static str; 6] = [
]; ];
fn render (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect) fn render (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
let style = Style::default().gray(); let style = Style::default().gray();
area.height = 18; let header = draw_sequencer_header(sequencer, buf, area)?;
let piano = draw_sequencer_vertical(sequencer, buf, Rect {
x: area.x,
y: area.y + header.height,
width: area.width,
height: area.height - header.height
})?;
let area = Rect {
x: area.x,
y: area.y,
width: header.width.max(piano.width),
height: header.height + piano.height
};
//draw_box_styled(buf, area, Some(Style::default().red()));
Ok(area)
}
fn draw_sequencer_header (sequencer: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let Rect { x, y, width, height } = area; let Rect { x, y, width, height } = area;
let style = Style::default().gray();
buf.set_string(x + 1, y + 1, &format!(" │ 00:00.00 / 00:00.00"), style); buf.set_string(x + 1, y + 1, &format!(" │ 00:00.00 / 00:00.00"), style);
buf.set_string(x + 2, y + 1, &format!("{}", &sequencer.name), style.white().bold()); buf.set_string(x + 2, y + 1, &format!("{}", &sequencer.name), style.white().bold());
buf.set_string(x + 1, y + 2, &format!(" ▶ PLAY │ ⏹ STOP │ ⏺ REC │ ⏺ DUB "), style); buf.set_string(x + 1, y + 2, &format!(" ▶ PLAY │ ⏹ STOP │ ⏺ REC │ ⏺ DUB "), style);
//buf.set_string(x + 1, y + 6, &format!(" │ Outputs... "), style.dim()); Ok(Rect { x, y, width, height: 4 })
}
let mut h = 9; fn draw_sequencer_vertical (sequencer: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let toggle = true; let Rect { x, y, .. } = area;
if toggle { let white = Style::default().gray();
for i in 0..16 { let black = Style::default().black();
buf.set_string(x + 2, y + 4 + i, &format!(" "), Style::default().on_black()); for i in 0..area.width-4 {
h = h + 1; let color = match i % 12 {
} 0 => white,
1 => black,
2 => white,
3 => black,
4 => white,
5 => white,
6 => black,
7 => white,
8 => black,
9 => white,
10 => black,
11 => white,
_ => unreachable!()
};
buf.set_string(x + 2 + i, y - 1, &format!(""), color);
buf.set_string(x + 2 + i, y, &format!(""), color);
} }
for i in 0..3 { let bg = Style::default().on_black();
buf.set_string(1 + i * 12 + x + 1, y + h - 5, &format!(""), Style::default().white()); for i in 0..area.height - 8 {
buf.set_string(1 + i * 12 + x + 2, y + h - 5, &format!(""), Style::default().black()); buf.set_string(x + 2, y + 1 + i, &" ".repeat((area.width-4)as usize), bg);
buf.set_string(1 + i * 12 + x + 3, y + h - 5, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 4, y + h - 5, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 5, y + h - 5, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 6, y + h - 5, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 7, y + h - 5, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 8, y + h - 5, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 9, y + h - 5, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 10, y + h - 5, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 11, y + h - 5, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 12, y + h - 5, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 1, y + h - 4, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 2, y + h -4, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 3, y + h -4, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 4, y + h -4, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 5, y + h -4, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 6, y + h -4, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 7, y + h -4, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 8, y + h -4, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 9, y + h -4, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 10, y + h -4, &format!(""), Style::default().white());
buf.set_string(1 + i * 12 + x + 11, y + h -4, &format!(""), Style::default().black());
buf.set_string(1 + i * 12 + x + 12, y + h -4, &format!(""), Style::default().white());
} }
draw_box(buf, Rect { x, y, width: 40, height: h - 2 }); Ok(Rect { x, y, width: area.width, height: area.height - 6 })
Ok((40,h-3)) }
//{ //{
//let mut area = area.clone(); //let mut area = area.clone();
//area.y = area.y + 3; //area.y = area.y + 3;
@ -329,7 +342,6 @@ fn render (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect)
//} //}
//} //}
// //
}
fn draw_sequence_button ( fn draw_sequence_button (
buf: &mut Buffer, buf: &mut Buffer,

View file

@ -41,12 +41,12 @@ impl Transport {
} }
pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect) pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect)
-> Usually<(u16, u16)> -> Usually<Rect>
{ {
area.x = area.width.saturating_sub(80) / 2; area.x = area.width.saturating_sub(80) / 2;
area.width = area.width.min(80); area.width = area.width.min(80);
area.height = 5; area.height = 5;
draw_box(buf, area); //draw_box(buf, area);
draw_leaf(buf, area, 1, 0, "REC"); draw_leaf(buf, area, 1, 0, "REC");
draw_leaf(buf, area, 1, 5, "DUB"); draw_leaf(buf, area, 1, 5, "DUB");
draw_leaf(buf, area, 1, 10, "STOP"); draw_leaf(buf, area, 1, 10, "STOP");
@ -91,7 +91,6 @@ pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect)
draw_leaf(buf, area, 3, 48, &format!("Rate {:>6}Hz", rate)); draw_leaf(buf, area, 3, 48, &format!("Rate {:>6}Hz", rate));
draw_leaf(buf, area, 3, 63, &format!("Frame {:>10}", frame)); draw_leaf(buf, area, 3, 63, &format!("Frame {:>10}", frame));
} }
Ok((area.width, area.height))
//let bbt = position.pos.bbt().map(|mut bbt|*bbt //let bbt = position.pos.bbt().map(|mut bbt|*bbt
//.with_bpm(state.bpm) //.with_bpm(state.bpm)
//.with_timesig(state.timesig.0, state.timesig.1)); //.with_timesig(state.timesig.0, state.timesig.1));
@ -131,6 +130,7 @@ pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect)
//None => String::from("(none)") //None => String::from("(none)")
//}).render(area.clone().offset(Offset { x: 50, y: 2 }), buf); //}).render(area.clone().offset(Offset { x: 50, y: 2 }), buf);
//} //}
Ok(area)
} }
//pub fn render ( //pub fn render (

View file

@ -1,47 +1,123 @@
use crate::prelude::*; use crate::prelude::*;
pub struct Rows(pub Vec<Box<dyn Device>>); pub struct Rows {
focused: bool,
focus: usize,
items: Vec<Box<dyn Device>>,
}
pub struct Columns(pub Vec<Box<dyn Device>>); impl Rows {
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
Self { focused, focus: 0, items }
}
}
impl Device for Rows { impl Device for Rows {
fn handle (&mut self, event: &EngineEvent) -> Usually<()> { fn handle (&mut self, event: &EngineEvent) -> Usually<()> {
Ok(()) if !self.focused {
} match event {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<(u16, u16)> { EngineEvent::Input(Event::Key(KeyEvent { code: KeyCode::Esc, .. })) => {
let mut x = 0u16; self.focused = true;
let mut y = 0u16; Ok(())
for device in self.0.iter() { },
let (w, h) = device.render(buf, Rect { _ => self.items[self.focus].handle(event)
x: area.x, }
y: area.y + y, } else {
width: area.width, match event {
height: area.height - y EngineEvent::Input(event) => match event {
})?; Event::Key(KeyEvent { code: KeyCode::Up, .. }) => {
x = x.max(w); if self.focus == 0 {
y = y + h; self.focus = self.items.len();
}
self.focus = self.focus - 1;
},
Event::Key(KeyEvent { code: KeyCode::Down, .. }) => {
self.focus = self.focus + 1;
if self.focus >= self.items.len() {
self.focus = 0;
}
},
Event::Key(KeyEvent { code: KeyCode::Enter, .. }) => {
self.focused = false;
},
Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => {
self.focused = true;
},
_ => {
println!("{event:?}");
}
},
_ => {}
}
Ok(())
} }
Ok((x, y)) }
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let mut w = 0u16;
let mut h = 0u16;
for (i, device) in self.items.iter().enumerate() {
let result = device.render(buf, Rect {
x: area.x,
y: area.y + h,
width: area.width,
height: area.height - h
})?;
if self.focused && i == self.focus {
draw_box_styled(buf, result, Some(Style::default().gray().bold().not_dim()))
}
w = w.max(result.width);
h = h + result.height;
}
Ok(Rect {
x: area.x,
y: area.y,
width: w,
height: h
})
}
}
pub struct Columns {
focused: bool,
focus: usize,
items: Vec<Box<dyn Device>>,
}
impl Columns {
pub fn new (focused: bool, items: Vec<Box<dyn Device>>) -> Self {
Self { focused, focus: 0, items }
} }
} }
impl Device for Columns { impl Device for Columns {
fn handle (&mut self, event: &EngineEvent) -> Result<(), Box<dyn Error>> { fn handle (&mut self, event: &EngineEvent) -> Usually<()> {
Ok(()) if self.focused {
self.items[self.focus].handle(event)
} else {
Ok(())
}
} }
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<(u16, u16)> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let mut x = 0u16; let mut w = 0u16;
let mut y = 0u16; let mut h = 0u16;
for device in self.0.iter() { for (i, device) in self.items.iter().enumerate() {
let (w, h) = device.render(buf, Rect { let result = device.render(buf, Rect {
x: area.x + x, x: area.x + w,
y: area.y, y: area.y,
width: area.width - x, width: area.width - w,
height: area.height height: area.height
})?; })?;
x = x + w; if self.focused && i == self.focus {
y = y.max(h); draw_box_styled(buf, result, Some(Style::default().yellow()))
}
w = w + result.width;
h = h.max(result.height);
} }
Ok((x, y)) Ok(Rect {
x: area.x,
y: area.y,
width: w,
height: h
})
} }
} }

View file

@ -19,34 +19,22 @@ fn main () -> Result<(), Box<dyn Error>> {
let cli = cli::Cli::parse(); let cli = cli::Cli::parse();
let xdg = microxdg::XdgApp::new("dawdle")?; let xdg = microxdg::XdgApp::new("dawdle")?;
crate::config::create_dirs(&xdg)?; crate::config::create_dirs(&xdg)?;
crate::device::run(Rows(vec![ crate::device::run(Rows::new(true, vec![
Box::new(Columns(vec![ Box::new(Sequencer::new("Rhythm#000")?),
Box::new(Chain::new("Chain#00", vec![
Box::new(Sequencer::new("Rhythm#000")?),
Box::new(Sampler::new("Sampler#00")?),
])?),
Box::new(Chain::new("Chain#01", vec![
Box::new(Sequencer::new("Melody#000")?),
Box::new(Plugin::new("Plugin#000")?),
])?),
])),
Box::new(Mixer::new("Mixer#000")?),
Box::new(Transport::new()?), Box::new(Transport::new()?),
])) ]))
//crate::device::run(Rows(vec![ //crate::device::run(Rows::new(true, vec![
////Box::new(Columns(vec![ //Box::new(Columns::new(false, vec![
////Box::new(Chain::new("Chain#00", vec![ //Box::new(Chain::new("Chain#00", vec![
////Box::new(Sequencer::new("Rhythm#000")?), //Box::new(Sequencer::new("Rhythm#000")?),
////Box::new(Sampler::new("Sampler#00")?), //Box::new(Sampler::new("Sampler#00")?),
////])?), //])?),
////Box::new(Chain::new("Chain#01", vec![ //Box::new(Chain::new("Chain#01", vec![
////Box::new(Sequencer::new("Melody#000")?), //Box::new(Sequencer::new("Melody#000")?),
////Box::new(Plugin::new("Plugin#000")?), //Box::new(Plugin::new("Plugin#000")?),
////])?), //])?),
////Box::new(Chain::new("Chain#02", vec![])?), //])),
////Box::new(Chain::new("Chain#03", vec![])?), //Box::new(Mixer::new("Mixer#000")?),
////])),
////Box::new(Mixer::new("Mixer#00")?),
//Box::new(Transport::new()?), //Box::new(Transport::new()?),
//])) //]))
} }

View file

@ -53,11 +53,7 @@ pub use jack::{
}; };
pub type BoxedProcessHandler = Box<dyn FnMut(&Client, &ProcessScope)-> Control + Send>; pub type BoxedProcessHandler = Box<dyn FnMut(&Client, &ProcessScope)-> Control + Send>;
pub type Jack<N> = AsyncClient<N, ClosureProcessHandler<BoxedProcessHandler>>; pub type Jack<N> = AsyncClient<N, ClosureProcessHandler<BoxedProcessHandler>>;
pub use crate::render::{ pub use crate::render::*;
draw_box,
draw_leaf,
draw_focus_corners
};
pub use crate::device::{ pub use crate::device::{
Device, Device,
DynamicDevice, DynamicDevice,

View file

@ -53,6 +53,21 @@ pub fn draw_box (buffer: &mut Buffer, area: Rect) {
buffer.set_string(area.x, area.y + area.height - 1, bottom, border); buffer.set_string(area.x, area.y + area.height - 1, bottom, border);
} }
pub fn draw_box_styled (buffer: &mut Buffer, area: Rect, style: Option<Style>) {
if area.width < 1 || area.height < 1 {
return
}
let style = style.unwrap_or(Style::default());
let top = format!("{}", "".repeat((area.width - 2).into()));
let bottom = format!("{}", "".repeat((area.width - 2).into()));
buffer.set_string(area.x, area.y, top, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
buffer.set_string(area.x, y, format!(""), style);
buffer.set_string(area.x + area.width - 1, y, format!(""), style);
}
buffer.set_string(area.x, area.y + area.height - 1, bottom, style);
}
pub fn draw_focus_corners (buffer: &mut Buffer, area: Rect) { pub fn draw_focus_corners (buffer: &mut Buffer, area: Rect) {
let focus = Style::default().yellow().bold().not_dim(); let focus = Style::default().yellow().bold().not_dim();
buffer.set_string(area.x, area.y, "", focus); buffer.set_string(area.x, area.y, "", focus);