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