| 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, 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| x.borrow().clone()) |
| 80 | .collect(), |
| 81 | drawable: Box::new(self), |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | |