use std::{fmt, ops};
use zng_unit::DipSideOffsets;
use zng_var::{animation::Transitionable, impl_from_and_into_var};
use super::{impl_length_comp_conversions, Factor, FactorPercent, FactorSideOffsets, Layout1d, LayoutMask, Length, PxSideOffsets};
#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
pub struct SideOffsets {
pub top: Length,
pub right: Length,
pub bottom: Length,
pub left: Length,
}
impl fmt::Debug for SideOffsets {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
f.debug_struct("SideOffsets")
.field("top", &self.top)
.field("right", &self.right)
.field("bottom", &self.bottom)
.field("left", &self.left)
.finish()
} else if self.all_eq() {
write!(f, "{:?}", self.top)
} else if self.dimensions_eq() {
write!(f, "({:?}, {:?})", self.top, self.left)
} else {
write!(f, "({:?}, {:?}, {:?}, {:?})", self.top, self.right, self.bottom, self.left)
}
}
}
impl SideOffsets {
pub fn new<T: Into<Length>, R: Into<Length>, B: Into<Length>, L: Into<Length>>(top: T, right: R, bottom: B, left: L) -> Self {
SideOffsets {
top: top.into(),
right: right.into(),
bottom: bottom.into(),
left: left.into(),
}
}
pub fn new_vh<TB: Into<Length>, LR: Into<Length>>(top_bottom: TB, left_right: LR) -> Self {
let top_bottom = top_bottom.into();
let left_right = left_right.into();
SideOffsets {
top: top_bottom.clone(),
bottom: top_bottom,
left: left_right.clone(),
right: left_right,
}
}
pub fn new_all<T: Into<Length>>(all_sides: T) -> Self {
let all_sides = all_sides.into();
SideOffsets {
top: all_sides.clone(),
right: all_sides.clone(),
bottom: all_sides.clone(),
left: all_sides,
}
}
pub fn zero() -> Self {
Self::new_all(Length::zero())
}
pub fn all_eq(&self) -> bool {
self.top == self.bottom && self.top == self.left && self.top == self.right
}
pub fn dimensions_eq(&self) -> bool {
self.top == self.bottom && self.left == self.right
}
}
impl super::Layout2d for SideOffsets {
type Px = PxSideOffsets;
fn layout_dft(&self, default: Self::Px) -> Self::Px {
PxSideOffsets::new(
self.top.layout_dft_y(default.top),
self.right.layout_dft_x(default.right),
self.bottom.layout_dft_y(default.bottom),
self.left.layout_dft_x(default.left),
)
}
fn affect_mask(&self) -> LayoutMask {
self.top.affect_mask() | self.right.affect_mask() | self.bottom.affect_mask() | self.left.affect_mask()
}
}
impl_from_and_into_var! {
fn from(all: Length) -> SideOffsets {
SideOffsets::new_all(all)
}
fn from(percent: FactorPercent) -> SideOffsets {
SideOffsets::new_all(percent)
}
fn from(norm: Factor) -> SideOffsets {
SideOffsets::new_all(norm)
}
fn from(f: f32) -> SideOffsets {
SideOffsets::new_all(f)
}
fn from(i: i32) -> SideOffsets {
SideOffsets::new_all(i)
}
fn from(offsets: PxSideOffsets) -> SideOffsets {
SideOffsets::new(offsets.top, offsets.right, offsets.bottom, offsets.left)
}
fn from(offsets: DipSideOffsets) -> SideOffsets {
SideOffsets::new(offsets.top, offsets.right, offsets.bottom, offsets.left)
}
}
impl_length_comp_conversions! {
fn from(top_bottom: TB, left_right: LR) -> SideOffsets {
SideOffsets::new_vh(top_bottom, left_right)
}
fn from(top: T, right: R, bottom: B, left: L) -> SideOffsets {
SideOffsets::new(top, right, bottom, left)
}
}
impl ops::Add for SideOffsets {
type Output = Self;
fn add(mut self, rhs: Self) -> Self {
self += rhs;
self
}
}
impl ops::AddAssign for SideOffsets {
fn add_assign(&mut self, rhs: Self) {
self.top += rhs.top;
self.right += rhs.right;
self.bottom += rhs.bottom;
self.left += rhs.left;
}
}
impl ops::Sub for SideOffsets {
type Output = Self;
fn sub(mut self, rhs: Self) -> Self {
self -= rhs;
self
}
}
impl ops::SubAssign for SideOffsets {
fn sub_assign(&mut self, rhs: Self) {
self.top -= rhs.top;
self.right -= rhs.right;
self.bottom -= rhs.bottom;
self.left -= rhs.left;
}
}
impl<S: Into<FactorSideOffsets>> ops::Mul<S> for SideOffsets {
type Output = Self;
fn mul(mut self, rhs: S) -> Self {
self *= rhs;
self
}
}
impl<S: Into<FactorSideOffsets>> ops::Mul<S> for &SideOffsets {
type Output = SideOffsets;
fn mul(self, rhs: S) -> Self::Output {
self.clone() * rhs
}
}
impl<S: Into<FactorSideOffsets>> ops::MulAssign<S> for SideOffsets {
fn mul_assign(&mut self, rhs: S) {
let rhs = rhs.into();
self.top *= rhs.top;
self.right *= rhs.right;
self.bottom *= rhs.bottom;
self.left *= rhs.left;
}
}
impl<S: Into<FactorSideOffsets>> ops::Div<S> for SideOffsets {
type Output = Self;
fn div(mut self, rhs: S) -> Self {
self /= rhs;
self
}
}
impl<S: Into<FactorSideOffsets>> ops::Div<S> for &SideOffsets {
type Output = SideOffsets;
fn div(self, rhs: S) -> Self::Output {
self.clone() / rhs
}
}
impl<S: Into<FactorSideOffsets>> ops::DivAssign<S> for SideOffsets {
fn div_assign(&mut self, rhs: S) {
let rhs = rhs.into();
self.top /= rhs.top;
self.right /= rhs.right;
self.bottom /= rhs.bottom;
self.left /= rhs.left;
}
}