zng_layout/unit/
point.rs

1use std::{fmt, ops};
2
3use zng_var::{animation::Transitionable, impl_from_and_into_var};
4
5use super::{DipPoint, Factor, Factor2d, FactorPercent, Layout1d, LayoutMask, Length, PxPoint, Size, Vector, impl_length_comp_conversions};
6
7/// 2D point in [`Length`] units.
8#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
9pub struct Point {
10    /// *x* offset in length units.
11    pub x: Length,
12    /// *y* offset in length units.
13    pub y: Length,
14}
15impl fmt::Debug for Point {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        if f.alternate() {
18            f.debug_struct("Point").field("x", &self.x).field("y", &self.y).finish()
19        } else {
20            write!(f, "({:?}, {:?})", self.x, self.y)
21        }
22    }
23}
24impl fmt::Display for Point {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        if let Some(p) = f.precision() {
27            write!(f, "({:.p$}, {:.p$})", self.x, self.y, p = p)
28        } else {
29            write!(f, "({}, {})", self.x, self.y)
30        }
31    }
32}
33impl Point {
34    /// New x, y from any [`Length`] unit.
35    pub fn new<X: Into<Length>, Y: Into<Length>>(x: X, y: Y) -> Self {
36        Point { x: x.into(), y: y.into() }
37    }
38
39    /// New x, y from single value of any [`Length`] unit.
40    pub fn splat(xy: impl Into<Length>) -> Self {
41        let xy = xy.into();
42        Point { x: xy.clone(), y: xy }
43    }
44
45    /// ***x:*** [`Length::zero`], ***y:*** [`Length::zero`].
46    pub fn zero() -> Self {
47        Self::new(Length::zero(), Length::zero())
48    }
49
50    /// Point at the top-middle of the available space.
51    ///
52    /// ***x:*** [`Length::half`], ***y:*** [`Length::zero`]
53    pub fn top() -> Self {
54        Self::new(Length::half(), Length::zero())
55    }
56
57    /// Point at the bottom-middle of the available space.
58    ///
59    /// ***x:*** [`Length::half`], ***y:*** [`Length::fill`]
60    pub fn bottom() -> Self {
61        Self::new(Length::half(), Length::fill())
62    }
63
64    /// Point at the middle-left of the available space.
65    ///
66    /// ***x:*** [`Length::zero`], ***y:*** [`Length::half`]
67    pub fn left() -> Self {
68        Self::new(Length::zero(), Length::half())
69    }
70
71    /// Point at the middle-right of the available space.
72    ///
73    /// ***x:*** [`Length::fill`], ***y:*** [`Length::half`]
74    pub fn right() -> Self {
75        Self::new(Length::fill(), Length::half())
76    }
77
78    /// Point at the top-left of the available space.
79    ///
80    /// ***x:*** [`Length::zero`], ***y:*** [`Length::zero`]
81    pub fn top_left() -> Self {
82        Self::zero()
83    }
84
85    /// Point at the top-right of the available space.
86    ///
87    /// ***x:*** [`Length::fill`], ***y:*** [`Length::zero`]
88    pub fn top_right() -> Self {
89        Self::new(Length::fill(), Length::zero())
90    }
91
92    /// Point at the bottom-left of the available space.
93    ///
94    /// ***x:*** [`Length::zero`], ***y:*** [`Length::fill`]
95    pub fn bottom_left() -> Self {
96        Self::new(Length::zero(), Length::fill())
97    }
98
99    /// Point at the bottom-right of the available space.
100    ///
101    /// ***x:*** [`Length::fill`], ***y:*** [`Length::fill`]
102    pub fn bottom_right() -> Self {
103        Self::new(Length::fill(), Length::fill())
104    }
105
106    /// Point at the center.
107    ///
108    /// ***x:*** [`Length::half`], ***y:*** [`Length::half`]
109    pub fn center() -> Self {
110        Self::new(Length::half(), Length::half())
111    }
112
113    /// Swap `x` and `y`.
114    pub fn yx(self) -> Self {
115        Point { y: self.x, x: self.y }
116    }
117
118    /// Returns `(x, y)`.
119    pub fn as_tuple(self) -> (Length, Length) {
120        (self.x, self.y)
121    }
122
123    /// Returns `[x, y]`.
124    pub fn as_array(self) -> [Length; 2] {
125        [self.x, self.y]
126    }
127
128    /// Returns `true` if all values are [`Length::Default`].
129    pub fn is_default(&self) -> bool {
130        self.x.is_default() && self.y.is_default()
131    }
132
133    /// Replaces [`Length::Default`] values with `overwrite` values.
134    pub fn replace_default(&mut self, overwrite: &Point) {
135        self.x.replace_default(&overwrite.x);
136        self.y.replace_default(&overwrite.y);
137    }
138
139    /// Cast to [`Vector`].
140    pub fn as_vector(self) -> Vector {
141        Vector { x: self.x, y: self.y }
142    }
143}
144impl super::Layout2d for Point {
145    type Px = PxPoint;
146
147    fn layout_dft(&self, default: Self::Px) -> Self::Px {
148        PxPoint::new(self.x.layout_dft_x(default.x), self.y.layout_dft_y(default.y))
149    }
150
151    fn affect_mask(&self) -> LayoutMask {
152        self.x.affect_mask() | self.y.affect_mask()
153    }
154}
155impl_length_comp_conversions! {
156    fn from(x: X, y: Y) -> Point {
157        Point::new(x, y)
158    }
159}
160impl_from_and_into_var! {
161    /// Splat.
162    fn from(all: Length) -> Point {
163        Point::splat(all)
164    }
165    /// Splat relative length.
166    fn from(percent: FactorPercent) -> Point {
167        Point::splat(percent)
168    }
169    /// Splat relative length.
170    fn from(norm: Factor) -> Point {
171        Point::splat(norm)
172    }
173
174    /// Splat exact length.
175    fn from(f: f32) -> Point {
176        Point::splat(f)
177    }
178    /// Splat exact length.
179    fn from(i: i32) -> Point {
180        Point::splat(i)
181    }
182    fn from(p: PxPoint) -> Point {
183        Point::new(p.x, p.y)
184    }
185    fn from(p: DipPoint) -> Point {
186        Point::new(p.x, p.y)
187    }
188    fn from(v: Vector) -> Point {
189        v.as_point()
190    }
191}
192impl<V: Into<Vector>> ops::Add<V> for Point {
193    type Output = Self;
194
195    fn add(mut self, rhs: V) -> Self {
196        self += rhs;
197        self
198    }
199}
200impl<'a> ops::Add<&'a Vector> for &Point {
201    type Output = Point;
202
203    fn add(self, rhs: &'a Vector) -> Self::Output {
204        self.clone() + rhs.clone()
205    }
206}
207impl<'a> ops::Add<&'a Size> for &Point {
208    type Output = Point;
209
210    fn add(self, rhs: &'a Size) -> Self::Output {
211        self.clone() + rhs.clone()
212    }
213}
214impl<V: Into<Vector>> ops::AddAssign<V> for Point {
215    fn add_assign(&mut self, rhs: V) {
216        let rhs = rhs.into();
217        self.x += rhs.x;
218        self.y += rhs.y;
219    }
220}
221impl<'a> ops::AddAssign<&'a Vector> for Point {
222    fn add_assign(&mut self, rhs: &'a Vector) {
223        *self += rhs.clone();
224    }
225}
226impl<'a> ops::AddAssign<&'a Size> for Point {
227    fn add_assign(&mut self, rhs: &'a Size) {
228        *self += rhs.clone();
229    }
230}
231impl<V: Into<Vector>> ops::Sub<V> for Point {
232    type Output = Self;
233
234    fn sub(mut self, rhs: V) -> Self {
235        self -= rhs;
236        self
237    }
238}
239impl<'a> ops::Sub<&'a Vector> for &Point {
240    type Output = Point;
241
242    fn sub(self, rhs: &'a Vector) -> Self::Output {
243        self.clone() - rhs.clone()
244    }
245}
246impl<'a> ops::Sub<&'a Size> for &Point {
247    type Output = Point;
248
249    fn sub(self, rhs: &'a Size) -> Self::Output {
250        self.clone() - rhs.clone()
251    }
252}
253impl<V: Into<Vector>> ops::SubAssign<V> for Point {
254    fn sub_assign(&mut self, rhs: V) {
255        let rhs = rhs.into();
256        self.x -= rhs.x;
257        self.y -= rhs.y;
258    }
259}
260impl<'a> ops::SubAssign<&'a Vector> for Point {
261    fn sub_assign(&mut self, rhs: &'a Vector) {
262        *self -= rhs.clone();
263    }
264}
265impl<'a> ops::SubAssign<&'a Size> for Point {
266    fn sub_assign(&mut self, rhs: &'a Size) {
267        *self -= rhs.clone();
268    }
269}
270impl<S: Into<Factor2d>> ops::Mul<S> for Point {
271    type Output = Self;
272
273    fn mul(mut self, rhs: S) -> Self {
274        self *= rhs;
275        self
276    }
277}
278impl<S: Into<Factor2d>> ops::Mul<S> for &Point {
279    type Output = Point;
280
281    fn mul(self, rhs: S) -> Self::Output {
282        self.clone() * rhs
283    }
284}
285impl<S: Into<Factor2d>> ops::MulAssign<S> for Point {
286    fn mul_assign(&mut self, rhs: S) {
287        let rhs = rhs.into();
288        self.x *= rhs.x;
289        self.y *= rhs.y;
290    }
291}
292impl<S: Into<Factor2d>> ops::Div<S> for Point {
293    type Output = Self;
294
295    fn div(mut self, rhs: S) -> Self {
296        self /= rhs;
297        self
298    }
299}
300impl<S: Into<Factor2d>> ops::Div<S> for &Point {
301    type Output = Point;
302
303    fn div(self, rhs: S) -> Self::Output {
304        self.clone() / rhs
305    }
306}
307impl<S: Into<Factor2d>> ops::DivAssign<S> for Point {
308    fn div_assign(&mut self, rhs: S) {
309        let rhs = rhs.into();
310        self.x /= rhs.x;
311        self.y /= rhs.y;
312    }
313}
314impl ops::Neg for Point {
315    type Output = Self;
316
317    fn neg(self) -> Self {
318        Point { x: -self.x, y: -self.y }
319    }
320}
321
322impl ops::Neg for &Point {
323    type Output = Point;
324
325    fn neg(self) -> Self::Output {
326        -self.clone()
327    }
328}