Skip to main content

ferroui_base/rendering/composition/server/server_composition_visual/
composition_clip.rs

1//! The WinUI clip of a visual (`Visual.Clip`, here `composition_clip`): the
2//! clip object is a render resource the visual observes, and the area it
3//! leaves visible is part of the own clip of the visual and is pushed onto
4//! the drawing context by the render walk.
5
6use super::ServerCompositionVisual;
7use crate::rendering::composition::server::{
8    CompositionClipShape, IServerObject, IServerRenderResource, IServerRenderResourceObserver,
9};
10use std::rc::Rc;
11
12impl ServerCompositionVisual {
13    /// The WinUI clip object of the visual (a server-side `InsetClip` or
14    /// `RectangleClip`).
15    pub fn composition_clip(&self) -> Option<Rc<dyn IServerObject>> {
16        self.props.base().composition_clip()
17    }
18
19    /// The area the WinUI clip of the visual leaves visible, in the
20    /// coordinates of the visual.
21    pub fn composition_clip_shape(&self) -> Option<CompositionClipShape> {
22        let clip = self.composition_clip()?;
23        CompositionClipShape::of(&*clip, self.size())
24    }
25
26    fn composition_clip_resource(&self) -> Option<Rc<dyn IServerRenderResource>> {
27        self.composition_clip().and_then(|clip| clip.as_render_resource())
28    }
29
30    /// Starts or stops observing the clip object: its changes (its
31    /// animations included) change the clip of the visual.
32    pub(super) fn observe_composition_clip(&self, observe: bool) {
33        let (Some(resource), Some(this)) = (self.composition_clip_resource(), self.rc()) else { return };
34        let observer: Rc<dyn IServerRenderResourceObserver> = this;
35        if observe {
36            resource.add_observer(&observer);
37        } else {
38            resource.remove_observer(&observer);
39        }
40    }
41
42    /// Whether `sender` is the clip object of the visual.
43    pub(super) fn is_composition_clip(&self, sender: &dyn IServerRenderResource) -> bool {
44        self.composition_clip_resource()
45            .is_some_and(|resource| std::ptr::addr_eq(Rc::as_ptr(&resource), sender as *const dyn IServerRenderResource))
46    }
47
48    /// The clip object, or a property of it, changed: what a change of the
49    /// geometry clip does.
50    pub(super) fn composition_clip_changed(&self) {
51        self.trigger_composition_fields_dirty();
52        self.trigger_clip_size_dirty();
53        self.own_bounds_dirty.set(true);
54    }
55}