Skip to main content

windows_composition/
visual.rs

1use super::*;
2
3/// How a visual's edges are rendered relative to its clip.
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum BorderMode {
6    /// Inherit the border mode from the parent visual.
7    Inherit,
8    /// Antialias the visual's edges (soft).
9    Soft,
10    /// Render the visual's edges without antialiasing (hard).
11    Hard,
12}
13
14impl From<BorderMode> for bindings::CompositionBorderMode {
15    fn from(mode: BorderMode) -> Self {
16        match mode {
17            BorderMode::Inherit => Self::Inherit,
18            BorderMode::Soft => Self::Soft,
19            BorderMode::Hard => Self::Hard,
20        }
21    }
22}
23
24/// Base type for every composition visual.
25#[derive(Clone)]
26pub struct Visual(pub(crate) bindings::Visual);
27
28impl Visual {
29    /// Sets the visual's offset from its parent, in DIPs.
30    pub fn set_offset(&self, x: f32, y: f32, z: f32) {
31        self.0.SetOffset(Vector3 { x, y, z }).unwrap();
32    }
33
34    /// Returns the visual's offset from its parent.
35    pub fn offset(&self) -> Vector3 {
36        self.0.Offset().unwrap()
37    }
38
39    /// Sets the visual's size, in DIPs.
40    pub fn set_size(&self, width: f32, height: f32) {
41        self.0
42            .SetSize(Vector2 {
43                x: width,
44                y: height,
45            })
46            .unwrap();
47    }
48
49    /// Returns the visual's size.
50    pub fn size(&self) -> Vector2 {
51        self.0.Size().unwrap()
52    }
53
54    /// Sets the visual's opacity in the range `0.0..=1.0`.
55    pub fn set_opacity(&self, opacity: f32) {
56        self.0.SetOpacity(opacity).unwrap();
57    }
58
59    /// Returns the visual's opacity.
60    pub fn opacity(&self) -> f32 {
61        self.0.Opacity().unwrap()
62    }
63
64    /// Sets whether the visual (and its subtree) is rendered.
65    pub fn set_visible(&self, visible: bool) {
66        self.0.SetIsVisible(visible).unwrap();
67    }
68
69    /// Returns whether the visual is visible.
70    pub fn is_visible(&self) -> bool {
71        self.0.IsVisible().unwrap()
72    }
73
74    /// Surfaces the underlying visual as an [`IInspectable`](windows_core::IInspectable).
75    #[cfg(feature = "reactor")]
76    pub fn as_raw(&self) -> windows_core::IInspectable {
77        self.0.clone().into()
78    }
79
80    /// Sets the visual's scale factor about its [center point](Self::set_center_point).
81    pub fn set_scale(&self, scale: Vector3) {
82        self.0.SetScale(scale).unwrap();
83    }
84
85    /// Returns the visual's current scale factor.
86    pub fn scale(&self) -> Vector3 {
87        self.0.Scale().unwrap()
88    }
89
90    /// Sets the point, in DIPs, about which rotation and scaling are applied.
91    pub fn set_center_point(&self, point: Vector3) {
92        self.0.SetCenterPoint(point).unwrap();
93    }
94
95    /// Sets the normalized anchor point (`0.0..=1.0` per axis) that the visual's
96    /// offset positions.
97    pub fn set_anchor_point(&self, point: Vector2) {
98        self.0.SetAnchorPoint(point).unwrap();
99    }
100
101    /// Sets how the visual's edges are rendered.
102    pub fn set_border_mode(&self, mode: BorderMode) {
103        self.0.SetBorderMode(mode.into()).unwrap();
104    }
105
106    /// Returns the visual's parent container, if it has one.
107    pub fn parent(&self) -> Option<ContainerVisual> {
108        // A root visual has no parent: the WinRT getter yields a null reference
109        // (surfaced as an error), which maps to `None` rather than a panic.
110        self.0.Parent().ok().map(ContainerVisual::new)
111    }
112
113    /// Sets the visual's size as a fraction of its parent's size (per axis).
114    pub fn set_relative_size_adjustment(&self, adjustment: Vector2) {
115        let visual: bindings::IVisual2 = self.0.cast().unwrap();
116        visual.SetRelativeSizeAdjustment(adjustment).unwrap();
117    }
118
119    /// Sets an offset expressed as a fraction of the parent's size (per axis).
120    pub fn set_relative_offset_adjustment(&self, adjustment: Vector3) {
121        let visual: bindings::IVisual2 = self.0.cast().unwrap();
122        visual.SetRelativeOffsetAdjustment(adjustment).unwrap();
123    }
124
125    /// Sets the visual whose coordinate space this visual's transform is
126    /// relative to.
127    pub fn set_parent_for_transform(&self, parent: &Self) {
128        let visual: bindings::IVisual2 = self.0.cast().unwrap();
129        visual.SetParentForTransform(&parent.0).unwrap();
130    }
131
132    /// Returns the compositor that created this visual.
133    pub fn compositor(&self) -> Compositor {
134        let object: bindings::ICompositionObject = self.0.cast().unwrap();
135        Compositor(object.Compositor().unwrap())
136    }
137
138    /// Starts an animation on the named property (for example `"Scale"`).
139    pub fn start_animation(&self, property: &str, animation: &impl Animation) {
140        let object: bindings::ICompositionObject = self.0.cast().unwrap();
141        object
142            .StartAnimation(property, &animation.as_animation().0)
143            .unwrap();
144    }
145
146    /// Attaches (or, with `None`, clears) the [`ImplicitAnimationCollection`]
147    /// that animates this visual's properties automatically when they change.
148    pub fn set_implicit_animations(&self, animations: Option<&ImplicitAnimationCollection>) {
149        let object: bindings::ICompositionObject2 = self.0.cast().unwrap();
150        object
151            .SetImplicitAnimations(animations.map(|a| &a.0))
152            .unwrap();
153    }
154}
155
156/// A visual that hosts a child visual tree via its [`children`](Self::children).
157#[derive(Clone)]
158pub struct ContainerVisual {
159    visual: Visual,
160    container: bindings::ContainerVisual,
161}
162
163impl ContainerVisual {
164    pub(crate) fn new(container: bindings::ContainerVisual) -> Self {
165        Self {
166            visual: Visual(container.cast().unwrap()),
167            container,
168        }
169    }
170
171    /// Returns the collection of child visuals.
172    pub fn children(&self) -> VisualCollection {
173        VisualCollection(self.container.Children().unwrap())
174    }
175}
176
177impl core::ops::Deref for ContainerVisual {
178    type Target = Visual;
179    fn deref(&self) -> &Visual {
180        &self.visual
181    }
182}
183
184/// Visual that paints its bounds with a [`Brush`] and can host child visuals.
185#[derive(Clone)]
186pub struct SpriteVisual {
187    container: ContainerVisual,
188    sprite: bindings::SpriteVisual,
189}
190
191impl SpriteVisual {
192    pub(crate) fn new(sprite: bindings::SpriteVisual) -> Self {
193        Self {
194            container: ContainerVisual::new(sprite.cast().unwrap()),
195            sprite,
196        }
197    }
198
199    /// Sets the brush that fills the visual's bounds.
200    pub fn set_brush(&self, brush: &impl Brush) {
201        self.sprite.SetBrush(&brush.as_brush().0).unwrap();
202    }
203}
204
205impl core::ops::Deref for SpriteVisual {
206    type Target = ContainerVisual;
207    fn deref(&self) -> &ContainerVisual {
208        &self.container
209    }
210}
211
212/// An ordered collection of child visuals under a [`ContainerVisual`].
213#[derive(Clone)]
214pub struct VisualCollection(pub(crate) bindings::VisualCollection);
215
216impl VisualCollection {
217    /// Returns the number of visuals in the collection.
218    pub fn count(&self) -> i32 {
219        self.0.Count().unwrap()
220    }
221
222    /// Inserts a visual at the top of the z-order (drawn last, on top).
223    pub fn insert_at_top(&self, visual: &Visual) {
224        self.0.InsertAtTop(&visual.0).unwrap();
225    }
226
227    /// Inserts a visual at the bottom of the z-order (drawn first, behind).
228    pub fn insert_at_bottom(&self, visual: &Visual) {
229        self.0.InsertAtBottom(&visual.0).unwrap();
230    }
231
232    /// Removes a visual from the collection.
233    pub fn remove(&self, visual: &Visual) {
234        self.0.Remove(&visual.0).unwrap();
235    }
236
237    /// Removes every visual from the collection.
238    pub fn remove_all(&self) {
239        self.0.RemoveAll().unwrap();
240    }
241}