zng_layout/unit/
factor.rs

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/// Scale factor applied to ***x*** and ***y*** dimensions.
37#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
38pub struct Factor2d {
39    /// Scale factor applied in the ***x*** dimension.
40    pub x: Factor,
41    /// Scale factor applied in the ***y*** dimension.
42    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    /// To relative width and height.
58    fn from(scale: Factor2d) -> Size {
59        Size {
60            width: scale.x.into(),
61            height: scale.y.into(),
62        }
63    }
64}
65impl Factor2d {
66    /// New scale with different scales for each dimension.
67    pub fn new(x: impl Into<Factor>, y: impl Into<Factor>) -> Self {
68        Factor2d { x: x.into(), y: y.into() }
69    }
70
71    /// Uniform scale applied to both ***x*** and ***y***.
72    pub fn uniform(xy: impl Into<Factor>) -> Self {
73        let xy = xy.into();
74        xy.into()
75    }
76
77    /// No scaling.
78    pub fn identity() -> Self {
79        Self::uniform(1.0)
80    }
81
82    /// If the scale is the same for both ***x*** and ***y***.
83    pub fn is_uniform(self) -> bool {
84        self.x == self.y
85    }
86
87    /// Computes the absolute value of x and y.
88    pub fn abs(mut self) -> Self {
89        self.x = self.x.abs();
90        self.y = self.y.abs();
91        self
92    }
93
94    /// Swap x and y.
95    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}
108/// Parse `"Factor"` or `"(Factor, Factor)"`
109impl 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/// Scale factor applied to margins.
377#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
378pub struct FactorSideOffsets {
379    /// Factor of top offset.
380    pub top: Factor,
381    /// Factor of right offset.
382    pub right: Factor,
383    /// Factor of bottom offset.
384    pub bottom: Factor,
385    /// Factor of left offset.
386    pub left: Factor,
387}
388impl FactorSideOffsets {
389    /// Factors applied to each offset.
390    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    /// Same scale applied to parallel offsets.
400    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    /// Uniform scale applied to all offsets.
408    pub fn new_all(uniform: impl Into<Factor>) -> Self {
409        let u = uniform.into();
410        Self::new(u, u, u, u)
411    }
412
413    /// Uniform 0%.
414    pub fn zero() -> Self {
415        Self::new_all(0.fct())
416    }
417
418    /// Uniform 100%.
419    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    /// All sides equal.
535    fn from(all: Factor) -> FactorSideOffsets {
536        FactorSideOffsets::new_all(all)
537    }
538
539    /// All sides equal.
540    fn from(percent: FactorPercent) -> FactorSideOffsets {
541        FactorSideOffsets::new_all(percent)
542    }
543
544    /// New dimension, top-bottom, left-right.
545    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    /// New top, right, bottom, left.
550    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}