1 | use super::{Drawable, PointCollection}; |
2 | use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind}; |
3 | |
4 | use std::borrow::Borrow; |
5 | |
6 | trait DynDrawable<DB: DrawingBackend> { |
7 | fn draw_dyn( |
8 | &self, |
9 | points: &mut dyn Iterator<Item = BackendCoord>, |
10 | backend: &mut DB, |
11 | parent_dim: (u32, u32), |
12 | ) -> Result<(), DrawingErrorKind<DB::ErrorType>>; |
13 | } |
14 | |
15 | impl<DB: DrawingBackend, T: Drawable<DB>> DynDrawable<DB> for T { |
16 | fn draw_dyn( |
17 | &self, |
18 | points: &mut dyn Iterator<Item = BackendCoord>, |
19 | backend: &mut DB, |
20 | parent_dim: (u32, u32), |
21 | ) -> Result<(), DrawingErrorKind<DB::ErrorType>> { |
22 | T::draw(self, pos:points, backend, parent_dim) |
23 | } |
24 | } |
25 | |
26 | /// The container for a dynamically dispatched element |
27 | pub struct DynElement<'a, DB, Coord> |
28 | where |
29 | DB: DrawingBackend, |
30 | Coord: Clone, |
31 | { |
32 | points: Vec<Coord>, |
33 | drawable: Box<dyn DynDrawable<DB> + 'a>, |
34 | } |
35 | |
36 | impl<'a, 'b: 'a, DB: DrawingBackend, Coord: Clone> PointCollection<'a, Coord> |
37 | for &'a DynElement<'b, DB, Coord> |
38 | { |
39 | type Point = &'a Coord; |
40 | type IntoIter = &'a Vec<Coord>; |
41 | fn point_iter(self) -> Self::IntoIter { |
42 | &self.points |
43 | } |
44 | } |
45 | |
46 | impl<'a, DB: DrawingBackend, Coord: Clone> Drawable<DB> for DynElement<'a, DB, Coord> { |
47 | fn draw<I: Iterator<Item = BackendCoord>>( |
48 | &self, |
49 | mut pos: I, |
50 | backend: &mut DB, |
51 | parent_dim: (u32, u32), |
52 | ) -> Result<(), DrawingErrorKind<DB::ErrorType>> { |
53 | self.drawable.draw_dyn(&mut pos, backend, parent_dim) |
54 | } |
55 | } |
56 | |
57 | /// The trait that makes the conversion from the statically dispatched element |
58 | /// to the dynamically dispatched element |
59 | pub trait IntoDynElement<'a, DB: DrawingBackend, Coord: Clone> |
60 | where |
61 | Self: 'a, |
62 | { |
63 | /// Make the conversion |
64 | fn into_dyn(self) -> DynElement<'a, DB, Coord>; |
65 | } |
66 | |
67 | impl<'b, T, DB, Coord> IntoDynElement<'b, DB, Coord> for T |
68 | where |
69 | T: Drawable<DB> + 'b, |
70 | for<'a> &'a T: PointCollection<'a, Coord>, |
71 | Coord: Clone, |
72 | DB: DrawingBackend, |
73 | { |
74 | fn into_dyn(self) -> DynElement<'b, DB, Coord> { |
75 | DynElement { |
76 | points: self |
77 | .point_iter() |
78 | .into_iter() |
79 | .map(|x: <&T as PointCollection>::Point| x.borrow().clone()) |
80 | .collect(), |
81 | drawable: Box::new(self), |
82 | } |
83 | } |
84 | } |
85 | |