use super::{
Area, Containment, ContainsLocalPosition, ContainsPosition, Coord, HasArea, HasBottom,
HasPosition, HasRight, HasSize, Inclusion, IntersectsLocalPosition, IntersectsPosition, IsArea,
IsSize, Placed, PlacedObject, PlacedShape, Position, ProvidesArea, ProvidesPlacedShape,
ProvidesSize, Shape, ShapeIterator, Size,
};
#[derive(Clone)]
pub struct PlacedShapeSlice {
area: Area,
values: Box<[(Inclusion, Box<dyn PlacedShape>)]>,
}
impl PlacedShapeSlice {
#[must_use]
pub fn new(values: Box<[(Inclusion, Box<dyn PlacedShape>)]>) -> Self {
if values.is_empty() {
Self {
area: Area::new(Position::zero(), Size::zero()),
values,
}
} else {
let mut left = Coord::MAX;
let mut top = Coord::MAX;
let mut right = Coord::MIN;
let mut bottom = Coord::MIN;
for value in values.iter() {
left = left.min(value.1.left());
top = top.min(value.1.top());
right = right.max(value.1.right());
bottom = bottom.max(value.1.bottom());
}
let mut area = Area::new(Position::new(left, top), Size::zero());
area.right_set(right);
area.bottom_set(bottom);
Self { area, values }
}
}
}
impl ContainsLocalPosition for PlacedShapeSlice {
fn contains_local_position(&self, position: Position) -> Containment {
self.contains_position(*self.position() + position)
}
}
impl ContainsPosition for PlacedShapeSlice {
fn contains_position(&self, position: Position) -> Containment {
if self.values.is_empty() {
Containment::Disjoint
} else {
let mut containment = Containment::Disjoint;
for value in self.values.iter() {
containment = match value.0 {
Inclusion::Include => containment.max(value.1.contains_position(position)),
Inclusion::Exclude => containment.min(value.1.contains_position(position)),
};
}
containment
}
}
}
impl HasArea for PlacedShapeSlice {
fn area(&self) -> &Area {
&self.area
}
fn area_mut(&mut self) -> &mut Area {
&mut self.area
}
}
impl HasPosition for PlacedShapeSlice {
fn position(&self) -> &Position {
self.area().position()
}
fn position_mut(&mut self) -> &mut Position {
self.area_mut().position_mut()
}
}
impl HasSize for PlacedShapeSlice {
fn size(&self) -> &Size {
self.area().size()
}
fn size_mut(&mut self) -> &mut Size {
self.area_mut().size_mut()
}
}
impl IntersectsLocalPosition for PlacedShapeSlice {
fn intersects_local_position(&self, position: Position) -> bool {
self.intersects_position(*self.position() + position)
}
}
impl IntersectsPosition for PlacedShapeSlice {
fn intersects_position(&self, position: Position) -> bool {
self.contains_position(position) != Containment::Disjoint
}
}
impl IsArea for PlacedShapeSlice {}
impl IsSize for PlacedShapeSlice {}
impl Placed for PlacedShapeSlice {}
impl PlacedObject for PlacedShapeSlice {}
impl ProvidesArea for PlacedShapeSlice {
fn provide_area(&self) -> Area {
*self.area()
}
}
impl ProvidesPlacedShape for PlacedShapeSlice {
fn provide_placed_shape(&self) -> Box<dyn PlacedShape> {
Box::new(self.clone())
}
}
impl ProvidesSize for PlacedShapeSlice {
fn provide_size(&self) -> Size {
*self.area.size()
}
}
impl Shape for PlacedShapeSlice {
fn box_shape_clone(&self) -> Box<dyn Shape> {
Box::new((*self).clone())
}
fn iter(&self) -> ShapeIterator {
ShapeIterator::new(self)
}
}