1use ratatui_core::style::Color;
2
3use crate::canvas::{Line, Painter, Shape};
4
5#[derive(Debug, Default, Clone, PartialEq)]
10pub struct Rectangle {
11 pub x: f64,
15 pub y: f64,
19 pub width: f64,
21 pub height: f64,
23 pub color: Color,
25}
26
27impl Rectangle {
28 pub const fn new(x: f64, y: f64, width: f64, height: f64, color: Color) -> Self {
30 Self {
31 x,
32 y,
33 width,
34 height,
35 color,
36 }
37 }
38}
39
40impl Shape for Rectangle {
41 fn draw(&self, painter: &mut Painter) {
42 let lines: [Line; 4] = [
43 Line {
44 x1: self.x,
45 y1: self.y,
46 x2: self.x,
47 y2: self.y + self.height,
48 color: self.color,
49 },
50 Line {
51 x1: self.x,
52 y1: self.y + self.height,
53 x2: self.x + self.width,
54 y2: self.y + self.height,
55 color: self.color,
56 },
57 Line {
58 x1: self.x + self.width,
59 y1: self.y,
60 x2: self.x + self.width,
61 y2: self.y + self.height,
62 color: self.color,
63 },
64 Line {
65 x1: self.x,
66 y1: self.y,
67 x2: self.x + self.width,
68 y2: self.y,
69 color: self.color,
70 },
71 ];
72 for line in &lines {
73 line.draw(painter);
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use ratatui_core::buffer::Buffer;
81 use ratatui_core::layout::{Margin, Rect};
82 use ratatui_core::style::Style;
83 use ratatui_core::symbols::Marker;
84 use ratatui_core::widgets::Widget;
85
86 use super::*;
87 use crate::canvas::Canvas;
88
89 #[test]
90 fn draw_block_lines() {
91 let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));
92 let canvas = Canvas::default()
93 .marker(Marker::Block)
94 .x_bounds([0.0, 10.0])
95 .y_bounds([0.0, 10.0])
96 .paint(|context| {
97 context.draw(&Rectangle {
98 x: 0.0,
99 y: 0.0,
100 width: 10.0,
101 height: 10.0,
102 color: Color::Red,
103 });
104 });
105 canvas.render(buffer.area, &mut buffer);
106 let mut expected = Buffer::with_lines([
107 "██████████",
108 "█ █",
109 "█ █",
110 "█ █",
111 "█ █",
112 "█ █",
113 "█ █",
114 "█ █",
115 "█ █",
116 "██████████",
117 ]);
118 expected.set_style(buffer.area, Style::new().red().on_red());
119 expected.set_style(buffer.area.inner(Margin::new(1, 1)), Style::reset());
120 assert_eq!(buffer, expected);
121 }
122
123 #[test]
124 fn draw_half_block_lines() {
125 let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));
126 let canvas = Canvas::default()
127 .marker(Marker::HalfBlock)
128 .x_bounds([0.0, 10.0])
129 .y_bounds([0.0, 10.0])
130 .paint(|context| {
131 context.draw(&Rectangle {
132 x: 0.0,
133 y: 0.0,
134 width: 10.0,
135 height: 10.0,
136 color: Color::Red,
137 });
138 });
139 canvas.render(buffer.area, &mut buffer);
140 let mut expected = Buffer::with_lines([
141 "█▀▀▀▀▀▀▀▀█",
142 "█ █",
143 "█ █",
144 "█ █",
145 "█ █",
146 "█ █",
147 "█ █",
148 "█ █",
149 "█ █",
150 "█▄▄▄▄▄▄▄▄█",
151 ]);
152 expected.set_style(buffer.area, Style::new().red().on_red());
153 expected.set_style(buffer.area.inner(Margin::new(1, 0)), Style::reset().red());
154 expected.set_style(buffer.area.inner(Margin::new(1, 1)), Style::reset());
155 assert_eq!(buffer, expected);
156 }
157
158 #[test]
159 fn draw_braille_lines() {
160 let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));
161 let canvas = Canvas::default()
162 .marker(Marker::Braille)
163 .x_bounds([0.0, 20.0])
164 .y_bounds([0.0, 20.0])
165 .paint(|context| {
166 context.draw(&Rectangle {
168 x: 0.0,
169 y: 0.0,
170 width: 20.0,
171 height: 20.0,
172 color: Color::Red,
173 });
174 context.draw(&Rectangle {
176 x: 4.0,
177 y: 4.0,
178 width: 12.0,
179 height: 12.0,
180 color: Color::Green,
181 });
182 });
183 canvas.render(buffer.area, &mut buffer);
184 let mut expected = Buffer::with_lines([
185 "⡏⠉⠉⠉⠉⠉⠉⠉⠉⢹",
186 "⡇ ⢸",
187 "⡇ ⡏⠉⠉⠉⠉⢹ ⢸",
188 "⡇ ⡇ ⢸ ⢸",
189 "⡇ ⡇ ⢸ ⢸",
190 "⡇ ⡇ ⢸ ⢸",
191 "⡇ ⡇ ⢸ ⢸",
192 "⡇ ⣇⣀⣀⣀⣀⣸ ⢸",
193 "⡇ ⢸",
194 "⣇⣀⣀⣀⣀⣀⣀⣀⣀⣸",
195 ]);
196 expected.set_style(buffer.area, Style::new().red());
197 expected.set_style(buffer.area.inner(Margin::new(1, 1)), Style::reset());
198 expected.set_style(buffer.area.inner(Margin::new(2, 2)), Style::new().green());
199 expected.set_style(buffer.area.inner(Margin::new(3, 3)), Style::reset());
200 assert_eq!(buffer, expected);
201 }
202}