1use super::*;
2use plotters_backend::DrawingBackend;
3use std::borrow::Borrow;
4use std::iter::{once, Once};
5use std::marker::PhantomData;
6use std::ops::Add;
7
8pub struct EmptyElement<Coord, DB: DrawingBackend> {
10 coord: Coord,
11 phantom: PhantomData<DB>,
12}
13
14impl<Coord, DB: DrawingBackend> EmptyElement<Coord, DB> {
15 pub fn at(coord: Coord) -> Self {
16 Self {
17 coord,
18 phantom: PhantomData,
19 }
20 }
21}
22
23impl<Coord, Other, DB: DrawingBackend> Add<Other> for EmptyElement<Coord, DB>
24where
25 Other: Drawable<DB>,
26 for<'a> &'a Other: PointCollection<'a, BackendCoord>,
27{
28 type Output = BoxedElement<Coord, DB, Other>;
29 fn add(self, other: Other) -> Self::Output {
30 BoxedElement {
31 offset: self.coord,
32 inner: other,
33 phantom: PhantomData,
34 }
35 }
36}
37
38impl<'a, Coord, DB: DrawingBackend> PointCollection<'a, Coord> for &'a EmptyElement<Coord, DB> {
39 type Point = &'a Coord;
40 type IntoIter = Once<&'a Coord>;
41 fn point_iter(self) -> Self::IntoIter {
42 once(&self.coord)
43 }
44}
45
46impl<Coord, DB: DrawingBackend> Drawable<DB> for EmptyElement<Coord, DB> {
47 fn draw<I: Iterator<Item = BackendCoord>>(
48 &self,
49 _pos: I,
50 _backend: &mut DB,
51 _: (u32, u32),
52 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
53 Ok(())
54 }
55}
56
57pub struct BoxedElement<Coord, DB: DrawingBackend, A: Drawable<DB>> {
59 inner: A,
60 offset: Coord,
61 phantom: PhantomData<DB>,
62}
63
64impl<'b, Coord, DB: DrawingBackend, A: Drawable<DB>> PointCollection<'b, Coord>
65 for &'b BoxedElement<Coord, DB, A>
66{
67 type Point = &'b Coord;
68 type IntoIter = Once<&'b Coord>;
69 fn point_iter(self) -> Self::IntoIter {
70 once(&self.offset)
71 }
72}
73
74impl<Coord, DB: DrawingBackend, A> Drawable<DB> for BoxedElement<Coord, DB, A>
75where
76 for<'a> &'a A: PointCollection<'a, BackendCoord>,
77 A: Drawable<DB>,
78{
79 fn draw<I: Iterator<Item = BackendCoord>>(
80 &self,
81 mut pos: I,
82 backend: &mut DB,
83 ps: (u32, u32),
84 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
85 if let Some((x0, y0)) = pos.next() {
86 self.inner.draw(
87 self.inner.point_iter().into_iter().map(|p| {
88 let p = p.borrow();
89 (p.0 + x0, p.1 + y0)
90 }),
91 backend,
92 ps,
93 )?;
94 }
95 Ok(())
96 }
97}
98
99impl<Coord, DB: DrawingBackend, My, Yours> Add<Yours> for BoxedElement<Coord, DB, My>
100where
101 My: Drawable<DB>,
102 for<'a> &'a My: PointCollection<'a, BackendCoord>,
103 Yours: Drawable<DB>,
104 for<'a> &'a Yours: PointCollection<'a, BackendCoord>,
105{
106 type Output = ComposedElement<Coord, DB, My, Yours>;
107 fn add(self, yours: Yours) -> Self::Output {
108 ComposedElement {
109 offset: self.offset,
110 first: self.inner,
111 second: yours,
112 phantom: PhantomData,
113 }
114 }
115}
116
117pub struct ComposedElement<Coord, DB: DrawingBackend, A, B>
119where
120 A: Drawable<DB>,
121 B: Drawable<DB>,
122{
123 first: A,
124 second: B,
125 offset: Coord,
126 phantom: PhantomData<DB>,
127}
128
129impl<'b, Coord, DB: DrawingBackend, A, B> PointCollection<'b, Coord>
130 for &'b ComposedElement<Coord, DB, A, B>
131where
132 A: Drawable<DB>,
133 B: Drawable<DB>,
134{
135 type Point = &'b Coord;
136 type IntoIter = Once<&'b Coord>;
137 fn point_iter(self) -> Self::IntoIter {
138 once(&self.offset)
139 }
140}
141
142impl<Coord, DB: DrawingBackend, A, B> Drawable<DB> for ComposedElement<Coord, DB, A, B>
143where
144 for<'a> &'a A: PointCollection<'a, BackendCoord>,
145 for<'b> &'b B: PointCollection<'b, BackendCoord>,
146 A: Drawable<DB>,
147 B: Drawable<DB>,
148{
149 fn draw<I: Iterator<Item = BackendCoord>>(
150 &self,
151 mut pos: I,
152 backend: &mut DB,
153 ps: (u32, u32),
154 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
155 if let Some((x0, y0)) = pos.next() {
156 self.first.draw(
157 self.first.point_iter().into_iter().map(|p| {
158 let p = p.borrow();
159 (p.0 + x0, p.1 + y0)
160 }),
161 backend,
162 ps,
163 )?;
164 self.second.draw(
165 self.second.point_iter().into_iter().map(|p| {
166 let p = p.borrow();
167 (p.0 + x0, p.1 + y0)
168 }),
169 backend,
170 ps,
171 )?;
172 }
173 Ok(())
174 }
175}
176
177impl<Coord, DB: DrawingBackend, A, B, C> Add<C> for ComposedElement<Coord, DB, A, B>
178where
179 A: Drawable<DB>,
180 for<'a> &'a A: PointCollection<'a, BackendCoord>,
181 B: Drawable<DB>,
182 for<'a> &'a B: PointCollection<'a, BackendCoord>,
183 C: Drawable<DB>,
184 for<'a> &'a C: PointCollection<'a, BackendCoord>,
185{
186 type Output = ComposedElement<Coord, DB, A, ComposedElement<BackendCoord, DB, B, C>>;
187 fn add(self, rhs: C) -> Self::Output {
188 ComposedElement {
189 offset: self.offset,
190 first: self.first,
191 second: ComposedElement {
192 offset: (0, 0),
193 first: self.second,
194 second: rhs,
195 phantom: PhantomData,
196 },
197 phantom: PhantomData,
198 }
199 }
200}