Skip to main content

dotzuki_renderer/
textbox.rs

1use crate::text_renderer::ScreenTileBuffer;
2
3pub const TILE_TOP_LEFT: u8 = 0x79;
4pub const TILE_TOP_RIGHT: u8 = 0x7B;
5pub const TILE_BOTTOM_LEFT: u8 = 0x7D;
6pub const TILE_BOTTOM_RIGHT: u8 = 0x7E;
7pub const TILE_HORIZONTAL: u8 = 0x7A;
8pub const TILE_VERTICAL: u8 = 0x7C;
9pub const TILE_SPACE: u8 = 0x7F;
10pub const TILE_DOWN_ARROW: u8 = 0xED;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct TextBoxFrame {
14    pub x: u32,
15    pub y: u32,
16    pub width: u32,
17    pub height: u32,
18}
19
20impl TextBoxFrame {
21    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
22        Self {
23            x,
24            y,
25            width,
26            height,
27        }
28    }
29
30    pub fn standard_dialog() -> Self {
31        Self {
32            x: 0,
33            y: 12,
34            width: 20,
35            height: 6,
36        }
37    }
38
39    pub fn menu_box(x: u32, y: u32, width: u32, height: u32) -> Self {
40        Self {
41            x,
42            y,
43            width,
44            height,
45        }
46    }
47
48    pub fn draw_frame(&self, buf: &mut ScreenTileBuffer) {
49        let x = self.x;
50        let y = self.y;
51        let w = self.width;
52        let h = self.height;
53
54        if w < 2 || h < 2 {
55            return;
56        }
57
58        let inner_w = w - 2;
59
60        buf.set(x, y, TILE_TOP_LEFT);
61        for i in 0..inner_w {
62            buf.set(x + 1 + i, y, TILE_HORIZONTAL);
63        }
64        buf.set(x + w - 1, y, TILE_TOP_RIGHT);
65
66        for row in 1..h - 1 {
67            buf.set(x, y + row, TILE_VERTICAL);
68            for col in 0..inner_w {
69                buf.set(x + 1 + col, y + row, TILE_SPACE);
70            }
71            buf.set(x + w - 1, y + row, TILE_VERTICAL);
72        }
73
74        buf.set(x, y + h - 1, TILE_BOTTOM_LEFT);
75        for i in 0..inner_w {
76            buf.set(x + 1 + i, y + h - 1, TILE_HORIZONTAL);
77        }
78        buf.set(x + w - 1, y + h - 1, TILE_BOTTOM_RIGHT);
79    }
80
81    pub fn clear(&self, buf: &mut ScreenTileBuffer) {
82        for row in 0..self.height {
83            for col in 0..self.width {
84                buf.set(self.x + col, self.y + row, TILE_SPACE);
85            }
86        }
87    }
88
89    pub fn clear_inner(&self, buf: &mut ScreenTileBuffer) {
90        if self.width < 2 || self.height < 2 {
91            return;
92        }
93        for row in 1..self.height - 1 {
94            for col in 1..self.width - 1 {
95                buf.set(self.x + col, self.y + row, TILE_SPACE);
96            }
97        }
98    }
99
100    pub fn show_down_arrow(&self, buf: &mut ScreenTileBuffer) {
101        if self.width >= 2 && self.height >= 2 {
102            let ax = self.x + self.width - 2;
103            let ay = self.y + self.height - 2;
104            buf.set(ax, ay, TILE_DOWN_ARROW);
105        }
106    }
107
108    pub fn hide_down_arrow(&self, buf: &mut ScreenTileBuffer) {
109        if self.width >= 2 && self.height >= 2 {
110            let ax = self.x + self.width - 2;
111            let ay = self.y + self.height - 2;
112            buf.set(ax, ay, TILE_SPACE);
113        }
114    }
115
116    pub fn text_start(&self) -> (u32, u32) {
117        (self.x + 1, self.y + 2)
118    }
119
120    pub fn second_line_start(&self) -> (u32, u32) {
121        (self.x + 1, self.y + 4)
122    }
123}