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, "({:.p$?}, {:.p$?})", self.x, self.y, p = f.precision().unwrap_or(0))
23 }
24 }
25}
26impl fmt::Display for Point {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 write!(f, "({:.p$}, {:.p$}", self.x, self.y, p = f.precision().unwrap_or(0))
29 }
30}
31impl std::str::FromStr for Point {
32 type Err = ParseCompositeError;
33
34 fn from_str(s: &str) -> Result<Self, Self::Err> {
35 let mut parser = LengthCompositeParser::new(s)?;
36 let a = parser.next()?;
37 if parser.has_ended() {
38 return Ok(Self::splat(a));
39 }
40 let b = parser.expect_last()?;
41 Ok(Self::new(a, b))
42 }
43}
44impl Point {
45 pub fn new<X: Into<Length>, Y: Into<Length>>(x: X, y: Y) -> Self {
47 Point { x: x.into(), y: y.into() }
48 }
49
50 pub fn splat(xy: impl Into<Length>) -> Self {
52 let xy = xy.into();
53 Point { x: xy.clone(), y: xy }
54 }
55
56 pub fn zero() -> Self {
58 Self::new(Length::zero(), Length::zero())
59 }
60
61 pub fn top() -> Self {
65 Self::new(Length::half(), Length::zero())
66 }
67
68 pub fn bottom() -> Self {
72 Self::new(Length::half(), Length::fill())
73 }
74
75 pub fn left() -> Self {
79 Self::new(Length::zero(), Length::half())
80 }
81
82 pub fn right() -> Self {
86 Self::new(Length::fill(), Length::half())
87 }
88
89 pub fn top_left() -> Self {
93 Self::zero()
94 }
95
96 pub fn top_right() -> Self {
100 Self::new(Length::fill(), Length::zero())
101 }
102
103 pub fn bottom_left() -> Self {
107 Self::new(Length::zero(), Length::fill())
108 }
109
110 pub fn bottom_right() -> Self {
114 Self::new(Length::fill(), Length::fill())
115 }
116
117 pub fn center() -> Self {
121 Self::new(Length::half(), Length::half())
122 }
123
124 pub fn yx(self) -> Self {
126 Point { y: self.x, x: self.y }
127 }
128
129 pub fn as_tuple(self) -> (Length, Length) {
131 (self.x, self.y)
132 }
133
134 pub fn as_array(self) -> [Length; 2] {
136 [self.x, self.y]
137 }
138
139 pub fn is_default(&self) -> bool {
141 self.x.is_default() && self.y.is_default()
142 }
143
144 pub fn has_default(&self) -> bool {
146 self.x.has_default() || self.y.has_default()
147 }
148
149 pub fn replace_default(&mut self, overwrite: &Point) {
151 self.x.replace_default(&overwrite.x);
152 self.y.replace_default(&overwrite.y);
153 }
154
155 pub fn as_vector(self) -> Vector {
157 Vector { x: self.x, y: self.y }
158 }
159}
160impl super::Layout2d for Point {
161 type Px = PxPoint;
162
163 fn layout_dft(&self, default: Self::Px) -> Self::Px {
164 PxPoint::new(self.x.layout_dft_x(default.x), self.y.layout_dft_y(default.y))
165 }
166
167 fn affect_mask(&self) -> LayoutMask {
168 self.x.affect_mask() | self.y.affect_mask()
169 }
170}
171impl_length_comp_conversions! {
172 fn from(x: X, y: Y) -> Point {
173 Point::new(x, y)
174 }
175}
176impl_from_and_into_var! {
177 fn from(all: Length) -> Point {
179 Point::splat(all)
180 }
181 fn from(percent: FactorPercent) -> Point {
183 Point::splat(percent)
184 }
185 fn from(norm: Factor) -> Point {
187 Point::splat(norm)
188 }
189
190 fn from(f: f32) -> Point {
192 Point::splat(f)
193 }
194 fn from(i: i32) -> Point {
196 Point::splat(i)
197 }
198 fn from(p: PxPoint) -> Point {
199 Point::new(p.x, p.y)
200 }
201 fn from(p: DipPoint) -> Point {
202 Point::new(p.x, p.y)
203 }
204 fn from(v: Vector) -> Point {
205 v.as_point()
206 }
207}
208impl<V: Into<Vector>> ops::Add<V> for Point {
209 type Output = Self;
210
211 fn add(mut self, rhs: V) -> Self {
212 self += rhs;
213 self
214 }
215}
216impl<'a> ops::Add<&'a Vector> for &Point {
217 type Output = Point;
218
219 fn add(self, rhs: &'a Vector) -> Self::Output {
220 self.clone() + rhs.clone()
221 }
222}
223impl<'a> ops::Add<&'a Size> for &Point {
224 type Output = Point;
225
226 fn add(self, rhs: &'a Size) -> Self::Output {
227 self.clone() + rhs.clone()
228 }
229}
230impl<V: Into<Vector>> ops::AddAssign<V> for Point {
231 fn add_assign(&mut self, rhs: V) {
232 let rhs = rhs.into();
233 self.x += rhs.x;
234 self.y += rhs.y;
235 }
236}
237impl<'a> ops::AddAssign<&'a Vector> for Point {
238 fn add_assign(&mut self, rhs: &'a Vector) {
239 *self += rhs.clone();
240 }
241}
242impl<'a> ops::AddAssign<&'a Size> for Point {
243 fn add_assign(&mut self, rhs: &'a Size) {
244 *self += rhs.clone();
245 }
246}
247impl<V: Into<Vector>> ops::Sub<V> for Point {
248 type Output = Self;
249
250 fn sub(mut self, rhs: V) -> Self {
251 self -= rhs;
252 self
253 }
254}
255impl<'a> ops::Sub<&'a Vector> for &Point {
256 type Output = Point;
257
258 fn sub(self, rhs: &'a Vector) -> Self::Output {
259 self.clone() - rhs.clone()
260 }
261}
262impl<'a> ops::Sub<&'a Size> for &Point {
263 type Output = Point;
264
265 fn sub(self, rhs: &'a Size) -> Self::Output {
266 self.clone() - rhs.clone()
267 }
268}
269impl<V: Into<Vector>> ops::SubAssign<V> for Point {
270 fn sub_assign(&mut self, rhs: V) {
271 let rhs = rhs.into();
272 self.x -= rhs.x;
273 self.y -= rhs.y;
274 }
275}
276impl<'a> ops::SubAssign<&'a Vector> for Point {
277 fn sub_assign(&mut self, rhs: &'a Vector) {
278 *self -= rhs.clone();
279 }
280}
281impl<'a> ops::SubAssign<&'a Size> for Point {
282 fn sub_assign(&mut self, rhs: &'a Size) {
283 *self -= rhs.clone();
284 }
285}
286impl<S: Into<Factor2d>> ops::Mul<S> for Point {
287 type Output = Self;
288
289 fn mul(mut self, rhs: S) -> Self {
290 self *= rhs;
291 self
292 }
293}
294impl<S: Into<Factor2d>> ops::Mul<S> for &Point {
295 type Output = Point;
296
297 fn mul(self, rhs: S) -> Self::Output {
298 self.clone() * rhs
299 }
300}
301impl<S: Into<Factor2d>> ops::MulAssign<S> for Point {
302 fn mul_assign(&mut self, rhs: S) {
303 let rhs = rhs.into();
304 self.x *= rhs.x;
305 self.y *= rhs.y;
306 }
307}
308impl<S: Into<Factor2d>> ops::Div<S> for Point {
309 type Output = Self;
310
311 fn div(mut self, rhs: S) -> Self {
312 self /= rhs;
313 self
314 }
315}
316impl<S: Into<Factor2d>> ops::Div<S> for &Point {
317 type Output = Point;
318
319 fn div(self, rhs: S) -> Self::Output {
320 self.clone() / rhs
321 }
322}
323impl<S: Into<Factor2d>> ops::DivAssign<S> for Point {
324 fn div_assign(&mut self, rhs: S) {
325 let rhs = rhs.into();
326 self.x /= rhs.x;
327 self.y /= rhs.y;
328 }
329}
330impl ops::Neg for Point {
331 type Output = Self;
332
333 fn neg(self) -> Self {
334 Point { x: -self.x, y: -self.y }
335 }
336}
337
338impl ops::Neg for &Point {
339 type Output = Point;
340
341 fn neg(self) -> Self::Output {
342 -self.clone()
343 }
344}