Skip to main content

ferroui_base/rendering/composition/
composition_gradient_stop.rs

1use super::animations::{ICompositionAnimation, ICompositionAnimationBase, ImplicitAnimationCollection};
2use super::expressions::ExpressionVariant;
3use super::generated::{
4    CompositionGradientStopHooks, CompositionGradientStopProps, ServerCompositionGradientStopProps,
5};
6use super::server::{CompositionProperty, ServerCompositionGradientStop, ServerObjectId};
7use super::transport::{BatchStreamWriter, IRegisterForSerialization};
8use super::{
9    AsCompositionObject, CompositionObject, Compositor, ICompositionObject, ICompositionObjectAnimations,
10    ICompositionObjectHost, ICompositorSerializable, PendingAnimations,
11};
12use crate::media::{Color, IGradientStop};
13use crate::utilities::MathUtilities;
14use std::any::Any;
15use std::rc::{Rc, Weak};
16
17/// A gradient stop of the composition brushes, with animatable color and
18/// offset.
19pub struct CompositionGradientStop {
20    this: Weak<CompositionGradientStop>,
21    object: CompositionObject,
22    props: CompositionGradientStopProps,
23}
24
25impl CompositionGradientStop {
26    fn create(compositor: &Rc<Compositor>) -> Rc<CompositionGradientStop> {
27        let server = compositor.create_server_object(|compositor, _| ServerCompositionGradientStop::new(compositor));
28        Rc::new_cyclic(|this: &Weak<CompositionGradientStop>| CompositionGradientStop {
29            this: this.clone(),
30            object: CompositionObject::new(compositor, Some(server)),
31            props: CompositionGradientStopProps::new(),
32        })
33    }
34
35    pub(crate) fn new(compositor: &Rc<Compositor>) -> Rc<CompositionGradientStop> {
36        let stop = Self::create(compositor);
37        stop.props.initialize_defaults(&*stop);
38        stop
39    }
40
41    pub(crate) fn with_offset_and_color(compositor: &Rc<Compositor>, offset: f64, color: Color) -> Rc<CompositionGradientStop> {
42        let stop = Self::create(compositor);
43        let mut offset = offset;
44        if MathUtilities::is_zero(offset) {
45            offset = 0.0;
46        }
47        stop.set_offset(if offset < 0.0 {
48            0.0
49        } else if offset > 1.0 {
50            1.0
51        } else {
52            offset
53        });
54        stop.set_color(color);
55        stop.props.initialize_defaults(&*stop);
56        stop
57    }
58
59    pub fn compositor(&self) -> &Rc<Compositor> {
60        self.object.compositor()
61    }
62
63    /// The embedded `CompositionObject`.
64    pub fn object(&self) -> &CompositionObject {
65        &self.object
66    }
67
68    /// The id of the server-side stop.
69    pub fn server(&self) -> ServerObjectId {
70        self.object.required_server()
71    }
72
73    pub fn color(&self) -> Color {
74        self.props.color()
75    }
76
77    pub fn set_color(&self, value: Color) {
78        self.props.set_color(self, value)
79    }
80
81    pub fn offset(&self) -> f64 {
82        self.props.offset()
83    }
84
85    pub fn set_offset(&self, value: f64) {
86        self.props.set_offset(self, value)
87    }
88
89    /// The collection of implicit animations attached to this object.
90    pub fn implicit_animations(&self) -> Option<Rc<ImplicitAnimationCollection>> {
91        self.object.implicit_animations()
92    }
93
94    pub fn set_implicit_animations(&self, value: Option<Rc<ImplicitAnimationCollection>>) {
95        self.object.set_implicit_animations(value)
96    }
97}
98
99/// `InitializeDefaultsExtra` activates the server object: done when the
100/// server object is created (see [`ServerCompositionGradientStop::new`]).
101impl CompositionGradientStopHooks for CompositionGradientStop {}
102
103impl IGradientStop for CompositionGradientStop {
104    fn color(&self) -> Color {
105        self.props.color()
106    }
107
108    fn offset(&self) -> f64 {
109        self.props.offset()
110    }
111
112    fn as_composition_gradient_stop(&self) -> Option<&CompositionGradientStop> {
113        Some(self)
114    }
115}
116
117impl IRegisterForSerialization for CompositionGradientStop {
118    fn register_for_serialization(&self) {
119        self.object
120            .register_for_serialization(|| self.this.upgrade().map(|this| this as Rc<dyn ICompositorSerializable>));
121    }
122}
123
124impl ICompositionObjectHost for CompositionGradientStop {
125    fn server(&self) -> ServerObjectId {
126        self.object.required_server()
127    }
128
129    fn pending_animations(&self) -> &PendingAnimations {
130        self.object.pending_animations()
131    }
132
133    fn implicit_animation(&self, property_name: &str) -> Option<Rc<dyn ICompositionAnimationBase>> {
134        self.object.implicit_animation(property_name)
135    }
136
137    fn start_animation_group(
138        &self,
139        grp: &Rc<dyn ICompositionAnimationBase>,
140        target: &str,
141        final_value: ExpressionVariant,
142    ) -> bool {
143        self.start_animation_group_for(&**grp, target, final_value)
144    }
145}
146
147impl ICompositionObjectAnimations for CompositionGradientStop {
148    fn try_start_animation(
149        &self,
150        property_name: &str,
151        animation: &dyn ICompositionAnimation,
152        final_value: Option<ExpressionVariant>,
153    ) -> bool {
154        self.props.start_animation(self, property_name, animation, final_value)
155    }
156
157    fn get_composition_property(&self, property_name: &str) -> Option<&'static CompositionProperty> {
158        ServerCompositionGradientStopProps::get_composition_property(property_name)
159    }
160
161    fn composition_object(&self) -> &CompositionObject {
162        &self.object
163    }
164}
165
166impl AsCompositionObject for CompositionGradientStop {
167    fn as_composition_object(&self) -> &CompositionObject {
168        &self.object
169    }
170
171    fn composition_type_name(&self) -> &'static str {
172        "CompositionGradientStop"
173    }
174}
175
176impl ICompositionObject for CompositionGradientStop {
177    fn server(&self) -> ServerObjectId {
178        self.object.required_server()
179    }
180
181    fn as_any(&self) -> &dyn Any {
182        self
183    }
184
185    fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
186        self
187    }
188}
189
190impl ICompositorSerializable for CompositionGradientStop {
191    fn try_get_server(&self, c: &Compositor) -> Option<ServerObjectId> {
192        self.object.try_get_server(c)
193    }
194
195    fn serialize_changes(&self, c: &Compositor, writer: &mut BatchStreamWriter<'_>) {
196        self.object.begin_serialize_changes(c);
197        self.props.serialize_changes_core(self, writer);
198    }
199}