Skip to main content

ferroui_base/rendering/composition/
drop_shadow.rs

1use super::composition_object_impls::composition_object_impls;
2use super::generated::{DropShadowHooks, DropShadowProps, ServerDropShadowProps};
3use super::server::{ServerDropShadow, ServerObjectId};
4use super::{CompositionBrush, CompositionDropShadowSourcePolicy, CompositionObject, Compositor, ICompositionObject};
5use crate::media::Color;
6use crate::Vector3D;
7use std::rc::{Rc, Weak};
8
9/// The shadow of a sprite or layer visual (WinUI
10/// `Microsoft.UI.Composition.DropShadow`), with animatable `BlurRadius`,
11/// `Color`, `Offset` and `Opacity`.
12///
13/// On a sprite visual the shadow is cast by the rectangle of the visual (a
14/// box shadow of the drawing context), by the alpha of its
15/// [`mask`](Self::mask) (any composition brush, such as the brush of
16/// `GetAlphaMask` of a shape, a text block or an image), or, with the
17/// `InheritFromVisualContent` [`source_policy`](Self::source_policy), by the
18/// alpha of the brush of the visual. On a layer visual it is cast by the
19/// composed children, or by the mask. The shadow is drawn under the content
20/// and nothing of it is removed; the Z of the offset moves it as the
21/// renderers project that depth for the visual (a visual turned out of its
22/// plane).
23///
24/// Deviation (winui-composition.md): without effects in the drawing context
25/// the shadow is the box shadow of the rectangle. WinUI's `CompositionShadow`
26/// base class has no members and is not a separate type.
27pub struct DropShadow {
28    this: Weak<DropShadow>,
29    object: CompositionObject,
30    props: DropShadowProps,
31}
32
33impl DropShadow {
34    pub(crate) fn new(compositor: &Rc<Compositor>) -> Rc<DropShadow> {
35        let server = compositor.create_server_object(|compositor, _| ServerDropShadow::new(compositor));
36        let shadow = Rc::new_cyclic(|this: &Weak<DropShadow>| DropShadow {
37            this: this.clone(),
38            object: CompositionObject::new(compositor, Some(server)),
39            props: DropShadowProps::new(),
40        });
41        shadow.props.initialize_defaults(&*shadow);
42        shadow
43    }
44
45    pub fn compositor(&self) -> &Rc<Compositor> {
46        self.object.compositor()
47    }
48
49    /// The embedded `CompositionObject`.
50    pub fn object(&self) -> &CompositionObject {
51        &self.object
52    }
53
54    /// The id of the server-side shadow.
55    pub fn server(&self) -> ServerObjectId {
56        self.object.required_server()
57    }
58
59    pub fn is_disposed(&self) -> bool {
60        self.object.is_disposed()
61    }
62
63    pub fn dispose(&self) {
64        self.object.dispose();
65    }
66
67    /// The generated properties of the shadow.
68    pub fn props(&self) -> &DropShadowProps {
69        &self.props
70    }
71
72    /// The radius of the blur (default 9).
73    pub fn blur_radius(&self) -> f32 {
74        self.props.blur_radius()
75    }
76
77    pub fn set_blur_radius(&self, value: f32) {
78        self.props.set_blur_radius(self, value)
79    }
80
81    /// The colour of the shadow (default black).
82    pub fn color(&self) -> Color {
83        self.props.color()
84    }
85
86    pub fn set_color(&self, value: Color) {
87        self.props.set_color(self, value)
88    }
89
90    /// The offset of the shadow from the visual (WinUI `Vector3`). The Z is
91    /// a depth in the space of the visual: it moves the shadow only where
92    /// the visual is turned out of its plane (`Orientation`, `RotationAxis`),
93    /// as the renderers project that visual.
94    pub fn offset(&self) -> Vector3D {
95        self.props.offset()
96    }
97
98    pub fn set_offset(&self, value: Vector3D) {
99        self.props.set_offset(self, value)
100    }
101
102    /// The opacity of the shadow (default 1).
103    pub fn opacity(&self) -> f32 {
104        self.props.opacity()
105    }
106
107    pub fn set_opacity(&self, value: f32) {
108        self.props.set_opacity(self, value)
109    }
110
111    /// The brush whose alpha shapes the shadow, painted over the area of the
112    /// visual; `None` for the shape of the visual. Ignored with the
113    /// `InheritFromVisualContent` source policy.
114    pub fn mask(&self) -> Option<Rc<CompositionBrush>> {
115        self.props.mask().and_then(|mask| mask.into_any_rc().downcast::<CompositionBrush>().ok())
116    }
117
118    pub fn set_mask(&self, value: Option<Rc<CompositionBrush>>) {
119        self.props.set_mask(self, value.map(|mask| mask as Rc<dyn ICompositionObject>))
120    }
121
122    /// What the shadow is cast from: `Default` for the mask (or the shape of
123    /// the visual), `InheritFromVisualContent` for the alpha of the content
124    /// of the visual (the brush of a sprite visual, the children of a layer
125    /// visual).
126    pub fn source_policy(&self) -> CompositionDropShadowSourcePolicy {
127        self.props.source_policy()
128    }
129
130    pub fn set_source_policy(&self, value: CompositionDropShadowSourcePolicy) {
131        self.props.set_source_policy(self, value)
132    }
133}
134
135/// `InitializeDefaultsExtra` activates the server object: done when the
136/// server object is created.
137impl DropShadowHooks for DropShadow {}
138
139composition_object_impls!(
140    DropShadow, "DropShadow",
141    serialize: |this, writer| this.props.serialize_changes_core(this, writer),
142    start_animation: |this, name, animation, final_value| this.props.start_animation(this, name, animation, final_value),
143    composition_property: |_this, name| ServerDropShadowProps::get_composition_property(name),
144);