ferroui_base/rendering/composition/generated/
composition_gradient_stop.rs1use bitflags::bitflags;
6use crate::media::Color;
7use crate::rendering::composition::ICompositionObjectHost;
8use crate::rendering::composition::animations::AnimationInstanceFactory;
9use crate::rendering::composition::animations::ICompositionAnimation;
10use crate::rendering::composition::expressions::ExpressionVariant;
11use crate::rendering::composition::server::CompositionProperty;
12use crate::rendering::composition::server::CompositionPropertyOf;
13use crate::rendering::composition::server::IServerAnimatedPropertyHost;
14use crate::rendering::composition::server::ServerPropertyValue;
15use crate::rendering::composition::server::props_of;
16use crate::rendering::composition::transport::BatchStreamReader;
17use crate::rendering::composition::transport::BatchStreamWriter;
18use crate::rendering::composition::transport::BatchValue;
19use crate::rendering::composition::transport::BatchValueReader;
20use std::any::Any;
21use std::any::TypeId;
22use std::cell::Cell;
23use std::sync::OnceLock;
24use std::time::Duration;
25
26bitflags! {
27 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
29 pub struct CompositionGradientStopChangedFields: u8 {
30 const COLOR = 1;
31 const COLOR_ANIMATED = 2;
32 const OFFSET = 4;
33 const OFFSET_ANIMATED = 8;
34 }
35}
36
37impl BatchValue for CompositionGradientStopChangedFields {
38 #[inline]
39 fn write_to(&self, out: &mut Vec<u8>) {
40 self.bits().write_to(out);
41 }
42
43 #[inline]
44 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
45 CompositionGradientStopChangedFields::from_bits_retain(u8::read_from(input))
46 }
47}
48
49pub trait CompositionGradientStopHooks: ICompositionObjectHost {
52 fn initialize_defaults_extra(&self) {}
53
54 fn validate_color_change(&self, _old_value: Color, _new_value: Color) {}
55 fn on_color_changed(&self) {}
56 fn on_color_changing(&self) {}
57
58 fn validate_offset_change(&self, _old_value: f64, _new_value: f64) {}
59 fn on_offset_changed(&self) {}
60 fn on_offset_changing(&self) {}
61}
62
63pub struct CompositionGradientStopProps {
65 changed_fields_of_composition_gradient_stop: Cell<CompositionGradientStopChangedFields>,
66 color: Cell<Color>,
67 offset: Cell<f64>,
68}
69
70impl Default for CompositionGradientStopProps {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl CompositionGradientStopProps {
77 pub fn new() -> Self {
81 Self {
82 changed_fields_of_composition_gradient_stop: Cell::new(CompositionGradientStopChangedFields::empty()),
83 color: Cell::new(Default::default()),
84 offset: Cell::new(Default::default()),
85 }
86 }
87
88 pub fn initialize_defaults(&self, host: &dyn CompositionGradientStopHooks) {
91 self.initialize_own_defaults(host);
92 }
93
94 pub fn initialize_own_defaults(&self, host: &dyn CompositionGradientStopHooks) {
96 CompositionGradientStopHooks::initialize_defaults_extra(host);
97 }
98
99 pub fn color(&self) -> Color {
101 self.color.get()
102 }
103
104 pub fn set_color(&self, host: &dyn CompositionGradientStopHooks, value: Color) {
106 let mut changed = false;
107 let old_value = self.color.get();
108 if old_value.differs(&value) {
109 CompositionGradientStopHooks::validate_color_change(host, old_value, value);
110 CompositionGradientStopHooks::on_color_changing(host);
111 changed = true;
112 self.color.set(value);
114 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::COLOR);
116 host.register_for_serialization();
117 host.pending_animations().remove(ServerCompositionGradientStopProps::id_of_color_property().base());
119 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() & !CompositionGradientStopChangedFields::COLOR_ANIMATED);
120 if let Some(animation) = host.implicit_animation("Color") {
122 if let Some(a) = animation.as_composition_animation() {
124 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::COLOR_ANIMATED);
125 host.pending_animations().set(
126 ServerCompositionGradientStopProps::id_of_color_property().base(),
127 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
128 );
129 }
130 host.start_animation_group(&animation, "Color", ExpressionVariant::create(value));
132 }
133 }
134 self.color.set(value);
135 if changed {
136 CompositionGradientStopHooks::on_color_changed(host);
137 }
138 }
139
140 pub fn offset(&self) -> f64 {
142 self.offset.get()
143 }
144
145 pub fn set_offset(&self, host: &dyn CompositionGradientStopHooks, value: f64) {
147 let mut changed = false;
148 let old_value = self.offset.get();
149 if old_value.differs(&value) {
150 CompositionGradientStopHooks::validate_offset_change(host, old_value, value);
151 CompositionGradientStopHooks::on_offset_changing(host);
152 changed = true;
153 self.offset.set(value);
155 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::OFFSET);
157 host.register_for_serialization();
158 host.pending_animations().remove(ServerCompositionGradientStopProps::id_of_offset_property().base());
160 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() & !CompositionGradientStopChangedFields::OFFSET_ANIMATED);
161 if let Some(animation) = host.implicit_animation("Offset") {
163 if let Some(a) = animation.as_composition_animation() {
165 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::OFFSET_ANIMATED);
166 host.pending_animations().set(
167 ServerCompositionGradientStopProps::id_of_offset_property().base(),
168 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
169 );
170 }
171 host.start_animation_group(&animation, "Offset", ExpressionVariant::create(value));
173 }
174 }
175 self.offset.set(value);
176 if changed {
177 CompositionGradientStopHooks::on_offset_changed(host);
178 }
179 }
180
181 pub fn start_animation(
185 &self,
186 host: &dyn CompositionGradientStopHooks,
187 property_name: &str,
188 animation: &dyn ICompositionAnimation,
189 final_value: Option<ExpressionVariant>,
190 ) -> bool {
191 if property_name == "Color" {
192 let server = animation.create_instance(host.server(), final_value);
193 host.pending_animations().set(ServerCompositionGradientStopProps::id_of_color_property().base(), server);
194 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::COLOR_ANIMATED);
195 host.register_for_serialization();
196 return true;
197 }
198 if property_name == "Offset" {
199 let server = animation.create_instance(host.server(), final_value);
200 host.pending_animations().set(ServerCompositionGradientStopProps::id_of_offset_property().base(), server);
201 self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::OFFSET_ANIMATED);
202 host.register_for_serialization();
203 return true;
204 }
205 false
206 }
207
208 pub fn serialize_changes_core(&self, host: &dyn CompositionGradientStopHooks, writer: &mut BatchStreamWriter<'_>) {
211 let changed = self.changed_fields_of_composition_gradient_stop.get();
212 writer.write(changed);
213 if changed.contains(CompositionGradientStopChangedFields::COLOR_ANIMATED) {
214 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionGradientStopProps::id_of_color_property().base()));
215 } else if changed.contains(CompositionGradientStopChangedFields::COLOR) {
216 writer.write(self.color.get());
217 }
218 if changed.contains(CompositionGradientStopChangedFields::OFFSET_ANIMATED) {
219 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionGradientStopProps::id_of_offset_property().base()));
220 } else if changed.contains(CompositionGradientStopChangedFields::OFFSET) {
221 writer.write(self.offset.get());
222 }
223 self.changed_fields_of_composition_gradient_stop.set(CompositionGradientStopChangedFields::empty());
224 }
225}
226
227pub trait ServerCompositionGradientStopHooks: IServerAnimatedPropertyHost {
230 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
231 fn on_fields_deserialized(&self, _changed: CompositionGradientStopChangedFields) {}
232}
233
234pub struct ServerCompositionGradientStopProps {
236 color: Cell<Color>,
237 offset: Cell<f64>,
238}
239
240impl Default for ServerCompositionGradientStopProps {
241 fn default() -> Self {
242 Self::new()
243 }
244}
245
246impl ServerCompositionGradientStopProps {
247 pub fn new() -> Self {
250 Self {
251 color: Cell::new(Default::default()),
252 offset: Cell::new(Default::default()),
253 }
254 }
255
256 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
259 if type_id == TypeId::of::<Self>() {
260 return Some(self);
261 }
262 None
263 }
264
265 pub fn id_of_color_property() -> &'static CompositionPropertyOf<Color> {
267 static PROPERTY: OnceLock<CompositionPropertyOf<Color>> = OnceLock::new();
268 PROPERTY.get_or_init(|| {
269 CompositionProperty::register::<ServerCompositionGradientStopProps, Color>(
270 "Color",
271 "ServerCompositionGradientStop",
272 |obj| props_of::<ServerCompositionGradientStopProps>(obj).color.get(),
273 |obj, v| props_of::<ServerCompositionGradientStopProps>(obj).color.set(v),
274 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionGradientStopProps>(obj).color.get())),
275 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionGradientStopProps>(obj).color.set(v.cast_or_default::<Color>())),
276 )
277 })
278 }
279
280 pub fn color(&self) -> Color {
282 self.color.get()
283 }
284
285 pub fn set_color(&self, host: &dyn ServerCompositionGradientStopHooks, value: Color) {
286 self.color.set(value);
287 host.remove_animation_for_property(Self::id_of_color_property().base());
288 }
289
290 pub fn id_of_offset_property() -> &'static CompositionPropertyOf<f64> {
292 static PROPERTY: OnceLock<CompositionPropertyOf<f64>> = OnceLock::new();
293 PROPERTY.get_or_init(|| {
294 CompositionProperty::register::<ServerCompositionGradientStopProps, f64>(
295 "Offset",
296 "ServerCompositionGradientStop",
297 |obj| props_of::<ServerCompositionGradientStopProps>(obj).offset.get(),
298 |obj, v| props_of::<ServerCompositionGradientStopProps>(obj).offset.set(v),
299 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionGradientStopProps>(obj).offset.get())),
300 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionGradientStopProps>(obj).offset.set(v.cast_or_default::<f64>())),
301 )
302 })
303 }
304
305 pub fn offset(&self) -> f64 {
307 self.offset.get()
308 }
309
310 pub fn set_offset(&self, host: &dyn ServerCompositionGradientStopHooks, value: f64) {
311 self.offset.set(value);
312 host.remove_animation_for_property(Self::id_of_offset_property().base());
313 }
314
315 pub fn deserialize_changes_core(
318 &self,
319 host: &dyn ServerCompositionGradientStopHooks,
320 reader: &mut BatchStreamReader<'_>,
321 committed_at: Duration,
322 ) {
323 ServerCompositionGradientStopHooks::deserialize_changes_extra(host, reader);
324 let changed = reader.read::<CompositionGradientStopChangedFields>();
325 if changed.contains(CompositionGradientStopChangedFields::COLOR_ANIMATED) {
326 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
327 panic!("a batch starts an animation of `Color` without an animation instance");
328 };
329 host.set_animated_value(
330 Self::id_of_color_property().base(),
331 ExpressionVariant::create(self.color.get()),
332 committed_at,
333 animation,
334 );
335 } else if changed.contains(CompositionGradientStopChangedFields::COLOR) {
336 let value = reader.read::<Color>();
337 self.set_color(host, value);
338 }
339 if changed.contains(CompositionGradientStopChangedFields::OFFSET_ANIMATED) {
340 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
341 panic!("a batch starts an animation of `Offset` without an animation instance");
342 };
343 host.set_animated_value(
344 Self::id_of_offset_property().base(),
345 ExpressionVariant::create(self.offset.get()),
346 committed_at,
347 animation,
348 );
349 } else if changed.contains(CompositionGradientStopChangedFields::OFFSET) {
350 let value = reader.read::<f64>();
351 self.set_offset(host, value);
352 }
353 ServerCompositionGradientStopHooks::on_fields_deserialized(host, changed);
354 }
355
356 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
359 if name == "Color" {
360 return Some(Self::id_of_color_property().base());
361 }
362 if name == "Offset" {
363 return Some(Self::id_of_offset_property().base());
364 }
365 None
366 }
367}