zng_layout/unit/
vector.rs1use std::{fmt, ops};
2
3use zng_var::{animation::Transitionable, impl_from_and_into_var};
4
5use crate::unit::{LengthCompositeParser, ParseCompositeError};
6
7use super::{
8 Dip, DipVector, Factor, Factor2d, FactorPercent, Layout1d, LayoutMask, Length, LengthUnits, Point, Px, PxVector, Size, Transform,
9 impl_length_comp_conversions,
10};
11
12#[derive(Clone, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Transitionable)]
14pub struct Vector {
15 pub x: Length,
17 pub y: Length,
19}
20impl fmt::Debug for Vector {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 if f.alternate() {
23 f.debug_struct("Vector").field("x", &self.x).field("y", &self.y).finish()
24 } else {
25 write!(f, "({:?}, {:?})", self.x, self.y)
26 }
27 }
28}
29impl fmt::Display for Vector {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 if let Some(p) = f.precision() {
32 write!(f, "({:.p$}, {:.p$})", self.x, self.y, p = p)
33 } else {
34 write!(f, "({}, {})", self.x, self.y)
35 }
36 }
37}
38impl std::str::FromStr for Vector {
39 type Err = ParseCompositeError;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 let mut parser = LengthCompositeParser::new(s)?;
43 let a = parser.next()?;
44 if parser.has_ended() {
45 return Ok(Self::splat(a));
46 }
47 let b = parser.expect_last()?;
48 Ok(Self::new(a, b))
49 }
50}
51impl Vector {
52 pub fn new<X: Into<Length>, Y: Into<Length>>(x: X, y: Y) -> Self {
54 Vector { x: x.into(), y: y.into() }
55 }
56
57 pub fn splat(xy: impl Into<Length>) -> Self {
59 let xy = xy.into();
60 Vector { x: xy.clone(), y: xy }
61 }
62
63 pub fn zero() -> Self {
65 Self::new(Length::zero(), Length::zero())
66 }
67
68 pub fn one() -> Self {
70 Self::new(1, 1)
71 }
72
73 pub fn one_px() -> Self {
75 Self::new(1.px(), 1.px())
76 }
77
78 pub fn yx(self) -> Self {
80 Vector { y: self.x, x: self.y }
81 }
82
83 pub fn as_tuple(self) -> (Length, Length) {
85 (self.x, self.y)
86 }
87
88 pub fn as_array(self) -> [Length; 2] {
90 [self.x, self.y]
91 }
92
93 pub fn abs(&self) -> Vector {
95 Vector {
96 x: self.x.abs(),
97 y: self.y.abs(),
98 }
99 }
100
101 pub fn is_default(&self) -> bool {
103 self.x.is_default() && self.y.is_default()
104 }
105
106 pub fn has_default(&self) -> bool {
108 self.x.has_default() && self.y.has_default()
109 }
110
111 pub fn replace_default(&mut self, overwrite: &Vector) {
113 self.x.replace_default(&overwrite.x);
114 self.y.replace_default(&overwrite.y);
115 }
116
117 pub fn as_point(self) -> Point {
119 Point { x: self.x, y: self.y }
120 }
121
122 pub fn as_size(self) -> Size {
124 Size {
125 width: self.x,
126 height: self.y,
127 }
128 }
129
130 pub fn into_transform(self) -> Transform {
132 Transform::new_translate(self.x, self.y)
133 }
134}
135impl super::Layout2d for Vector {
136 type Px = PxVector;
137
138 fn layout_dft(&self, default: Self::Px) -> Self::Px {
139 PxVector::new(self.x.layout_dft_x(default.x), self.y.layout_dft_y(default.y))
140 }
141
142 fn affect_mask(&self) -> LayoutMask {
143 self.x.affect_mask() | self.y.affect_mask()
144 }
145}
146impl_length_comp_conversions! {
147 fn from(x: X, y: Y) -> Vector {
148 Vector::new(x, y)
149 }
150}
151impl_from_and_into_var! {
152 fn from(p: PxVector) -> Vector {
153 Vector::new(p.x, p.y)
154 }
155 fn from(p: DipVector) -> Vector {
156 Vector::new(p.x, p.y)
157 }
158 fn from(p: Point) -> Vector {
159 p.as_vector()
160 }
161 fn from(s: Size) -> Vector {
162 s.as_vector()
163 }
164
165 fn from(length: Length) -> Vector {
167 Vector::splat(length)
168 }
169
170 fn from(percent: FactorPercent) -> Vector {
172 Length::from(percent).into()
173 }
174
175 fn from(norm: Factor) -> Vector {
177 Length::from(norm).into()
178 }
179
180 fn from(f: f32) -> Vector {
182 Length::from(f).into()
183 }
184
185 fn from(i: i32) -> Vector {
187 Length::from(i).into()
188 }
189
190 fn from(l: Px) -> Vector {
192 Length::from(l).into()
193 }
194
195 fn from(l: Dip) -> Vector {
197 Length::from(l).into()
198 }
199}
200impl ops::Add for Vector {
201 type Output = Self;
202
203 fn add(mut self, rhs: Self) -> Self {
204 self += rhs;
205 self
206 }
207}
208impl<'a> ops::Add<&'a Vector> for &Vector {
209 type Output = Vector;
210
211 fn add(self, rhs: &'a Vector) -> Self::Output {
212 self.clone() + rhs.clone()
213 }
214}
215impl ops::AddAssign for Vector {
216 fn add_assign(&mut self, rhs: Self) {
217 self.x += rhs.x;
218 self.y += rhs.y;
219 }
220}
221impl ops::Sub for Vector {
222 type Output = Self;
223
224 fn sub(mut self, rhs: Self) -> Self {
225 self -= rhs;
226 self
227 }
228}
229impl<'a> ops::Sub<&'a Vector> for &Vector {
230 type Output = Vector;
231
232 fn sub(self, rhs: &'a Vector) -> Self::Output {
233 self.clone() - rhs.clone()
234 }
235}
236impl ops::SubAssign for Vector {
237 fn sub_assign(&mut self, rhs: Self) {
238 self.x -= rhs.x;
239 self.y -= rhs.y;
240 }
241}
242impl<S: Into<Factor2d>> ops::Mul<S> for Vector {
243 type Output = Self;
244
245 fn mul(mut self, rhs: S) -> Self {
246 self *= rhs;
247 self
248 }
249}
250impl<S: Into<Factor2d>> ops::Mul<S> for &Vector {
251 type Output = Vector;
252
253 fn mul(self, rhs: S) -> Self::Output {
254 self.clone() * rhs
255 }
256}
257impl<S: Into<Factor2d>> ops::MulAssign<S> for Vector {
258 fn mul_assign(&mut self, rhs: S) {
259 let rhs = rhs.into();
260
261 self.x *= rhs.x;
262 self.y *= rhs.y;
263 }
264}
265impl<S: Into<Factor2d>> ops::Div<S> for Vector {
266 type Output = Self;
267
268 fn div(mut self, rhs: S) -> Self {
269 self /= rhs;
270 self
271 }
272}
273impl<S: Into<Factor2d>> ops::Div<S> for &Vector {
274 type Output = Vector;
275
276 fn div(self, rhs: S) -> Self::Output {
277 self.clone() / rhs
278 }
279}
280impl<S: Into<Factor2d>> ops::DivAssign<S> for Vector {
281 fn div_assign(&mut self, rhs: S) {
282 let rhs = rhs.into();
283 self.x /= rhs.x;
284 self.y /= rhs.y;
285 }
286}
287impl ops::Neg for Vector {
288 type Output = Self;
289
290 fn neg(self) -> Self {
291 Vector { x: -self.x, y: -self.y }
292 }
293}
294impl ops::Neg for &Vector {
295 type Output = Vector;
296
297 fn neg(self) -> Self::Output {
298 -self.clone()
299 }
300}