1use std::{
2 borrow::Cow,
3 hash::{
4 Hash,
5 Hasher,
6 },
7};
8
9use paste::paste;
10use ragnarok::CursorPoint;
11use rustc_hash::{
12 FxHashMap,
13 FxHasher,
14};
15use torin::{
16 content::Content,
17 gaps::Gaps,
18 prelude::{
19 Alignment,
20 Direction,
21 Length,
22 Position,
23 VisibleSize,
24 },
25 size::Size,
26};
27
28use crate::{
29 data::{
30 AccessibilityData,
31 EffectData,
32 LayoutData,
33 Overflow,
34 TextStyleData,
35 },
36 diff_key::DiffKey,
37 element::{
38 Element,
39 EventHandlerType,
40 },
41 elements::image::{
42 AspectRatio,
43 ImageCover,
44 ImageData,
45 SamplingMode,
46 },
47 event_handler::EventHandler,
48 events::{
49 data::{
50 Event,
51 KeyboardEventData,
52 MouseEventData,
53 SizedEventData,
54 WheelEventData,
55 },
56 name::EventName,
57 },
58 layers::Layer,
59 prelude::*,
60 style::{
61 font_size::FontSize,
62 font_slant::FontSlant,
63 font_weight::FontWeight,
64 font_width::FontWidth,
65 scale::Scale,
66 shader::ShaderFill,
67 text_height::TextHeightBehavior,
68 text_overflow::TextOverflow,
69 text_shadow::TextShadow,
70 transform_origin::TransformOrigin,
71 },
72};
73
74pub trait ChildrenExt: Sized {
76 fn get_children(&mut self) -> &mut Vec<Element>;
87
88 fn children(mut self, children: impl IntoIterator<Item = Element>) -> Self {
95 self.get_children().extend(children);
96 self
97 }
98
99 fn maybe_child<C: IntoElement>(mut self, child: Option<C>) -> Self {
106 if let Some(child) = child {
107 self.get_children().push(child.into_element());
108 }
109 self
110 }
111
112 fn child<C: IntoElement>(mut self, child: C) -> Self {
119 self.get_children().push(child.into_element());
120 self
121 }
122}
123
124pub trait KeyExt: Sized {
125 fn write_key(&mut self) -> &mut DiffKey;
126
127 fn key(mut self, key: impl Hash) -> Self {
128 let mut hasher = FxHasher::default();
129 key.hash(&mut hasher);
130 *self.write_key() = DiffKey::U64(hasher.finish());
131 self
132 }
133}
134
135pub trait ListExt {
136 fn with(self, other: Self) -> Self;
137}
138
139impl<T> ListExt for Vec<T> {
140 fn with(mut self, other: Self) -> Self {
141 self.extend(other);
142 self
143 }
144}
145
146macro_rules! event_handlers {
147 (
148 $handler_variant:ident, $event_data:ty;
149 $(
150 $name:ident => $event_variant:expr ;
151 )*
152 ) => {
153 paste! {
154 $(
155 fn [<on_$name>](mut self, [<on_$name>]: impl Into<EventHandler<Event<$event_data>>>) -> Self {
156 self.get_event_handlers()
157 .insert($event_variant, EventHandlerType::$handler_variant([<on_$name>].into()));
158 self
159 }
160 )*
161 }
162 };
163}
164
165pub trait EventHandlersExt: Sized {
166 fn get_event_handlers(&mut self) -> &mut FxHashMap<EventName, EventHandlerType>;
167
168 fn with_event_handlers(
169 mut self,
170 event_handlers: FxHashMap<EventName, EventHandlerType>,
171 ) -> Self {
172 *self.get_event_handlers() = event_handlers;
173 self
174 }
175
176 event_handlers! {
177 Mouse,
178 MouseEventData;
179
180 mouse_down => EventName::MouseDown;
181 mouse_up => EventName::MouseUp;
182 mouse_move => EventName::MouseMove;
183
184 }
185
186 event_handlers! {
187 Pointer,
188 PointerEventData;
189
190 global_pointer_press => EventName::GlobalPointerPress;
191 global_pointer_down => EventName::GlobalPointerDown;
192 global_pointer_move => EventName::GlobalPointerMove;
193
194 capture_global_pointer_move => EventName::CaptureGlobalPointerMove;
195 capture_global_pointer_press => EventName::CaptureGlobalPointerPress;
196 }
197
198 event_handlers! {
199 Keyboard,
200 KeyboardEventData;
201
202 key_down => EventName::KeyDown;
203 key_up => EventName::KeyUp;
204
205 global_key_down => EventName::GlobalKeyDown;
206 global_key_up => EventName::GlobalKeyUp;
207 }
208
209 event_handlers! {
210 Wheel,
211 WheelEventData;
212
213 wheel => EventName::Wheel;
214 }
215
216 event_handlers! {
217 Touch,
218 TouchEventData;
219
220 touch_cancel => EventName::TouchCancel;
221 touch_start => EventName::TouchStart;
222 touch_move => EventName::TouchMove;
223 touch_end => EventName::TouchEnd;
224 }
225
226 event_handlers! {
227 Pointer,
228 PointerEventData;
229
230 pointer_press => EventName::PointerPress;
231 pointer_down => EventName::PointerDown;
232 pointer_move => EventName::PointerMove;
233 pointer_enter => EventName::PointerEnter;
234 pointer_leave => EventName::PointerLeave;
235 pointer_over => EventName::PointerOver;
236 pointer_out => EventName::PointerOut;
237 }
238
239 event_handlers! {
240 File,
241 FileEventData;
242
243 file_drop => EventName::FileDrop;
244 global_file_hover => EventName::GlobalFileHover;
245 global_file_hover_cancelled => EventName::GlobalFileHoverCancelled;
246 }
247
248 event_handlers! {
249 ImePreedit,
250 ImePreeditEventData;
251
252 ime_preedit => EventName::ImePreedit;
253 }
254
255 fn on_sized(mut self, on_sized: impl Into<EventHandler<Event<SizedEventData>>>) -> Self
256 where
257 Self: LayoutExt,
258 {
259 self.get_event_handlers()
260 .insert(EventName::Sized, EventHandlerType::Sized(on_sized.into()));
261 self.get_layout().layout.has_layout_references = true;
262 self
263 }
264
265 fn on_press(self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
272 let on_press = on_press.into();
273 self.on_pointer_press({
274 let on_press = on_press.clone();
275 move |e: Event<PointerEventData>| {
276 let event = e.try_map(|d| match d {
277 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
278 Some(PressEventData::Mouse(m))
279 }
280 PointerEventData::Touch(t) => Some(PressEventData::Touch(t)),
281 _ => None,
282 });
283 if let Some(event) = event {
284 on_press.call(event);
285 }
286 }
287 })
288 .on_key_down(move |e: Event<KeyboardEventData>| {
289 if e.is_press_event() {
290 on_press.call(e.map(PressEventData::Keyboard))
291 }
292 })
293 }
294
295 fn on_secondary_down(
299 self,
300 on_secondary_down: impl Into<EventHandler<Event<PressEventData>>>,
301 ) -> Self {
302 let on_secondary_down = on_secondary_down.into();
303 self.on_pointer_down(move |e: Event<PointerEventData>| {
304 let event = e.try_map(|d| match d {
305 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Right) => {
306 Some(PressEventData::Mouse(m))
307 }
308 _ => None,
309 });
310 if let Some(event) = event {
311 on_secondary_down.call(event);
312 }
313 })
314 }
315
316 fn on_all_press(self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
321 let on_press = on_press.into();
322 self.on_pointer_press({
323 let on_press = on_press.clone();
324 move |e: Event<PointerEventData>| {
325 let event = e.map(|d| match d {
326 PointerEventData::Mouse(m) => PressEventData::Mouse(m),
327 PointerEventData::Touch(t) => PressEventData::Touch(t),
328 });
329 on_press.call(event);
330 }
331 })
332 .on_key_down(move |e: Event<KeyboardEventData>| {
333 if e.is_press_event() {
334 on_press.call(e.map(PressEventData::Keyboard))
335 }
336 })
337 }
338 fn on_focus_press(
344 self,
345 on_focus_press: impl Into<EventHandler<Event<FocusPressEventData>>>,
346 ) -> Self {
347 let on_focus_press = on_focus_press.into();
348 if cfg!(target_os = "android") {
349 self.on_pointer_press(move |e: Event<PointerEventData>| {
350 let event = e.try_map(|d| match d {
351 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
352 Some(FocusPressEventData::Mouse(m))
353 }
354 PointerEventData::Touch(t) => Some(FocusPressEventData::Touch(t)),
355 _ => None,
356 });
357 if let Some(event) = event {
358 on_focus_press.call(event);
359 }
360 })
361 } else {
362 self.on_pointer_down(move |e: Event<PointerEventData>| {
363 let event = e.try_map(|d| match d {
364 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
365 Some(FocusPressEventData::Mouse(m))
366 }
367 PointerEventData::Touch(t) => Some(FocusPressEventData::Touch(t)),
368 _ => None,
369 });
370 if let Some(event) = event {
371 on_focus_press.call(event);
372 }
373 })
374 }
375 }
376}
377
378#[derive(Debug, Clone, PartialEq)]
379pub enum FocusPressEventData {
380 Mouse(MouseEventData),
381 Touch(TouchEventData),
382}
383
384impl FocusPressEventData {
385 pub fn global_location(&self) -> CursorPoint {
386 match self {
387 Self::Mouse(m) => m.global_location,
388 Self::Touch(t) => t.global_location,
389 }
390 }
391
392 pub fn element_location(&self) -> CursorPoint {
393 match self {
394 Self::Mouse(m) => m.element_location,
395 Self::Touch(t) => t.element_location,
396 }
397 }
398
399 pub fn button(&self) -> Option<MouseButton> {
400 match self {
401 Self::Mouse(m) => m.button,
402 Self::Touch(_) => None,
403 }
404 }
405}
406
407#[derive(Debug, Clone, PartialEq)]
408pub enum PressEventData {
409 Mouse(MouseEventData),
410 Keyboard(KeyboardEventData),
411 Touch(TouchEventData),
412}
413
414pub trait ContainerWithContentExt
415where
416 Self: LayoutExt,
417{
418 fn direction(mut self, direction: Direction) -> Self {
419 self.get_layout().layout.direction = direction;
420 self
421 }
422 fn main_align(mut self, main_align: Alignment) -> Self {
423 self.get_layout().layout.main_alignment = main_align;
424 self
425 }
426
427 fn cross_align(mut self, cross_align: Alignment) -> Self {
428 self.get_layout().layout.cross_alignment = cross_align;
429 self
430 }
431
432 fn spacing(mut self, spacing: impl Into<f32>) -> Self {
433 self.get_layout().layout.spacing = Length::new(spacing.into());
434 self
435 }
436
437 fn content(mut self, content: Content) -> Self {
438 self.get_layout().layout.content = content;
439 self
440 }
441 fn center(mut self) -> Self {
442 self.get_layout().layout.main_alignment = Alignment::Center;
443 self.get_layout().layout.cross_alignment = Alignment::Center;
444
445 self
446 }
447
448 fn offset_x(mut self, offset_x: impl Into<f32>) -> Self {
449 self.get_layout().layout.offset_x = Length::new(offset_x.into());
450 self
451 }
452
453 fn offset_y(mut self, offset_y: impl Into<f32>) -> Self {
454 self.get_layout().layout.offset_y = Length::new(offset_y.into());
455 self
456 }
457
458 fn vertical(mut self) -> Self {
459 self.get_layout().layout.direction = Direction::vertical();
460 self
461 }
462
463 fn horizontal(mut self) -> Self {
464 self.get_layout().layout.direction = Direction::horizontal();
465 self
466 }
467}
468
469pub trait ContainerSizeExt
470where
471 Self: LayoutExt,
472{
473 fn width(mut self, width: impl Into<Size>) -> Self {
474 self.get_layout().layout.width = width.into();
475 self
476 }
477
478 fn height(mut self, height: impl Into<Size>) -> Self {
479 self.get_layout().layout.height = height.into();
480 self
481 }
482
483 fn expanded(mut self) -> Self {
485 self.get_layout().layout.width = Size::fill();
486 self.get_layout().layout.height = Size::fill();
487 self
488 }
489}
490
491impl<T: ContainerExt> ContainerSizeExt for T {}
492
493pub trait ContainerExt
494where
495 Self: LayoutExt,
496{
497 fn position(mut self, position: impl Into<Position>) -> Self {
498 self.get_layout().layout.position = position.into();
499 self
500 }
501
502 fn padding(mut self, padding: impl Into<Gaps>) -> Self {
503 self.get_layout().layout.padding = padding.into();
504 self
505 }
506
507 fn margin(mut self, margin: impl Into<Gaps>) -> Self {
508 self.get_layout().layout.margin = margin.into();
509 self
510 }
511
512 fn min_width(mut self, minimum_width: impl Into<Size>) -> Self {
513 self.get_layout().layout.minimum_width = minimum_width.into();
514 self
515 }
516
517 fn min_height(mut self, minimum_height: impl Into<Size>) -> Self {
518 self.get_layout().layout.minimum_height = minimum_height.into();
519 self
520 }
521
522 fn max_width(mut self, maximum_width: impl Into<Size>) -> Self {
523 self.get_layout().layout.maximum_width = maximum_width.into();
524 self
525 }
526
527 fn max_height(mut self, maximum_height: impl Into<Size>) -> Self {
528 self.get_layout().layout.maximum_height = maximum_height.into();
529 self
530 }
531
532 fn visible_width(mut self, visible_width: impl Into<VisibleSize>) -> Self {
533 self.get_layout().layout.visible_width = visible_width.into();
534 self
535 }
536
537 fn visible_height(mut self, visible_height: impl Into<VisibleSize>) -> Self {
538 self.get_layout().layout.visible_height = visible_height.into();
539 self
540 }
541}
542
543pub trait LayoutExt
544where
545 Self: Sized,
546{
547 fn get_layout(&mut self) -> &mut LayoutData;
548
549 fn layout(mut self, layout: LayoutData) -> Self {
550 *self.get_layout() = layout;
551 self
552 }
553}
554
555pub trait ImageExt
556where
557 Self: LayoutExt,
558{
559 fn get_image_data(&mut self) -> &mut ImageData;
560
561 fn image_data(mut self, image_data: ImageData) -> Self {
562 *self.get_image_data() = image_data;
563 self
564 }
565
566 fn sampling_mode(mut self, sampling_mode: SamplingMode) -> Self {
567 self.get_image_data().sampling_mode = sampling_mode;
568 self
569 }
570
571 fn aspect_ratio(mut self, aspect_ratio: AspectRatio) -> Self {
572 self.get_image_data().aspect_ratio = aspect_ratio;
573 self
574 }
575
576 fn image_cover(mut self, image_cover: ImageCover) -> Self {
577 self.get_image_data().image_cover = image_cover;
578 self
579 }
580}
581
582pub trait AccessibilityExt: Sized {
583 fn get_accessibility_data(&mut self) -> &mut AccessibilityData;
584
585 fn accessibility(mut self, accessibility: AccessibilityData) -> Self {
586 *self.get_accessibility_data() = accessibility;
587 self
588 }
589
590 fn a11y_id(mut self, a11y_id: impl Into<Option<AccessibilityId>>) -> Self {
591 self.get_accessibility_data().a11y_id = a11y_id.into();
592 self
593 }
594
595 fn a11y_focusable(mut self, a11y_focusable: impl Into<Focusable>) -> Self {
596 self.get_accessibility_data().a11y_focusable = a11y_focusable.into();
597 self
598 }
599
600 fn a11y_auto_focus(mut self, a11y_auto_focus: impl Into<bool>) -> Self {
601 self.get_accessibility_data().a11y_auto_focus = a11y_auto_focus.into();
602 self
603 }
604
605 fn a11y_member_of(mut self, a11y_member_of: impl Into<AccessibilityId>) -> Self {
606 self.get_accessibility_data()
607 .builder
608 .set_member_of(a11y_member_of.into());
609 self
610 }
611
612 fn a11y_role(mut self, a11y_role: impl Into<AccessibilityRole>) -> Self {
613 self.get_accessibility_data()
614 .builder
615 .set_role(a11y_role.into());
616 self
617 }
618
619 fn a11y_alt(mut self, value: impl Into<Box<str>>) -> Self {
620 self.get_accessibility_data().builder.set_label(value);
621 self
622 }
623
624 fn a11y_builder(mut self, with: impl FnOnce(&mut accesskit::Node)) -> Self {
625 with(&mut self.get_accessibility_data().builder);
626 self
627 }
628}
629
630pub trait TextStyleExt
631where
632 Self: Sized,
633{
634 fn get_text_style_data(&mut self) -> &mut TextStyleData;
635
636 fn text_style(mut self, data: TextStyleData) -> Self {
637 *self.get_text_style_data() = data;
638 self
639 }
640
641 fn color(mut self, color: impl Into<Color>) -> Self {
642 self.get_text_style_data().color = Some(Fill::Color(color.into()));
643 self
644 }
645
646 fn color_conic_gradient<S: Into<ConicGradient>>(mut self, color: S) -> Self {
647 self.get_text_style_data().color = Some(Fill::ConicGradient(Box::new(color.into())));
648 self
649 }
650
651 fn color_linear_gradient<S: Into<LinearGradient>>(mut self, color: S) -> Self {
652 self.get_text_style_data().color = Some(Fill::LinearGradient(Box::new(color.into())));
653 self
654 }
655
656 fn color_radial_gradient<S: Into<RadialGradient>>(mut self, color: S) -> Self {
657 self.get_text_style_data().color = Some(Fill::RadialGradient(Box::new(color.into())));
658 self
659 }
660
661 fn color_shader(mut self, color: impl Into<ShaderFill>) -> Self {
662 self.get_text_style_data().color = Some(Fill::Shader(Box::new(color.into())));
663 self
664 }
665
666 fn text_align(mut self, text_align: impl Into<TextAlign>) -> Self {
667 self.get_text_style_data().text_align = Some(text_align.into());
668 self
669 }
670
671 fn font_size(mut self, font_size: impl Into<FontSize>) -> Self {
672 self.get_text_style_data().font_size = Some(font_size.into());
673 self
674 }
675
676 fn font_family(mut self, font_family: impl Into<Cow<'static, str>>) -> Self {
677 self.get_text_style_data()
678 .font_families
679 .push(font_family.into());
680 self
681 }
682
683 fn font_slant(mut self, font_slant: impl Into<FontSlant>) -> Self {
684 self.get_text_style_data().font_slant = Some(font_slant.into());
685 self
686 }
687
688 fn font_weight(mut self, font_weight: impl Into<FontWeight>) -> Self {
689 self.get_text_style_data().font_weight = Some(font_weight.into());
690 self
691 }
692
693 fn font_width(mut self, font_width: impl Into<FontWidth>) -> Self {
694 self.get_text_style_data().font_width = Some(font_width.into());
695 self
696 }
697
698 fn text_height(mut self, text_height: impl Into<TextHeightBehavior>) -> Self {
699 self.get_text_style_data().text_height = Some(text_height.into());
700 self
701 }
702
703 fn text_overflow(mut self, text_overflow: impl Into<TextOverflow>) -> Self {
704 self.get_text_style_data().text_overflow = Some(text_overflow.into());
705 self
706 }
707
708 fn text_shadow(mut self, text_shadow: impl Into<TextShadow>) -> Self {
709 self.get_text_style_data()
710 .text_shadows
711 .push(text_shadow.into());
712 self
713 }
714
715 fn text_decoration(mut self, text_decoration: impl Into<TextDecoration>) -> Self {
716 self.get_text_style_data().text_decoration = Some(text_decoration.into());
717 self
718 }
719}
720
721pub trait StyleExt
722where
723 Self: Sized,
724{
725 fn get_style(&mut self) -> &mut StyleState;
726
727 fn background<S: Into<Color>>(mut self, background: S) -> Self {
728 self.get_style().background = Fill::Color(background.into());
729 self
730 }
731
732 fn background_conic_gradient<S: Into<ConicGradient>>(mut self, background: S) -> Self {
733 self.get_style().background = Fill::ConicGradient(Box::new(background.into()));
734 self
735 }
736
737 fn background_linear_gradient<S: Into<LinearGradient>>(mut self, background: S) -> Self {
738 self.get_style().background = Fill::LinearGradient(Box::new(background.into()));
739 self
740 }
741
742 fn background_radial_gradient<S: Into<RadialGradient>>(mut self, background: S) -> Self {
743 self.get_style().background = Fill::RadialGradient(Box::new(background.into()));
744 self
745 }
746
747 fn background_shader(mut self, background: impl Into<ShaderFill>) -> Self {
748 self.get_style().background = Fill::Shader(Box::new(background.into()));
749 self
750 }
751
752 fn border(mut self, border: impl Into<Option<Border>>) -> Self {
753 if let Some(border) = border.into() {
754 self.get_style().borders.push(border);
755 }
756 self
757 }
758
759 fn shadow(mut self, shadow: impl Into<Shadow>) -> Self {
760 self.get_style().shadows.push(shadow.into());
761 self
762 }
763
764 fn corner_radius(mut self, corner_radius: impl Into<CornerRadius>) -> Self {
765 self.get_style().corner_radius = corner_radius.into();
766 self
767 }
768}
769
770impl<T: StyleExt> CornerRadiusExt for T {
771 fn with_corner_radius(mut self, corner_radius: f32) -> Self {
772 self.get_style().corner_radius = CornerRadius::new_all(corner_radius);
773 self
774 }
775}
776
777pub trait CornerRadiusExt: Sized {
778 fn with_corner_radius(self, corner_radius: f32) -> Self;
779
780 fn rounded_none(self) -> Self {
782 self.with_corner_radius(0.)
783 }
784
785 fn rounded(self) -> Self {
787 self.with_corner_radius(6.)
788 }
789
790 fn rounded_sm(self) -> Self {
792 self.with_corner_radius(4.)
793 }
794
795 fn rounded_md(self) -> Self {
797 self.with_corner_radius(6.)
798 }
799
800 fn rounded_lg(self) -> Self {
802 self.with_corner_radius(8.)
803 }
804
805 fn rounded_xl(self) -> Self {
807 self.with_corner_radius(12.)
808 }
809
810 fn rounded_2xl(self) -> Self {
812 self.with_corner_radius(16.)
813 }
814
815 fn rounded_3xl(self) -> Self {
817 self.with_corner_radius(24.)
818 }
819
820 fn rounded_4xl(self) -> Self {
822 self.with_corner_radius(32.)
823 }
824
825 fn rounded_full(self) -> Self {
827 self.with_corner_radius(99.)
828 }
829}
830
831pub trait MaybeExt
832where
833 Self: Sized,
834{
835 fn maybe(self, bool: impl Into<bool>, then: impl FnOnce(Self) -> Self) -> Self {
836 if bool.into() { then(self) } else { self }
837 }
838
839 fn map<T>(self, data: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self {
840 if let Some(data) = data {
841 then(self, data)
842 } else {
843 self
844 }
845 }
846}
847
848pub trait LayerExt
849where
850 Self: Sized,
851{
852 fn get_layer(&mut self) -> &mut Layer;
853
854 fn layer(mut self, layer: impl Into<Layer>) -> Self {
855 *self.get_layer() = layer.into();
856 self
857 }
858}
859
860pub trait ScrollableExt
861where
862 Self: Sized,
863{
864 fn get_effect(&mut self) -> &mut EffectData;
865
866 fn scrollable(mut self, scrollable: impl Into<bool>) -> Self {
869 self.get_effect().scrollable = scrollable.into();
870 self
871 }
872}
873
874pub trait InteractiveExt
875where
876 Self: Sized,
877{
878 fn get_effect(&mut self) -> &mut EffectData;
879
880 fn interactive(mut self, interactive: impl Into<Interactive>) -> Self {
881 self.get_effect().interactive = interactive.into();
882 self
883 }
884}
885
886pub trait EffectExt: Sized {
887 fn get_effect(&mut self) -> &mut EffectData;
888
889 fn effect(mut self, effect: EffectData) -> Self {
890 *self.get_effect() = effect;
891 self
892 }
893
894 fn overflow(mut self, overflow: impl Into<Overflow>) -> Self {
895 self.get_effect().overflow = overflow.into();
896 self
897 }
898
899 fn blur(mut self, blur: impl Into<f32>) -> Self {
900 self.get_effect().blur = Some(blur.into());
901 self
902 }
903
904 fn rotation(mut self, rotation: impl Into<f32>) -> Self {
905 self.get_effect().rotation = Some(rotation.into());
906 self
907 }
908
909 fn opacity(mut self, opacity: impl Into<f32>) -> Self {
910 self.get_effect().opacity = Some(opacity.into());
911 self
912 }
913
914 fn scale(mut self, scale: impl Into<Scale>) -> Self {
915 self.get_effect().scale = Some(scale.into());
916 self
917 }
918
919 fn transform_origin(mut self, transform_origin: impl Into<TransformOrigin>) -> Self {
923 self.get_effect().transform_origin = transform_origin.into();
924 self
925 }
926}