kk/src/display/frame.rs

103 lines
2.9 KiB
Rust

use std::{io, process};
use termion::{color, cursor, screen::IntoAlternateScreen};
use super::theme::Theme;
const ESTIMATED_FRAME_BIT_SIZE: usize = 11;
pub enum FrameDef {
ByAbsolute(u16, u16),
ByPercent(u16, u16),
}
struct Frame {
start: (u16, u16),
end: (u16, u16),
}
impl Frame {
fn from_bottom_right(pos: (u16, u16), term: (u16, u16)) -> Self {
Self {
start: (term.0 - pos.0, term.1 - pos.1),
end: pos,
}
}
fn frame_str(&self, frame_char: char) -> String {
let (w_len, h_len) = (
(self.end.0 - self.start.0) as usize,
(self.end.1 - self.start.1 - 1) as usize,
);
let width_str = frame_char.to_string().repeat(w_len + 1);
let mut frame = String::with_capacity((h_len * 2) + (w_len * 2) * ESTIMATED_FRAME_BIT_SIZE);
let make_line =
|y: u16| format!("{left}{}", width_str, left = cursor::Goto(self.start.0, y));
frame.push_str(&make_line(self.start.1));
for y in self.start.1 + 1..self.end.1 {
frame.push_str(&format!(
"{left}{char}{right}{char}",
left = cursor::Goto(self.start.0, y),
right = cursor::Goto(self.end.0, y),
char = frame_char,
));
}
frame.push_str(&make_line(self.end.1));
frame
}
}
#[cfg(test)]
mod test {
use super::Frame;
#[test]
fn test_idk() {
let x = Frame::from_bottom_right((16, 16), (32, 32)).frame_str('=');
println!("starting");
println!("{}", x);
println!("ending");
assert!(false)
}
}
impl FrameDef {
fn abs_size(&self) -> Frame {
let (term_height, term_width) =
termion::terminal_size().expect("could not get terminal size");
let pos = match self {
FrameDef::ByAbsolute(h, w) => {
let (mut h, mut w) = (*h, *w);
if h > term_height {
h = term_height;
}
if w > term_width {
w = term_width;
}
(h, w)
}
FrameDef::ByPercent(h, w) => {
// term_height = 100%
// x = h%
// x = term_height * h / 100
let (h, w) = (
if *h > 100 { 100 } else { *h },
if *w > 100 { 100 } else { *w },
);
// (h * 100 / term_height, w * 100 / term_width)
(term_height * h / 100, term_width * w / 100)
}
};
Frame::from_bottom_right(pos, (term_height, term_width))
}
}
pub fn draw_frame(theme: Theme, frame_size: FrameDef) -> String {
let frame_specs = frame_size.abs_size();
format!(
"{fg}{bg}{frame}",
fg = theme.colors.frame_fg.fg_string(),
bg = theme.colors.frame_bg.bg_string(),
frame = frame_specs.frame_str('='),
)
}