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