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> {
37 coord: Coord,
38 phantom: PhantomData<DB>,
39}
40
41impl<Coord, DB: DrawingBackend> EmptyElement<Coord, DB> {
42 pub fn at(coord: Coord) -> Self {
48 Self {
49 coord,
50 phantom: PhantomData,
51 }
52 }
53}
54
55impl<Coord, Other, DB: DrawingBackend> Add<Other> for EmptyElement<Coord, DB>
56where
57 Other: Drawable<DB>,
58 for<'a> &'a Other: PointCollection<'a, BackendCoord>,
59{
60 type Output = BoxedElement<Coord, DB, Other>;
61 fn add(self, other: Other) -> Self::Output {
62 BoxedElement {
63 offset: self.coord,
64 inner: other,
65 phantom: PhantomData,
66 }
67 }
68}
69
70impl<'a, Coord, DB: DrawingBackend> PointCollection<'a, Coord> for &'a EmptyElement<Coord, DB> {
71 type Point = &'a Coord;
72 type IntoIter = Once<&'a Coord>;
73 fn point_iter(self) -> Self::IntoIter {
74 once(&self.coord)
75 }
76}
77
78impl<Coord, DB: DrawingBackend> Drawable<DB> for EmptyElement<Coord, DB> {
79 fn draw<I: Iterator<Item = BackendCoord>>(
80 &self,
81 _pos: I,
82 _backend: &mut DB,
83 _: (u32, u32),
84 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
85 Ok(())
86 }
87}
88
89pub struct BoxedElement<Coord, DB: DrawingBackend, A: Drawable<DB>> {
96 inner: A,
97 offset: Coord,
98 phantom: PhantomData<DB>,
99}
100
101impl<'b, Coord, DB: DrawingBackend, A: Drawable<DB>> PointCollection<'b, Coord>
102 for &'b BoxedElement<Coord, DB, A>
103{
104 type Point = &'b Coord;
105 type IntoIter = Once<&'b Coord>;
106 fn point_iter(self) -> Self::IntoIter {
107 once(&self.offset)
108 }
109}
110
111impl<Coord, DB: DrawingBackend, A> Drawable<DB> for BoxedElement<Coord, DB, A>
112where
113 for<'a> &'a A: PointCollection<'a, BackendCoord>,
114 A: Drawable<DB>,
115{
116 fn draw<I: Iterator<Item = BackendCoord>>(
117 &self,
118 mut pos: I,
119 backend: &mut DB,
120 ps: (u32, u32),
121 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
122 if let Some((x0, y0)) = pos.next() {
123 self.inner.draw(
124 self.inner.point_iter().into_iter().map(|p| {
125 let p = p.borrow();
126 (p.0 + x0, p.1 + y0)
127 }),
128 backend,
129 ps,
130 )?;
131 }
132 Ok(())
133 }
134}
135
136impl<Coord, DB: DrawingBackend, My, Yours> Add<Yours> for BoxedElement<Coord, DB, My>
137where
138 My: Drawable<DB>,
139 for<'a> &'a My: PointCollection<'a, BackendCoord>,
140 Yours: Drawable<DB>,
141 for<'a> &'a Yours: PointCollection<'a, BackendCoord>,
142{
143 type Output = ComposedElement<Coord, DB, My, Yours>;
144 fn add(self, yours: Yours) -> Self::Output {
145 ComposedElement {
146 offset: self.offset,
147 first: self.inner,
148 second: yours,
149 phantom: PhantomData,
150 }
151 }
152}
153
154pub struct ComposedElement<Coord, DB: DrawingBackend, A, B>
161where
162 A: Drawable<DB>,
163 B: Drawable<DB>,
164{
165 first: A,
166 second: B,
167 offset: Coord,
168 phantom: PhantomData<DB>,
169}
170
171impl<'b, Coord, DB: DrawingBackend, A, B> PointCollection<'b, Coord>
172 for &'b ComposedElement<Coord, DB, A, B>
173where
174 A: Drawable<DB>,
175 B: Drawable<DB>,
176{
177 type Point = &'b Coord;
178 type IntoIter = Once<&'b Coord>;
179 fn point_iter(self) -> Self::IntoIter {
180 once(&self.offset)
181 }
182}
183
184impl<Coord, DB: DrawingBackend, A, B> Drawable<DB> for ComposedElement<Coord, DB, A, B>
185where
186 for<'a> &'a A: PointCollection<'a, BackendCoord>,
187 for<'b> &'b B: PointCollection<'b, BackendCoord>,
188 A: Drawable<DB>,
189 B: Drawable<DB>,
190{
191 fn draw<I: Iterator<Item = BackendCoord>>(
192 &self,
193 mut pos: I,
194 backend: &mut DB,
195 ps: (u32, u32),
196 ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
197 if let Some((x0, y0)) = pos.next() {
198 self.first.draw(
199 self.first.point_iter().into_iter().map(|p| {
200 let p = p.borrow();
201 (p.0 + x0, p.1 + y0)
202 }),
203 backend,
204 ps,
205 )?;
206 self.second.draw(
207 self.second.point_iter().into_iter().map(|p| {
208 let p = p.borrow();
209 (p.0 + x0, p.1 + y0)
210 }),
211 backend,
212 ps,
213 )?;
214 }
215 Ok(())
216 }
217}
218
219impl<Coord, DB: DrawingBackend, A, B, C> Add<C> for ComposedElement<Coord, DB, A, B>
220where
221 A: Drawable<DB>,
222 for<'a> &'a A: PointCollection<'a, BackendCoord>,
223 B: Drawable<DB>,
224 for<'a> &'a B: PointCollection<'a, BackendCoord>,
225 C: Drawable<DB>,
226 for<'a> &'a C: PointCollection<'a, BackendCoord>,
227{
228 type Output = ComposedElement<Coord, DB, A, ComposedElement<BackendCoord, DB, B, C>>;
229 fn add(self, rhs: C) -> Self::Output {
230 ComposedElement {
231 offset: self.offset,
232 first: self.first,
233 second: ComposedElement {
234 offset: (0, 0),
235 first: self.second,
236 second: rhs,
237 phantom: PhantomData,
238 },
239 phantom: PhantomData,
240 }
241 }
242}