zng_layout/unit/
factor.rs

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