Skip to main content

ferroui_base/rendering/composition/generated/
composition_gradient_stop.rs

1// @generated by scripts/generate_composition.py — do not edit
2
3//! `CompositionGradientStop`.
4
5use 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    /// The fields of `CompositionGradientStop` that changed since its last serialization.
28    #[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
49/// The partial methods of `CompositionGradientStop`: implemented by the class that embeds
50/// [`CompositionGradientStopProps`]. Every hook defaults to doing nothing.
51pub 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
63/// The UI-thread properties of `CompositionGradientStop`.
64pub 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    /// Creates the properties with every field at the default of its type.
78    /// The defaults of the schema are applied by
79    /// [`initialize_defaults`](Self::initialize_defaults).
80    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    /// The `InitializeDefaults` calls of the constructor chain: the base
89    /// classes first, then this class.
90    pub fn initialize_defaults(&self, host: &dyn CompositionGradientStopHooks) {
91        self.initialize_own_defaults(host);
92    }
93
94    /// `InitializeDefaults` of this class alone.
95    pub fn initialize_own_defaults(&self, host: &dyn CompositionGradientStopHooks) {
96        CompositionGradientStopHooks::initialize_defaults_extra(host);
97    }
98
99    /// `Color` (animated).
100    pub fn color(&self) -> Color {
101        self.color.get()
102    }
103
104    /// Sets `Color` (animated).
105    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            // Update the backing value
113            self.color.set(value);
114            // Register object for serialization in the next batch
115            self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::COLOR);
116            host.register_for_serialization();
117            // Reset previous animation if any
118            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            // Check for implicit animations
121            if let Some(animation) = host.implicit_animation("Color") {
122                // Animation affects only current property
123                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                // Animation is triggered by the current field, but does not necessary affects it
131                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    /// `Offset` (animated).
141    pub fn offset(&self) -> f64 {
142        self.offset.get()
143    }
144
145    /// Sets `Offset` (animated).
146    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            // Update the backing value
154            self.offset.set(value);
155            // Register object for serialization in the next batch
156            self.changed_fields_of_composition_gradient_stop.set(self.changed_fields_of_composition_gradient_stop.get() | CompositionGradientStopChangedFields::OFFSET);
157            host.register_for_serialization();
158            // Reset previous animation if any
159            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            // Check for implicit animations
162            if let Some(animation) = host.implicit_animation("Offset") {
163                // Animation affects only current property
164                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                // Animation is triggered by the current field, but does not necessary affects it
172                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    /// Connects an animation with the named property. Returns `false` when
182    /// neither this class nor its generated bases have an animated property
183    /// of that name: the caller continues with its hand-written base.
184    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    /// Writes the changes of the object: the base class first, then the
209    /// changed-fields mask and the changed members of this class.
210    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
227/// The partial methods of `ServerCompositionGradientStop`: implemented by the class that embeds
228/// [`ServerCompositionGradientStopProps`]. Every hook defaults to doing nothing.
229pub trait ServerCompositionGradientStopHooks: IServerAnimatedPropertyHost {
230    fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
231    fn on_fields_deserialized(&self, _changed: CompositionGradientStopChangedFields) {}
232}
233
234/// The server-side properties of `ServerCompositionGradientStop`.
235pub 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    /// Creates the properties with every field at the default of its type; the
248    /// values of the UI thread arrive with the first batch.
249    pub fn new() -> Self {
250        Self {
251            color: Cell::new(Default::default()),
252            offset: Cell::new(Default::default()),
253        }
254    }
255
256    /// This block or the block of a base class, by type: what
257    /// `IServerObject::get_props` of the embedding class returns.
258    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    /// The composition property of `Color`.
266    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    /// `Color` (animated).
281    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    /// The composition property of `Offset`.
291    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    /// `Offset` (animated).
306    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    /// Reads the changes of the object: the base class first, then the
316    /// changed-fields mask and the changed members of this class.
317    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    /// The composition property with the given name, among the properties
357    /// of this class and of its generated bases that have a variant form.
358    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}