1use array_map::ArrayMap;
7use serde::{Deserialize, Serialize};
8
9use crate::prelude::*;
10use crate::transform::TranslateMut;
11
12#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
14pub struct Ring {
15 topv: Span,
17 botv: Span,
19 lefth: Span,
21 righth: Span,
23}
24
25#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
27pub enum RingContents {
28 Outer(Rect),
30 Inner(Rect),
32}
33
34impl RingContents {
35 pub fn rect(&self) -> Rect {
37 match self {
38 Self::Outer(r) => *r,
39 Self::Inner(r) => *r,
40 }
41 }
42
43 pub fn is_outer(&self) -> bool {
45 matches!(self, Self::Outer(_))
46 }
47
48 pub fn is_inner(&self) -> bool {
50 matches!(self, Self::Inner(_))
51 }
52}
53
54#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
56pub struct RingBuilder {
57 contents: Option<RingContents>,
58 widths: ArrayMap<Side, i64, 4>,
59}
60
61impl Ring {
62 #[inline]
64 pub fn builder() -> RingBuilder {
65 RingBuilder::new()
66 }
67
68 pub(crate) fn is_valid(&self) -> bool {
70 self.topv.start() > self.botv.stop() && self.righth.start() > self.lefth.stop()
71 }
72
73 pub fn outer_hspan(&self) -> Span {
75 Span::new(self.lefth.start(), self.righth.stop())
76 }
77
78 pub fn inner_hspan(&self) -> Span {
80 Span::new(self.lefth.stop(), self.righth.start())
81 }
82
83 pub fn outer_vspan(&self) -> Span {
85 Span::new(self.botv.start(), self.topv.stop())
86 }
87
88 pub fn inner_vspan(&self) -> Span {
90 Span::new(self.botv.stop(), self.topv.start())
91 }
92
93 pub fn outer(&self) -> Rect {
95 Rect::from_spans(self.outer_hspan(), self.outer_vspan())
96 }
97
98 pub fn inner(&self) -> Rect {
100 Rect::from_spans(self.inner_hspan(), self.inner_vspan())
101 }
102
103 #[inline]
105 pub fn rect(&self, side: Side) -> Rect {
106 match side {
107 Side::Top => Rect::from_spans(self.outer_hspan(), self.topv),
108 Side::Right => Rect::from_spans(self.righth, self.outer_vspan()),
109 Side::Bot => Rect::from_spans(self.outer_hspan(), self.botv),
110 Side::Left => Rect::from_spans(self.lefth, self.outer_vspan()),
111 }
112 }
113
114 #[inline]
116 pub fn inner_rect(&self, side: Side) -> Rect {
117 match side {
118 Side::Top => Rect::from_spans(self.inner_hspan(), self.topv),
119 Side::Right => Rect::from_spans(self.righth, self.inner_vspan()),
120 Side::Bot => Rect::from_spans(self.inner_hspan(), self.botv),
121 Side::Left => Rect::from_spans(self.lefth, self.inner_vspan()),
122 }
123 }
124
125 #[inline]
130 pub fn corner(&self, corner: Corner) -> Rect {
131 match corner {
132 Corner::LowerLeft => Rect::from_spans(self.lefth, self.botv),
133 Corner::UpperLeft => Rect::from_spans(self.lefth, self.topv),
134 Corner::LowerRight => Rect::from_spans(self.righth, self.botv),
135 Corner::UpperRight => Rect::from_spans(self.righth, self.topv),
136 }
137 }
138
139 #[inline]
141 pub fn left(&self) -> Rect {
142 self.rect(Side::Left)
143 }
144
145 #[inline]
147 pub fn right(&self) -> Rect {
148 self.rect(Side::Right)
149 }
150
151 #[inline]
153 pub fn top(&self) -> Rect {
154 self.rect(Side::Top)
155 }
156
157 #[inline]
159 pub fn bot(&self) -> Rect {
160 self.rect(Side::Bot)
161 }
162
163 #[inline]
167 pub fn rects(&self) -> [Rect; 4] {
168 [self.top(), self.right(), self.bot(), self.left()]
169 }
170
171 #[inline]
173 pub fn hrects(&self) -> [Rect; 2] {
174 [self.bot(), self.top()]
175 }
176
177 #[inline]
179 pub fn vrects(&self) -> [Rect; 2] {
180 [self.left(), self.right()]
181 }
182
183 pub fn inner_rects(&self) -> [Rect; 4] {
187 [
188 self.inner_rect(Side::Top),
189 self.inner_rect(Side::Right),
190 self.inner_rect(Side::Bot),
191 self.inner_rect(Side::Left),
192 ]
193 }
194
195 pub fn inner_vrects(&self) -> [Rect; 2] {
197 [self.inner_rect(Side::Left), self.inner_rect(Side::Right)]
198 }
199
200 pub fn inner_hrects(&self) -> [Rect; 2] {
202 [self.inner_rect(Side::Bot), self.inner_rect(Side::Top)]
203 }
204
205 pub fn dir_rects(&self, dir: Dir) -> [Rect; 2] {
209 match dir {
210 Dir::Horiz => self.hrects(),
211 Dir::Vert => self.vrects(),
212 }
213 }
214}
215
216impl Bbox for Ring {
217 #[inline]
218 fn bbox(&self) -> Option<Rect> {
219 self.outer().bbox()
220 }
221}
222
223impl Contains<Point> for Ring {
224 fn contains(&self, other: &Point) -> Containment {
225 self.rects()
226 .into_iter()
227 .map(move |r| r.contains(other))
228 .max()
229 .unwrap()
230 }
231}
232
233impl TranslateMut for Ring {
234 fn translate_mut(&mut self, p: Point) {
235 self.lefth.translate(p.x);
236 self.righth.translate(p.x);
237 self.botv.translate(p.y);
238 self.topv.translate(p.y);
239 }
240}
241
242impl From<RingBuilder> for Ring {
243 fn from(value: RingBuilder) -> Self {
244 let contents = value.contents.unwrap();
245 let r = contents.rect();
246
247 let sign = if contents.is_outer() {
248 Sign::Pos
249 } else {
250 Sign::Neg
251 };
252
253 let topv = Span::with_point_and_length(sign, r.top(), value.widths[Side::Top]);
254 let righth = Span::with_point_and_length(sign, r.right(), value.widths[Side::Right]);
255 let lefth = Span::with_point_and_length(!sign, r.left(), value.widths[Side::Left]);
256 let botv = Span::with_point_and_length(!sign, r.bot(), value.widths[Side::Bot]);
257
258 let res = Self {
259 topv,
260 botv,
261 lefth,
262 righth,
263 };
264
265 if contents.is_outer() {
266 assert_eq!(res.outer(), r);
267 } else {
268 assert_eq!(res.inner(), r);
269 }
270
271 assert!(res.is_valid());
272 res
273 }
274}
275
276impl RingBuilder {
277 #[inline]
279 pub fn new() -> Self {
280 Self::default()
281 }
282
283 #[inline]
285 pub fn build(&mut self) -> Ring {
286 Ring::from(*self)
287 }
288
289 pub fn outer(&mut self, rect: Rect) -> &mut Self {
293 self.contents = Some(RingContents::Outer(rect));
294 self
295 }
296
297 pub fn inner(&mut self, rect: Rect) -> &mut Self {
301 self.contents = Some(RingContents::Inner(rect));
302 self
303 }
304
305 pub fn left_width(&mut self, value: i64) -> &mut Self {
307 self.widths[Side::Left] = value;
308 self
309 }
310
311 pub fn right_width(&mut self, value: i64) -> &mut Self {
313 self.widths[Side::Right] = value;
314 self
315 }
316
317 pub fn bot_height(&mut self, value: i64) -> &mut Self {
319 self.widths[Side::Bot] = value;
320 self
321 }
322
323 pub fn top_height(&mut self, value: i64) -> &mut Self {
325 self.widths[Side::Top] = value;
326 self
327 }
328
329 pub fn widths(&mut self, value: i64) -> &mut Self {
331 self.left_width(value);
332 self.right_width(value)
333 }
334
335 pub fn heights(&mut self, value: i64) -> &mut Self {
337 self.top_height(value);
338 self.bot_height(value)
339 }
340
341 pub fn uniform_width(&mut self, value: i64) -> &mut Self {
343 self.widths(value);
344 self.heights(value)
345 }
346
347 pub fn dir_widths(&mut self, dir: Dir, value: i64) -> &mut Self {
352 match dir {
353 Dir::Vert => self.widths(value),
354 Dir::Horiz => self.heights(value),
355 }
356 }
357
358 pub fn side_width(&mut self, side: Side, value: i64) -> &mut Self {
360 use Side::*;
361 match side {
362 Top => self.top_height(value),
363 Bot => self.bot_height(value),
364 Left => self.left_width(value),
365 Right => self.right_width(value),
366 }
367 }
368}