nativeshell 0.1.0

NativeShell Rust package
Documentation
use std::ops::{Add, Div, Mul, Sub};

#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct _Rect<T> {
    pub x: T,
    pub y: T,
    pub width: T,
    pub height: T,
}

impl<T> _Rect<T>
where
    T: Add<Output = T>
        + Div<Output = T>
        + Sub<Output = T>
        + Mul<Output = T>
        + Copy
        + PartialOrd
        + From<i32>
        + Into<f64>
        + _CastNumber<f64>,
{
    pub fn xywh(x: T, y: T, width: T, height: T) -> Self {
        Self {
            x,
            y,
            width,
            height,
        }
    }

    pub fn origin_size(origin: &_Point<T>, size: &_Size<T>) -> Self {
        Self {
            x: origin.x,
            y: origin.y,
            width: size.width,
            height: size.height,
        }
    }

    pub fn x2(&self) -> T {
        self.x + self.width
    }

    pub fn y2(&self) -> T {
        self.y + self.height
    }

    pub fn is_inside(&self, point: &_Point<T>) -> bool {
        point.x >= self.x && point.x < self.x2() && point.y >= self.y && point.y < self.y2()
    }

    pub fn center(&self) -> _Point<T> {
        _Point::xy(
            self.x + self.width / T::from(2),
            self.y + self.height / T::from(2),
        )
    }

    pub fn origin(&self) -> _Point<T> {
        self.top_left()
    }

    pub fn top_left(&self) -> _Point<T> {
        _Point::xy(self.x, self.y)
    }

    pub fn bottom_right(&self) -> _Point<T> {
        _Point::xy(self.x2(), self.y2())
    }

    pub fn size(&self) -> _Size<T> {
        _Size {
            width: self.width,
            height: self.height,
        }
    }

    pub fn to_local(&self, origin: &_Point<T>) -> _Point<T> {
        _Point::xy(origin.x - self.x, origin.y - self.y)
    }

    pub fn translated(&self, delta: &_Point<T>) -> Self {
        Self {
            x: self.x + delta.x,
            y: self.y + delta.y,
            width: self.width,
            height: self.height,
        }
    }

    pub fn scaled(&self, factor: f64) -> Self {
        let scaled_x: f64 = self.x.into() * factor;
        let scaled_y: f64 = self.y.into() * factor;
        let scaled_width: f64 = self.width.into() * factor;
        let scaled_height: f64 = self.height.into() * factor;
        Self {
            x: T::cast_number(scaled_x),
            y: T::cast_number(scaled_y),
            width: T::cast_number(scaled_width),
            height: T::cast_number(scaled_height),
        }
    }
}

#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct _Point<T> {
    pub x: T,
    pub y: T,
}

impl<T> _Point<T>
where
    T: Sub<Output = T> + Mul<Output = T> + Add<Output = T> + Into<f64> + Copy + _CastNumber<f64>,
{
    pub fn xy(x: T, y: T) -> Self {
        Self { x, y }
    }

    pub fn distance(&self, p: &_Point<T>) -> f64 {
        let x = p.x - self.x;
        let y = p.y - self.y;
        let d: f64 = (x * x + y * y).into();
        d.sqrt()
    }

    pub fn translated(&self, delta: &_Point<T>) -> Self {
        Self {
            x: self.x + delta.x,
            y: self.y + delta.y,
        }
    }

    pub fn scaled(&self, factor: f64) -> Self {
        let scaled_x: f64 = self.x.into() * factor;
        let scaled_y: f64 = self.y.into() * factor;
        Self {
            x: T::cast_number(scaled_x),
            y: T::cast_number(scaled_y),
        }
    }
}

#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct _Size<T> {
    pub width: T,
    pub height: T,
}

impl<T> _Size<T>
where
    T: Sub<Output = T>
        + Mul<Output = T>
        + Add<Output = T>
        + Into<f64>
        + _CastNumber<f64>
        + Copy
        + Default,
{
    pub fn wh(width: T, height: T) -> Self {
        Self { width, height }
    }

    pub fn scaled(&self, factor: f64) -> Self {
        let scaled_width: f64 = self.width.into() * factor;
        let scaled_height: f64 = self.height.into() * factor;
        Self {
            width: T::cast_number(scaled_width),
            height: T::cast_number(scaled_height),
        }
    }
}

impl<T> std::ops::Sub<_Size<T>> for _Size<T>
where
    T: Sub<Output = T> + Copy,
{
    type Output = _Size<T>;

    fn sub(self, rhs: _Size<T>) -> Self::Output {
        Self::Output {
            width: self.width - rhs.width,
            height: self.height - rhs.height,
        }
    }
}

impl<'a, 'b, T> std::ops::Sub<&'b _Size<T>> for &'a _Size<T>
where
    T: Sub<Output = T> + Copy,
{
    type Output = _Size<T>;

    fn sub(self, rhs: &'b _Size<T>) -> Self::Output {
        Self::Output {
            width: self.width - rhs.width,
            height: self.height - rhs.height,
        }
    }
}

impl<'a, 'b, T> std::ops::Add<&'b _Size<T>> for &'a _Size<T>
where
    T: Add<Output = T> + Copy,
{
    type Output = _Size<T>;

    fn add(self, rhs: &'b _Size<T>) -> Self::Output {
        Self::Output {
            width: self.width + rhs.width,
            height: self.height + rhs.height,
        }
    }
}

impl<T> std::ops::Add<_Size<T>> for _Size<T>
where
    T: Add<Output = T> + Copy,
{
    type Output = _Size<T>;

    fn add(self, rhs: _Size<T>) -> Self::Output {
        Self::Output {
            width: self.width + rhs.width,
            height: self.height + rhs.height,
        }
    }
}

pub trait _CastNumber<T>: Sized {
    fn cast_number(_: T) -> Self;
}

impl _CastNumber<f64> for i32 {
    fn cast_number(i: f64) -> Self {
        i as i32
    }
}

impl _CastNumber<f64> for f64 {
    fn cast_number(i: f64) -> Self {
        i
    }
}

impl _CastNumber<i32> for i32 {
    fn cast_number(i: i32) -> Self {
        i
    }
}

impl _CastNumber<i32> for f64 {
    fn cast_number(i: i32) -> Self {
        i as f64
    }
}

impl From<IPoint> for Point {
    fn from(point: IPoint) -> Self {
        Self::xy(point.x as f64, point.y as f64)
    }
}

impl From<Point> for IPoint {
    fn from(point: Point) -> Self {
        Self::xy(point.x as i32, point.y as i32)
    }
}

impl From<ISize> for Size {
    fn from(size: ISize) -> Self {
        Self::wh(size.width as f64, size.height as f64)
    }
}

impl From<Size> for ISize {
    fn from(size: Size) -> Self {
        Self::wh(size.width as i32, size.height as i32)
    }
}

impl From<IRect> for Rect {
    fn from(rect: IRect) -> Self {
        Rect::xywh(
            rect.x as f64,
            rect.y as f64,
            rect.width as f64,
            rect.height as f64,
        )
    }
}

impl From<Rect> for IRect {
    fn from(rect: Rect) -> Self {
        IRect::xywh(
            rect.x as i32,
            rect.y as i32,
            rect.width as i32,
            rect.height as i32,
        )
    }
}

pub type Rect = _Rect<f64>;
pub type IRect = _Rect<i32>;
pub type Point = _Point<f64>;
pub type IPoint = _Point<i32>;
pub type Size = _Size<f64>;
pub type ISize = _Size<i32>;