buffer_graphics_lib/shapes/collection/
mod.rs

1use crate::drawing::Renderable;
2use crate::prelude::*;
3use crate::{sized_renderable, Graphics};
4use graphics_shapes::coord::Coord;
5use graphics_shapes::rect::Rect;
6use graphics_shapes::shape_box::ShapeBox;
7use graphics_shapes::Shape;
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10use std::fmt::Debug;
11use std::slice::Iter;
12
13pub mod mutation;
14
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[derive(Debug, Clone, PartialEq)]
17pub struct ShapeCollection {
18    shapes: Vec<Drawable<ShapeBox>>,
19    bounds: Rect,
20}
21
22pub fn calc_bounds(list: &[Drawable<ShapeBox>]) -> Rect {
23    if list.is_empty() {
24        return Rect::new((0, 0), (0, 0));
25    }
26    let mut bounds = Rect::new(
27        (list[0].left(), list[0].top()),
28        (list[0].right(), list[0].bottom()),
29    );
30    for shape in list.iter().skip(1) {
31        bounds = Rect::new(
32            (
33                bounds.left().min(shape.left()),
34                bounds.top().min(shape.top()),
35            ),
36            (
37                bounds.right().max(shape.right()),
38                bounds.bottom().max(shape.bottom()),
39            ),
40        );
41    }
42    bounds
43}
44
45impl Default for ShapeCollection {
46    fn default() -> Self {
47        ShapeCollection {
48            shapes: vec![],
49            bounds: Rect::new((0, 0), (0, 0)),
50        }
51    }
52}
53
54impl ShapeCollection {
55    #[inline]
56    pub fn iter(&self) -> Iter<'_, Drawable<ShapeBox>> {
57        self.shapes.iter()
58    }
59
60    #[inline]
61    pub fn len(&self) -> usize {
62        self.shapes.len()
63    }
64
65    #[inline]
66    pub fn is_empty(&self) -> bool {
67        self.shapes.is_empty()
68    }
69
70    #[inline]
71    fn update_bounds(&mut self) {
72        self.bounds = calc_bounds(&self.shapes);
73    }
74
75    #[inline]
76    pub fn remove(&mut self, idx: usize) -> Drawable<ShapeBox> {
77        self.shapes.remove(idx)
78    }
79
80    #[inline]
81    pub fn bounds(&self) -> &Rect {
82        &self.bounds
83    }
84
85    #[inline]
86    pub fn left(&self) -> isize {
87        self.bounds.left()
88    }
89
90    #[inline]
91    pub fn top(&self) -> isize {
92        self.bounds.top()
93    }
94
95    #[inline]
96    pub fn bottom(&self) -> isize {
97        self.bounds.bottom()
98    }
99
100    #[inline]
101    pub fn right(&self) -> isize {
102        self.bounds.right()
103    }
104
105    #[inline]
106    pub fn center(&self) -> Coord {
107        self.bounds.center()
108    }
109}
110
111impl Renderable<ShapeCollection> for ShapeCollection {
112    fn render(&self, graphics: &mut Graphics) {
113        for shape in &self.shapes {
114            shape.render(graphics);
115        }
116    }
117}
118
119sized_renderable!(
120    RenderableShapeCollection,
121    ShapeCollection,
122    |col: &ShapeCollection| (col.bounds().width(), col.bounds().height()),
123    |g: &mut Graphics, col: &ShapeCollection| col.render(g)
124);
125
126impl InsertDrawable<ShapeBox> for ShapeCollection {
127    fn insert(&mut self, index: usize, drawable: Drawable<ShapeBox>) {
128        self.shapes.insert(index, drawable);
129        self.update_bounds();
130    }
131
132    fn insert_above(&mut self, drawable: Drawable<ShapeBox>) {
133        self.shapes.push(drawable);
134        self.update_bounds();
135    }
136
137    fn insert_under(&mut self, drawable: Drawable<ShapeBox>) {
138        InsertDrawable::<ShapeBox>::insert(self, 0, drawable);
139    }
140}
141
142impl<S: Shape> InsertShape<S> for ShapeCollection {
143    fn insert(&mut self, index: usize, shape: S, draw_type: DrawType) {
144        InsertShapeBox::insert(self, index, shape.to_shape_box(), draw_type);
145    }
146
147    fn insert_above(&mut self, shape: S, draw_type: DrawType) {
148        InsertShapeBox::insert_above(self, shape.to_shape_box(), draw_type);
149    }
150
151    fn insert_under(&mut self, shape: S, draw_type: DrawType) {
152        InsertShapeBox::insert_under(self, shape.to_shape_box(), draw_type);
153    }
154}
155
156impl InsertShapeBox for ShapeCollection {
157    fn insert(&mut self, index: usize, shape_box: ShapeBox, draw_type: DrawType) {
158        InsertDrawable::insert(self, index, Drawable::from_obj(shape_box, draw_type))
159    }
160
161    fn insert_above(&mut self, shape_box: ShapeBox, draw_type: DrawType) {
162        InsertDrawable::insert_above(self, Drawable::from_obj(shape_box, draw_type))
163    }
164
165    fn insert_under(&mut self, shape_box: ShapeBox, draw_type: DrawType) {
166        InsertDrawable::insert_under(self, Drawable::from_obj(shape_box, draw_type))
167    }
168}
169
170pub trait InsertDrawable<S: Clone>: InsertShapeBox {
171    fn insert(&mut self, index: usize, drawable: Drawable<S>);
172    fn insert_above(&mut self, drawable: Drawable<S>);
173    fn insert_under(&mut self, drawable: Drawable<S>);
174}
175
176pub trait InsertShape<S> {
177    fn insert(&mut self, index: usize, shape: S, draw_type: DrawType);
178    fn insert_above(&mut self, shape: S, draw_type: DrawType);
179    fn insert_under(&mut self, shape: S, draw_type: DrawType);
180}
181
182pub trait InsertShapeBox {
183    fn insert(&mut self, index: usize, shape_box: ShapeBox, draw_type: DrawType);
184    fn insert_above(&mut self, shape_box: ShapeBox, draw_type: DrawType);
185    fn insert_under(&mut self, shape_box: ShapeBox, draw_type: DrawType);
186}