1use zng_unit::FactorUnits;
2
3use crate::unit::ParseFloatCompositeError;
4
5use super::{
6 DipPoint, DipRect, DipSideOffsets, DipSize, DipVector, Factor, FactorPercent, PxPoint, PxRect, PxSideOffsets, PxSize, PxVector, Size,
7};
8use std::{fmt, ops};
9use zng_var::impl_from_and_into_var;
10
11impl ops::Mul<Factor> for Factor2d {
12 type Output = Factor2d;
13
14 fn mul(self, rhs: Factor) -> Factor2d {
15 Factor2d::new(self.x * rhs, self.y * rhs)
16 }
17}
18impl ops::Div<Factor> for Factor2d {
19 type Output = Factor2d;
20
21 fn div(self, rhs: Factor) -> Factor2d {
22 Factor2d::new(self.x / rhs, self.y / rhs)
23 }
24}
25impl ops::MulAssign<Factor> for Factor2d {
26 fn mul_assign(&mut self, rhs: Factor) {
27 *self = *self * rhs;
28 }
29}
30impl ops::DivAssign<Factor> for Factor2d {
31 fn div_assign(&mut self, rhs: Factor) {
32 *self = *self / rhs;
33 }
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
38pub struct Factor2d {
39 pub x: Factor,
41 pub y: Factor,
43}
44impl_from_and_into_var! {
45 fn from<X: Into<Factor>, Y: Into<Factor>>((x, y): (X, Y)) -> Factor2d {
46 Factor2d { x: x.into(), y: y.into() }
47 }
48
49 fn from(xy: Factor) -> Factor2d {
50 Factor2d { x: xy, y: xy }
51 }
52
53 fn from(xy: FactorPercent) -> Factor2d {
54 xy.fct().into()
55 }
56
57 fn from(scale: Factor2d) -> Size {
59 Size {
60 width: scale.x.into(),
61 height: scale.y.into(),
62 }
63 }
64}
65impl Factor2d {
66 pub fn new(x: impl Into<Factor>, y: impl Into<Factor>) -> Self {
68 Factor2d { x: x.into(), y: y.into() }
69 }
70
71 pub fn uniform(xy: impl Into<Factor>) -> Self {
73 let xy = xy.into();
74 xy.into()
75 }
76
77 pub fn identity() -> Self {
79 Self::uniform(1.0)
80 }
81
82 pub fn is_uniform(self) -> bool {
84 self.x == self.y
85 }
86
87 pub fn abs(mut self) -> Self {
89 self.x = self.x.abs();
90 self.y = self.y.abs();
91 self
92 }
93
94 pub fn yx(self) -> Self {
96 Self::new(self.y, self.x)
97 }
98}
99impl fmt::Display for Factor2d {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 if self.is_uniform() {
102 write!(f, "{}", FactorPercent::from(self.x))
103 } else {
104 write!(f, "({}, {})", FactorPercent::from(self.x), FactorPercent::from(self.y))
105 }
106 }
107}
108impl std::str::FromStr for Factor2d {
110 type Err = ParseFloatCompositeError;
111
112 fn from_str(s: &str) -> Result<Self, Self::Err> {
113 if let Some(s) = s.strip_prefix('(')
114 && let Some(s) = s.strip_suffix(')')
115 {
116 let mut parser = ComponentParser { iter: s.split(',') };
117 let r = Factor2d {
118 x: parser.next()?,
119 y: parser.next()?,
120 };
121 parser.end()?;
122 Ok(r)
123 } else {
124 Ok(Factor2d::uniform(s.parse::<Factor>()?))
125 }
126 }
127}
128struct ComponentParser<'a> {
129 iter: std::str::Split<'a, char>,
130}
131impl<'a> ComponentParser<'a> {
132 fn next(&mut self) -> Result<Factor, ParseFloatCompositeError> {
133 let fct = self.iter.next().ok_or(ParseFloatCompositeError::MissingComponent)?.trim().parse()?;
134 Ok(fct)
135 }
136 fn end(mut self) -> Result<(), ParseFloatCompositeError> {
137 if self.iter.next().is_some() {
138 Err(ParseFloatCompositeError::ExtraComponent)
139 } else {
140 Ok(())
141 }
142 }
143}
144impl ops::Mul<Factor2d> for PxSize {
145 type Output = PxSize;
146
147 fn mul(self, rhs: Factor2d) -> PxSize {
148 PxSize::new(self.width * rhs.x, self.height * rhs.y)
149 }
150}
151impl ops::Mul<Factor2d> for DipSize {
152 type Output = DipSize;
153
154 fn mul(self, rhs: Factor2d) -> DipSize {
155 DipSize::new(self.width * rhs.x, self.height * rhs.y)
156 }
157}
158impl ops::Div<Factor2d> for PxSize {
159 type Output = PxSize;
160
161 fn div(self, rhs: Factor2d) -> PxSize {
162 PxSize::new(self.width / rhs.x, self.height / rhs.y)
163 }
164}
165impl ops::Div<Factor2d> for DipSize {
166 type Output = DipSize;
167
168 fn div(self, rhs: Factor2d) -> DipSize {
169 DipSize::new(self.width / rhs.x, self.height / rhs.y)
170 }
171}
172impl ops::MulAssign<Factor2d> for PxSize {
173 fn mul_assign(&mut self, rhs: Factor2d) {
174 *self = *self * rhs;
175 }
176}
177impl ops::MulAssign<Factor2d> for DipSize {
178 fn mul_assign(&mut self, rhs: Factor2d) {
179 *self = *self * rhs;
180 }
181}
182impl ops::DivAssign<Factor2d> for PxSize {
183 fn div_assign(&mut self, rhs: Factor2d) {
184 *self = *self / rhs;
185 }
186}
187impl ops::DivAssign<Factor2d> for DipSize {
188 fn div_assign(&mut self, rhs: Factor2d) {
189 *self = *self / rhs;
190 }
191}
192impl ops::Mul<Factor2d> for PxPoint {
193 type Output = PxPoint;
194
195 fn mul(self, rhs: Factor2d) -> PxPoint {
196 PxPoint::new(self.x * rhs.x, self.y * rhs.y)
197 }
198}
199impl ops::Div<Factor2d> for PxPoint {
200 type Output = PxPoint;
201
202 fn div(self, rhs: Factor2d) -> PxPoint {
203 PxPoint::new(self.x / rhs.x, self.y / rhs.y)
204 }
205}
206impl ops::MulAssign<Factor2d> for PxPoint {
207 fn mul_assign(&mut self, rhs: Factor2d) {
208 *self = *self * rhs;
209 }
210}
211impl ops::DivAssign<Factor2d> for PxPoint {
212 fn div_assign(&mut self, rhs: Factor2d) {
213 *self = *self / rhs;
214 }
215}
216
217impl ops::Mul<Factor2d> for DipPoint {
218 type Output = DipPoint;
219
220 fn mul(self, rhs: Factor2d) -> DipPoint {
221 DipPoint::new(self.x * rhs.x, self.y * rhs.y)
222 }
223}
224impl ops::Div<Factor2d> for DipPoint {
225 type Output = DipPoint;
226
227 fn div(self, rhs: Factor2d) -> DipPoint {
228 DipPoint::new(self.x / rhs.x, self.y / rhs.y)
229 }
230}
231impl ops::MulAssign<Factor2d> for DipPoint {
232 fn mul_assign(&mut self, rhs: Factor2d) {
233 *self = *self * rhs;
234 }
235}
236impl ops::DivAssign<Factor2d> for DipPoint {
237 fn div_assign(&mut self, rhs: Factor2d) {
238 *self = *self / rhs;
239 }
240}
241
242impl ops::Mul<Factor2d> for PxVector {
243 type Output = PxVector;
244
245 fn mul(self, rhs: Factor2d) -> PxVector {
246 PxVector::new(self.x * rhs.x, self.y * rhs.y)
247 }
248}
249impl ops::Div<Factor2d> for PxVector {
250 type Output = PxVector;
251
252 fn div(self, rhs: Factor2d) -> PxVector {
253 PxVector::new(self.x / rhs.x, self.y / rhs.y)
254 }
255}
256impl ops::MulAssign<Factor2d> for PxVector {
257 fn mul_assign(&mut self, rhs: Factor2d) {
258 *self = *self * rhs;
259 }
260}
261impl ops::DivAssign<Factor2d> for PxVector {
262 fn div_assign(&mut self, rhs: Factor2d) {
263 *self = *self / rhs;
264 }
265}
266
267impl ops::Mul<Factor2d> for DipVector {
268 type Output = DipVector;
269
270 fn mul(self, rhs: Factor2d) -> DipVector {
271 DipVector::new(self.x * rhs.x, self.y * rhs.y)
272 }
273}
274impl ops::Div<Factor2d> for DipVector {
275 type Output = DipVector;
276
277 fn div(self, rhs: Factor2d) -> DipVector {
278 DipVector::new(self.x / rhs.x, self.y / rhs.y)
279 }
280}
281impl ops::MulAssign<Factor2d> for DipVector {
282 fn mul_assign(&mut self, rhs: Factor2d) {
283 *self = *self * rhs;
284 }
285}
286impl ops::DivAssign<Factor2d> for DipVector {
287 fn div_assign(&mut self, rhs: Factor2d) {
288 *self = *self / rhs;
289 }
290}
291
292impl ops::Mul<Factor2d> for Factor2d {
293 type Output = Factor2d;
294
295 fn mul(self, rhs: Factor2d) -> Factor2d {
296 Factor2d::new(self.x * rhs.x, self.y * rhs.y)
297 }
298}
299impl ops::Div<Factor2d> for Factor2d {
300 type Output = Factor2d;
301
302 fn div(self, rhs: Factor2d) -> Factor2d {
303 Factor2d::new(self.x / rhs.x, self.y / rhs.y)
304 }
305}
306impl ops::MulAssign<Factor2d> for Factor2d {
307 fn mul_assign(&mut self, rhs: Factor2d) {
308 *self = *self * rhs;
309 }
310}
311impl ops::DivAssign<Factor2d> for Factor2d {
312 fn div_assign(&mut self, rhs: Factor2d) {
313 *self = *self / rhs;
314 }
315}
316impl ops::Mul<Factor2d> for PxRect {
317 type Output = PxRect;
318
319 fn mul(self, rhs: Factor2d) -> PxRect {
320 PxRect::new(self.origin * rhs, self.size * rhs)
321 }
322}
323impl ops::Div<Factor2d> for PxRect {
324 type Output = PxRect;
325
326 fn div(self, rhs: Factor2d) -> PxRect {
327 PxRect::new(self.origin / rhs, self.size / rhs)
328 }
329}
330impl ops::MulAssign<Factor2d> for PxRect {
331 fn mul_assign(&mut self, rhs: Factor2d) {
332 *self = *self * rhs;
333 }
334}
335impl ops::DivAssign<Factor2d> for PxRect {
336 fn div_assign(&mut self, rhs: Factor2d) {
337 *self = *self / rhs;
338 }
339}
340
341impl ops::Mul<Factor2d> for DipRect {
342 type Output = DipRect;
343
344 fn mul(self, rhs: Factor2d) -> DipRect {
345 DipRect::new(self.origin * rhs, self.size * rhs)
346 }
347}
348impl ops::Div<Factor2d> for DipRect {
349 type Output = DipRect;
350
351 fn div(self, rhs: Factor2d) -> DipRect {
352 DipRect::new(self.origin / rhs, self.size / rhs)
353 }
354}
355impl ops::MulAssign<Factor2d> for DipRect {
356 fn mul_assign(&mut self, rhs: Factor2d) {
357 *self = *self * rhs;
358 }
359}
360impl ops::DivAssign<Factor2d> for DipRect {
361 fn div_assign(&mut self, rhs: Factor2d) {
362 *self = *self / rhs;
363 }
364}
365
366impl ops::Neg for Factor2d {
367 type Output = Self;
368
369 fn neg(mut self) -> Self::Output {
370 self.x = -self.x;
371 self.y = -self.y;
372 self
373 }
374}
375
376#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
378pub struct FactorSideOffsets {
379 pub top: Factor,
381 pub right: Factor,
383 pub bottom: Factor,
385 pub left: Factor,
387}
388impl FactorSideOffsets {
389 pub fn new(top: impl Into<Factor>, right: impl Into<Factor>, bottom: impl Into<Factor>, left: impl Into<Factor>) -> Self {
391 Self {
392 top: top.into(),
393 right: right.into(),
394 bottom: bottom.into(),
395 left: left.into(),
396 }
397 }
398
399 pub fn new_vh(top_bottom: impl Into<Factor>, left_right: impl Into<Factor>) -> Self {
401 let tb = top_bottom.into();
402 let lr = left_right.into();
403
404 Self::new(tb, lr, tb, lr)
405 }
406
407 pub fn new_all(uniform: impl Into<Factor>) -> Self {
409 let u = uniform.into();
410 Self::new(u, u, u, u)
411 }
412
413 pub fn zero() -> Self {
415 Self::new_all(0.fct())
416 }
417
418 pub fn one() -> Self {
420 Self::new_all(1.fct())
421 }
422}
423impl ops::Mul<FactorSideOffsets> for FactorSideOffsets {
424 type Output = FactorSideOffsets;
425
426 fn mul(self, rhs: FactorSideOffsets) -> FactorSideOffsets {
427 FactorSideOffsets::new(
428 self.top * rhs.top,
429 self.right * rhs.right,
430 self.bottom * rhs.bottom,
431 self.left * rhs.left,
432 )
433 }
434}
435impl ops::Div<FactorSideOffsets> for FactorSideOffsets {
436 type Output = FactorSideOffsets;
437
438 fn div(self, rhs: FactorSideOffsets) -> FactorSideOffsets {
439 FactorSideOffsets::new(
440 self.top / rhs.top,
441 self.right / rhs.right,
442 self.bottom / rhs.bottom,
443 self.left / rhs.left,
444 )
445 }
446}
447impl ops::MulAssign<FactorSideOffsets> for FactorSideOffsets {
448 fn mul_assign(&mut self, rhs: FactorSideOffsets) {
449 self.top *= rhs.top;
450 self.right *= rhs.right;
451 self.bottom *= rhs.bottom;
452 self.left *= rhs.left;
453 }
454}
455impl ops::DivAssign<FactorSideOffsets> for FactorSideOffsets {
456 fn div_assign(&mut self, rhs: FactorSideOffsets) {
457 self.top /= rhs.top;
458 self.right /= rhs.right;
459 self.bottom /= rhs.bottom;
460 self.left /= rhs.left;
461 }
462}
463impl ops::Mul<FactorSideOffsets> for PxSideOffsets {
464 type Output = PxSideOffsets;
465
466 fn mul(self, rhs: FactorSideOffsets) -> PxSideOffsets {
467 PxSideOffsets::new(
468 self.top * rhs.top,
469 self.right * rhs.right,
470 self.bottom * rhs.bottom,
471 self.left * rhs.left,
472 )
473 }
474}
475impl ops::Div<FactorSideOffsets> for PxSideOffsets {
476 type Output = PxSideOffsets;
477
478 fn div(self, rhs: FactorSideOffsets) -> PxSideOffsets {
479 PxSideOffsets::new(
480 self.top / rhs.top,
481 self.right / rhs.right,
482 self.bottom / rhs.bottom,
483 self.left / rhs.left,
484 )
485 }
486}
487impl ops::MulAssign<FactorSideOffsets> for PxSideOffsets {
488 fn mul_assign(&mut self, rhs: FactorSideOffsets) {
489 *self = *self * rhs;
490 }
491}
492impl ops::DivAssign<FactorSideOffsets> for PxSideOffsets {
493 fn div_assign(&mut self, rhs: FactorSideOffsets) {
494 *self = *self / rhs;
495 }
496}
497
498impl ops::Mul<FactorSideOffsets> for DipSideOffsets {
499 type Output = DipSideOffsets;
500
501 fn mul(self, rhs: FactorSideOffsets) -> DipSideOffsets {
502 DipSideOffsets::new(
503 self.top * rhs.top,
504 self.right * rhs.right,
505 self.bottom * rhs.bottom,
506 self.left * rhs.left,
507 )
508 }
509}
510impl ops::Div<FactorSideOffsets> for DipSideOffsets {
511 type Output = DipSideOffsets;
512
513 fn div(self, rhs: FactorSideOffsets) -> DipSideOffsets {
514 DipSideOffsets::new(
515 self.top / rhs.top,
516 self.right / rhs.right,
517 self.bottom / rhs.bottom,
518 self.left / rhs.left,
519 )
520 }
521}
522impl ops::MulAssign<FactorSideOffsets> for DipSideOffsets {
523 fn mul_assign(&mut self, rhs: FactorSideOffsets) {
524 *self = *self * rhs;
525 }
526}
527impl ops::DivAssign<FactorSideOffsets> for DipSideOffsets {
528 fn div_assign(&mut self, rhs: FactorSideOffsets) {
529 *self = *self / rhs;
530 }
531}
532
533impl_from_and_into_var! {
534 fn from(all: Factor) -> FactorSideOffsets {
536 FactorSideOffsets::new_all(all)
537 }
538
539 fn from(percent: FactorPercent) -> FactorSideOffsets {
541 FactorSideOffsets::new_all(percent)
542 }
543
544 fn from<TB: Into<Factor>, LR: Into<Factor>>((top_bottom, left_right): (TB, LR)) -> FactorSideOffsets {
546 FactorSideOffsets::new_vh(top_bottom, left_right)
547 }
548
549 fn from<T: Into<Factor>, R: Into<Factor>, B: Into<Factor>, L: Into<Factor>>(
551 (top, right, bottom, left): (T, R, B, L),
552 ) -> FactorSideOffsets {
553 FactorSideOffsets::new(top, right, bottom, left)
554 }
555}