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}