kk/src/display/compose.rs

85 lines
1.8 KiB
Rust

use std::{
iter::Map,
ops::{Deref, Range},
vec::IntoIter,
};
use super::{frame::Frame, theme::ColorSet};
#[derive(Clone, Debug)]
pub enum Component {
String(String),
Goto(u16, u16),
Theme(ColorSet),
Padding(u16),
// Pre-formatted
Internal(String),
Repeated(char, u16),
Clear,
}
impl Component {
pub fn prepare_for(self, frame: &Frame) -> String {
match self {
Component::String(s) => s,
Component::Goto(x, y) => frame.goto(x, y),
Component::Theme(c) => c.to_string(),
Component::Clear => termion::clear::All.to_string(),
Component::Padding(len) => " ".repeat(len as usize),
Component::Internal(i) => i,
Component::Repeated(ch, len) => {
ch.to_string().repeat(len as usize)
}
}
}
}
#[derive(Clone, Debug)]
pub struct Components(pub Vec<Component>);
impl Deref for Components {
type Target = Vec<Component>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<Component>> for Components {
fn from(value: Vec<Component>) -> Self {
Self(value)
}
}
impl From<Component> for Components {
fn from(value: Component) -> Self {
Self(vec![value])
}
}
impl Components {
pub fn str_len(&self) -> u16 {
(&self.0)
.into_iter()
.map(|comp| {
if let Component::String(s) = comp {
s.len() as u16
} else {
0
}
})
.sum()
}
pub fn concat_for(self, frame: &Frame) -> String {
self.0
.into_iter()
.map(|component| component.prepare_for(frame))
.collect::<String>()
}
pub fn push(&mut self, comp: Component) {
self.0.push(comp)
}
}