use super::{Drawable, PointCollection}; use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind}; use std::borrow::Borrow; trait DynDrawable { fn draw_dyn( &self, points: &mut dyn Iterator, backend: &mut DB, parent_dim: (u32, u32), ) -> Result<(), DrawingErrorKind>; } impl> DynDrawable for T { fn draw_dyn( &self, points: &mut dyn Iterator, backend: &mut DB, parent_dim: (u32, u32), ) -> Result<(), DrawingErrorKind> { T::draw(self, points, backend, parent_dim) } } /// The container for a dynamically dispatched element pub struct DynElement<'a, DB, Coord> where DB: DrawingBackend, Coord: Clone, { points: Vec, drawable: Box + 'a>, } impl<'a, 'b: 'a, DB: DrawingBackend, Coord: Clone> PointCollection<'a, Coord> for &'a DynElement<'b, DB, Coord> { type Point = &'a Coord; type IntoIter = &'a Vec; fn point_iter(self) -> Self::IntoIter { &self.points } } impl<'a, DB: DrawingBackend, Coord: Clone> Drawable for DynElement<'a, DB, Coord> { fn draw>( &self, mut pos: I, backend: &mut DB, parent_dim: (u32, u32), ) -> Result<(), DrawingErrorKind> { self.drawable.draw_dyn(&mut pos, backend, parent_dim) } } /// The trait that makes the conversion from the statically dispatched element /// to the dynamically dispatched element pub trait IntoDynElement<'a, DB: DrawingBackend, Coord: Clone> where Self: 'a, { /// Make the conversion fn into_dyn(self) -> DynElement<'a, DB, Coord>; } impl<'b, T, DB, Coord> IntoDynElement<'b, DB, Coord> for T where T: Drawable + 'b, for<'a> &'a T: PointCollection<'a, Coord>, Coord: Clone, DB: DrawingBackend, { fn into_dyn(self) -> DynElement<'b, DB, Coord> { DynElement { points: self .point_iter() .into_iter() .map(|x| x.borrow().clone()) .collect(), drawable: Box::new(self), } } }