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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use crate::shapes::collection::shape_box::{FromDrawable, ShapeBox};
use crate::shapes::collection::ShapeCollection;
use graphics_shapes::coord::Coord;

macro_rules! shapebox_mutate_coord {
    ($name: ident, $param: ident) => {
        impl ShapeBox {
            pub fn $name<P: Into<Coord>>(&self, $param: P) -> ShapeBox {
                match self {
                    ShapeBox::Line(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Rect(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Triangle(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Circle(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Ellipse(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Polygon(s) => ShapeBox::from_drawable(s.$name($param)),
                }
            }
        }

        impl ShapeCollection {
            pub fn $name<P: Into<Coord>>(&self, $param: P) -> ShapeCollection {
                let $param = $param.into();
                ShapeCollection {
                    shapes: self
                        .shapes
                        .iter()
                        .map(|shape| shape.$name($param))
                        .collect(),
                }
            }
        }
    };
}

macro_rules! shapebox_mutate_one {
    ($name: ident, $param: ident, $param_type: ty) => {
        impl ShapeBox {
            pub fn $name(&self, $param: $param_type) -> ShapeBox {
                match self {
                    ShapeBox::Line(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Rect(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Triangle(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Circle(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Ellipse(s) => ShapeBox::from_drawable(s.$name($param)),
                    ShapeBox::Polygon(s) => ShapeBox::from_drawable(s.$name($param)),
                }
            }
        }

        impl ShapeCollection {
            pub fn $name(&self, $param: $param_type) -> ShapeCollection {
                ShapeCollection {
                    shapes: self
                        .shapes
                        .iter()
                        .map(|shape| shape.$name($param))
                        .collect(),
                }
            }
        }
    };
}

macro_rules! shapebox_mutate_two {
    ($name: ident, $param: ident, $param_type: ty) => {
        impl ShapeBox {
            pub fn $name<P: Into<Coord>>(&self, $param: $param_type, center: P) -> ShapeBox {
                match self {
                    ShapeBox::Line(s) => ShapeBox::from_drawable(s.$name($param, center)),
                    ShapeBox::Rect(s) => ShapeBox::from_drawable(s.$name($param, center)),
                    ShapeBox::Triangle(s) => ShapeBox::from_drawable(s.$name($param, center)),
                    ShapeBox::Circle(s) => ShapeBox::from_drawable(s.$name($param, center)),
                    ShapeBox::Ellipse(s) => ShapeBox::from_drawable(s.$name($param, center)),
                    ShapeBox::Polygon(s) => ShapeBox::from_drawable(s.$name($param, center)),
                }
            }
        }

        impl ShapeCollection {
            pub fn $name<P: Into<Coord>>(&self, $param: $param_type, center: P) -> ShapeCollection {
                let center = center.into();
                ShapeCollection {
                    shapes: self
                        .shapes
                        .iter()
                        .map(|shape| shape.$name($param, center))
                        .collect(),
                }
            }
        }
    };
}

shapebox_mutate_coord!(with_translation, delta);
shapebox_mutate_coord!(with_move, xy);
shapebox_mutate_one!(with_scale, scale, f32);
shapebox_mutate_one!(with_rotation, degrees, isize);
shapebox_mutate_two!(with_scale_around, scale, f32);
shapebox_mutate_two!(with_rotation_around, degrees, isize);