1use crate::{
2 draw_call::{DrawCall, DrawCalls, NonAbsolute},
3 pair::*,
4 rect::Rect,
5};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct Area {
9 rect: Rect,
10 calls: DrawCalls,
11}
12
13impl Area {
14 pub fn new(rect: Rect) -> Self {
15 Self {
16 rect,
17 calls: DrawCalls::new(),
18 }
19 }
20
21 pub fn rect(&self) -> Rect {
22 self.rect.with_pos(Pair::fill(0))
23 }
24
25 pub fn size(&self) -> Pair<Size> {
26 self.rect.size
27 }
28
29 pub fn center(&self) -> Pair<Pos> {
30 self.rect.with_pos(Pair::fill(0)).center()
31 }
32
33 pub fn center_rect(&self, rect: Rect) -> Rect {
34 rect.center_in(self.rect())
35 }
36
37 pub fn push(&mut self, call: DrawCall<NonAbsolute>) {
38 let _ = self.try_push(call);
39 }
40
41 pub fn push_all(&mut self, calls: Vec<DrawCall<NonAbsolute>>) {
42 let _ = self.try_push_all(calls);
43 }
44
45 pub fn try_push(&mut self, call: DrawCall<NonAbsolute>) -> Result<(), AreaOverflowError> {
46 if let Some(absolute) = call.to_absolute(self.rect) {
47 self.calls.push(absolute);
48
49 return Ok(());
50 }
51
52 Err(AreaOverflowError)
53 }
54
55 pub fn try_push_all(
56 &mut self,
57 calls: Vec<DrawCall<NonAbsolute>>,
58 ) -> Result<(), AreaOverflowError> {
59 for call in calls {
60 self.try_push(call)?;
61 }
62
63 Ok(())
64 }
65
66 pub fn push_element(&mut self, rect: Rect, element: Element) {
67 let _ = self.try_push_element(rect, element);
68 }
69
70 pub fn try_push_element(
71 &mut self,
72 rect: Rect,
73 element: Element,
74 ) -> Result<(), AreaOverflowError> {
75 let mut area = Area::new(rect.map_pos(|pos| pos + self.rect.pos));
76
77 if !area.rect.is_inside(self.rect) {
78 return Err(AreaOverflowError);
79 }
80
81 element(&mut area);
82
83 self.calls.extend(area.collect());
84
85 Ok(())
86 }
87
88 pub(crate) fn collect(self) -> DrawCalls {
89 self.calls
90 }
91}
92
93#[derive(Debug)]
94pub struct AreaOverflowError;
95
96pub type Element = Box<dyn Fn(&mut Area)>;