1use std::{
2 borrow::Cow,
3 hash::{
4 Hash,
5 Hasher,
6 },
7};
8
9use paste::paste;
10use ragnarok::CursorPoint;
11use rustc_hash::FxHasher;
12use torin::{
13 content::Content,
14 gaps::Gaps,
15 prelude::{
16 Alignment,
17 Direction,
18 Length,
19 Position,
20 VisibleSize,
21 },
22 size::Size,
23};
24
25use crate::{
26 data::{
27 AccessibilityData,
28 EffectData,
29 LayoutData,
30 Overflow,
31 TextStyleData,
32 },
33 diff_key::DiffKey,
34 element::{
35 Element,
36 EventHandlerType,
37 EventHandlers,
38 },
39 elements::image::{
40 AspectRatio,
41 ImageCover,
42 ImageData,
43 SamplingMode,
44 },
45 event_handler::EventHandler,
46 events::{
47 data::{
48 Event,
49 KeyboardEventData,
50 MouseEventData,
51 SizedEventData,
52 StyledEventData,
53 VisibleEventData,
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 text_height::TextHeightBehavior,
67 text_overflow::TextOverflow,
68 text_shadow::TextShadow,
69 transform_origin::TransformOrigin,
70 },
71};
72
73pub trait ChildrenExt: Sized {
75 fn get_children(&mut self) -> &mut Vec<Element>;
86
87 fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self {
94 self.get_children()
95 .extend(children.into_iter().map(IntoElement::into_element));
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 {
126 fn write_key(&mut self) -> &mut DiffKey;
128
129 fn key(mut self, key: impl Hash) -> Self
133 where
134 Self: 'static,
135 {
136 let mut hasher = FxHasher::default();
137 std::any::TypeId::of::<Self>().hash(&mut hasher);
138 key.hash(&mut hasher);
139 *self.write_key() = DiffKey::U64(hasher.finish());
140 self
141 }
142}
143
144pub trait ListExt {
146 fn with(self, other: Self) -> Self;
148}
149
150impl<T> ListExt for Vec<T> {
151 fn with(mut self, other: Self) -> Self {
152 self.extend(other);
153 self
154 }
155}
156
157macro_rules! event_handlers {
158 (
159 $handler_variant:ident, $event_data:ty;
160 $(
161 $(#[$attr:meta])*
162 $name:ident => $event_variant:expr ;
163 )*
164 ) => {
165 paste! {
166 $(
167 $(#[$attr])*
168 fn [<on_$name>](mut self, [<on_$name>]: impl Into<EventHandler<Event<$event_data>>>) -> Self {
169 self.get_event_handlers()
170 .insert($event_variant, EventHandlerType::$handler_variant([<on_$name>].into()));
171 self
172 }
173 )*
174 }
175 };
176}
177
178pub trait EventHandlersExt: Sized {
186 fn get_event_handlers(&mut self) -> &mut EventHandlers;
188
189 fn event_handlers(mut self, event_handlers: EventHandlers) -> Self {
191 *self.get_event_handlers() = event_handlers;
192 self
193 }
194
195 event_handlers! {
196 Mouse,
197 MouseEventData;
198
199 mouse_down => EventName::MouseDown;
201 mouse_up => EventName::MouseUp;
203 mouse_move => EventName::MouseMove;
205
206 }
207
208 event_handlers! {
209 Pointer,
210 PointerEventData;
211
212 global_pointer_press => EventName::GlobalPointerPress;
214 global_pointer_down => EventName::GlobalPointerDown;
216 global_pointer_move => EventName::GlobalPointerMove;
218
219 capture_global_pointer_move => EventName::CaptureGlobalPointerMove;
221 capture_global_pointer_press => EventName::CaptureGlobalPointerPress;
223 }
224
225 event_handlers! {
226 Keyboard,
227 KeyboardEventData;
228
229 key_down => EventName::KeyDown;
231 key_up => EventName::KeyUp;
233
234 global_key_down => EventName::GlobalKeyDown;
236 global_key_up => EventName::GlobalKeyUp;
238 }
239
240 event_handlers! {
241 Wheel,
242 WheelEventData;
243
244 wheel => EventName::Wheel;
246 }
247
248 event_handlers! {
249 Touch,
250 TouchEventData;
251
252 touch_cancel => EventName::TouchCancel;
254 touch_start => EventName::TouchStart;
256 touch_move => EventName::TouchMove;
258 touch_end => EventName::TouchEnd;
260 }
261
262 event_handlers! {
263 Pointer,
264 PointerEventData;
265
266 pointer_press => EventName::PointerPress;
268 pointer_down => EventName::PointerDown;
270 pointer_move => EventName::PointerMove;
272 pointer_enter => EventName::PointerEnter;
274 pointer_leave => EventName::PointerLeave;
276 pointer_over => EventName::PointerOver;
278 pointer_out => EventName::PointerOut;
280 }
281
282 event_handlers! {
283 File,
284 FileEventData;
285
286 file_drop => EventName::FileDrop;
288 global_file_hover => EventName::GlobalFileHover;
290 global_file_hover_cancelled => EventName::GlobalFileHoverCancelled;
292 }
293
294 event_handlers! {
295 ImePreedit,
296 ImePreeditEventData;
297
298 ime_preedit => EventName::ImePreedit;
300 }
301
302 fn on_sized(mut self, on_sized: impl Into<EventHandler<Event<SizedEventData>>>) -> Self
304 where
305 Self: LayoutExt,
306 {
307 self.get_event_handlers()
308 .insert(EventName::Sized, EventHandlerType::Sized(on_sized.into()));
309 self.get_layout().layout.has_layout_references = true;
310 self
311 }
312
313 fn on_visible(mut self, on_visible: impl Into<EventHandler<Event<VisibleEventData>>>) -> Self {
315 self.get_event_handlers().insert(
316 EventName::Visible,
317 EventHandlerType::Visible(on_visible.into()),
318 );
319 self
320 }
321
322 fn on_hidden(mut self, on_hidden: impl Into<EventHandler<Event<VisibleEventData>>>) -> Self {
324 self.get_event_handlers().insert(
325 EventName::Hidden,
326 EventHandlerType::Visible(on_hidden.into()),
327 );
328 self
329 }
330
331 fn on_styled(mut self, on_styled: impl Into<EventHandler<Event<StyledEventData>>>) -> Self {
333 self.get_event_handlers().insert(
334 EventName::Styled,
335 EventHandlerType::Styled(on_styled.into()),
336 );
337 self
338 }
339
340 fn on_press(self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
347 let on_press = on_press.into();
348 self.on_pointer_press({
349 let on_press = on_press.clone();
350 move |e: Event<PointerEventData>| {
351 let event = e.try_map(|d| match d {
352 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
353 Some(PressEventData::Mouse(m))
354 }
355 PointerEventData::Touch(t) => Some(PressEventData::Touch(t)),
356 _ => None,
357 });
358 if let Some(event) = event {
359 on_press.call(event);
360 }
361 }
362 })
363 .on_key_down(move |e: Event<KeyboardEventData>| {
364 if e.is_press_event() {
365 on_press.call(e.map(PressEventData::Keyboard))
366 }
367 })
368 }
369
370 fn on_secondary_down(
374 self,
375 on_secondary_down: impl Into<EventHandler<Event<PressEventData>>>,
376 ) -> Self {
377 let on_secondary_down = on_secondary_down.into();
378 self.on_pointer_down(move |e: Event<PointerEventData>| {
379 let event = e.try_map(|d| match d {
380 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Right) => {
381 Some(PressEventData::Mouse(m))
382 }
383 _ => None,
384 });
385 if let Some(event) = event {
386 on_secondary_down.call(event);
387 }
388 })
389 }
390
391 fn on_all_press(self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
396 let on_press = on_press.into();
397 self.on_pointer_press({
398 let on_press = on_press.clone();
399 move |e: Event<PointerEventData>| {
400 let event = e.map(|d| match d {
401 PointerEventData::Mouse(m) => PressEventData::Mouse(m),
402 PointerEventData::Touch(t) => PressEventData::Touch(t),
403 });
404 on_press.call(event);
405 }
406 })
407 .on_key_down(move |e: Event<KeyboardEventData>| {
408 if e.is_press_event() {
409 on_press.call(e.map(PressEventData::Keyboard))
410 }
411 })
412 }
413 fn on_focus_press(
419 self,
420 on_focus_press: impl Into<EventHandler<Event<FocusPressEventData>>>,
421 ) -> Self {
422 let on_focus_press = on_focus_press.into();
423 if cfg!(target_os = "android") {
424 self.on_pointer_press(move |e: Event<PointerEventData>| {
425 let event = e.try_map(|d| match d {
426 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
427 Some(FocusPressEventData::Mouse(m))
428 }
429 PointerEventData::Touch(t) => Some(FocusPressEventData::Touch(t)),
430 _ => None,
431 });
432 if let Some(event) = event {
433 on_focus_press.call(event);
434 }
435 })
436 } else {
437 self.on_pointer_down(move |e: Event<PointerEventData>| {
438 let event = e.try_map(|d| match d {
439 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
440 Some(FocusPressEventData::Mouse(m))
441 }
442 PointerEventData::Touch(t) => Some(FocusPressEventData::Touch(t)),
443 _ => None,
444 });
445 if let Some(event) = event {
446 on_focus_press.call(event);
447 }
448 })
449 }
450 }
451}
452
453#[derive(Debug, Clone, PartialEq)]
455pub enum FocusPressEventData {
456 Mouse(MouseEventData),
457 Touch(TouchEventData),
458}
459
460impl FocusPressEventData {
461 pub fn global_location(&self) -> CursorPoint {
462 match self {
463 Self::Mouse(m) => m.global_location,
464 Self::Touch(t) => t.global_location,
465 }
466 }
467
468 pub fn element_location(&self) -> CursorPoint {
469 match self {
470 Self::Mouse(m) => m.element_location,
471 Self::Touch(t) => t.element_location,
472 }
473 }
474
475 pub fn button(&self) -> Option<MouseButton> {
476 match self {
477 Self::Mouse(m) => m.button,
478 Self::Touch(_) => None,
479 }
480 }
481}
482
483#[derive(Debug, Clone, PartialEq)]
485pub enum PressEventData {
486 Mouse(MouseEventData),
487 Keyboard(KeyboardEventData),
488 Touch(TouchEventData),
489}
490
491pub trait ContainerWithContentExt
493where
494 Self: LayoutExt,
495{
496 fn direction(mut self, direction: Direction) -> Self {
498 self.get_layout().layout.direction = direction;
499 self
500 }
501 fn main_align(mut self, main_align: impl Into<Alignment>) -> Self {
503 self.get_layout().layout.main_alignment = main_align.into();
504 self
505 }
506
507 fn cross_align(mut self, cross_align: impl Into<Alignment>) -> Self {
509 self.get_layout().layout.cross_alignment = cross_align.into();
510 self
511 }
512
513 fn spacing(mut self, spacing: f32) -> Self {
515 self.get_layout().layout.spacing = Length::new(spacing);
516 self
517 }
518
519 fn content(mut self, content: Content) -> Self {
521 self.get_layout().layout.content = content;
522 self
523 }
524 fn center(mut self) -> Self {
526 self.get_layout().layout.main_alignment = Alignment::Center;
527 self.get_layout().layout.cross_alignment = Alignment::Center;
528
529 self
530 }
531
532 fn offset_x(mut self, offset_x: f32) -> Self {
534 self.get_layout().layout.offset_x = Length::new(offset_x);
535 self
536 }
537
538 fn offset_y(mut self, offset_y: f32) -> Self {
540 self.get_layout().layout.offset_y = Length::new(offset_y);
541 self
542 }
543
544 fn vertical(mut self) -> Self {
546 self.get_layout().layout.direction = Direction::vertical();
547 self
548 }
549
550 fn horizontal(mut self) -> Self {
552 self.get_layout().layout.direction = Direction::horizontal();
553 self
554 }
555}
556
557pub trait ContainerSizeExt
559where
560 Self: LayoutExt,
561{
562 fn width(mut self, width: impl Into<Size>) -> Self {
564 self.get_layout().layout.width = width.into();
565 self
566 }
567
568 fn height(mut self, height: impl Into<Size>) -> Self {
570 self.get_layout().layout.height = height.into();
571 self
572 }
573
574 fn expanded(mut self) -> Self {
576 self.get_layout().layout.width = Size::fill();
577 self.get_layout().layout.height = Size::fill();
578 self
579 }
580}
581
582impl<T: ContainerExt> ContainerSizeExt for T {}
583
584pub trait ContainerPositionExt
586where
587 Self: LayoutExt,
588{
589 fn position(mut self, position: impl Into<Position>) -> Self {
591 self.get_layout().layout.position = position.into();
592 self
593 }
594
595 fn margin(mut self, margin: impl Into<Gaps>) -> Self {
597 self.get_layout().layout.margin = margin.into();
598 self
599 }
600}
601
602impl<T: ContainerExt> ContainerPositionExt for T {}
603
604pub trait ContainerExt
606where
607 Self: LayoutExt,
608{
609 fn padding(mut self, padding: impl Into<Gaps>) -> Self {
611 self.get_layout().layout.padding = padding.into();
612 self
613 }
614}
615
616pub trait ContainerConstraintsExt
618where
619 Self: LayoutExt,
620{
621 fn min_width(mut self, minimum_width: impl Into<Size>) -> Self {
623 self.get_layout().layout.minimum_width = minimum_width.into();
624 self
625 }
626
627 fn min_height(mut self, minimum_height: impl Into<Size>) -> Self {
629 self.get_layout().layout.minimum_height = minimum_height.into();
630 self
631 }
632
633 fn max_width(mut self, maximum_width: impl Into<Size>) -> Self {
635 self.get_layout().layout.maximum_width = maximum_width.into();
636 self
637 }
638
639 fn max_height(mut self, maximum_height: impl Into<Size>) -> Self {
641 self.get_layout().layout.maximum_height = maximum_height.into();
642 self
643 }
644
645 fn visible_width(mut self, visible_width: impl Into<VisibleSize>) -> Self {
647 self.get_layout().layout.visible_width = visible_width.into();
648 self
649 }
650
651 fn visible_height(mut self, visible_height: impl Into<VisibleSize>) -> Self {
653 self.get_layout().layout.visible_height = visible_height.into();
654 self
655 }
656}
657
658impl<T: ContainerExt> ContainerConstraintsExt for T {}
659
660pub trait LayoutExt
662where
663 Self: Sized,
664{
665 fn get_layout(&mut self) -> &mut LayoutData;
667
668 fn layout(mut self, layout: LayoutData) -> Self {
670 *self.get_layout() = layout;
671 self
672 }
673}
674
675pub trait ImageExt
677where
678 Self: LayoutExt,
679{
680 fn get_image_data(&mut self) -> &mut ImageData;
682
683 fn image_data(mut self, image_data: ImageData) -> Self {
685 *self.get_image_data() = image_data;
686 self
687 }
688
689 fn sampling_mode(mut self, sampling_mode: SamplingMode) -> Self {
691 self.get_image_data().sampling_mode = sampling_mode;
692 self
693 }
694
695 fn aspect_ratio(mut self, aspect_ratio: AspectRatio) -> Self {
697 self.get_image_data().aspect_ratio = aspect_ratio;
698 self
699 }
700
701 fn image_cover(mut self, image_cover: ImageCover) -> Self {
703 self.get_image_data().image_cover = image_cover;
704 self
705 }
706
707 fn snap_to_grid(mut self, snap_to_grid: bool) -> Self {
709 self.get_image_data().snap_to_grid = snap_to_grid;
710 self
711 }
712}
713
714pub trait AccessibilityExt: Sized {
716 fn get_accessibility_data(&mut self) -> &mut AccessibilityData;
718
719 fn accessibility(mut self, accessibility: AccessibilityData) -> Self {
721 *self.get_accessibility_data() = accessibility;
722 self
723 }
724
725 fn a11y_id(mut self, a11y_id: impl Into<Option<AccessibilityId>>) -> Self {
727 self.get_accessibility_data().a11y_id = a11y_id.into();
728 self
729 }
730
731 fn a11y_focusable(mut self, a11y_focusable: impl Into<Focusable>) -> Self {
733 self.get_accessibility_data().a11y_focusable = a11y_focusable.into();
734 self
735 }
736
737 fn a11y_auto_focus(mut self, a11y_auto_focus: impl Into<bool>) -> Self {
739 self.get_accessibility_data().a11y_auto_focus = a11y_auto_focus.into();
740 self
741 }
742
743 fn a11y_member_of(mut self, a11y_member_of: impl Into<AccessibilityId>) -> Self {
745 self.get_accessibility_data()
746 .builder
747 .set_member_of(a11y_member_of.into());
748 self
749 }
750
751 fn a11y_role(mut self, a11y_role: impl Into<AccessibilityRole>) -> Self {
753 self.get_accessibility_data()
754 .builder
755 .set_role(a11y_role.into());
756 self
757 }
758
759 fn a11y_alt(mut self, value: impl Into<Box<str>>) -> Self {
761 self.get_accessibility_data().builder.set_label(value);
762 self
763 }
764
765 fn a11y_builder(mut self, with: impl FnOnce(&mut accesskit::Node)) -> Self {
767 with(&mut self.get_accessibility_data().builder);
768 self
769 }
770}
771
772pub trait TextStyleExt
774where
775 Self: Sized,
776{
777 fn get_text_style_data(&mut self) -> &mut TextStyleData;
779
780 fn text_style(mut self, data: TextStyleData) -> Self {
782 *self.get_text_style_data() = data;
783 self
784 }
785
786 fn color(mut self, color: impl Into<Fill>) -> Self {
788 self.get_text_style_data().color = Some(color.into());
789 self
790 }
791
792 fn text_align(mut self, text_align: impl Into<TextAlign>) -> Self {
794 self.get_text_style_data().text_align = Some(text_align.into());
795 self
796 }
797
798 fn font_size(mut self, font_size: impl Into<FontSize>) -> Self {
800 self.get_text_style_data().font_size = Some(font_size.into());
801 self
802 }
803
804 fn font_family(mut self, font_family: impl Into<Cow<'static, str>>) -> Self {
806 self.get_text_style_data()
807 .font_families
808 .push(font_family.into());
809 self
810 }
811
812 fn font_slant(mut self, font_slant: impl Into<FontSlant>) -> Self {
814 self.get_text_style_data().font_slant = Some(font_slant.into());
815 self
816 }
817
818 fn font_weight(mut self, font_weight: impl Into<FontWeight>) -> Self {
820 self.get_text_style_data().font_weight = Some(font_weight.into());
821 self
822 }
823
824 fn font_width(mut self, font_width: impl Into<FontWidth>) -> Self {
826 self.get_text_style_data().font_width = Some(font_width.into());
827 self
828 }
829
830 fn text_height(mut self, text_height: impl Into<TextHeightBehavior>) -> Self {
832 self.get_text_style_data().text_height = Some(text_height.into());
833 self
834 }
835
836 fn text_overflow(mut self, text_overflow: impl Into<TextOverflow>) -> Self {
838 self.get_text_style_data().text_overflow = Some(text_overflow.into());
839 self
840 }
841
842 fn text_shadow(mut self, text_shadow: impl Into<TextShadow>) -> Self {
844 self.get_text_style_data()
845 .text_shadows
846 .push(text_shadow.into());
847 self
848 }
849
850 fn text_decoration(mut self, text_decoration: impl Into<TextDecoration>) -> Self {
852 self.get_text_style_data().text_decoration = Some(text_decoration.into());
853 self
854 }
855}
856
857pub trait StyleExt
859where
860 Self: Sized,
861{
862 fn get_style(&mut self) -> &mut StyleState;
864
865 fn style(mut self, style: StyleState) -> Self {
867 *self.get_style() = style;
868 self
869 }
870
871 fn background(mut self, background: impl Into<Fill>) -> Self {
873 self.get_style().background = background.into();
874 self
875 }
876
877 fn border(mut self, border: impl Into<Option<Border>>) -> Self {
879 if let Some(border) = border.into() {
880 self.get_style().borders.push(border);
881 }
882 self
883 }
884
885 fn shadow(mut self, shadow: impl Into<Shadow>) -> Self {
887 self.get_style().shadows.push(shadow.into());
888 self
889 }
890
891 fn corner_radius(mut self, corner_radius: impl Into<CornerRadius>) -> Self {
893 self.get_style().corner_radius = corner_radius.into();
894 self
895 }
896
897 fn cursor(mut self, cursor: impl Into<Option<CursorIcon>>) -> Self {
902 self.get_style().cursor = cursor.into();
903 self
904 }
905}
906
907impl<T: StyleExt> CornerRadiusExt for T {
908 fn with_corner_radius(mut self, corner_radius: f32) -> Self {
909 self.get_style().corner_radius = CornerRadius::new_all(corner_radius);
910 self
911 }
912}
913
914pub trait CornerRadiusExt: Sized {
916 fn with_corner_radius(self, corner_radius: f32) -> Self;
918
919 fn rounded_none(self) -> Self {
921 self.with_corner_radius(0.)
922 }
923
924 fn rounded(self) -> Self {
926 self.with_corner_radius(6.)
927 }
928
929 fn rounded_sm(self) -> Self {
931 self.with_corner_radius(4.)
932 }
933
934 fn rounded_md(self) -> Self {
936 self.with_corner_radius(6.)
937 }
938
939 fn rounded_lg(self) -> Self {
941 self.with_corner_radius(8.)
942 }
943
944 fn rounded_xl(self) -> Self {
946 self.with_corner_radius(12.)
947 }
948
949 fn rounded_2xl(self) -> Self {
951 self.with_corner_radius(16.)
952 }
953
954 fn rounded_3xl(self) -> Self {
956 self.with_corner_radius(24.)
957 }
958
959 fn rounded_4xl(self) -> Self {
961 self.with_corner_radius(32.)
962 }
963
964 fn rounded_full(self) -> Self {
966 self.with_corner_radius(99.)
967 }
968}
969
970pub trait MaybeExt
972where
973 Self: Sized,
974{
975 fn maybe(self, bool: impl Into<bool>, then: impl FnOnce(Self) -> Self) -> Self {
977 if bool.into() { then(self) } else { self }
978 }
979
980 fn map<T>(self, data: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self {
982 if let Some(data) = data {
983 then(self, data)
984 } else {
985 self
986 }
987 }
988}
989
990pub trait LayerExt
992where
993 Self: Sized,
994{
995 fn get_layer(&mut self) -> &mut Layer;
997
998 fn layer(mut self, layer: impl Into<Layer>) -> Self {
1000 *self.get_layer() = layer.into();
1001 self
1002 }
1003}
1004
1005pub trait ScrollableExt
1006where
1007 Self: Sized,
1008{
1009 fn get_effect(&mut self) -> &mut EffectData;
1011
1012 fn scrollable(mut self, scrollable: impl Into<bool>) -> Self {
1015 self.get_effect().scrollable = scrollable.into();
1016 self
1017 }
1018}
1019
1020pub trait InteractiveExt
1022where
1023 Self: Sized,
1024{
1025 fn get_effect(&mut self) -> &mut EffectData;
1027
1028 fn interactive(mut self, interactive: impl Into<Interactive>) -> Self {
1030 self.get_effect().interactive = interactive.into();
1031 self
1032 }
1033}
1034
1035pub trait EffectExt: Sized {
1037 fn get_effect(&mut self) -> &mut EffectData;
1039
1040 fn effect(mut self, effect: EffectData) -> Self {
1042 *self.get_effect() = effect;
1043 self
1044 }
1045
1046 fn overflow(mut self, overflow: impl Into<Overflow>) -> Self {
1048 self.get_effect().overflow = overflow.into();
1049 self
1050 }
1051
1052 fn blur(mut self, blur: f32) -> Self {
1054 self.get_effect().blur = Some(blur);
1055 self
1056 }
1057
1058 fn rotation(mut self, rotation: f32) -> Self {
1060 self.get_effect().rotation = Some(rotation);
1061 self
1062 }
1063
1064 fn opacity(mut self, opacity: f32) -> Self {
1066 self.get_effect().opacity = Some(opacity);
1067 self
1068 }
1069
1070 fn scale(mut self, scale: impl Into<Scale>) -> Self {
1072 self.get_effect().scale = Some(scale.into());
1073 self
1074 }
1075
1076 fn transform_origin(mut self, transform_origin: impl Into<TransformOrigin>) -> Self {
1080 self.get_effect().transform_origin = transform_origin.into();
1081 self
1082 }
1083}