103 lines
2.9 KiB
Rust
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('='),
|
||
|
)
|
||
|
}
|