Skip to main content

freya_core/style/
transform_origin.rs

1use torin::prelude::{
2    Area,
3    Point2D,
4};
5
6/// Position of a [`TransformOrigin`] along a single axis.
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum OriginValue {
10    /// Fraction of the element's length along the axis, where `0.0` is the start
11    /// and `1.0` is the end.
12    Fraction(f32),
13    /// Absolute pixels measured from the element's top-left corner.
14    Pixels(f32),
15}
16
17impl OriginValue {
18    /// Resolve this value into an absolute offset given the element's length on the axis.
19    fn resolve(self, length: f32) -> f32 {
20        match self {
21            OriginValue::Fraction(fraction) => length * fraction,
22            OriginValue::Pixels(pixels) => pixels,
23        }
24    }
25}
26
27/// Reference point that the scale and rotation effects of an element pivot around.
28///
29/// Defaults to the element's center.
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31#[derive(Debug, Clone, Copy, PartialEq)]
32pub struct TransformOrigin {
33    pub x: OriginValue,
34    pub y: OriginValue,
35}
36
37impl Default for TransformOrigin {
38    fn default() -> Self {
39        Self::center()
40    }
41}
42
43impl TransformOrigin {
44    /// Resolve the origin point in absolute coordinates for the given element area.
45    pub fn origin(&self, area: &Area) -> Point2D {
46        Point2D::new(
47            area.min_x() + self.x.resolve(area.width()),
48            area.min_y() + self.y.resolve(area.height()),
49        )
50    }
51
52    pub fn center() -> Self {
53        Self {
54            x: OriginValue::Fraction(0.5),
55            y: OriginValue::Fraction(0.5),
56        }
57    }
58
59    pub fn top_left() -> Self {
60        Self {
61            x: OriginValue::Fraction(0.0),
62            y: OriginValue::Fraction(0.0),
63        }
64    }
65
66    pub fn top() -> Self {
67        Self {
68            x: OriginValue::Fraction(0.5),
69            y: OriginValue::Fraction(0.0),
70        }
71    }
72
73    pub fn top_right() -> Self {
74        Self {
75            x: OriginValue::Fraction(1.0),
76            y: OriginValue::Fraction(0.0),
77        }
78    }
79
80    pub fn left() -> Self {
81        Self {
82            x: OriginValue::Fraction(0.0),
83            y: OriginValue::Fraction(0.5),
84        }
85    }
86
87    pub fn right() -> Self {
88        Self {
89            x: OriginValue::Fraction(1.0),
90            y: OriginValue::Fraction(0.5),
91        }
92    }
93
94    pub fn bottom_left() -> Self {
95        Self {
96            x: OriginValue::Fraction(0.0),
97            y: OriginValue::Fraction(1.0),
98        }
99    }
100
101    pub fn bottom() -> Self {
102        Self {
103            x: OriginValue::Fraction(0.5),
104            y: OriginValue::Fraction(1.0),
105        }
106    }
107
108    pub fn bottom_right() -> Self {
109        Self {
110            x: OriginValue::Fraction(1.0),
111            y: OriginValue::Fraction(1.0),
112        }
113    }
114}
115
116/// Shorthand for a fractional [`TransformOrigin`], where `0.0` is the start and `1.0` the end of each axis.
117impl From<(f32, f32)> for TransformOrigin {
118    fn from((x, y): (f32, f32)) -> Self {
119        Self {
120            x: OriginValue::Fraction(x),
121            y: OriginValue::Fraction(y),
122        }
123    }
124}