1use crate::{
4 BoxShadow, Overflow, Overscroll, ScrollbarGutter, TransitionProperty, properties::StyleValue, style::{ FontStyle, FontWeight, IntoThemed, LetterSpacing },
5};
6
7use super::{
8 AlignItems,
9 Background,
10 Border,
11 Outline,
12 Color,
13 Cursor,
14 Display,
15 Edges,
16 FlexDirection,
17 FlexWrap,
18 GridPlacement,
19 GridTrack,
20 JustifyContent,
21 Length,
22 LineHeight,
23 Position,
24 ScrollbarStyle,
25 Size,
26 Style,
27 TextAlign,
28 TextDecoration,
29};
30
31pub trait StyleBuilder: Sized {
32 fn style_mut(&mut self) -> &mut Style;
33
34 fn mark_dirty(&mut self) {}
35
36 fn width<M>(mut self, width: impl IntoThemed<Length, M>) -> Self {
37 self.style_mut().size.get_or_insert_with(Default::default).width = Some(
38 width.resolve_themed()
39 );
40
41 self.mark_dirty();
42
43 self
44 }
45
46 fn height<M>(mut self, height: impl IntoThemed<Length, M>) -> Self {
47 self.style_mut().size.get_or_insert_with(Default::default).height = Some(
48 height.resolve_themed()
49 );
50
51 self.mark_dirty();
52
53 self
54 }
55
56 fn size<W, H, MW, MH>(mut self, width: W, height: H) -> Self
57 where W: IntoThemed<Length, MW>, H: IntoThemed<Length, MH>
58 {
59 self.style_mut().size = Some(Size::new(width.resolve_themed(), height.resolve_themed()));
60
61 self.mark_dirty();
62
63 self
64 }
65
66 fn padding<M>(mut self, padding: impl IntoThemed<Edges, M>) -> Self {
67 self.style_mut().padding = Some(padding.resolve_themed());
68
69 self.mark_dirty();
70
71 self
72 }
73
74 fn color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
75 self.style_mut().color = Some(color.resolve_themed());
76
77 self.mark_dirty();
78
79 self
80 }
81
82 fn selection_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
83 self.style_mut().selection_color = Some(color.resolve_themed());
84
85 self.mark_dirty();
86
87 self
88 }
89
90 fn selection_background<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
91 self.style_mut().selection_background = Some(color.resolve_themed());
92
93 self.mark_dirty();
94
95 self
96 }
97
98 fn caret_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
99 self.style_mut().caret_color = Some(color.resolve_themed());
100
101 self.mark_dirty();
102
103 self
104 }
105
106 fn selection_border_width<M>(mut self, width: impl IntoThemed<Length, M>) -> Self {
107 self.style_mut().selection_border_width = Some(width.resolve_themed());
108
109 self.mark_dirty();
110
111 self
112 }
113
114 fn selection_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
115 self.style_mut().selection_border_color = Some(color.resolve_themed());
116
117 self.mark_dirty();
118
119 self
120 }
121
122 fn selection_border_radius<M>(mut self, radius: impl IntoThemed<Length, M>) -> Self {
123 self.style_mut().selection_border_radius = Some(radius.resolve_themed());
124
125 self.mark_dirty();
126
127 self
128 }
129
130 fn cursor(mut self, cursor: Cursor) -> Self {
131 self.style_mut().cursor = Some(cursor);
132
133 self.mark_dirty();
134
135 self
136 }
137
138 fn background<M>(mut self, background: impl IntoThemed<Background, M>) -> Self {
139 self.style_mut().background = Some(background.resolve_themed());
140
141 self.mark_dirty();
142
143 self
144 }
145
146 fn font_size<M>(mut self, size: impl IntoThemed<Length, M>) -> Self {
147 self.style_mut().font_size = Some(size.resolve_themed());
148
149 self.mark_dirty();
150
151 self
152 }
153
154 fn font_weight(mut self, weight: FontWeight) -> Self {
155 self.style_mut().font_weight = Some(weight);
156
157 self.mark_dirty();
158
159 self
160 }
161
162 fn font_style(mut self, style: FontStyle) -> Self {
163 self.style_mut().font_style = Some(style);
164
165 self.mark_dirty();
166
167 self
168 }
169
170 fn letter_spacing(mut self, spacing: impl Into<LetterSpacing>) -> Self {
171 self.style_mut().letter_spacing = Some(spacing.into());
172
173 self.mark_dirty();
174
175 self
176 }
177
178 fn text_align(mut self, align: TextAlign) -> Self {
179 self.style_mut().text_align = Some(align);
180
181 self.mark_dirty();
182
183 self
184 }
185
186 fn text_decoration(mut self, decoration: TextDecoration) -> Self {
187 self.style_mut().text_decoration = Some(decoration);
188
189 self.mark_dirty();
190
191 self
192 }
193
194 fn line_height(mut self, height: impl Into<LineHeight>) -> Self {
195 self.style_mut().line_height = Some(height.into());
196
197 self.mark_dirty();
198
199 self
200 }
201
202 fn margin<M>(mut self, margin: impl IntoThemed<Edges, M>) -> Self {
203 self.style_mut().margin = Some(margin.resolve_themed());
204
205 self.mark_dirty();
206
207 self
208 }
209
210 fn border<M>(mut self, border: impl IntoThemed<Border, M>) -> Self {
211 self.style_mut().border = Some(border.resolve_themed());
212
213 self.mark_dirty();
214
215 self
216 }
217
218 fn outline<M>(mut self, outline: impl IntoThemed<StyleValue<Outline>, M>) -> Self {
219 self.style_mut().outline = outline.resolve_themed();
220
221 self.mark_dirty();
222
223 self
224 }
225
226 fn box_shadow(mut self, shadows: impl Into<Vec<BoxShadow>>) -> Self {
227 self.style_mut().box_shadow = Some(shadows.into());
228 self.mark_dirty();
229 self
230 }
231
232 fn box_shadow_none(mut self) -> Self {
233 self.style_mut().box_shadow = None;
234 self.mark_dirty();
235 self
236 }
237
238 fn min_width<M>(mut self, width: impl IntoThemed<Length, M>) -> Self {
239 self.style_mut().min_size.get_or_insert_with(Default::default).width = Some(
240 width.resolve_themed()
241 );
242
243 self.mark_dirty();
244
245 self
246 }
247
248 fn min_height<M>(mut self, height: impl IntoThemed<Length, M>) -> Self {
249 self.style_mut().min_size.get_or_insert_with(Default::default).height = Some(
250 height.resolve_themed()
251 );
252
253 self.mark_dirty();
254
255 self
256 }
257
258 fn min_size<W, H, MW, MH>(mut self, width: W, height: H) -> Self
259 where W: IntoThemed<Length, MW>, H: IntoThemed<Length, MH>
260 {
261 self.style_mut().min_size = Some(
262 Size::new(width.resolve_themed(), height.resolve_themed())
263 );
264
265 self.mark_dirty();
266
267 self
268 }
269
270 fn max_width<M>(mut self, width: impl IntoThemed<Length, M>) -> Self {
271 self.style_mut().max_size.get_or_insert_with(Default::default).width = Some(
272 width.resolve_themed()
273 );
274
275 self.mark_dirty();
276
277 self
278 }
279
280 fn max_height<M>(mut self, height: impl IntoThemed<Length, M>) -> Self {
281 self.style_mut().max_size.get_or_insert_with(Default::default).height = Some(
282 height.resolve_themed()
283 );
284
285 self.mark_dirty();
286
287 self
288 }
289
290 fn max_size<W, H, MW, MH>(mut self, width: W, height: H) -> Self
291 where W: IntoThemed<Length, MW>, H: IntoThemed<Length, MH>
292 {
293 self.style_mut().max_size = Some(
294 Size::new(width.resolve_themed(), height.resolve_themed())
295 );
296
297 self.mark_dirty();
298
299 self
300 }
301
302 fn display(mut self, display: Display) -> Self {
303 self.style_mut().display = Some(display);
304
305 self.mark_dirty();
306
307 self
308 }
309
310 fn position(mut self, position: Position) -> Self {
311 self.style_mut().position = Some(position);
312
313 self.mark_dirty();
314
315 self
316 }
317
318 fn top<M>(mut self, value: impl IntoThemed<Length, M>) -> Self {
319 self.style_mut().top = Some(value.resolve_themed());
320
321 self.mark_dirty();
322
323 self
324 }
325
326 fn right<M>(mut self, value: impl IntoThemed<Length, M>) -> Self {
327 self.style_mut().right = Some(value.resolve_themed());
328
329 self.mark_dirty();
330
331 self
332 }
333
334 fn bottom<M>(mut self, value: impl IntoThemed<Length, M>) -> Self {
335 self.style_mut().bottom = Some(value.resolve_themed());
336
337 self.mark_dirty();
338
339 self
340 }
341
342 fn left<M>(mut self, value: impl IntoThemed<Length, M>) -> Self {
343 self.style_mut().left = Some(value.resolve_themed());
344
345 self.mark_dirty();
346
347 self
348 }
349
350 fn z_index(mut self, z_index: i32) -> Self {
352 self.style_mut().z_index = Some(z_index);
353
354 self.mark_dirty();
355
356 self
357 }
358
359 fn overflow_x(mut self, overflow: Overflow) -> Self {
360 self.style_mut().overflow_x = Some(overflow);
361
362 self.mark_dirty();
363
364 self
365 }
366
367 fn overflow_y(mut self, overflow: Overflow) -> Self {
368 self.style_mut().overflow_y = Some(overflow);
369
370 self.mark_dirty();
371
372 self
373 }
374
375 fn overflow(mut self, x: Overflow, y: Overflow) -> Self {
376 self.style_mut().overflow_x = Some(x);
377
378 self.style_mut().overflow_y = Some(y);
379
380 self.mark_dirty();
381
382 self
383 }
384
385 fn overscroll(mut self, overscroll: Overscroll) -> Self {
386 self.style_mut().overscroll = Some(overscroll);
387
388 self.mark_dirty();
389
390 self
391 }
392
393 fn flex_direction(mut self, direction: FlexDirection) -> Self {
394 self.style_mut().flex_direction = Some(direction);
395
396 self.mark_dirty();
397
398 self
399 }
400
401 fn flex_wrap(mut self, wrap: FlexWrap) -> Self {
402 self.style_mut().flex_wrap = Some(wrap);
403
404 self.mark_dirty();
405
406 self
407 }
408
409 fn flex_grow(mut self, grow: f32) -> Self {
410 self.style_mut().flex_grow = Some(grow);
411
412 self.mark_dirty();
413
414 self
415 }
416
417 fn flex_shrink(mut self, shrink: f32) -> Self {
418 self.style_mut().flex_shrink = Some(shrink);
419
420 self.mark_dirty();
421
422 self
423 }
424
425 fn flex_basis<M>(mut self, basis: impl IntoThemed<Length, M>) -> Self {
426 self.style_mut().flex_basis = Some(basis.resolve_themed());
427
428 self.mark_dirty();
429
430 self
431 }
432
433 fn align_items(mut self, align: AlignItems) -> Self {
434 self.style_mut().align_items = Some(align);
435
436 self.mark_dirty();
437
438 self
439 }
440
441 fn align_self(mut self, align: AlignItems) -> Self {
442 self.style_mut().align_self = Some(align);
443
444 self.mark_dirty();
445
446 self
447 }
448
449 fn justify_content(mut self, justify: JustifyContent) -> Self {
450 self.style_mut().justify_content = Some(justify);
451
452 self.mark_dirty();
453
454 self
455 }
456
457 fn align_content(mut self, align: JustifyContent) -> Self {
458 self.style_mut().align_content = Some(align);
459
460 self.mark_dirty();
461
462 self
463 }
464
465 fn gap<W, H, MW, MH>(mut self, horizontal: W, vertical: H) -> Self
466 where W: IntoThemed<Length, MW>, H: IntoThemed<Length, MH>
467 {
468 self.style_mut().gap = Some((horizontal.resolve_themed(), vertical.resolve_themed()));
469
470 self.mark_dirty();
471
472 self
473 }
474
475 fn grid_template_columns(mut self, columns: impl Into<Vec<GridTrack>>) -> Self {
476 self.style_mut().grid_template_columns = Some(columns.into());
477
478 self.mark_dirty();
479
480 self
481 }
482
483 fn grid_template_rows(mut self, rows: impl Into<Vec<GridTrack>>) -> Self {
484 self.style_mut().grid_template_rows = Some(rows.into());
485
486 self.mark_dirty();
487
488 self
489 }
490
491 fn grid_column(mut self, column: GridPlacement) -> Self {
492 self.style_mut().grid_column = Some(column);
493
494 self.mark_dirty();
495
496 self
497 }
498
499 fn grid_row(mut self, row: GridPlacement) -> Self {
500 self.style_mut().grid_row = Some(row);
501
502 self.mark_dirty();
503
504 self
505 }
506
507 fn scrollbar_gutter(mut self, gutter: ScrollbarGutter) -> Self {
508 self.style_mut().scrollbar_gutter = Some(gutter);
509
510 self.mark_dirty();
511
512 self
513 }
514
515 fn scrollbar_thickness(mut self, thickness: f32) -> Self {
516 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).thickness =
517 Some(thickness);
518
519 self.mark_dirty();
520
521 self
522 }
523
524 fn scrollbar_min_thumb_length(mut self, length: f32) -> Self {
525 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).min_thumb_length =
526 Some(length);
527
528 self.mark_dirty();
529
530 self
531 }
532
533 fn scrollbar_thumb_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
534 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).thumb_color = Some(
535 color.resolve_themed()
536 );
537 self.mark_dirty();
538 self
539 }
540
541 fn scrollbar_thumb_radius<M>(mut self, radius: impl IntoThemed<f32, M>) -> Self {
542 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).thumb_radius = Some(
543 radius.resolve_themed()
544 );
545 self.mark_dirty();
546 self
547 }
548
549 fn scrollbar_track_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
550 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).track_color = Some(
551 color.resolve_themed()
552 );
553 self.mark_dirty();
554 self
555 }
556
557 fn scrollbar_button_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
558 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).button_color = Some(
559 color.resolve_themed()
560 );
561 self.mark_dirty();
562 self
563 }
564
565 fn scrollbar_arrow_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
566 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).arrow_color = Some(
567 color.resolve_themed()
568 );
569
570 self.mark_dirty();
571
572 self
573 }
574
575 fn scrollbar_thumb_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
576 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).thumb_border_color =
577 Some(color.resolve_themed());
578
579 self.mark_dirty();
580
581 self
582 }
583
584 fn scrollbar_track_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
585 self.style_mut().scrollbar.get_or_insert_with(ScrollbarStyle::default).track_border_color =
586 Some(color.resolve_themed());
587
588 self.mark_dirty();
589
590 self
591 }
592
593 fn scrollbar_hover_thickness(mut self, thickness: f32) -> Self {
598 self.style_mut().scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).thickness =
599 Some(thickness);
600
601 self.mark_dirty();
602
603 self
604 }
605
606 fn scrollbar_hover_min_thumb_length(mut self, length: f32) -> Self {
607 self
608
609 .style_mut()
610
611 .scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).min_thumb_length =
612 Some(length);
613
614 self.mark_dirty();
615
616 self
617 }
618
619 fn scrollbar_hover_thumb_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
620 self.style_mut().scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).thumb_color =
621 Some(color.resolve_themed());
622
623 self.mark_dirty();
624
625 self
626 }
627
628 fn scrollbar_hover_thumb_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
629 self
630
631 .style_mut()
632
633 .scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).thumb_border_color = Some(
634 color.resolve_themed()
635 );
636
637 self.mark_dirty();
638
639 self
640 }
641
642 fn scrollbar_hover_track_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
643 self.style_mut().scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).track_color =
644 Some(color.resolve_themed());
645
646 self.mark_dirty();
647
648 self
649 }
650
651 fn scrollbar_hover_track_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
652 self
653
654 .style_mut()
655
656 .scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).track_border_color = Some(
657 color.resolve_themed()
658 );
659
660 self.mark_dirty();
661
662 self
663 }
664
665 fn scrollbar_hover_button_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
666 self.style_mut().scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).button_color =
667 Some(color.resolve_themed());
668
669 self.mark_dirty();
670
671 self
672 }
673
674 fn scrollbar_hover_arrow_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
675 self.style_mut().scrollbar_hover.get_or_insert_with(ScrollbarStyle::default).arrow_color =
676 Some(color.resolve_themed());
677
678 self.mark_dirty();
679
680 self
681 }
682
683 fn scrollbar_pressed_thickness(mut self, thickness: f32) -> Self {
688 self.style_mut().scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).thickness =
689 Some(thickness);
690
691 self.mark_dirty();
692
693 self
694 }
695
696 fn scrollbar_pressed_min_thumb_length(mut self, length: f32) -> Self {
697 self
698
699 .style_mut()
700
701 .scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).min_thumb_length =
702 Some(length);
703
704 self.mark_dirty();
705
706 self
707 }
708
709 fn scrollbar_pressed_thumb_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
710 self.style_mut().scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).thumb_color =
711 Some(color.resolve_themed());
712
713 self.mark_dirty();
714
715 self
716 }
717
718 fn scrollbar_pressed_thumb_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
719 self
720
721 .style_mut()
722
723 .scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).thumb_border_color =
724 Some(color.resolve_themed());
725
726 self.mark_dirty();
727
728 self
729 }
730
731 fn scrollbar_pressed_track_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
732 self.style_mut().scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).track_color =
733 Some(color.resolve_themed());
734
735 self.mark_dirty();
736
737 self
738 }
739
740 fn scrollbar_pressed_track_border_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
741 self
742
743 .style_mut()
744
745 .scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).track_border_color =
746 Some(color.resolve_themed());
747
748 self.mark_dirty();
749
750 self
751 }
752
753 fn scrollbar_pressed_button_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
754 self
755
756 .style_mut()
757
758 .scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).button_color = Some(
759 color.resolve_themed()
760 );
761
762 self.mark_dirty();
763
764 self
765 }
766
767 fn scrollbar_pressed_arrow_color<M>(mut self, color: impl IntoThemed<Color, M>) -> Self {
768 self.style_mut().scrollbar_pressed.get_or_insert_with(ScrollbarStyle::default).arrow_color =
769 Some(color.resolve_themed());
770
771 self.mark_dirty();
772
773 self
774 }
775
776 fn scale(mut self, scale: f32) -> Self {
777 self.style_mut().scale = Some(scale);
778
779 self.mark_dirty();
780
781 self
782 }
783
784 fn content_scale(mut self, scale: f32) -> Self {
785 self.style_mut().content_scale = Some(scale);
786
787 self.mark_dirty();
788
789 self
790 }
791
792 fn transition(mut self, transition: crate::Transition) -> Self {
793 self.style_mut().transition = Some(transition);
794
795 let props = self.style_mut().transition_properties.unwrap_or(TransitionProperty::NONE);
796
797 self.style_mut().transition_properties = Some(props.union(TransitionProperty::DEFAULT));
798
799 self.mark_dirty();
800
801 self
802 }
803
804 fn transition_all(mut self, transition: crate::Transition) -> Self {
805 self.style_mut().transition = Some(transition);
806
807 let props = self.style_mut().transition_properties.unwrap_or(TransitionProperty::NONE);
808
809 self.style_mut().transition_properties = Some(props.union(TransitionProperty::ALL));
810
811 self.mark_dirty();
812
813 self
814 }
815
816 fn transition_colors(mut self, transition: crate::Transition) -> Self {
817 self.style_mut().transition_overrides.colors = Some(transition);
818
819 let props = self.style_mut().transition_properties.unwrap_or(TransitionProperty::NONE);
820
821 self.style_mut().transition_properties = Some(props.union(TransitionProperty::COLORS));
822
823 self.mark_dirty();
824
825 self
826 }
827
828 fn transition_opacity(mut self, transition: crate::Transition) -> Self {
829 self.style_mut().transition_overrides.opacity = Some(transition);
830
831 let props = self.style_mut().transition_properties.unwrap_or(TransitionProperty::NONE);
832
833 self.style_mut().transition_properties = Some(props.union(TransitionProperty::OPACITY));
834
835 self.mark_dirty();
836
837 self
838 }
839
840 fn transition_shadow(mut self, transition: crate::Transition) -> Self {
843 self.style_mut().transition_overrides.shadow = Some(transition);
844
845 let props = self.style_mut().transition_properties.unwrap_or(TransitionProperty::NONE);
846
847 self.style_mut().transition_properties = Some(props.union(TransitionProperty::SHADOW));
848
849 self.mark_dirty();
850
851 self
852 }
853
854 fn transition_transform(mut self, transition: crate::Transition) -> Self {
855 self.style_mut().transition_overrides.transform = Some(transition);
856
857 let props = self.style_mut().transition_properties.unwrap_or(TransitionProperty::NONE);
858
859 self.style_mut().transition_properties = Some(props.union(TransitionProperty::TRANSFORM));
860
861 self.mark_dirty();
862
863 self
864 }
865
866 fn transition_none(mut self) -> Self {
867 self.style_mut().transition = None;
868
869 self.style_mut().transition_overrides = Default::default();
870
871 self.style_mut().transition_properties = Some(TransitionProperty::NONE);
872
873 self.mark_dirty();
874
875 self
876 }
877}
878
879#[derive(Default)]
880pub struct StylePatch(Style);
881
882impl StylePatch {
883 pub fn new() -> Self {
884 Self(Style::default())
885 }
886
887 pub fn build(self) -> Style {
888 self.0
889 }
890}
891
892impl StyleBuilder for StylePatch {
893 fn style_mut(&mut self) -> &mut Style {
894 &mut self.0
895 }
896}