use std::io::{Stdout, Write}; use termion::{cursor, raw::RawTerminal}; use crate::Result; #[derive(Clone)] pub struct Widget { pub width: usize, pub height: usize, pub x: usize, pub y: usize, title: String, } impl Widget { pub fn new(width: usize, height: usize, x: usize, y: usize, title: String) -> Result { Ok(Widget { width, height, x, y, title }) } pub fn print( &self, stdout: &mut RawTerminal, x: usize, y: usize, text: &str, ) -> Result<()> { write!(stdout, "{}{}", cursor::Goto(1 + x as u16, 1 + y as u16), text)?; Ok(()) } pub fn print_border(&self, stdout: &mut RawTerminal) -> Result<()> { let x = self.x; let y = self.y; let width = self.width; let height = self.height; let hline = "─"; let vline = "│"; let topleftcorner = "┌"; let toprightcorner = "┐"; let downleftcorner = "└"; let downrightcorner = "┘"; self.print(stdout, x, y, topleftcorner)?; self.print(stdout, x, y + height, downleftcorner)?; self.print(stdout, x + width - 1, y, toprightcorner)?; self.print(stdout, x + width - 1, y + height, downrightcorner)?; for j in (y + 1)..(y + height) { self.print(stdout, x, j, vline)?; self.print(stdout, x + width - 1, j, vline)?; } for i in (x + 1)..(x + width - 1) { self.print(stdout, i, y, hline)?; self.print(stdout, i, y + height, hline)?; } Ok(()) } pub fn clear_current_line(&self, stdout: &mut RawTerminal) -> Result<()> { let width = self.width; for i in self.x..(width - 3) { self.print(stdout, i, self.y, " ")?; } Ok(()) } pub fn draw(&self, stdout: &mut RawTerminal) -> Result<()> { self.print_border(stdout)?; self.print(stdout, self.x + 3, self.y, &format!(" {} ", &self.title.clone()))?; Ok(()) } } pub trait Layout { fn draw( &mut self, stdout: &mut RawTerminal, x: usize, y: usize, layout_width: usize, layout_height: usize, ) -> Result<(usize, usize)>; } pub struct VBox { widgets: Vec, width: usize, } impl VBox { pub fn new(widgets: Vec, width: usize) -> Self { Self { widgets, width } } } impl Layout for VBox { fn draw( &mut self, stdout: &mut RawTerminal, x: usize, y: usize, layout_width: usize, layout_height: usize, ) -> Result<(usize, usize)> { let len = self.widgets.len(); let widget_width = layout_width / self.width; for (i, widget) in self.widgets.iter_mut().enumerate() { widget.width = widget_width - 1; widget.height = (layout_height / len) - 1; widget.x = x; widget.y = (widget.height + 1) * i + y; widget.draw(stdout)?; } Ok((widget_width, y)) } } pub struct HBox { widgets: Vec, pub height: usize, } impl HBox { pub fn new(widgets: Vec, height: usize) -> Self { Self { widgets, height } } } impl Layout for HBox { fn draw( &mut self, stdout: &mut RawTerminal, x: usize, y: usize, layout_width: usize, layout_height: usize, ) -> Result<(usize, usize)> { let len = self.widgets.len(); let widget_height = layout_height / self.height; for (i, widget) in self.widgets.iter_mut().enumerate() { widget.width = layout_width / len - 1; widget.height = widget_height - 1; widget.x = (widget.width + 1) * i + x; widget.y = y; widget.draw(stdout)?; } Ok((x, widget_height)) } }