From d627d257ad597acb62c8d8142f0baa03ac8a8b1a Mon Sep 17 00:00:00 2001 From: unspeaker Date: Wed, 12 Jun 2024 23:21:56 +0300 Subject: [PATCH] wip: layout --- src/device.rs | 14 ++--- src/device/chain.rs | 14 ++--- src/device/launcher.rs | 4 +- src/device/looper.rs | 4 +- src/device/mixer.rs | 8 +-- src/device/plugin.rs | 6 +- src/device/sampler.rs | 12 ++-- src/device/sequencer.rs | 88 ++++++++++++++------------ src/device/transport.rs | 6 +- src/layout.rs | 134 +++++++++++++++++++++++++++++++--------- src/main.rs | 40 +++++------- src/prelude.rs | 6 +- src/render.rs | 15 +++++ 13 files changed, 220 insertions(+), 131 deletions(-) diff --git a/src/device.rs b/src/device.rs index a07b2834..d101029a 100644 --- a/src/device.rs +++ b/src/device.rs @@ -36,7 +36,7 @@ pub fn run (device: impl Device + Send + Sync + 'static) -> Result<(), Box Result<(), Box Result<(), Box Usually<()> { Ok(()) } - fn render (&self, _buffer: &mut Buffer, _area: Rect) -> Usually<(u16, u16)> { - Ok((0,0)) + fn render (&self, _buffer: &mut Buffer, _area: Rect) -> Usually { + Ok(Rect { x: 0, y: 0, width: 0, height: 0 }) } fn process (&mut self, _client: Client, _scope: ProcessScope) {} } pub struct DynamicDevice { pub state: Mutex, - pub render: MutexUsually<(u16, u16)> + Send>>, + pub render: MutexUsually + Send>>, pub handle: MutexUsually<()> + Send>>, pub process: Mutex> } @@ -113,7 +113,7 @@ impl DynamicDevice { process: P, state: T ) -> Self where - R: FnMut(&T, &mut Buffer, Rect)->Usually<(u16, u16)> + Send + 'static, + R: FnMut(&T, &mut Buffer, Rect)->Usually + Send + 'static, H: FnMut(&mut T, &EngineEvent) -> Result<(), Box> + Send + 'static, P: FnMut(&mut T) + Send + 'static { @@ -133,7 +133,7 @@ impl Device for DynamicDevice { fn handle (&mut self, event: &EngineEvent) -> Usually<()> { 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 { self.render.lock().unwrap()(&*self.state.lock().unwrap(), buf, area) } } diff --git a/src/device/chain.rs b/src/device/chain.rs index 24dcbdc3..c28d3ec6 100644 --- a/src/device/chain.rs +++ b/src/device/chain.rs @@ -15,7 +15,7 @@ impl Chain { } pub fn render (state: &Chain, buf: &mut Buffer, area: Rect) - -> Usually<(u16, u16)> + -> Usually { let Rect { x, y, width, height } = area; 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; y = y + 1; for device in state.devices.iter() { - let (w, h) = device.render(buf, Rect { + let result = device.render(buf, Rect { x: area.x, y: area.y + y, 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()); - x = x.max(w); - y = y + h; + x = x.max(result.width); + y = y + result.height; y = y + 1; 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 + 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; //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 + 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> { diff --git a/src/device/launcher.rs b/src/device/launcher.rs index 7c1c3adc..652d9303 100644 --- a/src/device/launcher.rs +++ b/src/device/launcher.rs @@ -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 { + Ok(Rect::default()) +} pub fn handle (state: &mut Launcher, event: &Event) -> Result<(), Box> { Ok(()) diff --git a/src/device/looper.rs b/src/device/looper.rs index 7e067dc0..28993bbb 100644 --- a/src/device/looper.rs +++ b/src/device/looper.rs @@ -13,7 +13,7 @@ impl Looper { } pub fn render (state: &Looper, buf: &mut Buffer, area: Rect) - -> Usually<(u16, u16)> + -> Usually { //let move_to = |col, row| MoveTo(offset.0 + col, offset.1 + row); //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, 3))?.queue(PrintStyledContent(" Loop 2 [ ] ████████ Track 2".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> { diff --git a/src/device/mixer.rs b/src/device/mixer.rs index cc73ce4a..5ad91dfb 100644 --- a/src/device/mixer.rs +++ b/src/device/mixer.rs @@ -42,10 +42,10 @@ impl Mixer { } pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect) - -> Usually<(u16, u16)> + -> Usually { if area.height < 2 { - return Ok((0, 0)) + return Ok(area) } area.x = area.width.saturating_sub(80) / 2; area.width = area.width.min(80); @@ -87,7 +87,7 @@ pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect) //fn render_meters ( //state: &mut Mixer, //stdout: &mut Stdout, - //offset: (u16, u16) + //offset: Rect //) -> Result<(), Box> { //let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); //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> { diff --git a/src/device/plugin.rs b/src/device/plugin.rs index b36921c1..db27f014 100644 --- a/src/device/plugin.rs +++ b/src/device/plugin.rs @@ -13,10 +13,10 @@ impl Plugin { } pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, width, height }: Rect) - -> Usually<(u16, u16)> + -> Usually { 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 + 13, y + 1, &format!("│ Plugin Name"), style.not_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 + 5, &format!(" Parameter 3 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> { diff --git a/src/device/sampler.rs b/src/device/sampler.rs index 24fce4b8..0ac2b8a3 100644 --- a/src/device/sampler.rs +++ b/src/device/sampler.rs @@ -107,28 +107,28 @@ impl Sample { } pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, width, height }: Rect) - -> Usually<(u16, u16)> + -> Usually { let style = Style::default().gray(); 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 + 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", 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", 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", 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 ", 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()); //render_table(state, stdout, offset)?; //render_meters(state, stdout, offset)?; - Ok((40, 11)) + Ok(Rect { x, y, width: 40, height: 11 }) } //fn render_table ( diff --git a/src/device/sequencer.rs b/src/device/sequencer.rs index 626cfa79..6e0781c8 100644 --- a/src/device/sequencer.rs +++ b/src/device/sequencer.rs @@ -206,52 +206,65 @@ const KEYS_VERTICAL: [&'static str; 6] = [ ]; fn render (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect) - -> Usually<(u16, u16)> + -> Usually { 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 { 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 + 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 + 6, &format!(" │ Outputs... "), style.dim()); + Ok(Rect { x, y, width, height: 4 }) +} - let mut h = 9; - let toggle = true; - if toggle { - for i in 0..16 { - buf.set_string(x + 2, y + 4 + i, &format!(" "), Style::default().on_black()); - h = h + 1; - } +fn draw_sequencer_vertical (sequencer: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { + let Rect { x, y, .. } = area; + let white = Style::default().gray(); + let black = Style::default().black(); + for i in 0..area.width-4 { + 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 { - buf.set_string(1 + i * 12 + x + 1, y + h - 5, &format!("▄"), Style::default().white()); - buf.set_string(1 + i * 12 + x + 2, y + h - 5, &format!("▄"), Style::default().black()); - 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()); + let bg = Style::default().on_black(); + for i in 0..area.height - 8 { + buf.set_string(x + 2, y + 1 + i, &" ".repeat((area.width-4)as usize), bg); } - draw_box(buf, Rect { x, y, width: 40, height: h - 2 }); - Ok((40,h-3)) + Ok(Rect { x, y, width: area.width, height: area.height - 6 }) +} + //{ //let mut area = area.clone(); //area.y = area.y + 3; @@ -329,7 +342,6 @@ fn render (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect) //} //} // -} fn draw_sequence_button ( buf: &mut Buffer, diff --git a/src/device/transport.rs b/src/device/transport.rs index 139b4030..cbbe68d5 100644 --- a/src/device/transport.rs +++ b/src/device/transport.rs @@ -41,12 +41,12 @@ impl Transport { } pub fn render (state: &Transport, buf: &mut Buffer, mut area: Rect) - -> Usually<(u16, u16)> + -> Usually { area.x = area.width.saturating_sub(80) / 2; area.width = area.width.min(80); area.height = 5; - draw_box(buf, area); + //draw_box(buf, area); draw_leaf(buf, area, 1, 0, "REC"); draw_leaf(buf, area, 1, 5, "DUB"); 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, 63, &format!("Frame {:>10}", frame)); } - Ok((area.width, area.height)) //let bbt = position.pos.bbt().map(|mut bbt|*bbt //.with_bpm(state.bpm) //.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)") //}).render(area.clone().offset(Offset { x: 50, y: 2 }), buf); //} + Ok(area) } //pub fn render ( diff --git a/src/layout.rs b/src/layout.rs index 3317389f..4776568c 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,47 +1,123 @@ use crate::prelude::*; -pub struct Rows(pub Vec>); +pub struct Rows { + focused: bool, + focus: usize, + items: Vec>, +} -pub struct Columns(pub Vec>); +impl Rows { + pub fn new (focused: bool, items: Vec>) -> Self { + Self { focused, focus: 0, items } + } +} impl Device for Rows { fn handle (&mut self, event: &EngineEvent) -> Usually<()> { - Ok(()) - } - fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<(u16, u16)> { - let mut x = 0u16; - let mut y = 0u16; - for device in self.0.iter() { - let (w, h) = device.render(buf, Rect { - x: area.x, - y: area.y + y, - width: area.width, - height: area.height - y - })?; - x = x.max(w); - y = y + h; + if !self.focused { + match event { + EngineEvent::Input(Event::Key(KeyEvent { code: KeyCode::Esc, .. })) => { + self.focused = true; + Ok(()) + }, + _ => self.items[self.focus].handle(event) + } + } else { + match event { + EngineEvent::Input(event) => match event { + Event::Key(KeyEvent { code: KeyCode::Up, .. }) => { + if self.focus == 0 { + 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 { + 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>, +} + +impl Columns { + pub fn new (focused: bool, items: Vec>) -> Self { + Self { focused, focus: 0, items } } } impl Device for Columns { - fn handle (&mut self, event: &EngineEvent) -> Result<(), Box> { - Ok(()) + fn handle (&mut self, event: &EngineEvent) -> Usually<()> { + if self.focused { + self.items[self.focus].handle(event) + } else { + Ok(()) + } } - fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<(u16, u16)> { - let mut x = 0u16; - let mut y = 0u16; - for device in self.0.iter() { - let (w, h) = device.render(buf, Rect { - x: area.x + x, + fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { + 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 + w, y: area.y, - width: area.width - x, + width: area.width - w, height: area.height })?; - x = x + w; - y = y.max(h); + if self.focused && i == self.focus { + 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 + }) } } diff --git a/src/main.rs b/src/main.rs index f8e566ed..042fd47b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,34 +19,22 @@ fn main () -> Result<(), Box> { let cli = cli::Cli::parse(); let xdg = microxdg::XdgApp::new("dawdle")?; crate::config::create_dirs(&xdg)?; - crate::device::run(Rows(vec![ - Box::new(Columns(vec![ - 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")?), + crate::device::run(Rows::new(true, vec![ + Box::new(Sequencer::new("Rhythm#000")?), Box::new(Transport::new()?), ])) - //crate::device::run(Rows(vec![ - ////Box::new(Columns(vec![ - ////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(Chain::new("Chain#02", vec![])?), - ////Box::new(Chain::new("Chain#03", vec![])?), - ////])), - ////Box::new(Mixer::new("Mixer#00")?), + //crate::device::run(Rows::new(true, vec![ + //Box::new(Columns::new(false, vec![ + //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()?), //])) } diff --git a/src/prelude.rs b/src/prelude.rs index 9feef33a..a3e25122 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -53,11 +53,7 @@ pub use jack::{ }; pub type BoxedProcessHandler = Box Control + Send>; pub type Jack = AsyncClient>; -pub use crate::render::{ - draw_box, - draw_leaf, - draw_focus_corners -}; +pub use crate::render::*; pub use crate::device::{ Device, DynamicDevice, diff --git a/src/render.rs b/src/render.rs index 92bd73b8..2b8d03b9 100644 --- a/src/render.rs +++ b/src/render.rs @@ -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); } +pub fn draw_box_styled (buffer: &mut Buffer, area: Rect, style: Option