Skip to main content

ferroui_base/media/
i_transform.rs

1use crate::media::ref_adapter::RefAdapter;
2use crate::media::{IMutableTransform, Transform};
3use crate::reactive::IDisposable;
4use crate::{FerroObject, Matrix, ObjectType, Ref, Upcast};
5use std::any::Any;
6use std::rc::Rc;
7
8/// Represents a transform on a visual or brush.
9///
10/// Implemented by the immutable transform types and, through an adapter, by
11/// every class deriving from [`Transform`]: a handle of such a class converts
12/// to `Rc<dyn ITransform>` with `into()`.
13pub trait ITransform: 'static {
14    /// The transform's matrix.
15    fn value(&self) -> Matrix;
16
17    /// The implementing value, for downcasts to immutable transform types.
18    fn as_any(&self) -> &dyn Any;
19
20    /// The object behind the transform when it is a mutable [`Transform`].
21    fn as_object(&self) -> Option<&FerroObject> {
22        None
23    }
24
25    /// The transform viewed as [`IMutableTransform`], when it is one.
26    fn as_mutable_transform(&self) -> Option<&dyn IMutableTransform> {
27        None
28    }
29
30    /// The composition render resource behind the object, if it is a
31    /// mutable object with server-side counterparts on the compositors it
32    /// is used with.
33    fn as_composition_render_resource(
34        &self,
35    ) -> Option<&dyn crate::rendering::composition::drawing::ICompositionRenderResource> {
36        None
37    }
38
39    /// The identity of the transform, used for reference equality.
40    #[doc(hidden)]
41    fn reference_id(&self) -> *const () {
42        self as *const Self as *const ()
43    }
44}
45
46/// Transforms compare by reference.
47impl PartialEq for dyn ITransform {
48    #[inline]
49    fn eq(&self, other: &Self) -> bool {
50        self.reference_id() == other.reference_id()
51    }
52}
53
54impl std::fmt::Debug for dyn ITransform {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        write!(f, "{}", self.value())
57    }
58}
59
60impl<T: ObjectType + Upcast<Transform>> RefAdapter<T> {
61    #[inline]
62    fn transform(&self) -> &Transform {
63        (*self.0).upcast()
64    }
65}
66
67impl<T: ObjectType + Upcast<Transform>> ITransform for RefAdapter<T> {
68    #[inline]
69    fn value(&self) -> Matrix {
70        self.transform().value()
71    }
72
73    fn as_any(&self) -> &dyn Any {
74        self.transform()
75    }
76
77    fn as_object(&self) -> Option<&FerroObject> {
78        Some(self.object())
79    }
80
81    fn as_mutable_transform(&self) -> Option<&dyn IMutableTransform> {
82        Some(self)
83    }
84
85    fn as_composition_render_resource(
86        &self,
87    ) -> Option<&dyn crate::rendering::composition::drawing::ICompositionRenderResource> {
88        Some(self.transform())
89    }
90
91    fn reference_id(&self) -> *const () {
92        RefAdapter::reference_id(self)
93    }
94}
95
96impl<T: ObjectType + Upcast<Transform>> IMutableTransform for RefAdapter<T> {
97    fn changed(&self, handler: Rc<dyn Fn()>) -> Rc<dyn IDisposable> {
98        self.transform().changed(move || handler())
99    }
100}
101
102impl<T: ObjectType + Upcast<Transform>> From<Ref<T>> for Rc<dyn ITransform> {
103    #[inline]
104    fn from(value: Ref<T>) -> Self {
105        Rc::new(RefAdapter(value))
106    }
107}
108
109impl<T: ObjectType + Upcast<Transform>> From<&Ref<T>> for Rc<dyn ITransform> {
110    #[inline]
111    fn from(value: &Ref<T>) -> Self {
112        Rc::new(RefAdapter(value.clone()))
113    }
114}