hephae_ui/
style.rs

1//! Defines everything necessary to style a [`Ui`] node.
2
3use bevy_ecs::prelude::*;
4use bevy_reflect::prelude::*;
5use bevy_transform::prelude::*;
6use taffy::{BlockContainerStyle, BlockItemStyle, CoreStyle, FlexboxContainerStyle, FlexboxItemStyle};
7
8use crate::node::{ComputedUi, UiCaches};
9
10/// A [`Ui`] node, complete with its styling information.
11#[derive(Component, Reflect, Clone)]
12#[require(Transform, ComputedUi)]
13#[reflect(Component, Default)]
14pub struct Ui {
15    /// Layout strategy to be used when laying out this node.
16    pub display: Display,
17    /// Defines whether size styles apply to the content box or the border box of the node.
18    pub box_sizing: BoxSizing,
19    /// How children overflowing their container should affect layout in the X axis.
20    pub overflow_x: Overflow,
21    /// How children overflowing their container should affect layout in the Y axis.
22    pub overflow_y: Overflow,
23    /// How much space (in pixels) should be reserved for the scrollbars of [`Overflow::Scroll`].
24    pub scrollbar_width: f32,
25    /// Determines what the `inset` value use as a base offset.
26    pub position: Position,
27    /// Determines how the position of this element should be tweaked relative to the layout
28    /// defined.
29    pub inset: UiBorder,
30    /// Sets the initial size of the node.
31    pub size: UiSize,
32    /// Controls the minimum size of the node.
33    pub min_size: UiSize,
34    /// Controls the maximum size of the node.
35    pub max_size: UiSize,
36    /// Sets the preferred aspect ratio for the node, calculated as width divided by height.
37    pub aspect_ratio: Option<f32>,
38    /// How large the margin should be on each side.
39    pub margin: UiBorder,
40    /// How large the padding should be on each side.
41    pub padding: UiBorder,
42    /// How large the border should be on each side.
43    pub border: UiBorder,
44    /// Defines which direction the main axis flows in.
45    pub flex_direction: FlexDirection,
46    /// Defines wrapping behavior for when children nodes exhaust their available space.
47    pub flex_wrap: FlexWrap,
48    /// Determines ow large the gaps between nodes. in the container should be.
49    pub gap: UiSize,
50    /// Determines how content contained within this node should be aligned in the cross/block axis.
51    pub align_content: AlignContent,
52    /// Determines how this node's children should be aligned in the cross/block axis.
53    pub align_items: AlignItems,
54    /// Determines how content contained within this node should be aligned in the main/inline axis.
55    pub justify_content: JustifyContent,
56    /// Sets the initial main axis size of the node.
57    pub flex_basis: Val,
58    /// The relative rate at which this node grows when it is expanding to fill space.
59    pub flex_grow: f32,
60    /// The relative rate at which this node shrinks when it is contracting to fit into space.
61    pub flex_shrink: f32,
62    /// Determines how this node should be aligned in the cross/block axis, falling back to the
63    /// parent's [`AlignItems`] if not set.
64    pub align_self: AlignSelf,
65}
66
67impl Ui {
68    /// The default value.
69    pub const DEFAULT: Self = Self {
70        display: Display::DEFAULT,
71        box_sizing: BoxSizing::DEFAULT,
72        overflow_x: Overflow::DEFAULT,
73        overflow_y: Overflow::DEFAULT,
74        scrollbar_width: 0.,
75        position: Position::DEFAULT,
76        inset: UiBorder::DEFAULT,
77        size: UiSize::DEFAULT,
78        min_size: UiSize::DEFAULT,
79        max_size: UiSize::DEFAULT,
80        aspect_ratio: None,
81        margin: UiBorder::all(Val::Abs(0.)),
82        padding: UiBorder::all(Val::Abs(0.)),
83        border: UiBorder::all(Val::Abs(0.)),
84        flex_direction: FlexDirection::DEFAULT,
85        flex_wrap: FlexWrap::DEFAULT,
86        gap: UiSize::all(Val::Abs(0.)),
87        align_content: AlignContent::DEFAULT,
88        align_items: AlignItems::DEFAULT,
89        justify_content: JustifyContent::DEFAULT,
90        flex_basis: Val::DEFAULT,
91        flex_grow: 0.,
92        flex_shrink: 1.,
93        align_self: AlignSelf::DEFAULT,
94    };
95}
96
97impl Default for Ui {
98    #[inline]
99    fn default() -> Self {
100        Self::DEFAULT
101    }
102}
103
104pub(crate) fn ui_changed(query: Query<Entity, Changed<Ui>>, mut caches: UiCaches) {
105    for e in &query {
106        caches.invalidate(e)
107    }
108}
109
110#[derive(Copy, Clone)]
111pub(crate) struct WithCtx<T> {
112    pub width: f32,
113    pub height: f32,
114    pub item: T,
115}
116
117/// UI dimension values.
118#[derive(Reflect, Copy, Clone)]
119#[reflect(Default)]
120pub enum Val {
121    /// Absolute pixel units.
122    Abs(f32),
123    /// Ratio of parent's units.
124    Rel(f32),
125    /// Ratio of viewport width.
126    Vw(f32),
127    /// Ratio of viewport height.
128    Vh(f32),
129    /// Should be automatically computed.
130    Auto,
131}
132
133impl Val {
134    /// The default value for [`Val`].
135    pub const DEFAULT: Self = Val::Auto;
136}
137
138impl Default for Val {
139    #[inline]
140    fn default() -> Self {
141        Self::DEFAULT
142    }
143}
144
145impl From<WithCtx<Val>> for taffy::Dimension {
146    #[inline]
147    fn from(WithCtx { width, height, item }: WithCtx<Val>) -> Self {
148        match item {
149            Val::Abs(abs) => Self::Length(abs),
150            Val::Rel(rel) => Self::Percent(rel),
151            Val::Vw(w) => Self::Length(width * w),
152            Val::Vh(h) => Self::Length(height * h),
153            Val::Auto => Self::Auto,
154        }
155    }
156}
157
158impl From<WithCtx<Val>> for taffy::LengthPercentage {
159    #[inline]
160    fn from(WithCtx { width, height, item }: WithCtx<Val>) -> Self {
161        match item {
162            Val::Abs(abs) => Self::Length(abs),
163            Val::Rel(rel) => Self::Percent(rel),
164            Val::Vw(w) => Self::Length(width * w),
165            Val::Vh(h) => Self::Length(height * h),
166            Val::Auto => Self::Length(0.),
167        }
168    }
169}
170
171impl From<WithCtx<Val>> for taffy::LengthPercentageAuto {
172    #[inline]
173    fn from(WithCtx { width, height, item }: WithCtx<Val>) -> Self {
174        match item {
175            Val::Abs(abs) => Self::Length(abs),
176            Val::Rel(rel) => Self::Percent(rel),
177            Val::Vw(w) => Self::Length(width * w),
178            Val::Vh(h) => Self::Length(height * h),
179            Val::Auto => Self::Auto,
180        }
181    }
182}
183
184/// A two-dimensional [`Val`], defining the area of a rectangle.
185#[derive(Reflect, Copy, Clone)]
186#[reflect(Default)]
187pub struct UiSize {
188    /// The width of the area.
189    pub width: Val,
190    /// The height of the area.
191    pub height: Val,
192}
193
194impl UiSize {
195    /// The default value for [`UiSize`].
196    pub const DEFAULT: Self = Self {
197        width: Val::DEFAULT,
198        height: Val::DEFAULT,
199    };
200}
201
202impl Default for UiSize {
203    #[inline]
204    fn default() -> Self {
205        Self::DEFAULT
206    }
207}
208
209impl UiSize {
210    /// Creates a new [`UiSize`].
211    #[inline]
212    pub const fn new(width: Val, height: Val) -> Self {
213        Self { width, height }
214    }
215
216    /// Creates a new [`UiSize`] that has the same values for all axes.
217    #[inline]
218    pub const fn all(value: Val) -> Self {
219        Self::new(value, value)
220    }
221
222    /// Creates a new [`UiSize`] that has all [absolute](Val::Abs) values.
223    #[inline]
224    pub const fn abs(width: f32, height: f32) -> Self {
225        Self::new(Val::Abs(width), Val::Abs(height))
226    }
227
228    /// Creates a new [`UiSize`] that has all [relative](Val::Rel) values.
229    #[inline]
230    pub const fn rel(width: f32, height: f32) -> Self {
231        Self::new(Val::Rel(width), Val::Rel(height))
232    }
233}
234
235impl<T: From<WithCtx<Val>>> From<WithCtx<UiSize>> for taffy::Size<T> {
236    #[inline]
237    fn from(WithCtx { width, height, item }: WithCtx<UiSize>) -> Self {
238        Self {
239            width: WithCtx {
240                width,
241                height,
242                item: item.width,
243            }
244            .into(),
245            height: WithCtx {
246                width,
247                height,
248                item: item.height,
249            }
250            .into(),
251        }
252    }
253}
254
255/// A rectangle defined by its borders.
256#[derive(Reflect, Copy, Clone)]
257#[reflect(Default)]
258pub struct UiBorder {
259    /// The left offset or position of this border.
260    pub left: Val,
261    /// The right offset or position of this border.
262    pub right: Val,
263    /// The bottom offset or position of this border.
264    pub bottom: Val,
265    /// The top offset or position of this border.
266    pub top: Val,
267}
268
269impl UiBorder {
270    /// The default value of [`UiBorder`].
271    pub const DEFAULT: Self = Self {
272        left: Val::DEFAULT,
273        right: Val::DEFAULT,
274        bottom: Val::DEFAULT,
275        top: Val::DEFAULT,
276    };
277
278    /// Creates a new [`UiBorder`].
279    #[inline]
280    pub const fn new(left: Val, right: Val, bottom: Val, top: Val) -> Self {
281        Self {
282            left,
283            right,
284            bottom,
285            top,
286        }
287    }
288
289    /// Creates a new [`UiBorder`] that has the same values for all sides.
290    #[inline]
291    pub const fn all(value: Val) -> Self {
292        Self::new(value, value, value, value)
293    }
294}
295
296impl Default for UiBorder {
297    #[inline]
298    fn default() -> Self {
299        Self::DEFAULT
300    }
301}
302
303impl<T: From<WithCtx<Val>>> From<WithCtx<UiBorder>> for taffy::Rect<T> {
304    #[inline]
305    fn from(
306        WithCtx {
307            width,
308            height,
309            item:
310                UiBorder {
311                    left,
312                    right,
313                    bottom,
314                    top,
315                },
316        }: WithCtx<UiBorder>,
317    ) -> Self {
318        Self {
319            left: WithCtx {
320                width,
321                height,
322                item: left,
323            }
324            .into(),
325            right: WithCtx {
326                width,
327                height,
328                item: right,
329            }
330            .into(),
331            bottom: WithCtx {
332                width,
333                height,
334                item: bottom,
335            }
336            .into(),
337            top: WithCtx {
338                width,
339                height,
340                item: top,
341            }
342            .into(),
343        }
344    }
345}
346
347/// Layout strategy to be used when laying out this node.
348#[derive(Reflect, Copy, Clone)]
349#[reflect(Default)]
350pub enum Display {
351    /// Use `flex` layout.
352    Flexbox,
353    /// Use `block` layout.
354    Block,
355    /// Collapse this node recursively, making it look like it doesn't exist at all.
356    None,
357}
358
359impl Display {
360    /// The default value of [`Display`].
361    pub const DEFAULT: Self = Display::Flexbox;
362}
363
364impl Default for Display {
365    #[inline]
366    fn default() -> Self {
367        Self::DEFAULT
368    }
369}
370
371impl From<Display> for taffy::BoxGenerationMode {
372    #[inline]
373    fn from(value: Display) -> Self {
374        match value {
375            Display::Flexbox | Display::Block => Self::Normal,
376            Display::None => Self::None,
377        }
378    }
379}
380
381/// Specifies whether size styles for this node are assigned to the node's "content box" or "border
382/// box".
383#[derive(Reflect, Copy, Clone, PartialEq, Eq, Debug)]
384#[reflect(Default)]
385pub enum BoxSizing {
386    /// Size styles such `size`, `min_size`, `max_size` specify the box's "content box" (the size
387    /// excluding padding/border/margin).
388    BorderBox,
389    /// Size styles such `size`, `min_size`, `max_size` specify the box's "border box" (the size
390    /// excluding margin but including padding/border).
391    ContentBox,
392}
393
394impl BoxSizing {
395    /// The default value of [`BoxSizing`].
396    pub const DEFAULT: Self = Self::BorderBox;
397}
398
399impl Default for BoxSizing {
400    #[inline]
401    fn default() -> Self {
402        Self::DEFAULT
403    }
404}
405
406impl From<BoxSizing> for taffy::BoxSizing {
407    #[inline]
408    fn from(value: BoxSizing) -> Self {
409        match value {
410            BoxSizing::BorderBox => Self::BorderBox,
411            BoxSizing::ContentBox => Self::ContentBox,
412        }
413    }
414}
415
416/// How children overflowing their container should affect layout.
417#[derive(Reflect, Copy, Clone, PartialEq, Eq, Debug)]
418#[reflect(Default)]
419pub enum Overflow {
420    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size
421    /// of its content. Content that overflows this node *should* contribute to the scroll
422    /// region of its parent.
423    Visible,
424    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size
425    /// of its content. Content that overflows this node should *not* contribute to the scroll
426    /// region of its parent.
427    Clip,
428    /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
429    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
430    Hidden,
431    /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally,
432    /// space should be reserved for a scrollbar. The amount of space reserved is controlled by
433    /// the `scrollbar_width` property. Content that overflows this node should *not* contribute
434    /// to the scroll region of its parent.
435    Scroll,
436}
437
438impl Overflow {
439    /// The default value of [`Overflow`].
440    pub const DEFAULT: Self = Self::Visible;
441}
442
443impl Default for Overflow {
444    #[inline]
445    fn default() -> Self {
446        Self::DEFAULT
447    }
448}
449
450impl From<Overflow> for taffy::Overflow {
451    #[inline]
452    fn from(value: Overflow) -> Self {
453        match value {
454            Overflow::Visible => Self::Visible,
455            Overflow::Clip => Self::Clip,
456            Overflow::Hidden => Self::Hidden,
457            Overflow::Scroll => Self::Scroll,
458        }
459    }
460}
461
462/// The positioning strategy for this item.
463#[derive(Reflect, Copy, Clone, PartialEq, Eq)]
464#[reflect(Default)]
465pub enum Position {
466    /// The offset is computed relative to the final position given by the layout algorithm.
467    /// Offsets do not affect the position of any other items; they are effectively a correction
468    /// factor applied at the end.
469    Relative,
470    /// The offset is computed relative to this item's closest positioned ancestor, if any.
471    /// Otherwise, it is placed relative to the origin.
472    /// No space is created for the item in the page layout, and its size will not be altered.
473    Absolute,
474}
475
476impl Position {
477    /// The default value of [`Position`].
478    pub const DEFAULT: Self = Self::Relative;
479}
480
481impl Default for Position {
482    #[inline]
483    fn default() -> Self {
484        Self::DEFAULT
485    }
486}
487
488impl From<Position> for taffy::Position {
489    #[inline]
490    fn from(value: Position) -> Self {
491        match value {
492            Position::Relative => Self::Relative,
493            Position::Absolute => Self::Absolute,
494        }
495    }
496}
497
498impl CoreStyle for WithCtx<&Ui> {
499    #[inline]
500    fn box_generation_mode(&self) -> taffy::BoxGenerationMode {
501        self.item.display.into()
502    }
503
504    #[inline]
505    fn is_block(&self) -> bool {
506        matches!(self.item.display, Display::Block)
507    }
508
509    #[inline]
510    fn box_sizing(&self) -> taffy::BoxSizing {
511        self.item.box_sizing.into()
512    }
513
514    #[inline]
515    fn overflow(&self) -> taffy::Point<taffy::Overflow> {
516        taffy::Point {
517            x: self.item.overflow_y.into(),
518            y: self.item.overflow_y.into(),
519        }
520    }
521
522    #[inline]
523    fn scrollbar_width(&self) -> f32 {
524        self.item.scrollbar_width
525    }
526
527    #[inline]
528    fn position(&self) -> taffy::Position {
529        self.item.position.into()
530    }
531
532    #[inline]
533    fn inset(&self) -> taffy::Rect<taffy::LengthPercentageAuto> {
534        WithCtx {
535            width: self.width,
536            height: self.height,
537            item: self.item.inset,
538        }
539        .into()
540    }
541
542    #[inline]
543    fn size(&self) -> taffy::Size<taffy::Dimension> {
544        WithCtx {
545            width: self.width,
546            height: self.height,
547            item: self.item.size,
548        }
549        .into()
550    }
551
552    #[inline]
553    fn min_size(&self) -> taffy::Size<taffy::Dimension> {
554        WithCtx {
555            width: self.width,
556            height: self.height,
557            item: self.item.min_size,
558        }
559        .into()
560    }
561
562    #[inline]
563    fn max_size(&self) -> taffy::Size<taffy::Dimension> {
564        WithCtx {
565            width: self.width,
566            height: self.height,
567            item: self.item.max_size,
568        }
569        .into()
570    }
571
572    #[inline]
573    fn aspect_ratio(&self) -> Option<f32> {
574        self.item.aspect_ratio
575    }
576
577    #[inline]
578    fn margin(&self) -> taffy::Rect<taffy::LengthPercentageAuto> {
579        WithCtx {
580            width: self.width,
581            height: self.height,
582            item: self.item.margin,
583        }
584        .into()
585    }
586
587    #[inline]
588    fn padding(&self) -> taffy::Rect<taffy::LengthPercentage> {
589        WithCtx {
590            width: self.width,
591            height: self.height,
592            item: self.item.padding,
593        }
594        .into()
595    }
596
597    #[inline]
598    fn border(&self) -> taffy::Rect<taffy::LengthPercentage> {
599        WithCtx {
600            width: self.width,
601            height: self.height,
602            item: self.item.border,
603        }
604        .into()
605    }
606}
607
608/// The direction of the flexbox layout main axis.
609#[derive(Reflect, Copy, Clone, PartialEq, Eq)]
610#[reflect(Default)]
611pub enum FlexDirection {
612    /// Items will be added from left to right in a row.
613    Row,
614    /// Items will be added from top to bottom in a column.
615    Column,
616    /// Items will be added from right to left in a row.
617    RowReverse,
618    /// Items will be added from bottom to top in a column.
619    ColumnReverse,
620}
621
622impl FlexDirection {
623    /// The default value of [`FlexDirection`].
624    pub const DEFAULT: Self = Self::Row;
625}
626
627impl Default for FlexDirection {
628    #[inline]
629    fn default() -> Self {
630        Self::DEFAULT
631    }
632}
633
634impl From<FlexDirection> for taffy::FlexDirection {
635    #[inline]
636    fn from(value: FlexDirection) -> Self {
637        match value {
638            FlexDirection::Row => Self::Row,
639            FlexDirection::Column => Self::Column,
640            FlexDirection::RowReverse => Self::RowReverse,
641            FlexDirection::ColumnReverse => Self::ColumnReverse,
642        }
643    }
644}
645
646/// Controls whether flex items are forced onto one line or can wrap onto multiple lines.
647#[derive(Reflect, Copy, Clone, PartialEq, Eq)]
648#[reflect(Default)]
649pub enum FlexWrap {
650    /// Items will not wrap and stay on a single line,
651    NoWrap,
652    /// Items will wrap according to this item's [`FlexDirection`],
653    Wrap,
654    /// Items will wrap in the opposite direction to this item's [`FlexDirection`].
655    WrapReverse,
656}
657
658impl FlexWrap {
659    /// The default value of [`FlexWrap`].
660    pub const DEFAULT: Self = Self::NoWrap;
661}
662
663impl Default for FlexWrap {
664    #[inline]
665    fn default() -> Self {
666        Self::DEFAULT
667    }
668}
669
670impl From<FlexWrap> for taffy::FlexWrap {
671    #[inline]
672    fn from(value: FlexWrap) -> Self {
673        match value {
674            FlexWrap::NoWrap => Self::NoWrap,
675            FlexWrap::Wrap => Self::Wrap,
676            FlexWrap::WrapReverse => Self::WrapReverse,
677        }
678    }
679}
680
681/// Sets the distribution of space between and around content items.
682/// For Flexbox it controls alignment in the cross axis.
683/// For Grid it controls alignment in the block axis.
684#[derive(Reflect, Copy, Clone, PartialEq, Eq)]
685#[reflect(Default)]
686pub enum AlignContent {
687    /// Items are placed as-is.
688    None,
689    /// Items are packed toward the start of the axis.
690    Start,
691    /// Items are packed toward the end of the axis.
692    End,
693    /// Items are packed towards the `flex-relative` start of the axis.
694    FlexStart,
695    /// Items are packed towards the `flex-relative` end of the axis.
696    FlexEnd,
697    /// Items are centered around the middle of the axis.
698    Center,
699    /// Items are stretched to fill the container.
700    Stretch,
701    /// The first and last items are aligned flush with the edges of the container (no gap)
702    /// The gap between items is distributed evenly.
703    SpaceBetween,
704    /// The gap between the first and last items is exactly **the same** as the gap between items.
705    /// The gaps are distributed evenly
706    SpaceEvenly,
707    /// The gap between the first and last items is exactly **half** the gap between items.
708    /// The gaps are distributed evenly in proportion to these ratios.
709    SpaceAround,
710}
711
712impl AlignContent {
713    /// The default value of [`AlignContent`].
714    pub const DEFAULT: Self = Self::None;
715}
716
717impl Default for AlignContent {
718    #[inline]
719    fn default() -> Self {
720        Self::None
721    }
722}
723
724impl From<AlignContent> for Option<taffy::AlignContent> {
725    #[inline]
726    fn from(value: AlignContent) -> Self {
727        match value {
728            AlignContent::None => None,
729            AlignContent::Start => Some(taffy::AlignContent::Start),
730            AlignContent::End => Some(taffy::AlignContent::End),
731            AlignContent::FlexStart => Some(taffy::AlignContent::FlexStart),
732            AlignContent::FlexEnd => Some(taffy::AlignContent::FlexEnd),
733            AlignContent::Center => Some(taffy::AlignContent::Center),
734            AlignContent::Stretch => Some(taffy::AlignContent::Stretch),
735            AlignContent::SpaceBetween => Some(taffy::AlignContent::SpaceBetween),
736            AlignContent::SpaceEvenly => Some(taffy::AlignContent::SpaceEvenly),
737            AlignContent::SpaceAround => Some(taffy::AlignContent::SpaceAround),
738        }
739    }
740}
741
742/// Used to control how child nodes are aligned.
743/// For Flexbox it controls alignment in the cross axis.
744/// For Grid it controls alignment in the block axis.
745#[derive(Reflect, Copy, Clone, PartialEq, Eq)]
746#[reflect(Default)]
747pub enum AlignItems {
748    /// Items are placed as-is.
749    None,
750    /// Items are packed toward the start of the axis.
751    Start,
752    /// Items are packed toward the end of the axis.
753    End,
754    /// Items are packed towards the flex-relative start of the axis.
755    FlexStart,
756    /// Items are packed towards the flex-relative end of the axis.
757    FlexEnd,
758    /// Items are packed along the center of the cross axis.
759    Center,
760    /// Items are aligned such as their baselines align.
761    Baseline,
762    /// Stretch to fill the container.
763    Stretch,
764}
765
766impl AlignItems {
767    /// The default value of [`AlignItems`].
768    pub const DEFAULT: Self = Self::None;
769}
770
771impl Default for AlignItems {
772    #[inline]
773    fn default() -> Self {
774        Self::DEFAULT
775    }
776}
777
778impl From<AlignItems> for Option<taffy::AlignItems> {
779    #[inline]
780    fn from(value: AlignItems) -> Self {
781        match value {
782            AlignItems::None => None,
783            AlignItems::Start => Some(taffy::AlignItems::Start),
784            AlignItems::End => Some(taffy::AlignItems::End),
785            AlignItems::FlexStart => Some(taffy::AlignItems::FlexStart),
786            AlignItems::FlexEnd => Some(taffy::AlignItems::FlexEnd),
787            AlignItems::Center => Some(taffy::AlignItems::Center),
788            AlignItems::Baseline => Some(taffy::AlignItems::Baseline),
789            AlignItems::Stretch => Some(taffy::AlignItems::Stretch),
790        }
791    }
792}
793
794/// Sets the distribution of space between and around content items.
795/// For Flexbox it controls alignment in the main axis.
796/// For Grid it controls alignment in the inline axis.
797pub type JustifyContent = AlignContent;
798
799impl FlexboxContainerStyle for WithCtx<&Ui> {
800    #[inline]
801    fn flex_direction(&self) -> taffy::FlexDirection {
802        self.item.flex_direction.into()
803    }
804
805    #[inline]
806    fn flex_wrap(&self) -> taffy::FlexWrap {
807        self.item.flex_wrap.into()
808    }
809
810    #[inline]
811    fn gap(&self) -> taffy::Size<taffy::LengthPercentage> {
812        WithCtx {
813            width: self.width,
814            height: self.height,
815            item: self.item.gap,
816        }
817        .into()
818    }
819
820    #[inline]
821    fn align_content(&self) -> Option<taffy::AlignContent> {
822        self.item.align_content.into()
823    }
824
825    #[inline]
826    fn align_items(&self) -> Option<taffy::AlignItems> {
827        self.item.align_items.into()
828    }
829
830    #[inline]
831    fn justify_content(&self) -> Option<taffy::JustifyContent> {
832        self.item.justify_content.into()
833    }
834}
835
836/// Controls alignment of an individual node.
837pub type AlignSelf = AlignItems;
838
839impl FlexboxItemStyle for WithCtx<&Ui> {
840    #[inline]
841    fn flex_basis(&self) -> taffy::Dimension {
842        WithCtx {
843            width: self.width,
844            height: self.height,
845            item: self.item.flex_basis,
846        }
847        .into()
848    }
849
850    #[inline]
851    fn flex_grow(&self) -> f32 {
852        self.item.flex_grow
853    }
854
855    #[inline]
856    fn flex_shrink(&self) -> f32 {
857        self.item.flex_shrink
858    }
859
860    #[inline]
861    fn align_self(&self) -> Option<taffy::AlignSelf> {
862        self.item.align_self.into()
863    }
864}
865
866impl BlockContainerStyle for WithCtx<&Ui> {
867    #[inline]
868    fn text_align(&self) -> taffy::TextAlign {
869        taffy::TextAlign::Auto
870    }
871}
872
873impl BlockItemStyle for WithCtx<&Ui> {
874    #[inline]
875    fn is_table(&self) -> bool {
876        false
877    }
878}