use std::{fmt, mem, ops};
use zng_var::{animation::Transitionable, impl_from_and_into_var};
use super::{impl_length_comp_conversions, Factor, Factor2d, FactorPercent, Layout1d, LayoutMask, Length, Px, PxVector};
#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
pub struct GridSpacing {
pub column: Length,
pub row: Length,
}
impl GridSpacing {
pub fn new<C: Into<Length>, R: Into<Length>>(column: C, row: R) -> Self {
GridSpacing {
column: column.into(),
row: row.into(),
}
}
pub fn new_all<S: Into<Length>>(same: S) -> Self {
let same = same.into();
GridSpacing {
column: same.clone(),
row: same,
}
}
}
impl super::Layout2d for GridSpacing {
type Px = PxGridSpacing;
fn layout_dft(&self, default: Self::Px) -> Self::Px {
PxGridSpacing {
column: self.column.layout_dft_x(default.column),
row: self.row.layout_dft_y(default.row),
}
}
fn affect_mask(&self) -> LayoutMask {
self.column.affect_mask() | self.row.affect_mask()
}
}
impl_length_comp_conversions! {
fn from(column: C, row: R) -> GridSpacing {
GridSpacing::new(column, row)
}
}
impl_from_and_into_var! {
fn from(all: Length) -> GridSpacing {
GridSpacing::new_all(all)
}
fn from(percent: FactorPercent) -> GridSpacing {
GridSpacing::new_all(percent)
}
fn from(norm: Factor) -> GridSpacing {
GridSpacing::new_all(norm)
}
fn from(f: f32) -> GridSpacing {
GridSpacing::new_all(f)
}
fn from(i: i32) -> GridSpacing {
GridSpacing::new_all(i)
}
fn from(spacing: PxGridSpacing) -> GridSpacing {
GridSpacing::new(spacing.column, spacing.row)
}
}
impl fmt::Debug for GridSpacing {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
f.debug_struct("GridSpacing")
.field("column", &self.column)
.field("row", &self.row)
.finish()
} else if self.column == self.row {
write!(f, "{:?}", self.column)
} else {
write!(f, "({:?}, {:?})", self.column, self.row)
}
}
}
impl<S: Into<Factor2d>> ops::Mul<S> for GridSpacing {
type Output = Self;
fn mul(self, rhs: S) -> Self {
let fct = rhs.into();
GridSpacing {
column: self.column * fct.x,
row: self.row * fct.y,
}
}
}
impl<S: Into<Factor2d>> ops::Mul<S> for &GridSpacing {
type Output = GridSpacing;
fn mul(self, rhs: S) -> Self::Output {
self.clone() * rhs
}
}
impl<S: Into<Factor2d>> ops::MulAssign<S> for GridSpacing {
fn mul_assign(&mut self, rhs: S) {
let column = mem::take(&mut self.column);
let row = mem::take(&mut self.row);
let fct = rhs.into();
self.column = column * fct.x;
self.row = row * fct.y;
}
}
impl<S: Into<Factor2d>> ops::Div<S> for GridSpacing {
type Output = Self;
fn div(self, rhs: S) -> Self {
let fct = rhs.into();
GridSpacing {
column: self.column / fct.x,
row: self.row / fct.y,
}
}
}
impl<S: Into<Factor2d>> ops::Div<S> for &GridSpacing {
type Output = GridSpacing;
fn div(self, rhs: S) -> Self::Output {
self.clone() / rhs
}
}
impl<S: Into<Factor2d>> ops::DivAssign<S> for GridSpacing {
fn div_assign(&mut self, rhs: S) {
let column = mem::take(&mut self.column);
let row = mem::take(&mut self.row);
let fct = rhs.into();
self.column = column / fct.x;
self.row = row / fct.y;
}
}
#[derive(Clone, Default, Copy, Debug)]
pub struct PxGridSpacing {
pub column: Px,
pub row: Px,
}
impl PxGridSpacing {
pub fn new(column: Px, row: Px) -> Self {
Self { column, row }
}
pub fn zero() -> Self {
PxGridSpacing { column: Px(0), row: Px(0) }
}
pub fn to_vector(self) -> PxVector {
PxVector::new(self.column, self.row)
}
}
impl ops::Add for GridSpacing {
type Output = Self;
fn add(mut self, rhs: Self) -> Self {
self += rhs;
self
}
}
impl ops::AddAssign for GridSpacing {
fn add_assign(&mut self, rhs: Self) {
self.column += rhs.column;
self.row += rhs.row;
}
}
impl ops::Sub for GridSpacing {
type Output = Self;
fn sub(mut self, rhs: Self) -> Self {
self -= rhs;
self
}
}
impl ops::SubAssign for GridSpacing {
fn sub_assign(&mut self, rhs: Self) {
self.column -= rhs.column;
self.row -= rhs.row;
}
}
impl From<PxGridSpacing> for PxVector {
fn from(s: PxGridSpacing) -> Self {
s.to_vector()
}
}
impl From<PxVector> for PxGridSpacing {
fn from(s: PxVector) -> Self {
PxGridSpacing { column: s.x, row: s.y }
}
}