Skip to main content

ferroui_base/rendering/composition/brushes/
server_simple_content_brush.rs

1//! The server-side counterpart of the mutable scene brushes (the visual
2//! brush and the drawing brush).
3
4use crate::rendering::composition::server::{
5    impl_simple_server_render_resource, server_simple_brush, IServerObject, IServerRenderResource,
6    IServerRenderResourceObserver, ServerCompositor, SimpleServerRenderResource,
7};
8use crate::media::{
9    AlignmentX, AlignmentY, IBrush, ISceneBrush, ISceneBrushContent, ITileBrush, ITransform, Stretch, TileMode,
10};
11use crate::rendering::composition::drawing::{
12    CompositionRenderDataSceneBrushContent, CompositionRenderDataSceneBrushContentProperties,
13};
14use crate::rendering::composition::generated::{
15    ServerCompositionSimpleBrushHooks, ServerCompositionSimpleBrushProps, ServerCompositionSimpleTileBrushHooks,
16    ServerCompositionSimpleTileBrushProps,
17};
18use crate::rendering::composition::transport::BatchStreamReader;
19use crate::{RelativePoint, RelativeRect};
20use std::any::{Any, TypeId};
21use std::cell::RefCell;
22use std::rc::{Rc, Weak};
23use std::time::Duration;
24
25server_simple_brush! {
26    /// The server-side counterpart of a mutable scene brush: the tile brush
27    /// properties and the render data the content was recorded into.
28    ServerCompositionSimpleContentBrush {
29        props: ServerCompositionSimpleTileBrushProps = ServerCompositionSimpleTileBrushProps::new(),
30        content: RefCell<Option<CompositionRenderDataSceneBrushContentProperties>> = RefCell::new(None),
31    }
32    brush: |b| b.props.base();
33    deserialize: |d, reader, committed_at| {
34        d.props.deserialize_changes_core(d, reader, committed_at);
35        let content =
36            CompositionRenderDataSceneBrushContentProperties::deserialize(reader, d.base.compositor().as_ref());
37        d.set_content(content);
38    };
39    find: |f, type_id| f.props.find_props(type_id);
40    dispose: |x| x.remove_content_observer();
41    as: { as_tile_brush -> ITileBrush, as_scene_brush -> ISceneBrush }
42}
43
44impl ServerCompositionSimpleTileBrushHooks for ServerCompositionSimpleContentBrush {}
45
46impl ServerCompositionSimpleContentBrush {
47    /// The properties of the brush.
48    pub fn props(&self) -> &ServerCompositionSimpleTileBrushProps {
49        &self.props
50    }
51
52    fn as_observer(&self) -> Option<Rc<dyn IServerRenderResourceObserver>> {
53        self.to_rc().map(|this| this as Rc<dyn IServerRenderResourceObserver>)
54    }
55
56    /// Replaces the content; the brush observes the render data of its
57    /// content, so that a change of what was recorded (or of a resource it
58    /// was recorded with) invalidates whatever draws with the brush.
59    fn set_content(&self, content: Option<CompositionRenderDataSceneBrushContentProperties>) {
60        let old = self.content.borrow().as_ref().map(|content| content.render_data.clone());
61        let new = content.as_ref().map(|content| content.render_data.clone());
62        let same = match (&old, &new) {
63            (Some(old), Some(new)) => Rc::ptr_eq(old, new),
64            (None, None) => true,
65            _ => false,
66        };
67        if !same {
68            if let Some(observer) = self.as_observer() {
69                if let Some(old) = &old {
70                    old.remove_observer(&observer);
71                }
72                if let Some(new) = &new {
73                    new.add_observer(&observer);
74                }
75            }
76        }
77
78        *self.content.borrow_mut() = content;
79    }
80
81    fn remove_content_observer(&self) {
82        let render_data = self.content.borrow().as_ref().map(|content| content.render_data.clone());
83        if let (Some(render_data), Some(observer)) = (render_data, self.as_observer()) {
84            render_data.remove_observer(&observer);
85        }
86    }
87}
88
89impl ITileBrush for ServerCompositionSimpleContentBrush {
90    fn alignment_x(&self) -> AlignmentX {
91        self.props.alignment_x()
92    }
93
94    fn alignment_y(&self) -> AlignmentY {
95        self.props.alignment_y()
96    }
97
98    fn destination_rect(&self) -> RelativeRect {
99        self.props.destination_rect()
100    }
101
102    fn source_rect(&self) -> RelativeRect {
103        self.props.source_rect()
104    }
105
106    fn stretch(&self) -> Stretch {
107        self.props.stretch()
108    }
109
110    fn tile_mode(&self) -> TileMode {
111        self.props.tile_mode()
112    }
113}
114
115impl ISceneBrush for ServerCompositionSimpleContentBrush {
116    fn create_content(&self) -> Option<Rc<dyn ISceneBrushContent>> {
117        let content = self.content.borrow();
118        let content = content.as_ref()?;
119        if content.render_data.is_disposed() {
120            return None;
121        }
122        let this: Rc<dyn ITileBrush> = self.to_rc()?;
123        Some(Rc::new(CompositionRenderDataSceneBrushContent::new(this, content)))
124    }
125}