use crate::Size;
use std::fmt::Display;
use std::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Default, Copy, Clone, PartialEq, PartialOrd, Debug)]
#[cfg_attr(feature = "ffi", repr(C))]
pub struct Position {
pub x: f32,
pub y: f32,
}
impl Position {
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
pub const fn translate(&mut self, x: f32, y: f32) {
self.x += x;
self.y += y;
}
pub fn unit(value: f32) -> Self {
Self { x: value, y: value }
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
pub struct Bounds {
pub x: [f32; 2],
pub y: [f32; 2],
}
impl Bounds {
pub fn new(position: Position, size: Size) -> Self {
Self {
x: [position.x, position.x + size.width],
y: [position.y, position.y + size.height],
}
}
pub fn within(&self, position: &Position) -> bool {
if position.x > self.x[0]
&& position.x < self.x[1]
&& position.y > self.y[0]
&& position.y < self.y[1]
{
return true;
}
false
}
}
impl Add for Position {
type Output = Position;
fn add(self, rhs: Self) -> Self {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl Sub for Position {
type Output = Position;
fn sub(self, rhs: Self) -> Self {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl Add<f32> for Position {
type Output = Position;
fn add(self, rhs: f32) -> Self {
Self {
x: self.x + rhs,
y: self.y + rhs,
}
}
}
impl Sub<f32> for Position {
type Output = Position;
fn sub(self, rhs: f32) -> Self {
Self {
x: self.x - rhs,
y: self.x - rhs,
}
}
}
impl AddAssign for Position {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl AddAssign<f32> for Position {
fn add_assign(&mut self, rhs: f32) {
self.x += rhs;
self.y += rhs;
}
}
impl SubAssign for Position {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
}
}
impl SubAssign<f32> for Position {
fn sub_assign(&mut self, rhs: f32) {
self.x -= rhs;
self.y -= rhs;
}
}
impl Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(prec) = f.precision() {
write!(f, "{:.prec$}x{:.prec$}", self.x, self.y)
} else {
write!(f, "{}x{}", self.x, self.y)
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn display() {
let pos = Position::new(5.0, 35.35);
let string = format!("{pos}");
assert_eq!(string, "5x35.35");
}
#[test]
fn display_with_precision() {
let pos = Position::new(50.0, 20.24242);
let string = format!("{pos:.2}");
assert_eq!(string, "50.00x20.24");
}
}