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::{
40 image::{
41 AspectRatio,
42 Image,
43 ImageCover,
44 ImageData,
45 SamplingMode,
46 },
47 label::Label,
48 paragraph::Paragraph,
49 rect::Rect,
50 },
51 event_handler::EventHandler,
52 events::{
53 data::{
54 Event,
55 KeyboardEventData,
56 MouseEventData,
57 SizedEventData,
58 StyledEventData,
59 VisibleEventData,
60 WheelEventData,
61 },
62 name::EventName,
63 },
64 layers::Layer,
65 prelude::*,
66 style::{
67 font_feature::FontFeature,
68 font_size::FontSize,
69 font_slant::FontSlant,
70 font_weight::FontWeight,
71 font_width::FontWidth,
72 letter_spacing::LetterSpacing,
73 scale::Scale,
74 text_height::TextHeightBehavior,
75 text_overflow::TextOverflow,
76 text_shadow::TextShadow,
77 transform_origin::TransformOrigin,
78 },
79};
80
81pub trait ChildrenExt: Sized {
83 fn children_mut(&mut self) -> &mut Vec<Element>;
94
95 fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self {
102 self.children_mut()
103 .extend(children.into_iter().map(IntoElement::into_element));
104 self
105 }
106
107 fn maybe_child<C: IntoElement>(mut self, child: Option<C>) -> Self {
114 if let Some(child) = child {
115 self.children_mut().push(child.into_element());
116 }
117 self
118 }
119
120 fn child<C: IntoElement>(mut self, child: C) -> Self {
127 self.children_mut().push(child.into_element());
128 self
129 }
130}
131
132pub trait KeyExt: Sized {
134 fn key_mut(&mut self) -> &mut DiffKey;
136
137 fn key(mut self, key: impl Hash) -> Self
141 where
142 Self: 'static,
143 {
144 let mut hasher = FxHasher::default();
145 std::any::TypeId::of::<Self>().hash(&mut hasher);
146 key.hash(&mut hasher);
147 *self.key_mut() = DiffKey::U64(hasher.finish());
148 self
149 }
150}
151
152pub trait WithExt: Sized {
154 fn with(self, with: impl FnOnce(Self) -> Self) -> Self {
156 with(self)
157 }
158}
159
160impl WithExt for Rect {}
161impl WithExt for Label {}
162impl WithExt for Paragraph {}
163impl WithExt for Image {}
164
165macro_rules! event_handlers {
166 (
167 $handler_variant:ident, $event_data:ty;
168 $(
169 $(#[$attr:meta])*
170 $name:ident => $event_variant:expr ;
171 )*
172 ) => {
173 paste! {
174 $(
175 $(#[$attr])*
176 fn [<on_$name>](mut self, [<on_$name>]: impl Into<EventHandler<Event<$event_data>>>) -> Self {
177 self.event_handlers_mut()
178 .insert($event_variant, EventHandlerType::$handler_variant([<on_$name>].into()));
179 self
180 }
181 )*
182 }
183 };
184}
185
186pub trait EventHandlersExt: Sized {
194 fn event_handlers_mut(&mut self) -> &mut EventHandlers;
196
197 fn event_handlers(mut self, event_handlers: EventHandlers) -> Self {
199 *self.event_handlers_mut() = event_handlers;
200 self
201 }
202
203 event_handlers! {
204 AccessibilityAction,
205 AccessibilityActionEventData;
206
207 accessibility_action => EventName::AccessibilityAction;
209 }
210
211 event_handlers! {
212 Mouse,
213 MouseEventData;
214
215 mouse_down => EventName::MouseDown;
217 mouse_up => EventName::MouseUp;
219 mouse_move => EventName::MouseMove;
221
222 }
223
224 event_handlers! {
225 Pointer,
226 PointerEventData;
227
228 global_pointer_up => EventName::GlobalPointerUp;
230 global_pointer_down => EventName::GlobalPointerDown;
232 global_pointer_move => EventName::GlobalPointerMove;
234
235 capture_global_pointer_move => EventName::CaptureGlobalPointerMove;
237 capture_global_pointer_up => EventName::CaptureGlobalPointerUp;
239 }
240
241 event_handlers! {
242 Keyboard,
243 KeyboardEventData;
244
245 key_down => EventName::KeyDown;
247 key_up => EventName::KeyUp;
249
250 global_key_down => EventName::GlobalKeyDown;
252 global_key_up => EventName::GlobalKeyUp;
254 }
255
256 event_handlers! {
257 Wheel,
258 WheelEventData;
259
260 wheel => EventName::Wheel;
262 }
263
264 event_handlers! {
265 Touch,
266 TouchEventData;
267
268 touch_cancel => EventName::TouchCancel;
270 touch_start => EventName::TouchStart;
272 touch_move => EventName::TouchMove;
274 touch_end => EventName::TouchEnd;
276 }
277
278 event_handlers! {
279 Pointer,
280 PointerEventData;
281
282 pointer_press => EventName::PointerPress;
284 pointer_down => EventName::PointerDown;
286 pointer_move => EventName::PointerMove;
288 pointer_enter => EventName::PointerEnter;
290 pointer_leave => EventName::PointerLeave;
292 pointer_over => EventName::PointerOver;
294 pointer_out => EventName::PointerOut;
296 }
297
298 event_handlers! {
299 File,
300 FileEventData;
301
302 file_drop => EventName::FileDrop;
304 global_file_hover => EventName::GlobalFileHover;
306 global_file_hover_cancelled => EventName::GlobalFileHoverCancelled;
308 }
309
310 event_handlers! {
311 ImePreedit,
312 ImePreeditEventData;
313
314 ime_preedit => EventName::ImePreedit;
316 }
317
318 fn on_sized(mut self, on_sized: impl Into<EventHandler<Event<SizedEventData>>>) -> Self
320 where
321 Self: LayoutExt,
322 {
323 self.event_handlers_mut()
324 .insert(EventName::Sized, EventHandlerType::Sized(on_sized.into()));
325 self.layout_mut().layout.has_layout_references = true;
326 self
327 }
328
329 fn on_visible(mut self, on_visible: impl Into<EventHandler<Event<VisibleEventData>>>) -> Self {
331 self.event_handlers_mut().insert(
332 EventName::Visible,
333 EventHandlerType::Visible(on_visible.into()),
334 );
335 self
336 }
337
338 fn on_hidden(mut self, on_hidden: impl Into<EventHandler<Event<VisibleEventData>>>) -> Self {
340 self.event_handlers_mut().insert(
341 EventName::Hidden,
342 EventHandlerType::Visible(on_hidden.into()),
343 );
344 self
345 }
346
347 fn on_styled(mut self, on_styled: impl Into<EventHandler<Event<StyledEventData>>>) -> Self {
349 self.event_handlers_mut().insert(
350 EventName::Styled,
351 EventHandlerType::Styled(on_styled.into()),
352 );
353 self
354 }
355
356 fn on_press(self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self
364 where
365 Self: AccessibilityExt,
366 {
367 let on_press = on_press.into();
368 self.a11y_builder(|builder| builder.add_action(AccessibilityAction::Click))
369 .on_accessibility_action({
370 let on_press = on_press.clone();
371 move |event: Event<AccessibilityActionEventData>| {
372 if event.action == AccessibilityAction::Click {
373 on_press.call(event.map(PressEventData::Accessibility));
374 }
375 }
376 })
377 .on_pointer_press({
378 let on_press = on_press.clone();
379 move |e: Event<PointerEventData>| {
380 let event = e.try_map(|d| match d {
381 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
382 Some(PressEventData::Mouse(m))
383 }
384 PointerEventData::Touch(t) => Some(PressEventData::Touch(t)),
385 _ => None,
386 });
387 if let Some(event) = event {
388 on_press.call(event);
389 }
390 }
391 })
392 .on_key_down(move |e: Event<KeyboardEventData>| {
393 if e.is_press_event() {
394 on_press.call(e.map(PressEventData::Keyboard))
395 }
396 })
397 }
398
399 fn on_secondary_down(
403 self,
404 on_secondary_down: impl Into<EventHandler<Event<PressEventData>>>,
405 ) -> Self {
406 let on_secondary_down = on_secondary_down.into();
407 self.on_pointer_down(move |e: Event<PointerEventData>| {
408 let event = e.try_map(|d| match d {
409 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Right) => {
410 Some(PressEventData::Mouse(m))
411 }
412 _ => None,
413 });
414 if let Some(event) = event {
415 on_secondary_down.call(event);
416 }
417 })
418 }
419
420 fn on_all_press(self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self
426 where
427 Self: AccessibilityExt,
428 {
429 let on_press = on_press.into();
430 self.a11y_builder(|builder| builder.add_action(AccessibilityAction::Click))
431 .on_accessibility_action({
432 let on_press = on_press.clone();
433 move |event: Event<AccessibilityActionEventData>| {
434 if event.action == AccessibilityAction::Click {
435 on_press.call(event.map(PressEventData::Accessibility));
436 }
437 }
438 })
439 .on_pointer_press({
440 let on_press = on_press.clone();
441 move |e: Event<PointerEventData>| {
442 let event = e.map(|d| match d {
443 PointerEventData::Mouse(m) => PressEventData::Mouse(m),
444 PointerEventData::Touch(t) => PressEventData::Touch(t),
445 });
446 on_press.call(event);
447 }
448 })
449 .on_key_down(move |e: Event<KeyboardEventData>| {
450 if e.is_press_event() {
451 on_press.call(e.map(PressEventData::Keyboard))
452 }
453 })
454 }
455 fn on_focus_press(
461 self,
462 on_focus_press: impl Into<EventHandler<Event<FocusPressEventData>>>,
463 ) -> Self {
464 let on_focus_press = on_focus_press.into();
465 if cfg!(target_os = "android") {
466 self.on_pointer_press(move |e: Event<PointerEventData>| {
467 let event = e.try_map(|d| match d {
468 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
469 Some(FocusPressEventData::Mouse(m))
470 }
471 PointerEventData::Touch(t) => Some(FocusPressEventData::Touch(t)),
472 _ => None,
473 });
474 if let Some(event) = event {
475 on_focus_press.call(event);
476 }
477 })
478 } else {
479 self.on_pointer_down(move |e: Event<PointerEventData>| {
480 let event = e.try_map(|d| match d {
481 PointerEventData::Mouse(m) if m.button == Some(MouseButton::Left) => {
482 Some(FocusPressEventData::Mouse(m))
483 }
484 PointerEventData::Touch(t) => Some(FocusPressEventData::Touch(t)),
485 _ => None,
486 });
487 if let Some(event) = event {
488 on_focus_press.call(event);
489 }
490 })
491 }
492 }
493}
494
495#[derive(Debug, Clone, PartialEq)]
497pub enum FocusPressEventData {
498 Mouse(MouseEventData),
499 Touch(TouchEventData),
500}
501
502impl FocusPressEventData {
503 pub fn global_location(&self) -> CursorPoint {
504 match self {
505 Self::Mouse(m) => m.global_location,
506 Self::Touch(t) => t.global_location,
507 }
508 }
509
510 pub fn element_location(&self) -> CursorPoint {
511 match self {
512 Self::Mouse(m) => m.element_location,
513 Self::Touch(t) => t.element_location,
514 }
515 }
516
517 pub fn button(&self) -> Option<MouseButton> {
518 match self {
519 Self::Mouse(m) => m.button,
520 Self::Touch(_) => None,
521 }
522 }
523}
524
525#[derive(Debug, Clone, PartialEq)]
527pub enum PressEventData {
528 Accessibility(AccessibilityActionEventData),
529 Mouse(MouseEventData),
530 Keyboard(KeyboardEventData),
531 Touch(TouchEventData),
532}
533
534pub trait ContainerWithContentExt
536where
537 Self: LayoutExt,
538{
539 fn direction(mut self, direction: Direction) -> Self {
541 self.layout_mut().layout.direction = direction;
542 self
543 }
544 fn main_align(mut self, main_align: impl Into<Alignment>) -> Self {
546 self.layout_mut().layout.main_alignment = main_align.into();
547 self
548 }
549
550 fn cross_align(mut self, cross_align: impl Into<Alignment>) -> Self {
552 self.layout_mut().layout.cross_alignment = cross_align.into();
553 self
554 }
555
556 fn spacing(mut self, spacing: f32) -> Self {
558 self.layout_mut().layout.spacing = Length::new(spacing);
559 self
560 }
561
562 fn content(mut self, content: Content) -> Self {
564 self.layout_mut().layout.content = content;
565 self
566 }
567 fn center(mut self) -> Self {
569 self.layout_mut().layout.main_alignment = Alignment::Center;
570 self.layout_mut().layout.cross_alignment = Alignment::Center;
571
572 self
573 }
574
575 fn offset_x(mut self, offset_x: f32) -> Self {
577 self.layout_mut().layout.offset_x = Length::new(offset_x);
578 self
579 }
580
581 fn offset_y(mut self, offset_y: f32) -> Self {
583 self.layout_mut().layout.offset_y = Length::new(offset_y);
584 self
585 }
586
587 fn vertical(mut self) -> Self {
589 self.layout_mut().layout.direction = Direction::vertical();
590 self
591 }
592
593 fn horizontal(mut self) -> Self {
595 self.layout_mut().layout.direction = Direction::horizontal();
596 self
597 }
598}
599
600pub trait ContainerSizeExt
602where
603 Self: LayoutExt,
604{
605 fn width(mut self, width: impl Into<Size>) -> Self {
607 self.layout_mut().layout.width = width.into();
608 self
609 }
610
611 fn height(mut self, height: impl Into<Size>) -> Self {
613 self.layout_mut().layout.height = height.into();
614 self
615 }
616
617 fn expanded(mut self) -> Self {
619 self.layout_mut().layout.width = Size::fill();
620 self.layout_mut().layout.height = Size::fill();
621 self
622 }
623}
624
625impl<T: ContainerExt> ContainerSizeExt for T {}
626
627pub trait ContainerPositionExt
629where
630 Self: LayoutExt,
631{
632 fn position(mut self, position: impl Into<Position>) -> Self {
634 self.layout_mut().layout.position = position.into();
635 self
636 }
637
638 fn margin(mut self, margin: impl Into<Gaps>) -> Self {
640 self.layout_mut().layout.margin = margin.into();
641 self
642 }
643}
644
645impl<T: ContainerExt> ContainerPositionExt for T {}
646
647pub trait ContainerExt
649where
650 Self: LayoutExt,
651{
652 fn padding(mut self, padding: impl Into<Gaps>) -> Self {
654 self.layout_mut().layout.padding = padding.into();
655 self
656 }
657}
658
659pub trait ContainerConstraintsExt
661where
662 Self: LayoutExt,
663{
664 fn min_width(mut self, minimum_width: impl Into<Size>) -> Self {
666 self.layout_mut().layout.minimum_width = minimum_width.into();
667 self
668 }
669
670 fn min_height(mut self, minimum_height: impl Into<Size>) -> Self {
672 self.layout_mut().layout.minimum_height = minimum_height.into();
673 self
674 }
675
676 fn max_width(mut self, maximum_width: impl Into<Size>) -> Self {
678 self.layout_mut().layout.maximum_width = maximum_width.into();
679 self
680 }
681
682 fn max_height(mut self, maximum_height: impl Into<Size>) -> Self {
684 self.layout_mut().layout.maximum_height = maximum_height.into();
685 self
686 }
687
688 fn visible_width(mut self, visible_width: impl Into<VisibleSize>) -> Self {
690 self.layout_mut().layout.visible_width = visible_width.into();
691 self
692 }
693
694 fn visible_height(mut self, visible_height: impl Into<VisibleSize>) -> Self {
696 self.layout_mut().layout.visible_height = visible_height.into();
697 self
698 }
699}
700
701impl<T: ContainerExt> ContainerConstraintsExt for T {}
702
703pub trait LayoutExt
705where
706 Self: Sized,
707{
708 fn layout_mut(&mut self) -> &mut LayoutData;
710
711 fn layout(mut self, layout: LayoutData) -> Self {
713 *self.layout_mut() = layout;
714 self
715 }
716}
717
718pub trait ImageExt
720where
721 Self: LayoutExt,
722{
723 fn image_data_mut(&mut self) -> &mut ImageData;
725
726 fn image_data(mut self, image_data: ImageData) -> Self {
728 *self.image_data_mut() = image_data;
729 self
730 }
731
732 fn sampling_mode(mut self, sampling_mode: SamplingMode) -> Self {
734 self.image_data_mut().sampling_mode = sampling_mode;
735 self
736 }
737
738 fn aspect_ratio(mut self, aspect_ratio: AspectRatio) -> Self {
740 self.image_data_mut().aspect_ratio = aspect_ratio;
741 self
742 }
743
744 fn image_cover(mut self, image_cover: ImageCover) -> Self {
746 self.image_data_mut().image_cover = image_cover;
747 self
748 }
749
750 fn snap_to_grid(mut self, snap_to_grid: bool) -> Self {
752 self.image_data_mut().snap_to_grid = snap_to_grid;
753 self
754 }
755
756 fn blur(mut self, blur: f32) -> Self {
758 self.image_data_mut().blur = blur;
759 self
760 }
761}
762
763pub trait AccessibilityExt: Sized {
765 fn accessibility_data_mut(&mut self) -> &mut AccessibilityData;
767
768 fn accessibility(mut self, accessibility: AccessibilityData) -> Self {
770 *self.accessibility_data_mut() = accessibility;
771 self
772 }
773
774 fn a11y_id(mut self, a11y_id: impl Into<Option<AccessibilityId>>) -> Self {
776 self.accessibility_data_mut().a11y_id = a11y_id.into();
777 self
778 }
779
780 fn a11y_enabled(mut self, enabled: impl Into<bool>) -> Self {
782 let builder = &mut self.accessibility_data_mut().builder;
783 if enabled.into() {
784 builder.clear_disabled();
785 } else {
786 builder.set_disabled();
787 }
788 self
789 }
790
791 fn a11y_focusable(mut self, a11y_focusable: impl Into<Focusable>) -> Self {
793 self.accessibility_data_mut().a11y_focusable = a11y_focusable.into();
794 self
795 }
796
797 fn a11y_auto_focus(mut self, a11y_auto_focus: impl Into<bool>) -> Self {
799 self.accessibility_data_mut().a11y_auto_focus = a11y_auto_focus.into();
800 self
801 }
802
803 fn a11y_member_of(mut self, a11y_member_of: impl Into<AccessibilityId>) -> Self {
805 self.accessibility_data_mut()
806 .builder
807 .set_member_of(a11y_member_of.into());
808 self
809 }
810
811 fn a11y_role(mut self, a11y_role: impl Into<AccessibilityRole>) -> Self {
813 self.accessibility_data_mut()
814 .builder
815 .set_role(a11y_role.into());
816 self
817 }
818
819 fn a11y_alt(mut self, value: impl Into<String>) -> Self {
821 self.accessibility_data_mut().builder.set_label(value);
822 self
823 }
824
825 fn a11y_builder(mut self, with: impl FnOnce(&mut accesskit::Node)) -> Self {
827 with(&mut self.accessibility_data_mut().builder);
828 self
829 }
830}
831
832pub trait TextStyleExt
834where
835 Self: Sized,
836{
837 fn text_style_data_mut(&mut self) -> &mut TextStyleData;
839
840 fn text_style(mut self, data: TextStyleData) -> Self {
842 *self.text_style_data_mut() = data;
843 self
844 }
845
846 fn color(mut self, color: impl Into<Fill>) -> Self {
848 self.text_style_data_mut().color = Some(color.into());
849 self
850 }
851
852 fn text_align(mut self, text_align: impl Into<TextAlign>) -> Self {
854 self.text_style_data_mut().text_align = Some(text_align.into());
855 self
856 }
857
858 fn font_size(mut self, font_size: impl Into<FontSize>) -> Self {
860 self.text_style_data_mut().font_size = Some(font_size.into());
861 self
862 }
863
864 fn letter_spacing(mut self, letter_spacing: impl Into<LetterSpacing>) -> Self {
866 self.text_style_data_mut().letter_spacing = Some(letter_spacing.into());
867 self
868 }
869
870 fn font_feature(mut self, font_feature: impl Into<FontFeature>) -> Self {
872 self.text_style_data_mut()
873 .font_features
874 .push(font_feature.into());
875 self
876 }
877
878 fn font_tabular(self) -> Self {
880 self.font_feature(FontFeature::TABULAR_NUMBERS)
881 }
882
883 fn font_small_caps(self) -> Self {
885 self.font_feature(FontFeature::SMALL_CAPS)
886 }
887
888 fn font_slashed_zero(self) -> Self {
890 self.font_feature(FontFeature::SLASHED_ZERO)
891 }
892
893 fn font_fractions(self) -> Self {
895 self.font_feature(FontFeature::FRACTIONS)
896 }
897
898 fn font_no_ligatures(self) -> Self {
900 self.font_feature(FontFeature::NO_LIGATURES)
901 }
902
903 fn font_family(mut self, font_family: impl Into<Cow<'static, str>>) -> Self {
905 self.text_style_data_mut()
906 .font_families
907 .push(font_family.into());
908 self
909 }
910
911 fn font_slant(mut self, font_slant: impl Into<FontSlant>) -> Self {
913 self.text_style_data_mut().font_slant = Some(font_slant.into());
914 self
915 }
916
917 fn font_weight(mut self, font_weight: impl Into<FontWeight>) -> Self {
919 self.text_style_data_mut().font_weight = Some(font_weight.into());
920 self
921 }
922
923 fn font_width(mut self, font_width: impl Into<FontWidth>) -> Self {
925 self.text_style_data_mut().font_width = Some(font_width.into());
926 self
927 }
928
929 fn text_height(mut self, text_height: impl Into<TextHeightBehavior>) -> Self {
931 self.text_style_data_mut().text_height = Some(text_height.into());
932 self
933 }
934
935 fn text_shadow(mut self, text_shadow: impl Into<TextShadow>) -> Self {
937 self.text_style_data_mut()
938 .text_shadows
939 .get_or_insert_default()
940 .push(text_shadow.into());
941 self
942 }
943
944 fn text_shadows(mut self, text_shadows: impl IntoIterator<Item = TextShadow>) -> Self {
946 self.text_style_data_mut().text_shadows = Some(text_shadows.into_iter().collect());
947 self
948 }
949
950 fn text_decoration(mut self, text_decoration: impl Into<TextDecoration>) -> Self {
952 self.text_style_data_mut().text_decoration = Some(text_decoration.into());
953 self
954 }
955}
956
957pub trait TextOverflowExt: TextStyleExt {
959 fn text_overflow(mut self, text_overflow: impl Into<TextOverflow>) -> Self {
961 self.text_style_data_mut().text_overflow = Some(text_overflow.into());
962 self
963 }
964}
965
966pub trait BackgroundExt: StyleExt {
968 fn background(mut self, background: impl Into<Fill>) -> Self {
970 self.style_mut().background = background.into();
971 self
972 }
973}
974
975pub trait StyleExt
977where
978 Self: Sized,
979{
980 fn style_mut(&mut self) -> &mut StyleState;
982
983 fn style(mut self, style: StyleState) -> Self {
985 *self.style_mut() = style;
986 self
987 }
988}
989
990pub trait DecorationExt: StyleExt {
992 fn border(mut self, border: impl Into<Option<Border>>) -> Self {
994 if let Some(border) = border.into() {
995 self.style_mut().borders.push(border);
996 }
997 self
998 }
999
1000 fn shadow(mut self, shadow: impl Into<Shadow>) -> Self {
1002 self.style_mut().shadows.push(shadow.into());
1003 self
1004 }
1005
1006 fn corner_radius(mut self, corner_radius: impl Into<CornerRadius>) -> Self {
1008 self.style_mut().corner_radius = corner_radius.into();
1009 self
1010 }
1011}
1012
1013impl<T: DecorationExt> CornerRadiusExt for T {
1014 fn with_corner_radius(mut self, corner_radius: f32) -> Self {
1015 self.style_mut().corner_radius = CornerRadius::new_all(corner_radius);
1016 self
1017 }
1018}
1019
1020pub trait CornerRadiusExt: Sized {
1022 fn with_corner_radius(self, corner_radius: f32) -> Self;
1024
1025 fn rounded_none(self) -> Self {
1027 self.with_corner_radius(0.)
1028 }
1029
1030 fn rounded(self) -> Self {
1032 self.with_corner_radius(6.)
1033 }
1034
1035 fn rounded_sm(self) -> Self {
1037 self.with_corner_radius(4.)
1038 }
1039
1040 fn rounded_md(self) -> Self {
1042 self.with_corner_radius(6.)
1043 }
1044
1045 fn rounded_lg(self) -> Self {
1047 self.with_corner_radius(8.)
1048 }
1049
1050 fn rounded_xl(self) -> Self {
1052 self.with_corner_radius(12.)
1053 }
1054
1055 fn rounded_2xl(self) -> Self {
1057 self.with_corner_radius(16.)
1058 }
1059
1060 fn rounded_3xl(self) -> Self {
1062 self.with_corner_radius(24.)
1063 }
1064
1065 fn rounded_4xl(self) -> Self {
1067 self.with_corner_radius(32.)
1068 }
1069
1070 fn rounded_full(self) -> Self {
1072 self.with_corner_radius(99.)
1073 }
1074}
1075
1076pub trait MaybeExt
1078where
1079 Self: Sized,
1080{
1081 fn maybe(self, bool: impl Into<bool>, then: impl FnOnce(Self) -> Self) -> Self {
1083 if bool.into() { then(self) } else { self }
1084 }
1085
1086 fn map<T>(self, data: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self {
1088 if let Some(data) = data {
1089 then(self, data)
1090 } else {
1091 self
1092 }
1093 }
1094}
1095
1096pub trait LayerExt
1098where
1099 Self: Sized,
1100{
1101 fn layer_mut(&mut self) -> &mut Layer;
1103
1104 fn layer(mut self, layer: impl Into<Layer>) -> Self {
1106 *self.layer_mut() = layer.into();
1107 self
1108 }
1109}
1110
1111pub trait ScrollableExt
1112where
1113 Self: Sized,
1114{
1115 fn effect_mut(&mut self) -> &mut EffectData;
1117
1118 fn scrollable(mut self, scrollable: impl Into<bool>) -> Self {
1121 self.effect_mut().scrollable = scrollable.into();
1122 self
1123 }
1124}
1125
1126pub trait InteractiveExt
1128where
1129 Self: Sized,
1130{
1131 fn effect_mut(&mut self) -> &mut EffectData;
1133
1134 fn interactive(mut self, interactive: impl Into<Interactive>) -> Self {
1136 self.effect_mut().interactive = interactive.into();
1137 self
1138 }
1139}
1140
1141pub trait EffectExt: Sized {
1143 fn effect_mut(&mut self) -> &mut EffectData;
1145
1146 fn cursor(mut self, cursor: impl Into<Option<CursorIcon>>) -> Self {
1151 self.effect_mut().cursor = cursor.into();
1152 self
1153 }
1154
1155 fn cursor_visible(mut self, visible: impl Into<Option<bool>>) -> Self {
1159 self.effect_mut().cursor_visible = visible.into();
1160 self
1161 }
1162
1163 fn effect(mut self, effect: EffectData) -> Self {
1165 *self.effect_mut() = effect;
1166 self
1167 }
1168
1169 fn overflow(mut self, overflow: impl Into<Overflow>) -> Self {
1171 self.effect_mut().overflow = overflow.into();
1172 self
1173 }
1174
1175 fn backdrop_blur(mut self, blur: f32) -> Self {
1177 self.effect_mut().blur = Some(blur);
1178 self
1179 }
1180
1181 fn rotation(mut self, rotation: f32) -> Self {
1183 self.effect_mut().rotation = Some(rotation);
1184 self
1185 }
1186
1187 fn opacity(mut self, opacity: f32) -> Self {
1189 self.effect_mut().opacity = Some(opacity);
1190 self
1191 }
1192
1193 fn scale(mut self, scale: impl Into<Scale>) -> Self {
1195 self.effect_mut().scale = Some(scale.into());
1196 self
1197 }
1198
1199 fn transform_origin(mut self, transform_origin: impl Into<TransformOrigin>) -> Self {
1203 self.effect_mut().transform_origin = transform_origin.into();
1204 self
1205 }
1206}