use std::fmt;
use std::ops::Mul;
use super::{
Area, CardinalRotation, Containment, ContainsLocalPosition, HasHeight, HasSize, HasWidth,
IntersectsLocalPosition, IsPosition, IsSize, Length, PlacedShape, Position, ProvidesArea,
ProvidesPlacedShape, ProvidesShape, ProvidesSize, Shape, ShapeIterator,
};
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct Size {
height: Length,
width: Length,
}
impl Size {
#[must_use]
pub fn new(width: Length, height: Length) -> Self {
Self { height, width }
}
#[must_use]
pub fn zero() -> Self {
Self {
height: 0,
width: 0,
}
}
}
impl ContainsLocalPosition for Size {
fn contains_local_position(&self, position: Position) -> Containment {
#[allow(clippy::cast_sign_loss)]
if position.x() < 0
|| position.y() < 0
|| position.x() as Length >= self.width()
|| position.y() as Length >= self.height()
{
Containment::Disjoint
} else if position.x() as Length + 1 == self.width()
|| position.y() as Length + 1 == self.height()
{
Containment::Intersects
} else {
Containment::Contains
}
}
}
impl fmt::Display for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "( width: {}, height: {} )", self.width(), self.height())
}
}
impl HasSize for Size {
fn size(&self) -> &Size {
self
}
fn size_mut(&mut self) -> &mut Size {
self
}
}
impl IntersectsLocalPosition for Size {
fn intersects_local_position(&self, position: Position) -> bool {
#[allow(clippy::cast_sign_loss)]
!(position.x() < 0
|| position.y() < 0
|| position.x() as Length >= self.width()
|| position.y() as Length >= self.height())
}
}
impl IsSize for Size {}
impl HasHeight for Size {
fn height(&self) -> Length {
self.height
}
fn height_mut(&mut self) -> &mut Length {
&mut self.height
}
}
impl HasWidth for Size {
fn width(&self) -> Length {
self.width
}
fn width_mut(&mut self) -> &mut Length {
&mut self.width
}
}
impl Mul<CardinalRotation> for Size {
type Output = Self;
fn mul(self, rotation: CardinalRotation) -> Self::Output {
match rotation {
CardinalRotation::None | CardinalRotation::Full180 => self,
CardinalRotation::Right90 | CardinalRotation::Left90 => {
Self::new(self.height(), self.width())
}
}
}
}
impl ProvidesArea for Size {
fn provide_area(&self) -> Area {
Area::from(*self)
}
}
impl ProvidesPlacedShape for Size {
fn provide_placed_shape(&self) -> Box<dyn PlacedShape> {
Box::new(self.provide_area())
}
}
impl ProvidesShape for Size {
fn provide_shape(&self) -> &dyn Shape {
self
}
}
impl ProvidesSize for Size {
fn provide_size(&self) -> Size {
*self.size()
}
}
impl Shape for Size {
fn box_shape_clone(&self) -> Box<dyn Shape> {
Box::new(*self)
}
fn is_empty(&self) -> bool {
self.height == 0 && self.width == 0
}
fn iter(&self) -> ShapeIterator {
ShapeIterator::new(self)
}
}