Skip to main content

ferroui_base/media/
rotate_transform.rs

1use crate::media::{Transform, TransformImpl};
2use crate::{
3    ferro_class, ferro_property, instantiate, FerroObjectImpl, FerroObjectImplExt, FerroProperty,
4    FerroPropertyChangedEventArgs, Matrix,
5    Ref, StyledProperty,
6};
7
8/// Rotates a visual.
9#[repr(C)]
10pub struct RotateTransform {
11    base: Transform,
12}
13
14ferro_class!(RotateTransform: Transform);
15crate::ferro_class_info!(RotateTransform { new: RotateTransform::new });
16
17impl FerroObjectImpl for RotateTransform {
18    fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
19        Self::parent_on_property_changed(this, change);
20
21        // Only the angle raises the changed notification: the reference
22        // implementation observes the angle property alone.
23        if change.property() == Self::angle_property().as_property() {
24            this.raise_changed();
25        }
26    }
27}
28
29impl TransformImpl for RotateTransform {
30    fn value(this: &Self) -> Matrix {
31        let (center_x, center_y) = (this.center_x(), this.center_y());
32        Matrix::create_translation(-center_x, -center_y)
33            * Matrix::create_rotation(Matrix::to_radians(this.angle()))
34            * Matrix::create_translation(center_x, center_y)
35    }
36}
37
38crate::ferro_properties! { impl RotateTransform {
39    ferro_property!(pub fn angle_property() -> StyledProperty<f64> {
40        FerroProperty::register::<RotateTransform, _>("Angle", 0.0)
41    });
42
43    ferro_property!(pub fn center_x_property() -> StyledProperty<f64> {
44        FerroProperty::register::<RotateTransform, _>("CenterX", 0.0)
45    });
46
47    ferro_property!(pub fn center_y_property() -> StyledProperty<f64> {
48        FerroProperty::register::<RotateTransform, _>("CenterY", 0.0)
49    });
50} }
51
52impl RotateTransform {
53    /// Creates the class data.
54    pub fn construct() -> Self {
55        Self { base: Transform::construct() }
56    }
57
58    pub fn new() -> Ref<Self> {
59        instantiate(Self::construct())
60    }
61
62    /// Creates a rotation of `angle` degrees.
63    pub fn with_angle(angle: f64) -> Ref<Self> {
64        let result = Self::new();
65        result.set_angle(angle);
66        result
67    }
68
69    /// Creates a rotation of `angle` degrees around the given center.
70    pub fn with_angle_and_center(angle: f64, center_x: f64, center_y: f64) -> Ref<Self> {
71        let result = Self::new();
72        result.set_angle(angle);
73        result.set_center_x(center_x);
74        result.set_center_y(center_y);
75        result
76    }
77
78    /// The angle of rotation, in degrees.
79    pub fn angle(&self) -> f64 {
80        self.get_value(Self::angle_property())
81    }
82
83    pub fn set_angle(&self, value: f64) {
84        self.set_value(Self::angle_property(), value)
85    }
86
87    /// The x-coordinate of the rotation center point. The default is 0.
88    pub fn center_x(&self) -> f64 {
89        self.get_value(Self::center_x_property())
90    }
91
92    pub fn set_center_x(&self, value: f64) {
93        self.set_value(Self::center_x_property(), value)
94    }
95
96    /// The y-coordinate of the rotation center point. The default is 0.
97    pub fn center_y(&self) -> f64 {
98        self.get_value(Self::center_y_property())
99    }
100
101    pub fn set_center_y(&self, value: f64) {
102        self.set_value(Self::center_y_property(), value)
103    }
104}