zng_layout/unit/
size.rs

1use std::{fmt, ops};
2
3use zng_var::{animation::Transitionable, impl_from_and_into_var};
4
5use super::{DipSize, Factor, Factor2d, FactorPercent, Layout1d, LayoutMask, Length, PxSize, Rect, Vector, impl_length_comp_conversions};
6
7/// 2D size in [`Length`] units.
8#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
9pub struct Size {
10    /// *width* in length units.
11    pub width: Length,
12    /// *height* in length units.
13    pub height: Length,
14}
15impl fmt::Debug for Size {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        if f.alternate() {
18            f.debug_struct("Size")
19                .field("width", &self.width)
20                .field("height", &self.height)
21                .finish()
22        } else {
23            write!(f, "({:?}, {:?})", self.width, self.height)
24        }
25    }
26}
27impl fmt::Display for Size {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        if let Some(p) = f.precision() {
30            write!(f, "{:.p$} × {:.p$}", self.width, self.height, p = p)
31        } else {
32            write!(f, "{} × {}", self.width, self.height)
33        }
34    }
35}
36impl Size {
37    /// New width, height from any [`Length`] unit.
38    pub fn new<W: Into<Length>, H: Into<Length>>(width: W, height: H) -> Self {
39        Size {
40            width: width.into(),
41            height: height.into(),
42        }
43    }
44
45    /// New width, height from single value of any [`Length`] unit.
46    pub fn splat(wh: impl Into<Length>) -> Self {
47        let wh = wh.into();
48        Size {
49            width: wh.clone(),
50            height: wh,
51        }
52    }
53
54    /// ***width:*** [`Length::zero`], ***height:*** [`Length::zero`]
55    pub fn zero() -> Self {
56        Self::new(Length::zero(), Length::zero())
57    }
58
59    /// Size that fills the available space.
60    ///
61    /// ***width:*** [`Length::fill`], ***height:*** [`Length::fill`]
62    pub fn fill() -> Self {
63        Self::new(Length::fill(), Length::fill())
64    }
65
66    /// Returns `(width, height)`.
67    pub fn as_tuple(self) -> (Length, Length) {
68        (self.width, self.height)
69    }
70
71    /// Returns `[width, height]`.
72    pub fn as_array(self) -> [Length; 2] {
73        [self.width, self.height]
74    }
75
76    /// Returns `true` if all values are [`Length::Default`].
77    pub fn is_default(&self) -> bool {
78        self.width.is_default() && self.height.is_default()
79    }
80
81    /// Replaces [`Length::Default`] values with `overwrite` values.
82    pub fn replace_default(&mut self, overwrite: &Size) {
83        self.width.replace_default(&overwrite.width);
84        self.height.replace_default(&overwrite.height);
85    }
86
87    /// Returns a vector of x: width and y: height.
88    pub fn as_vector(self) -> Vector {
89        Vector {
90            x: self.width,
91            y: self.height,
92        }
93    }
94}
95impl super::Layout2d for Size {
96    type Px = PxSize;
97
98    fn layout_dft(&self, default: Self::Px) -> Self::Px {
99        PxSize::new(self.width.layout_dft_x(default.width), self.height.layout_dft_y(default.height))
100    }
101
102    fn affect_mask(&self) -> LayoutMask {
103        self.width.affect_mask() | self.height.affect_mask()
104    }
105}
106impl_length_comp_conversions! {
107    fn from(width: W, height: H) -> Size {
108        Size::new(width, height)
109    }
110}
111impl_from_and_into_var! {
112    /// Splat.
113    fn from(all: Length) -> Size {
114        Size::splat(all)
115    }
116
117    /// Splat relative length.
118    fn from(percent: FactorPercent) -> Size {
119        Size::splat(percent)
120    }
121    /// Splat relative length.
122    fn from(norm: Factor) -> Size {
123        Size::splat(norm)
124    }
125
126    /// Splat exact length.
127    fn from(f: f32) -> Size {
128        Size::splat(f)
129    }
130    /// Splat exact length.
131    fn from(i: i32) -> Size {
132        Size::splat(i)
133    }
134    fn from(size: PxSize) -> Size {
135        Size::new(size.width, size.height)
136    }
137    fn from(size: DipSize) -> Size {
138        Size::new(size.width, size.height)
139    }
140    fn from(v: Vector) -> Size {
141        v.as_size()
142    }
143    fn from(r: Rect) -> Size {
144        r.size
145    }
146}
147impl<S: Into<Size>> ops::Add<S> for Size {
148    type Output = Size;
149
150    fn add(self, rhs: S) -> Self::Output {
151        let rhs = rhs.into();
152
153        Size {
154            width: self.width + rhs.width,
155            height: self.height + rhs.height,
156        }
157    }
158}
159impl<S: Into<Size>> ops::AddAssign<S> for Size {
160    fn add_assign(&mut self, rhs: S) {
161        let rhs = rhs.into();
162        self.width += rhs.width;
163        self.height += rhs.height;
164    }
165}
166impl<S: Into<Size>> ops::Sub<S> for Size {
167    type Output = Size;
168
169    fn sub(self, rhs: S) -> Self::Output {
170        let rhs = rhs.into();
171
172        Size {
173            width: self.width - rhs.width,
174            height: self.height - rhs.height,
175        }
176    }
177}
178impl<S: Into<Size>> ops::SubAssign<S> for Size {
179    fn sub_assign(&mut self, rhs: S) {
180        let rhs = rhs.into();
181        self.width -= rhs.width;
182        self.height -= rhs.height;
183    }
184}
185impl<S: Into<Factor2d>> ops::Mul<S> for Size {
186    type Output = Self;
187
188    fn mul(mut self, rhs: S) -> Self {
189        self *= rhs;
190        self
191    }
192}
193impl<S: Into<Factor2d>> ops::Mul<S> for &Size {
194    type Output = Size;
195
196    fn mul(self, rhs: S) -> Self::Output {
197        self.clone() * rhs
198    }
199}
200impl<S: Into<Factor2d>> ops::MulAssign<S> for Size {
201    fn mul_assign(&mut self, rhs: S) {
202        let rhs = rhs.into();
203        self.width *= rhs.x;
204        self.height *= rhs.y;
205    }
206}
207impl<S: Into<Factor2d>> ops::Div<S> for Size {
208    type Output = Self;
209
210    fn div(mut self, rhs: S) -> Self {
211        self /= rhs;
212        self
213    }
214}
215impl<S: Into<Factor2d>> ops::Div<S> for &Size {
216    type Output = Size;
217
218    fn div(self, rhs: S) -> Self::Output {
219        self.clone() / rhs
220    }
221}
222impl<S: Into<Factor2d>> ops::DivAssign<S> for Size {
223    fn div_assign(&mut self, rhs: S) {
224        let rhs = rhs.into();
225        self.width /= rhs.x;
226        self.height /= rhs.y;
227    }
228}