zng_layout/unit/
point.rs

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