1use super::{Drawable, PointCollection};
2use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
3
4use std::borrow::Borrow;
5
6trait 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
15impl<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
27pub struct DynElement<'a, DB, Coord>
28where
29 DB: DrawingBackend,
30 Coord: Clone,
31{
32 points: Vec<Coord>,
33 drawable: Box<dyn DynDrawable<DB> + 'a>,
34}
35
36impl<'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
46impl<'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
59pub trait IntoDynElement<'a, DB: DrawingBackend, Coord: Clone>
60where
61 Self: 'a,
62{
63 /// Make the conversion
64 fn into_dyn(self) -> DynElement<'a, DB, Coord>;
65}
66
67impl<'b, T, DB, Coord> IntoDynElement<'b, DB, Coord> for T
68where
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