milk_tea/
draw_call.rs

1use crate::{
2    pair::{Pair, Pos, Size},
3    rect::Rect,
4    text_size::UnicodeSize,
5};
6use crossterm::style::ContentStyle;
7use std::marker::PhantomData;
8
9pub type DrawCalls = Vec<DrawCall<Absolute>>;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct DrawCall<IsAbsolute> {
13    pos: Pair<Pos>,
14    kind: DrawCallKind,
15    _is_absolute: PhantomData<IsAbsolute>,
16}
17
18impl<T> DrawCall<T> {
19    pub fn new(pos: Pair<Pos>, kind: DrawCallKind) -> Self {
20        Self {
21            pos,
22            kind,
23            _is_absolute: PhantomData,
24        }
25    }
26
27    pub fn pos(&self) -> Pair<Pos> {
28        self.pos
29    }
30
31    pub fn kind(&self) -> &DrawCallKind {
32        &self.kind
33    }
34
35    pub fn rect(&self) -> Rect {
36        Rect::new(self.pos, self.size())
37    }
38
39    pub fn size(&self) -> Pair<Size> {
40        match &self.kind {
41            DrawCallKind::PrintLine(string) => Pair::new(single_line(string).width(), 1),
42            DrawCallKind::SetStyle(_) => Pair::new(1, 1),
43        }
44    }
45}
46
47impl DrawCall<NonAbsolute> {
48    pub fn to_absolute(&self, rect: Rect) -> Option<DrawCall<Absolute>> {
49        let self_rect = self.rect().map_pos(|pos| pos + rect.pos);
50
51        if !(self_rect.is_inside(rect)) {
52            return None;
53        }
54
55        Some(DrawCall {
56            pos: self_rect.pos,
57            kind: self.kind.clone(),
58            _is_absolute: PhantomData,
59        })
60    }
61}
62
63#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
64pub struct NonAbsolute;
65
66#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
67pub struct Absolute;
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub enum DrawCallKind {
71    PrintLine(String),
72    SetStyle(ContentStyle),
73}
74
75pub fn single_line(string: &str) -> String {
76    string.lines().collect::<Vec<&str>>().concat()
77}