1use super::{Drawable, PointCollection};
2use crate::drawing::backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
3use crate::style::ShapeStyle;
4
5pub struct Pixel<'a, Coord> {
7 pos: Coord,
8 style: ShapeStyle<'a>,
9}
10
11impl<'a, Coord> Pixel<'a, Coord> {
12 pub fn new<P: Into<Coord>, S: Into<ShapeStyle<'a>>>(pos: P, style: S) -> Self {
13 Self {
14 pos: pos.into(),
15 style: style.into(),
16 }
17 }
18}
19
20impl<'b, 'a, Coord: 'a> PointCollection<'a, Coord> for &'a Pixel<'b, Coord> {
21 type Borrow = &'a Coord;
22 type IntoIter = std::iter::Once<&'a Coord>;
23 fn point_iter(self) -> Self::IntoIter {
24 std::iter::once(&self.pos)
25 }
26}
27
28impl<'a, Coord: 'a, DB: DrawingBackend> Drawable<DB> for Pixel<'a, Coord> {
29 fn draw<I: Iterator<Item = BackendCoord>>(
30 &self,
31 mut points: I,
32 backend: &mut DB,
33 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
34 if let Some((x, y)) = points.next() {
35 return backend.draw_pixel((x, y), &Box::new(self.style.color));
36 }
37 Ok(())
38 }
39}
40
41#[cfg(test)]
42#[test]
43fn test_pixel_element() {
44 use crate::prelude::*;
45 let da = crate::create_mocked_drawing_area(300, 300, |m| {
46 m.check_draw_pixel(|c, (x, y)| {
47 assert_eq!(x, 150);
48 assert_eq!(y, 152);
49 assert_eq!(c.0, 255);
50 assert_eq!(c.1, 0);
51 assert_eq!(c.2, 0);
52 assert_eq!(c.3, 1.0);
53 });
54
55 m.drop_check(|b| {
56 assert_eq!(b.num_draw_pixel_call, 1);
57 assert_eq!(b.draw_count, 1);
58 });
59 });
60 da.draw(&Pixel::new((150, 152), &Red))
61 .expect("Drawing Failure");
62}
63
64pub struct Path<'a, Coord> {
66 points: Vec<Coord>,
67 style: ShapeStyle<'a>,
68}
69impl<'a, Coord> Path<'a, Coord> {
70 pub fn new<P: Into<Vec<Coord>>, S: Into<ShapeStyle<'a>>>(points: P, style: S) -> Self {
75 Self {
76 points: points.into(),
77 style: style.into(),
78 }
79 }
80}
81
82impl<'b, 'a, Coord: 'a> PointCollection<'a, Coord> for &'a Path<'b, Coord> {
83 type Borrow = &'a Coord;
84 type IntoIter = &'a [Coord];
85 fn point_iter(self) -> &'a [Coord] {
86 &self.points
87 }
88}
89
90impl<'a, Coord: 'a, DB: DrawingBackend> Drawable<DB> for Path<'a, Coord> {
91 fn draw<I: Iterator<Item = BackendCoord>>(
92 &self,
93 points: I,
94 backend: &mut DB,
95 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
96 backend.draw_path(points, &Box::new(self.style.color))
97 }
98}
99
100#[cfg(test)]
101#[test]
102fn test_path_element() {
103 use crate::prelude::*;
104 let da = crate::create_mocked_drawing_area(300, 300, |m| {
105 m.check_draw_path(|c, path| {
106 assert_eq!(c.0, 0);
107 assert_eq!(c.1, 0);
108 assert_eq!(c.2, 255);
109 assert_eq!(c.3, 1.0);
110 assert_eq!(path, vec![(100, 101), (105, 107), (150, 157)]);
111 });
112 m.drop_check(|b| {
113 assert_eq!(b.num_draw_path_call, 1);
114 assert_eq!(b.draw_count, 1);
115 });
116 });
117 da.draw(&Path::new(vec![(100, 101), (105, 107), (150, 157)], &Blue))
118 .expect("Drawing Failure");
119}
120
121pub struct Rectangle<'a, Coord> {
123 points: [Coord; 2],
124 style: ShapeStyle<'a>,
125 margin: (u32, u32, u32, u32),
126}
127
128impl<'a, Coord> Rectangle<'a, Coord> {
129 pub fn new<S: Into<ShapeStyle<'a>>>(points: [Coord; 2], style: S) -> Self {
134 Self {
135 points,
136 style: style.into(),
137 margin: (0, 0, 0, 0),
138 }
139 }
140
141 pub fn set_margin(&mut self, t: u32, b: u32, l: u32, r: u32) -> &mut Self {
147 self.margin = (t, b, l, r);
148 self
149 }
150}
151
152impl<'b, 'a, Coord: 'a> PointCollection<'a, Coord> for &'a Rectangle<'b, Coord> {
153 type Borrow = &'a Coord;
154 type IntoIter = &'a [Coord];
155 fn point_iter(self) -> &'a [Coord] {
156 &self.points
157 }
158}
159
160impl<'a, Coord: 'a, DB: DrawingBackend> Drawable<DB> for Rectangle<'a, Coord> {
161 fn draw<I: Iterator<Item = BackendCoord>>(
162 &self,
163 mut points: I,
164 backend: &mut DB,
165 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
166 match (points.next(), points.next()) {
167 (Some(mut a), Some(mut b)) => {
168 a.1 += self.margin.0 as i32;
169 b.1 -= self.margin.1 as i32;
170 a.0 += self.margin.2 as i32;
171 b.0 -= self.margin.3 as i32;
172 backend.draw_rect(a, b, &Box::new(self.style.color), self.style.filled)
173 }
174 _ => Ok(()),
175 }
176 }
177}
178
179#[cfg(test)]
180#[test]
181fn test_rect_element() {
182 use crate::prelude::*;
183 let da = crate::create_mocked_drawing_area(300, 300, |m| {
184 m.check_draw_rect(|c, f, u, d| {
185 assert_eq!(c.0, 0);
186 assert_eq!(c.1, 0);
187 assert_eq!(c.2, 255);
188 assert_eq!(c.3, 1.0);
189 assert_eq!(f, false);
190 assert_eq!([u, d], [(100, 101), (105, 107)]);
191 });
192 m.drop_check(|b| {
193 assert_eq!(b.num_draw_rect_call, 1);
194 assert_eq!(b.draw_count, 1);
195 });
196 });
197 da.draw(&Rectangle::new([(100, 101), (105, 107)], &Blue))
198 .expect("Drawing Failure");
199}
200
201pub struct Circle<'a, Coord> {
203 center: Coord,
204 size: u32,
205 style: ShapeStyle<'a>,
206}
207
208impl<'a, Coord> Circle<'a, Coord> {
209 pub fn new<S: Into<ShapeStyle<'a>>>(coord: Coord, size: u32, style: S) -> Self {
215 Self {
216 center: coord,
217 size,
218 style: style.into(),
219 }
220 }
221}
222
223impl<'b, 'a, Coord: 'a> PointCollection<'a, Coord> for &'a Circle<'b, Coord> {
224 type Borrow = &'a Coord;
225 type IntoIter = std::iter::Once<&'a Coord>;
226 fn point_iter(self) -> std::iter::Once<&'a Coord> {
227 std::iter::once(&self.center)
228 }
229}
230
231impl<'a, Coord: 'a, DB: DrawingBackend> Drawable<DB> for Circle<'a, Coord> {
232 fn draw<I: Iterator<Item = BackendCoord>>(
233 &self,
234 mut points: I,
235 backend: &mut DB,
236 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
237 if let Some((x, y)) = points.next() {
238 return backend.draw_circle(
239 (x, y),
240 self.size,
241 &Box::new(self.style.color),
242 self.style.filled,
243 );
244 }
245 Ok(())
246 }
247}
248
249#[cfg(test)]
250#[test]
251fn test_circle_element() {
252 use crate::prelude::*;
253 let da = crate::create_mocked_drawing_area(300, 300, |m| {
254 m.check_draw_circle(|c, f, s, r| {
255 assert_eq!(c.0, 0);
256 assert_eq!(c.1, 0);
257 assert_eq!(c.2, 255);
258 assert_eq!(c.3, 1.0);
259 assert_eq!(f, false);
260 assert_eq!(s, (150, 151));
261 assert_eq!(r, 20);
262 });
263 m.drop_check(|b| {
264 assert_eq!(b.num_draw_circle_call, 1);
265 assert_eq!(b.draw_count, 1);
266 });
267 });
268 da.draw(&Circle::new((150, 151), 20, &Blue))
269 .expect("Drawing Failure");
270}