ferroui_base/media/effects/
i_effect.rs1use crate::media::effects::{
2 BlurEffect, DropShadowDirectionEffect, DropShadowEffect, Effect, IBlurEffect, IDirectionDropShadowEffect,
3 IDropShadowEffect,
4};
5use crate::media::ref_adapter::RefAdapter;
6use crate::{FerroObject, ObjectType, Ref, Upcast};
7use std::any::Any;
8use std::rc::Rc;
9
10pub trait IEffect: 'static {
17 fn as_any(&self) -> &dyn Any;
20
21 fn as_object(&self) -> Option<&FerroObject> {
23 None
24 }
25
26 fn as_blur_effect(&self) -> Option<&dyn IBlurEffect> {
28 None
29 }
30
31 fn as_drop_shadow_effect(&self) -> Option<&dyn IDropShadowEffect> {
33 None
34 }
35
36 fn as_direction_drop_shadow_effect(&self) -> Option<&dyn IDirectionDropShadowEffect> {
38 None
39 }
40
41 fn as_mutable_effect(&self) -> Option<&dyn IMutableEffect> {
43 None
44 }
45
46 fn as_immutable_effect(&self) -> Option<&dyn IImmutableEffect> {
48 None
49 }
50
51 fn into_immutable_effect(self: Rc<Self>) -> Option<std::sync::Arc<dyn IImmutableEffect>> {
55 None
56 }
57
58 #[doc(hidden)]
60 fn reference_id(&self) -> *const () {
61 self as *const Self as *const ()
62 }
63}
64
65impl PartialEq for dyn IEffect {
68 #[inline]
69 fn eq(&self, other: &Self) -> bool {
70 self.reference_id() == other.reference_id()
71 }
72}
73
74impl std::fmt::Debug for dyn IEffect {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 if let Some(blur) = self.as_blur_effect() {
77 write!(f, "IEffect(blur({}))", blur.radius())
78 } else if let Some(shadow) = self.as_drop_shadow_effect() {
79 write!(
80 f,
81 "IEffect(drop-shadow({} {} {} {}))",
82 shadow.offset_x(),
83 shadow.offset_y(),
84 shadow.blur_radius(),
85 shadow.color()
86 )
87 } else {
88 f.write_str("IEffect")
89 }
90 }
91}
92
93pub trait IMutableEffect: IEffect {
95 fn to_immutable(&self) -> std::sync::Arc<dyn IImmutableEffect>;
97}
98
99pub trait IImmutableEffect: IEffect + Send + Sync {
101 fn equals(&self, other: Option<&dyn IEffect>) -> bool;
103}
104
105impl<T: ObjectType + Upcast<Effect>> IEffect for RefAdapter<T> {
106 fn as_any(&self) -> &dyn Any {
107 Upcast::<Effect>::upcast(&*self.0)
108 }
109
110 fn as_object(&self) -> Option<&FerroObject> {
111 Some(self.object())
112 }
113
114 fn as_blur_effect(&self) -> Option<&dyn IBlurEffect> {
115 if self.object().is::<BlurEffect>() {
116 Some(self)
117 } else {
118 None
119 }
120 }
121
122 fn as_drop_shadow_effect(&self) -> Option<&dyn IDropShadowEffect> {
123 if self.object().is::<DropShadowEffect>() || self.object().is::<DropShadowDirectionEffect>() {
124 Some(self)
125 } else {
126 None
127 }
128 }
129
130 fn as_direction_drop_shadow_effect(&self) -> Option<&dyn IDirectionDropShadowEffect> {
131 if self.object().is::<DropShadowDirectionEffect>() {
132 Some(self)
133 } else {
134 None
135 }
136 }
137
138 fn as_mutable_effect(&self) -> Option<&dyn IMutableEffect> {
139 if self.object().is::<BlurEffect>()
140 || self.object().is::<DropShadowEffect>()
141 || self.object().is::<DropShadowDirectionEffect>()
142 {
143 Some(self)
144 } else {
145 None
146 }
147 }
148
149 fn reference_id(&self) -> *const () {
150 RefAdapter::reference_id(self)
151 }
152}
153
154impl<T: ObjectType + Upcast<Effect>> IMutableEffect for RefAdapter<T> {
155 fn to_immutable(&self) -> std::sync::Arc<dyn IImmutableEffect> {
156 let object = self.object();
157 if let Some(blur) = object.downcast_ref::<BlurEffect>() {
158 blur.to_immutable()
159 } else if let Some(shadow) = object.downcast_ref::<DropShadowEffect>() {
160 shadow.to_immutable()
161 } else {
162 self.class::<DropShadowDirectionEffect>().to_immutable()
163 }
164 }
165}
166
167impl<T: ObjectType + Upcast<Effect>> From<Ref<T>> for Rc<dyn IEffect> {
168 #[inline]
169 fn from(value: Ref<T>) -> Self {
170 Rc::new(RefAdapter(value))
171 }
172}
173
174impl<T: ObjectType + Upcast<Effect>> From<&Ref<T>> for Rc<dyn IEffect> {
175 #[inline]
176 fn from(value: &Ref<T>) -> Self {
177 Rc::new(RefAdapter(value.clone()))
178 }
179}