buffer_graphics_lib/shapes/collection/
mutation.rs1use crate::prelude::*;
2use graphics_shapes::shape_box::ShapeBox;
3
4impl ShapeCollection {
5 pub fn with_draw_type(&self, draw_type: DrawType) -> ShapeCollection {
6 let shapes: Vec<Drawable<ShapeBox>> = self
7 .iter()
8 .map(|shape| shape.with_draw_type(draw_type))
9 .collect();
10 ShapeCollection {
11 shapes,
12 bounds: self.bounds.clone(),
13 }
14 }
15}
16
17impl ShapeCollection {
18 pub fn with_translation<P: Into<Coord>>(&self, delta: P) -> ShapeCollection {
19 let delta = delta.into();
20 let shapes: Vec<Drawable<ShapeBox>> = self
21 .iter()
22 .map(|shape| shape.with_translation(delta))
23 .collect();
24 let bounds = calc_bounds(&shapes);
25 ShapeCollection { shapes, bounds }
26 }
27
28 pub fn with_move<P: Into<Coord>>(&self, xy: P) -> ShapeCollection {
29 let xy = xy.into();
30 let collection_start = Coord::new(self.left(), self.top());
31 let diff = xy - collection_start;
32 let shapes: Vec<Drawable<ShapeBox>> = self
33 .iter()
34 .map(|shape| shape.with_translation(diff))
35 .collect();
36 let bounds = calc_bounds(&shapes);
37 ShapeCollection { shapes, bounds }
38 }
39}
40
41macro_rules! shapebox_mutate_one {
42 ($name: ident, $drawable_name: ident, $param: ident, $param_type: ty) => {
43 impl ShapeCollection {
44 pub fn $name(&self, $param: $param_type) -> ShapeCollection {
45 let center = self.center();
46 let shapes: Vec<Drawable<ShapeBox>> = self
47 .shapes
48 .iter()
49 .map(|shape| shape.$drawable_name($param, center))
50 .collect();
51 let bounds = calc_bounds(&shapes);
52 ShapeCollection { shapes, bounds }
53 }
54 }
55 };
56}
57
58macro_rules! shapebox_mutate_two {
59 ($name: ident, $param: ident, $param_type: ty) => {
60 impl ShapeCollection {
61 pub fn $name<P: Into<Coord>>(&self, $param: $param_type, center: P) -> ShapeCollection {
62 let center = center.into();
63 let shapes: Vec<Drawable<ShapeBox>> = self
64 .shapes
65 .iter()
66 .map(|shape| shape.$name($param, center))
67 .collect();
68 let bounds = calc_bounds(&shapes);
69 ShapeCollection { shapes, bounds }
70 }
71 }
72 };
73}
74
75shapebox_mutate_one!(with_scale, with_scale_around, scale, f32);
76shapebox_mutate_one!(with_rotation, with_rotation_around, degrees, isize);
77shapebox_mutate_two!(with_scale_around, scale, f32);
78shapebox_mutate_two!(with_rotation_around, degrees, isize);
79
80#[cfg(test)]
81mod test {
82 use crate::prelude::*;
83 use graphics_shapes::shape_box::ShapeBox;
84 use ici_files::prelude::*;
85
86 #[test]
87 fn check_with_translation() {
88 let mut collection = ShapeCollection::default();
89 InsertShape::insert_above(&mut collection, Rect::new((20, 20), (40, 40)), fill(RED));
90 InsertShape::insert_above(&mut collection, Rect::new((60, 20), (80, 40)), fill(RED));
91
92 let moved = collection.with_translation((0, 20));
93
94 assert_eq!(
95 moved.shapes,
96 vec![
97 Drawable::from_obj(ShapeBox::from(Rect::new((20, 40), (40, 60))), fill(RED)),
98 Drawable::from_obj(ShapeBox::from(Rect::new((60, 40), (80, 60))), fill(RED)),
99 ]
100 );
101 }
102
103 #[test]
104 fn check_with_move() {
105 let mut collection = ShapeCollection::default();
106 InsertShape::insert_above(&mut collection, Rect::new((20, 20), (40, 40)), fill(RED));
107 InsertShape::insert_above(&mut collection, Rect::new((60, 20), (80, 40)), fill(RED));
108
109 let moved = collection.with_move((0, 0));
110
111 assert_eq!(
112 moved.shapes,
113 vec![
114 Drawable::from_obj(ShapeBox::from(Rect::new((0, 0), (20, 20))), fill(RED)),
115 Drawable::from_obj(ShapeBox::from(Rect::new((40, 0), (60, 20))), fill(RED)),
116 ]
117 );
118 }
119}