1use bitflags::bitflags;
8use crate::Matrix;
9use crate::RelativePoint;
10use crate::Vector;
11use crate::rendering::composition::ICompositionObjectHost;
12use crate::rendering::composition::animations::AnimationInstanceFactory;
13use crate::rendering::composition::animations::ICompositionAnimation;
14use crate::rendering::composition::expressions::ExpressionVariant;
15use crate::rendering::composition::server::CompositionProperty;
16use crate::rendering::composition::server::CompositionPropertyOf;
17use crate::rendering::composition::server::IServerAnimatedPropertyHost;
18use crate::rendering::composition::server::ServerPropertyValue;
19use crate::rendering::composition::server::props_of;
20use crate::rendering::composition::transport::BatchStreamReader;
21use crate::rendering::composition::transport::BatchStreamWriter;
22use crate::rendering::composition::transport::BatchValue;
23use crate::rendering::composition::transport::BatchValueReader;
24use std::any::Any;
25use std::any::TypeId;
26use std::cell::Cell;
27use std::sync::OnceLock;
28use std::time::Duration;
29
30bitflags! {
31 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
33 pub struct CompositionLinearGradientBrushChangedFields: u16 {
34 const START_POINT = 1;
35 const START_POINT_ANIMATED = 2;
36 const END_POINT = 4;
37 const END_POINT_ANIMATED = 8;
38 const ANCHOR_POINT = 16;
39 const ANCHOR_POINT_ANIMATED = 32;
40 const CENTER_POINT = 64;
41 const CENTER_POINT_ANIMATED = 128;
42 const OFFSET = 256;
43 const OFFSET_ANIMATED = 512;
44 const ROTATION_ANGLE = 1024;
45 const ROTATION_ANGLE_ANIMATED = 2048;
46 const SCALE = 4096;
47 const SCALE_ANIMATED = 8192;
48 const TRANSFORM_MATRIX = 16384;
49 const TRANSFORM_MATRIX_ANIMATED = 32768;
50 }
51}
52
53impl BatchValue for CompositionLinearGradientBrushChangedFields {
54 #[inline]
55 fn write_to(&self, out: &mut Vec<u8>) {
56 self.bits().write_to(out);
57 }
58
59 #[inline]
60 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
61 CompositionLinearGradientBrushChangedFields::from_bits_retain(u16::read_from(input))
62 }
63}
64
65pub trait CompositionLinearGradientBrushHooks: ICompositionObjectHost {
68 fn base_serialize_changes_core(&self, writer: &mut BatchStreamWriter<'_>);
71
72 fn initialize_defaults_extra(&self) {}
73
74 fn validate_start_point_change(&self, _old_value: RelativePoint, _new_value: RelativePoint) {}
75 fn on_start_point_changed(&self) {}
76 fn on_start_point_changing(&self) {}
77
78 fn validate_end_point_change(&self, _old_value: RelativePoint, _new_value: RelativePoint) {}
79 fn on_end_point_changed(&self) {}
80 fn on_end_point_changing(&self) {}
81
82 fn validate_anchor_point_change(&self, _old_value: Vector, _new_value: Vector) {}
83 fn on_anchor_point_changed(&self) {}
84 fn on_anchor_point_changing(&self) {}
85
86 fn validate_center_point_change(&self, _old_value: Vector, _new_value: Vector) {}
87 fn on_center_point_changed(&self) {}
88 fn on_center_point_changing(&self) {}
89
90 fn validate_offset_change(&self, _old_value: Vector, _new_value: Vector) {}
91 fn on_offset_changed(&self) {}
92 fn on_offset_changing(&self) {}
93
94 fn validate_rotation_angle_change(&self, _old_value: f32, _new_value: f32) {}
95 fn on_rotation_angle_changed(&self) {}
96 fn on_rotation_angle_changing(&self) {}
97
98 fn validate_scale_change(&self, _old_value: Vector, _new_value: Vector) {}
99 fn on_scale_changed(&self) {}
100 fn on_scale_changing(&self) {}
101
102 fn validate_transform_matrix_change(&self, _old_value: Matrix, _new_value: Matrix) {}
103 fn on_transform_matrix_changed(&self) {}
104 fn on_transform_matrix_changing(&self) {}
105}
106
107pub struct CompositionLinearGradientBrushProps {
109 changed_fields_of_composition_linear_gradient_brush: Cell<CompositionLinearGradientBrushChangedFields>,
110 start_point: Cell<RelativePoint>,
111 end_point: Cell<RelativePoint>,
112 anchor_point: Cell<Vector>,
113 center_point: Cell<Vector>,
114 offset: Cell<Vector>,
115 rotation_angle: Cell<f32>,
116 scale: Cell<Vector>,
117 transform_matrix: Cell<Matrix>,
118}
119
120impl Default for CompositionLinearGradientBrushProps {
121 fn default() -> Self {
122 Self::new()
123 }
124}
125
126impl CompositionLinearGradientBrushProps {
127 pub fn new() -> Self {
131 Self {
132 changed_fields_of_composition_linear_gradient_brush: Cell::new(CompositionLinearGradientBrushChangedFields::empty()),
133 start_point: Cell::new(Default::default()),
134 end_point: Cell::new(Default::default()),
135 anchor_point: Cell::new(Default::default()),
136 center_point: Cell::new(Default::default()),
137 offset: Cell::new(Default::default()),
138 rotation_angle: Cell::new(Default::default()),
139 scale: Cell::new(Default::default()),
140 transform_matrix: Cell::new(Default::default()),
141 }
142 }
143
144 pub fn initialize_defaults(&self, host: &dyn CompositionLinearGradientBrushHooks) {
147 self.initialize_own_defaults(host);
148 }
149
150 pub fn initialize_own_defaults(&self, host: &dyn CompositionLinearGradientBrushHooks) {
152 CompositionLinearGradientBrushHooks::initialize_defaults_extra(host);
153 self.set_scale(host, Vector::new(1.0, 1.0));
154 self.set_transform_matrix(host, Matrix::IDENTITY);
155 }
156
157 pub fn start_point(&self) -> RelativePoint {
159 self.start_point.get()
160 }
161
162 pub fn set_start_point(&self, host: &dyn CompositionLinearGradientBrushHooks, value: RelativePoint) {
164 let mut changed = false;
165 let old_value = self.start_point.get();
166 if old_value.differs(&value) {
167 CompositionLinearGradientBrushHooks::validate_start_point_change(host, old_value, value);
168 CompositionLinearGradientBrushHooks::on_start_point_changing(host);
169 changed = true;
170 self.start_point.set(value);
172 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::START_POINT);
174 host.register_for_serialization();
175 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_start_point_property().base());
177 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::START_POINT_ANIMATED);
178 if let Some(animation) = host.implicit_animation("StartPoint") {
180 if let Some(a) = animation.as_composition_animation() {
182 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::START_POINT_ANIMATED);
183 host.pending_animations().set(
184 ServerCompositionLinearGradientBrushProps::id_of_start_point_property().base(),
185 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
186 );
187 }
188 host.start_animation_group(&animation, "StartPoint", ExpressionVariant::create(value));
190 }
191 }
192 self.start_point.set(value);
193 if changed {
194 CompositionLinearGradientBrushHooks::on_start_point_changed(host);
195 }
196 }
197
198 pub fn end_point(&self) -> RelativePoint {
200 self.end_point.get()
201 }
202
203 pub fn set_end_point(&self, host: &dyn CompositionLinearGradientBrushHooks, value: RelativePoint) {
205 let mut changed = false;
206 let old_value = self.end_point.get();
207 if old_value.differs(&value) {
208 CompositionLinearGradientBrushHooks::validate_end_point_change(host, old_value, value);
209 CompositionLinearGradientBrushHooks::on_end_point_changing(host);
210 changed = true;
211 self.end_point.set(value);
213 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::END_POINT);
215 host.register_for_serialization();
216 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_end_point_property().base());
218 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::END_POINT_ANIMATED);
219 if let Some(animation) = host.implicit_animation("EndPoint") {
221 if let Some(a) = animation.as_composition_animation() {
223 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::END_POINT_ANIMATED);
224 host.pending_animations().set(
225 ServerCompositionLinearGradientBrushProps::id_of_end_point_property().base(),
226 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
227 );
228 }
229 host.start_animation_group(&animation, "EndPoint", ExpressionVariant::create(value));
231 }
232 }
233 self.end_point.set(value);
234 if changed {
235 CompositionLinearGradientBrushHooks::on_end_point_changed(host);
236 }
237 }
238
239 pub fn anchor_point(&self) -> Vector {
241 self.anchor_point.get()
242 }
243
244 pub fn set_anchor_point(&self, host: &dyn CompositionLinearGradientBrushHooks, value: Vector) {
246 let mut changed = false;
247 let old_value = self.anchor_point.get();
248 if old_value.differs(&value) {
249 CompositionLinearGradientBrushHooks::validate_anchor_point_change(host, old_value, value);
250 CompositionLinearGradientBrushHooks::on_anchor_point_changing(host);
251 changed = true;
252 self.anchor_point.set(value);
254 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::ANCHOR_POINT);
256 host.register_for_serialization();
257 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_anchor_point_property().base());
259 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::ANCHOR_POINT_ANIMATED);
260 if let Some(animation) = host.implicit_animation("AnchorPoint") {
262 if let Some(a) = animation.as_composition_animation() {
264 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::ANCHOR_POINT_ANIMATED);
265 host.pending_animations().set(
266 ServerCompositionLinearGradientBrushProps::id_of_anchor_point_property().base(),
267 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
268 );
269 }
270 host.start_animation_group(&animation, "AnchorPoint", ExpressionVariant::create(value));
272 }
273 }
274 self.anchor_point.set(value);
275 if changed {
276 CompositionLinearGradientBrushHooks::on_anchor_point_changed(host);
277 }
278 }
279
280 pub fn center_point(&self) -> Vector {
282 self.center_point.get()
283 }
284
285 pub fn set_center_point(&self, host: &dyn CompositionLinearGradientBrushHooks, value: Vector) {
287 let mut changed = false;
288 let old_value = self.center_point.get();
289 if old_value.differs(&value) {
290 CompositionLinearGradientBrushHooks::validate_center_point_change(host, old_value, value);
291 CompositionLinearGradientBrushHooks::on_center_point_changing(host);
292 changed = true;
293 self.center_point.set(value);
295 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::CENTER_POINT);
297 host.register_for_serialization();
298 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_center_point_property().base());
300 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::CENTER_POINT_ANIMATED);
301 if let Some(animation) = host.implicit_animation("CenterPoint") {
303 if let Some(a) = animation.as_composition_animation() {
305 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::CENTER_POINT_ANIMATED);
306 host.pending_animations().set(
307 ServerCompositionLinearGradientBrushProps::id_of_center_point_property().base(),
308 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
309 );
310 }
311 host.start_animation_group(&animation, "CenterPoint", ExpressionVariant::create(value));
313 }
314 }
315 self.center_point.set(value);
316 if changed {
317 CompositionLinearGradientBrushHooks::on_center_point_changed(host);
318 }
319 }
320
321 pub fn offset(&self) -> Vector {
323 self.offset.get()
324 }
325
326 pub fn set_offset(&self, host: &dyn CompositionLinearGradientBrushHooks, value: Vector) {
328 let mut changed = false;
329 let old_value = self.offset.get();
330 if old_value.differs(&value) {
331 CompositionLinearGradientBrushHooks::validate_offset_change(host, old_value, value);
332 CompositionLinearGradientBrushHooks::on_offset_changing(host);
333 changed = true;
334 self.offset.set(value);
336 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::OFFSET);
338 host.register_for_serialization();
339 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_offset_property().base());
341 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::OFFSET_ANIMATED);
342 if let Some(animation) = host.implicit_animation("Offset") {
344 if let Some(a) = animation.as_composition_animation() {
346 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::OFFSET_ANIMATED);
347 host.pending_animations().set(
348 ServerCompositionLinearGradientBrushProps::id_of_offset_property().base(),
349 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
350 );
351 }
352 host.start_animation_group(&animation, "Offset", ExpressionVariant::create(value));
354 }
355 }
356 self.offset.set(value);
357 if changed {
358 CompositionLinearGradientBrushHooks::on_offset_changed(host);
359 }
360 }
361
362 pub fn rotation_angle(&self) -> f32 {
364 self.rotation_angle.get()
365 }
366
367 pub fn set_rotation_angle(&self, host: &dyn CompositionLinearGradientBrushHooks, value: f32) {
369 let mut changed = false;
370 let old_value = self.rotation_angle.get();
371 if old_value.differs(&value) {
372 CompositionLinearGradientBrushHooks::validate_rotation_angle_change(host, old_value, value);
373 CompositionLinearGradientBrushHooks::on_rotation_angle_changing(host);
374 changed = true;
375 self.rotation_angle.set(value);
377 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE);
379 host.register_for_serialization();
380 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_rotation_angle_property().base());
382 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE_ANIMATED);
383 if let Some(animation) = host.implicit_animation("RotationAngle") {
385 if let Some(a) = animation.as_composition_animation() {
387 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE_ANIMATED);
388 host.pending_animations().set(
389 ServerCompositionLinearGradientBrushProps::id_of_rotation_angle_property().base(),
390 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
391 );
392 }
393 host.start_animation_group(&animation, "RotationAngle", ExpressionVariant::create(value));
395 }
396 }
397 self.rotation_angle.set(value);
398 if changed {
399 CompositionLinearGradientBrushHooks::on_rotation_angle_changed(host);
400 }
401 }
402
403 pub fn scale(&self) -> Vector {
405 self.scale.get()
406 }
407
408 pub fn set_scale(&self, host: &dyn CompositionLinearGradientBrushHooks, value: Vector) {
410 let mut changed = false;
411 let old_value = self.scale.get();
412 if old_value.differs(&value) {
413 CompositionLinearGradientBrushHooks::validate_scale_change(host, old_value, value);
414 CompositionLinearGradientBrushHooks::on_scale_changing(host);
415 changed = true;
416 self.scale.set(value);
418 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::SCALE);
420 host.register_for_serialization();
421 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_scale_property().base());
423 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::SCALE_ANIMATED);
424 if let Some(animation) = host.implicit_animation("Scale") {
426 if let Some(a) = animation.as_composition_animation() {
428 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::SCALE_ANIMATED);
429 host.pending_animations().set(
430 ServerCompositionLinearGradientBrushProps::id_of_scale_property().base(),
431 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
432 );
433 }
434 host.start_animation_group(&animation, "Scale", ExpressionVariant::create(value));
436 }
437 }
438 self.scale.set(value);
439 if changed {
440 CompositionLinearGradientBrushHooks::on_scale_changed(host);
441 }
442 }
443
444 pub fn transform_matrix(&self) -> Matrix {
446 self.transform_matrix.get()
447 }
448
449 pub fn set_transform_matrix(&self, host: &dyn CompositionLinearGradientBrushHooks, value: Matrix) {
451 let mut changed = false;
452 let old_value = self.transform_matrix.get();
453 if old_value.differs(&value) {
454 CompositionLinearGradientBrushHooks::validate_transform_matrix_change(host, old_value, value);
455 CompositionLinearGradientBrushHooks::on_transform_matrix_changing(host);
456 changed = true;
457 self.transform_matrix.set(value);
459 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX);
461 host.register_for_serialization();
462 host.pending_animations().remove(ServerCompositionLinearGradientBrushProps::id_of_transform_matrix_property().base());
464 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() & !CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
465 if let Some(animation) = host.implicit_animation("TransformMatrix") {
467 if let Some(a) = animation.as_composition_animation() {
469 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
470 host.pending_animations().set(
471 ServerCompositionLinearGradientBrushProps::id_of_transform_matrix_property().base(),
472 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
473 );
474 }
475 host.start_animation_group(&animation, "TransformMatrix", ExpressionVariant::create(value));
477 }
478 }
479 self.transform_matrix.set(value);
480 if changed {
481 CompositionLinearGradientBrushHooks::on_transform_matrix_changed(host);
482 }
483 }
484
485 pub fn start_animation(
489 &self,
490 host: &dyn CompositionLinearGradientBrushHooks,
491 property_name: &str,
492 animation: &dyn ICompositionAnimation,
493 final_value: Option<ExpressionVariant>,
494 ) -> bool {
495 if property_name == "StartPoint" {
496 let server = animation.create_instance(host.server(), final_value);
497 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_start_point_property().base(), server);
498 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::START_POINT_ANIMATED);
499 host.register_for_serialization();
500 return true;
501 }
502 if property_name == "EndPoint" {
503 let server = animation.create_instance(host.server(), final_value);
504 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_end_point_property().base(), server);
505 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::END_POINT_ANIMATED);
506 host.register_for_serialization();
507 return true;
508 }
509 if property_name == "AnchorPoint" {
510 let server = animation.create_instance(host.server(), final_value);
511 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_anchor_point_property().base(), server);
512 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::ANCHOR_POINT_ANIMATED);
513 host.register_for_serialization();
514 return true;
515 }
516 if property_name == "CenterPoint" {
517 let server = animation.create_instance(host.server(), final_value);
518 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_center_point_property().base(), server);
519 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::CENTER_POINT_ANIMATED);
520 host.register_for_serialization();
521 return true;
522 }
523 if property_name == "Offset" {
524 let server = animation.create_instance(host.server(), final_value);
525 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_offset_property().base(), server);
526 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::OFFSET_ANIMATED);
527 host.register_for_serialization();
528 return true;
529 }
530 if property_name == "RotationAngle" {
531 let server = animation.create_instance(host.server(), final_value);
532 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_rotation_angle_property().base(), server);
533 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE_ANIMATED);
534 host.register_for_serialization();
535 return true;
536 }
537 if property_name == "Scale" {
538 let server = animation.create_instance(host.server(), final_value);
539 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_scale_property().base(), server);
540 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::SCALE_ANIMATED);
541 host.register_for_serialization();
542 return true;
543 }
544 if property_name == "TransformMatrix" {
545 let server = animation.create_instance(host.server(), final_value);
546 host.pending_animations().set(ServerCompositionLinearGradientBrushProps::id_of_transform_matrix_property().base(), server);
547 self.changed_fields_of_composition_linear_gradient_brush.set(self.changed_fields_of_composition_linear_gradient_brush.get() | CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
548 host.register_for_serialization();
549 return true;
550 }
551 false
552 }
553
554 pub fn serialize_changes_core(&self, host: &dyn CompositionLinearGradientBrushHooks, writer: &mut BatchStreamWriter<'_>) {
557 CompositionLinearGradientBrushHooks::base_serialize_changes_core(host, writer);
558 let changed = self.changed_fields_of_composition_linear_gradient_brush.get();
559 writer.write(changed);
560 if changed.contains(CompositionLinearGradientBrushChangedFields::START_POINT_ANIMATED) {
561 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_start_point_property().base()));
562 } else if changed.contains(CompositionLinearGradientBrushChangedFields::START_POINT) {
563 writer.write(self.start_point.get());
564 }
565 if changed.contains(CompositionLinearGradientBrushChangedFields::END_POINT_ANIMATED) {
566 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_end_point_property().base()));
567 } else if changed.contains(CompositionLinearGradientBrushChangedFields::END_POINT) {
568 writer.write(self.end_point.get());
569 }
570 if changed.contains(CompositionLinearGradientBrushChangedFields::ANCHOR_POINT_ANIMATED) {
571 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_anchor_point_property().base()));
572 } else if changed.contains(CompositionLinearGradientBrushChangedFields::ANCHOR_POINT) {
573 writer.write(self.anchor_point.get());
574 }
575 if changed.contains(CompositionLinearGradientBrushChangedFields::CENTER_POINT_ANIMATED) {
576 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_center_point_property().base()));
577 } else if changed.contains(CompositionLinearGradientBrushChangedFields::CENTER_POINT) {
578 writer.write(self.center_point.get());
579 }
580 if changed.contains(CompositionLinearGradientBrushChangedFields::OFFSET_ANIMATED) {
581 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_offset_property().base()));
582 } else if changed.contains(CompositionLinearGradientBrushChangedFields::OFFSET) {
583 writer.write(self.offset.get());
584 }
585 if changed.contains(CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE_ANIMATED) {
586 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_rotation_angle_property().base()));
587 } else if changed.contains(CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE) {
588 writer.write(self.rotation_angle.get());
589 }
590 if changed.contains(CompositionLinearGradientBrushChangedFields::SCALE_ANIMATED) {
591 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_scale_property().base()));
592 } else if changed.contains(CompositionLinearGradientBrushChangedFields::SCALE) {
593 writer.write(self.scale.get());
594 }
595 if changed.contains(CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX_ANIMATED) {
596 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionLinearGradientBrushProps::id_of_transform_matrix_property().base()));
597 } else if changed.contains(CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX) {
598 writer.write(self.transform_matrix.get());
599 }
600 self.changed_fields_of_composition_linear_gradient_brush.set(CompositionLinearGradientBrushChangedFields::empty());
601 }
602}
603
604pub trait ServerCompositionLinearGradientBrushHooks: IServerAnimatedPropertyHost {
607 fn base_deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, committed_at: Duration);
610
611 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
612 fn on_fields_deserialized(&self, _changed: CompositionLinearGradientBrushChangedFields) {}
613}
614
615pub struct ServerCompositionLinearGradientBrushProps {
617 start_point: Cell<RelativePoint>,
618 end_point: Cell<RelativePoint>,
619 anchor_point: Cell<Vector>,
620 center_point: Cell<Vector>,
621 offset: Cell<Vector>,
622 rotation_angle: Cell<f32>,
623 scale: Cell<Vector>,
624 transform_matrix: Cell<Matrix>,
625}
626
627impl Default for ServerCompositionLinearGradientBrushProps {
628 fn default() -> Self {
629 Self::new()
630 }
631}
632
633impl ServerCompositionLinearGradientBrushProps {
634 pub fn new() -> Self {
637 Self {
638 start_point: Cell::new(Default::default()),
639 end_point: Cell::new(Default::default()),
640 anchor_point: Cell::new(Default::default()),
641 center_point: Cell::new(Default::default()),
642 offset: Cell::new(Default::default()),
643 rotation_angle: Cell::new(Default::default()),
644 scale: Cell::new(Default::default()),
645 transform_matrix: Cell::new(Default::default()),
646 }
647 }
648
649 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
652 if type_id == TypeId::of::<Self>() {
653 return Some(self);
654 }
655 None
656 }
657
658 pub fn id_of_start_point_property() -> &'static CompositionPropertyOf<RelativePoint> {
660 static PROPERTY: OnceLock<CompositionPropertyOf<RelativePoint>> = OnceLock::new();
661 PROPERTY.get_or_init(|| {
662 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, RelativePoint>(
663 "StartPoint",
664 "ServerCompositionLinearGradientBrush",
665 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).start_point.get(),
666 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).start_point.set(v),
667 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).start_point.get())),
668 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).start_point.set(v.cast_or_default::<RelativePoint>())),
669 )
670 })
671 }
672
673 pub fn start_point(&self) -> RelativePoint {
675 self.start_point.get()
676 }
677
678 pub fn set_start_point(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: RelativePoint) {
679 self.start_point.set(value);
680 host.remove_animation_for_property(Self::id_of_start_point_property().base());
681 }
682
683 pub fn id_of_end_point_property() -> &'static CompositionPropertyOf<RelativePoint> {
685 static PROPERTY: OnceLock<CompositionPropertyOf<RelativePoint>> = OnceLock::new();
686 PROPERTY.get_or_init(|| {
687 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, RelativePoint>(
688 "EndPoint",
689 "ServerCompositionLinearGradientBrush",
690 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).end_point.get(),
691 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).end_point.set(v),
692 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).end_point.get())),
693 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).end_point.set(v.cast_or_default::<RelativePoint>())),
694 )
695 })
696 }
697
698 pub fn end_point(&self) -> RelativePoint {
700 self.end_point.get()
701 }
702
703 pub fn set_end_point(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: RelativePoint) {
704 self.end_point.set(value);
705 host.remove_animation_for_property(Self::id_of_end_point_property().base());
706 }
707
708 pub fn id_of_anchor_point_property() -> &'static CompositionPropertyOf<Vector> {
710 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
711 PROPERTY.get_or_init(|| {
712 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, Vector>(
713 "AnchorPoint",
714 "ServerCompositionLinearGradientBrush",
715 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).anchor_point.get(),
716 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).anchor_point.set(v),
717 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).anchor_point.get())),
718 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).anchor_point.set(v.cast_or_default::<Vector>())),
719 )
720 })
721 }
722
723 pub fn anchor_point(&self) -> Vector {
725 self.anchor_point.get()
726 }
727
728 pub fn set_anchor_point(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: Vector) {
729 self.anchor_point.set(value);
730 host.remove_animation_for_property(Self::id_of_anchor_point_property().base());
731 }
732
733 pub fn id_of_center_point_property() -> &'static CompositionPropertyOf<Vector> {
735 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
736 PROPERTY.get_or_init(|| {
737 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, Vector>(
738 "CenterPoint",
739 "ServerCompositionLinearGradientBrush",
740 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).center_point.get(),
741 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).center_point.set(v),
742 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).center_point.get())),
743 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).center_point.set(v.cast_or_default::<Vector>())),
744 )
745 })
746 }
747
748 pub fn center_point(&self) -> Vector {
750 self.center_point.get()
751 }
752
753 pub fn set_center_point(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: Vector) {
754 self.center_point.set(value);
755 host.remove_animation_for_property(Self::id_of_center_point_property().base());
756 }
757
758 pub fn id_of_offset_property() -> &'static CompositionPropertyOf<Vector> {
760 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
761 PROPERTY.get_or_init(|| {
762 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, Vector>(
763 "Offset",
764 "ServerCompositionLinearGradientBrush",
765 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).offset.get(),
766 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).offset.set(v),
767 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).offset.get())),
768 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).offset.set(v.cast_or_default::<Vector>())),
769 )
770 })
771 }
772
773 pub fn offset(&self) -> Vector {
775 self.offset.get()
776 }
777
778 pub fn set_offset(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: Vector) {
779 self.offset.set(value);
780 host.remove_animation_for_property(Self::id_of_offset_property().base());
781 }
782
783 pub fn id_of_rotation_angle_property() -> &'static CompositionPropertyOf<f32> {
785 static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
786 PROPERTY.get_or_init(|| {
787 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, f32>(
788 "RotationAngle",
789 "ServerCompositionLinearGradientBrush",
790 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).rotation_angle.get(),
791 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).rotation_angle.set(v),
792 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).rotation_angle.get())),
793 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).rotation_angle.set(v.cast_or_default::<f32>())),
794 )
795 })
796 }
797
798 pub fn rotation_angle(&self) -> f32 {
800 self.rotation_angle.get()
801 }
802
803 pub fn set_rotation_angle(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: f32) {
804 self.rotation_angle.set(value);
805 host.remove_animation_for_property(Self::id_of_rotation_angle_property().base());
806 }
807
808 pub fn id_of_scale_property() -> &'static CompositionPropertyOf<Vector> {
810 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
811 PROPERTY.get_or_init(|| {
812 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, Vector>(
813 "Scale",
814 "ServerCompositionLinearGradientBrush",
815 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).scale.get(),
816 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).scale.set(v),
817 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).scale.get())),
818 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).scale.set(v.cast_or_default::<Vector>())),
819 )
820 })
821 }
822
823 pub fn scale(&self) -> Vector {
825 self.scale.get()
826 }
827
828 pub fn set_scale(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: Vector) {
829 self.scale.set(value);
830 host.remove_animation_for_property(Self::id_of_scale_property().base());
831 }
832
833 pub fn id_of_transform_matrix_property() -> &'static CompositionPropertyOf<Matrix> {
835 static PROPERTY: OnceLock<CompositionPropertyOf<Matrix>> = OnceLock::new();
836 PROPERTY.get_or_init(|| {
837 CompositionProperty::register::<ServerCompositionLinearGradientBrushProps, Matrix>(
838 "TransformMatrix",
839 "ServerCompositionLinearGradientBrush",
840 |obj| props_of::<ServerCompositionLinearGradientBrushProps>(obj).transform_matrix.get(),
841 |obj, v| props_of::<ServerCompositionLinearGradientBrushProps>(obj).transform_matrix.set(v),
842 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionLinearGradientBrushProps>(obj).transform_matrix.get())),
843 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionLinearGradientBrushProps>(obj).transform_matrix.set(v.cast_or_default::<Matrix>())),
844 )
845 })
846 }
847
848 pub fn transform_matrix(&self) -> Matrix {
850 self.transform_matrix.get()
851 }
852
853 pub fn set_transform_matrix(&self, host: &dyn ServerCompositionLinearGradientBrushHooks, value: Matrix) {
854 self.transform_matrix.set(value);
855 host.remove_animation_for_property(Self::id_of_transform_matrix_property().base());
856 }
857
858 pub fn deserialize_changes_core(
861 &self,
862 host: &dyn ServerCompositionLinearGradientBrushHooks,
863 reader: &mut BatchStreamReader<'_>,
864 committed_at: Duration,
865 ) {
866 ServerCompositionLinearGradientBrushHooks::base_deserialize_changes_core(host, reader, committed_at);
867 ServerCompositionLinearGradientBrushHooks::deserialize_changes_extra(host, reader);
868 let changed = reader.read::<CompositionLinearGradientBrushChangedFields>();
869 if changed.contains(CompositionLinearGradientBrushChangedFields::START_POINT_ANIMATED) {
870 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
871 panic!("a batch starts an animation of `StartPoint` without an animation instance");
872 };
873 host.set_animated_value(
874 Self::id_of_start_point_property().base(),
875 ExpressionVariant::create(self.start_point.get()),
876 committed_at,
877 animation,
878 );
879 } else if changed.contains(CompositionLinearGradientBrushChangedFields::START_POINT) {
880 let value = reader.read::<RelativePoint>();
881 self.set_start_point(host, value);
882 }
883 if changed.contains(CompositionLinearGradientBrushChangedFields::END_POINT_ANIMATED) {
884 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
885 panic!("a batch starts an animation of `EndPoint` without an animation instance");
886 };
887 host.set_animated_value(
888 Self::id_of_end_point_property().base(),
889 ExpressionVariant::create(self.end_point.get()),
890 committed_at,
891 animation,
892 );
893 } else if changed.contains(CompositionLinearGradientBrushChangedFields::END_POINT) {
894 let value = reader.read::<RelativePoint>();
895 self.set_end_point(host, value);
896 }
897 if changed.contains(CompositionLinearGradientBrushChangedFields::ANCHOR_POINT_ANIMATED) {
898 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
899 panic!("a batch starts an animation of `AnchorPoint` without an animation instance");
900 };
901 host.set_animated_value(
902 Self::id_of_anchor_point_property().base(),
903 ExpressionVariant::create(self.anchor_point.get()),
904 committed_at,
905 animation,
906 );
907 } else if changed.contains(CompositionLinearGradientBrushChangedFields::ANCHOR_POINT) {
908 let value = reader.read::<Vector>();
909 self.set_anchor_point(host, value);
910 }
911 if changed.contains(CompositionLinearGradientBrushChangedFields::CENTER_POINT_ANIMATED) {
912 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
913 panic!("a batch starts an animation of `CenterPoint` without an animation instance");
914 };
915 host.set_animated_value(
916 Self::id_of_center_point_property().base(),
917 ExpressionVariant::create(self.center_point.get()),
918 committed_at,
919 animation,
920 );
921 } else if changed.contains(CompositionLinearGradientBrushChangedFields::CENTER_POINT) {
922 let value = reader.read::<Vector>();
923 self.set_center_point(host, value);
924 }
925 if changed.contains(CompositionLinearGradientBrushChangedFields::OFFSET_ANIMATED) {
926 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
927 panic!("a batch starts an animation of `Offset` without an animation instance");
928 };
929 host.set_animated_value(
930 Self::id_of_offset_property().base(),
931 ExpressionVariant::create(self.offset.get()),
932 committed_at,
933 animation,
934 );
935 } else if changed.contains(CompositionLinearGradientBrushChangedFields::OFFSET) {
936 let value = reader.read::<Vector>();
937 self.set_offset(host, value);
938 }
939 if changed.contains(CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE_ANIMATED) {
940 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
941 panic!("a batch starts an animation of `RotationAngle` without an animation instance");
942 };
943 host.set_animated_value(
944 Self::id_of_rotation_angle_property().base(),
945 ExpressionVariant::create(self.rotation_angle.get()),
946 committed_at,
947 animation,
948 );
949 } else if changed.contains(CompositionLinearGradientBrushChangedFields::ROTATION_ANGLE) {
950 let value = reader.read::<f32>();
951 self.set_rotation_angle(host, value);
952 }
953 if changed.contains(CompositionLinearGradientBrushChangedFields::SCALE_ANIMATED) {
954 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
955 panic!("a batch starts an animation of `Scale` without an animation instance");
956 };
957 host.set_animated_value(
958 Self::id_of_scale_property().base(),
959 ExpressionVariant::create(self.scale.get()),
960 committed_at,
961 animation,
962 );
963 } else if changed.contains(CompositionLinearGradientBrushChangedFields::SCALE) {
964 let value = reader.read::<Vector>();
965 self.set_scale(host, value);
966 }
967 if changed.contains(CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX_ANIMATED) {
968 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
969 panic!("a batch starts an animation of `TransformMatrix` without an animation instance");
970 };
971 host.set_animated_value(
972 Self::id_of_transform_matrix_property().base(),
973 ExpressionVariant::create(self.transform_matrix.get()),
974 committed_at,
975 animation,
976 );
977 } else if changed.contains(CompositionLinearGradientBrushChangedFields::TRANSFORM_MATRIX) {
978 let value = reader.read::<Matrix>();
979 self.set_transform_matrix(host, value);
980 }
981 ServerCompositionLinearGradientBrushHooks::on_fields_deserialized(host, changed);
982 }
983
984 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
987 if name == "StartPoint" {
988 return Some(Self::id_of_start_point_property().base());
989 }
990 if name == "EndPoint" {
991 return Some(Self::id_of_end_point_property().base());
992 }
993 if name == "AnchorPoint" {
994 return Some(Self::id_of_anchor_point_property().base());
995 }
996 if name == "CenterPoint" {
997 return Some(Self::id_of_center_point_property().base());
998 }
999 if name == "Offset" {
1000 return Some(Self::id_of_offset_property().base());
1001 }
1002 if name == "RotationAngle" {
1003 return Some(Self::id_of_rotation_angle_property().base());
1004 }
1005 if name == "Scale" {
1006 return Some(Self::id_of_scale_property().base());
1007 }
1008 if name == "TransformMatrix" {
1009 return Some(Self::id_of_transform_matrix_property().base());
1010 }
1011 None
1012 }
1013}