aboutsummaryrefslogtreecommitdiff
path: root/src/element/dynelem.rs
blob: d32c06d727da6ca2fdc24acfae2b907431da5223 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use super::{Drawable, PointCollection};
use crate::drawing::backend::{BackendCoord, DrawingBackend, DrawingErrorKind};

use std::borrow::Borrow;

trait DynDrawable<DB: DrawingBackend> {
    fn draw_dyn(
        &self,
        points: &mut dyn Iterator<Item = BackendCoord>,
        backend: &mut DB,
        parent_dim: (u32, u32),
    ) -> Result<(), DrawingErrorKind<DB::ErrorType>>;
}

impl<DB: DrawingBackend, T: Drawable<DB>> DynDrawable<DB> for T {
    fn draw_dyn(
        &self,
        points: &mut dyn Iterator<Item = BackendCoord>,
        backend: &mut DB,
        parent_dim: (u32, u32),
    ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
        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<Coord>,
    drawable: Box<dyn DynDrawable<DB> + 'a>,
}

impl<'a, 'b: 'a, DB: DrawingBackend, Coord: Clone> PointCollection<'a, Coord>
    for &'a DynElement<'b, DB, Coord>
{
    type Borrow = &'a Coord;
    type IntoIter = &'a Vec<Coord>;
    fn point_iter(self) -> Self::IntoIter {
        &self.points
    }
}

impl<'a, DB: DrawingBackend, Coord: Clone> Drawable<DB> for DynElement<'a, DB, Coord> {
    fn draw<I: Iterator<Item = BackendCoord>>(
        &self,
        mut pos: I,
        backend: &mut DB,
        parent_dim: (u32, u32),
    ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
        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<DB> + '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),
        }
    }
}