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#[derive(Clone, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Transitionable)]
11pub struct Point {
12 pub x: Length,
14 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 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 pub fn splat(xy: impl Into<Length>) -> Self {
56 let xy = xy.into();
57 Point { x: xy.clone(), y: xy }
58 }
59
60 pub fn zero() -> Self {
62 Self::new(Length::zero(), Length::zero())
63 }
64
65 pub fn top() -> Self {
69 Self::new(Length::half(), Length::zero())
70 }
71
72 pub fn bottom() -> Self {
76 Self::new(Length::half(), Length::fill())
77 }
78
79 pub fn left() -> Self {
83 Self::new(Length::zero(), Length::half())
84 }
85
86 pub fn right() -> Self {
90 Self::new(Length::fill(), Length::half())
91 }
92
93 pub fn top_left() -> Self {
97 Self::zero()
98 }
99
100 pub fn top_right() -> Self {
104 Self::new(Length::fill(), Length::zero())
105 }
106
107 pub fn bottom_left() -> Self {
111 Self::new(Length::zero(), Length::fill())
112 }
113
114 pub fn bottom_right() -> Self {
118 Self::new(Length::fill(), Length::fill())
119 }
120
121 pub fn center() -> Self {
125 Self::new(Length::half(), Length::half())
126 }
127
128 pub fn yx(self) -> Self {
130 Point { y: self.x, x: self.y }
131 }
132
133 pub fn as_tuple(self) -> (Length, Length) {
135 (self.x, self.y)
136 }
137
138 pub fn as_array(self) -> [Length; 2] {
140 [self.x, self.y]
141 }
142
143 pub fn is_default(&self) -> bool {
145 self.x.is_default() && self.y.is_default()
146 }
147
148 pub fn has_default(&self) -> bool {
150 self.x.has_default() || self.y.has_default()
151 }
152
153 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 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 fn from(all: Length) -> Point {
183 Point::splat(all)
184 }
185 fn from(percent: FactorPercent) -> Point {
187 Point::splat(percent)
188 }
189 fn from(norm: Factor) -> Point {
191 Point::splat(norm)
192 }
193
194 fn from(f: f32) -> Point {
196 Point::splat(f)
197 }
198 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}