Skip to main content

ferroui_base/rendering/composition/
i_composition_object_host.rs

1//! The seam between the generated property blocks of composition objects
2//! and the hand-written classes that embed them.
3
4use super::animations::{AnimationInstanceFactory, ICompositionAnimationBase};
5use super::expressions::ExpressionVariant;
6use super::server::{CompositionProperty, ServerObjectId};
7use super::transport::IRegisterForSerialization;
8use std::any::Any;
9use std::cell::RefCell;
10use std::rc::Rc;
11
12/// A UI-thread composition object as other composition objects refer to
13/// it: something with a server-side counterpart.
14pub trait ICompositionObject: 'static {
15    /// The id of the server-side counterpart of the object.
16    fn server(&self) -> ServerObjectId;
17
18    fn as_any(&self) -> &dyn Any;
19
20    fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
21}
22
23/// The animation instances created on the UI thread (as their factories)
24/// that have not been sent to the server yet, by the property they animate.
25#[derive(Default)]
26pub struct PendingAnimations {
27    items: RefCell<Vec<(i32, AnimationInstanceFactory)>>,
28}
29
30impl PendingAnimations {
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    pub fn count(&self) -> usize {
36        self.items.borrow().len()
37    }
38
39    /// Drops the pending animation of a property. Returns whether there
40    /// was one.
41    pub fn remove(&self, property: &CompositionProperty) -> bool {
42        self.get_and_remove(property).is_some()
43    }
44
45    /// Sets the pending animation of a property, replacing the previous
46    /// one.
47    pub fn set(&self, property: &CompositionProperty, animation: AnimationInstanceFactory) {
48        let mut items = self.items.borrow_mut();
49        match items.iter_mut().find(|(id, _)| *id == property.id()) {
50            Some(entry) => entry.1 = animation,
51            None => items.push((property.id(), animation)),
52        }
53    }
54
55    /// Takes the pending animation of a property.
56    pub fn get_and_remove(&self, property: &CompositionProperty) -> Option<AnimationInstanceFactory> {
57        let mut items = self.items.borrow_mut();
58        let index = items.iter().position(|(id, _)| *id == property.id())?;
59        Some(items.remove(index).1)
60    }
61}
62
63/// What a generated client property block needs from the composition
64/// object that embeds it (the members of upstream `CompositionObject` the
65/// generated code uses).
66pub trait ICompositionObjectHost: IRegisterForSerialization {
67    /// The id of the server-side counterpart of the object.
68    fn server(&self) -> ServerObjectId;
69
70    /// The animations waiting to be sent with the next batch.
71    fn pending_animations(&self) -> &PendingAnimations;
72
73    /// The implicit animation attached to a property of the object, if
74    /// there is one (`ImplicitAnimations?.TryGetValue(name)`).
75    fn implicit_animation(&self, property_name: &str) -> Option<Rc<dyn ICompositionAnimationBase>>;
76
77    /// Starts an animation or an animation group triggered by the change
78    /// of property `target` to `final_value`. Returns whether one of the
79    /// animations targets that property.
80    fn start_animation_group(
81        &self,
82        grp: &Rc<dyn ICompositionAnimationBase>,
83        target: &str,
84        final_value: ExpressionVariant,
85    ) -> bool;
86}