diff --git a/crates/bevy_ui/src/layout/convert.rs b/crates/bevy_ui/src/layout/convert.rs index a45bb5ab0a11d..91a34a796df9e 100644 --- a/crates/bevy_ui/src/layout/convert.rs +++ b/crates/bevy_ui/src/layout/convert.rs @@ -157,10 +157,15 @@ impl From for Option { match value { AlignItems::Default => None, AlignItems::Start => taffy::style::AlignItems::START.into(), + AlignItems::StartSafe => taffy::style::AlignItems::SAFE_START.into(), AlignItems::End => taffy::style::AlignItems::END.into(), + AlignItems::EndSafe => taffy::style::AlignItems::SAFE_END.into(), AlignItems::FlexStart => taffy::style::AlignItems::FLEX_START.into(), + AlignItems::FlexStartSafe => taffy::style::AlignItems::SAFE_FLEX_START.into(), AlignItems::FlexEnd => taffy::style::AlignItems::FLEX_END.into(), + AlignItems::FlexEndSafe => taffy::style::AlignItems::SAFE_FLEX_END.into(), AlignItems::Center => taffy::style::AlignItems::CENTER.into(), + AlignItems::CenterSafe => taffy::style::AlignItems::SAFE_CENTER.into(), AlignItems::Baseline => taffy::style::AlignItems::BASELINE.into(), AlignItems::Stretch => taffy::style::AlignItems::STRETCH.into(), } @@ -172,8 +177,11 @@ impl From for Option { match value { JustifyItems::Default => None, JustifyItems::Start => taffy::style::JustifyItems::START.into(), + JustifyItems::StartSafe => taffy::style::JustifyItems::SAFE_START.into(), JustifyItems::End => taffy::style::JustifyItems::END.into(), + JustifyItems::EndSafe => taffy::style::JustifyItems::SAFE_END.into(), JustifyItems::Center => taffy::style::JustifyItems::CENTER.into(), + JustifyItems::CenterSafe => taffy::style::JustifyItems::SAFE_CENTER.into(), JustifyItems::Baseline => taffy::style::JustifyItems::BASELINE.into(), JustifyItems::Stretch => taffy::style::JustifyItems::STRETCH.into(), } @@ -185,10 +193,15 @@ impl From for Option { match value { AlignSelf::Auto => None, AlignSelf::Start => taffy::style::AlignSelf::START.into(), + AlignSelf::StartSafe => taffy::style::AlignSelf::SAFE_START.into(), AlignSelf::End => taffy::style::AlignSelf::END.into(), + AlignSelf::EndSafe => taffy::style::AlignSelf::SAFE_END.into(), AlignSelf::FlexStart => taffy::style::AlignSelf::FLEX_START.into(), + AlignSelf::FlexStartSafe => taffy::style::AlignSelf::SAFE_FLEX_START.into(), AlignSelf::FlexEnd => taffy::style::AlignSelf::FLEX_END.into(), + AlignSelf::FlexEndSafe => taffy::style::AlignSelf::SAFE_FLEX_END.into(), AlignSelf::Center => taffy::style::AlignSelf::CENTER.into(), + AlignSelf::CenterSafe => taffy::style::AlignSelf::SAFE_CENTER.into(), AlignSelf::Baseline => taffy::style::AlignSelf::BASELINE.into(), AlignSelf::Stretch => taffy::style::AlignSelf::STRETCH.into(), } @@ -200,8 +213,11 @@ impl From for Option { match value { JustifySelf::Auto => None, JustifySelf::Start => taffy::style::JustifySelf::START.into(), + JustifySelf::StartSafe => taffy::style::JustifySelf::SAFE_START.into(), JustifySelf::End => taffy::style::JustifySelf::END.into(), + JustifySelf::EndSafe => taffy::style::JustifySelf::SAFE_END.into(), JustifySelf::Center => taffy::style::JustifySelf::CENTER.into(), + JustifySelf::CenterSafe => taffy::style::JustifySelf::SAFE_CENTER.into(), JustifySelf::Baseline => taffy::style::JustifySelf::BASELINE.into(), JustifySelf::Stretch => taffy::style::JustifySelf::STRETCH.into(), } @@ -213,10 +229,15 @@ impl From for Option { match value { AlignContent::Default => None, AlignContent::Start => taffy::style::AlignContent::START.into(), + AlignContent::StartSafe => taffy::style::AlignContent::SAFE_START.into(), AlignContent::End => taffy::style::AlignContent::END.into(), + AlignContent::EndSafe => taffy::style::AlignContent::SAFE_END.into(), AlignContent::FlexStart => taffy::style::AlignContent::FLEX_START.into(), + AlignContent::FlexStartSafe => taffy::style::AlignContent::SAFE_FLEX_START.into(), AlignContent::FlexEnd => taffy::style::AlignContent::FLEX_END.into(), + AlignContent::FlexEndSafe => taffy::style::AlignContent::SAFE_FLEX_END.into(), AlignContent::Center => taffy::style::AlignContent::CENTER.into(), + AlignContent::CenterSafe => taffy::style::AlignContent::SAFE_CENTER.into(), AlignContent::Stretch => taffy::style::AlignContent::STRETCH.into(), AlignContent::SpaceBetween => taffy::style::AlignContent::SPACE_BETWEEN.into(), AlignContent::SpaceAround => taffy::style::AlignContent::SPACE_AROUND.into(), @@ -230,10 +251,15 @@ impl From for Option { match value { JustifyContent::Default => None, JustifyContent::Start => taffy::style::JustifyContent::START.into(), + JustifyContent::StartSafe => taffy::style::JustifyContent::SAFE_START.into(), JustifyContent::End => taffy::style::JustifyContent::END.into(), + JustifyContent::EndSafe => taffy::style::JustifyContent::SAFE_END.into(), JustifyContent::FlexStart => taffy::style::JustifyContent::FLEX_START.into(), + JustifyContent::FlexStartSafe => taffy::style::JustifyContent::SAFE_FLEX_START.into(), JustifyContent::FlexEnd => taffy::style::JustifyContent::FLEX_END.into(), + JustifyContent::FlexEndSafe => taffy::style::JustifyContent::SAFE_FLEX_END.into(), JustifyContent::Center => taffy::style::JustifyContent::CENTER.into(), + JustifyContent::CenterSafe => taffy::style::JustifyContent::SAFE_CENTER.into(), JustifyContent::Stretch => taffy::style::JustifyContent::STRETCH.into(), JustifyContent::SpaceBetween => taffy::style::JustifyContent::SPACE_BETWEEN.into(), JustifyContent::SpaceAround => taffy::style::JustifyContent::SPACE_AROUND.into(), diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 322b49fd8d106..27ebc2c820fbb 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -884,6 +884,11 @@ pub enum InlineDirection { /// - For Flexbox containers, sets default cross axis alignment of the child items. /// - For CSS Grid containers, controls block (vertical) axis alignment of children of this grid container within their grid areas. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -897,16 +902,26 @@ pub enum AlignItems { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed towards the start of the axis, unless the flex direction is reversed; /// then they are packed towards the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// The items are packed towards the end of the axis, unless the flex direction is reversed; /// then they are packed towards the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// The items are packed along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are packed such that their baselines align. Baseline, /// The items are stretched to fill the space they're given. @@ -915,6 +930,46 @@ pub enum AlignItems { impl AlignItems { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + AlignItems::StartSafe + | AlignItems::CenterSafe + | AlignItems::EndSafe + | AlignItems::FlexStartSafe + | AlignItems::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + AlignItems::Default + | AlignItems::Start + | AlignItems::Center + | AlignItems::End + | AlignItems::FlexStart + | AlignItems::FlexEnd + | AlignItems::Baseline + | AlignItems::Stretch => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + AlignItems::Start => AlignItems::StartSafe, + AlignItems::Center => AlignItems::CenterSafe, + AlignItems::End => AlignItems::EndSafe, + AlignItems::FlexStart => AlignItems::FlexStartSafe, + AlignItems::FlexEnd => AlignItems::FlexEndSafe, + AlignItems::Default + | AlignItems::StartSafe + | AlignItems::EndSafe + | AlignItems::CenterSafe + | AlignItems::FlexStartSafe + | AlignItems::FlexEndSafe + | AlignItems::Baseline + | AlignItems::Stretch => self, + } + } } impl Default for AlignItems { @@ -927,6 +982,11 @@ impl Default for AlignItems { /// - For Flexbox containers, this property has no effect. See `justify_content` for main axis alignment of flex items. /// - For CSS Grid containers, sets default inline (horizontal) axis alignment of child items within their grid areas. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -940,10 +1000,16 @@ pub enum JustifyItems { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed along the center of the axis Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are packed such that their baselines align. Baseline, /// The items are stretched to fill the space they're given. @@ -952,6 +1018,36 @@ pub enum JustifyItems { impl JustifyItems { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + JustifyItems::StartSafe | JustifyItems::CenterSafe | JustifyItems::EndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + JustifyItems::Default + | JustifyItems::Start + | JustifyItems::Center + | JustifyItems::End + | JustifyItems::Baseline + | JustifyItems::Stretch => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + JustifyItems::Start => JustifyItems::StartSafe, + JustifyItems::Center => JustifyItems::CenterSafe, + JustifyItems::End => JustifyItems::EndSafe, + JustifyItems::Default + | JustifyItems::StartSafe + | JustifyItems::EndSafe + | JustifyItems::CenterSafe + | JustifyItems::Baseline + | JustifyItems::Stretch => self, + } + } } impl Default for JustifyItems { @@ -964,6 +1060,11 @@ impl Default for JustifyItems { /// - For Flexbox items, controls cross axis alignment of the item. /// - For CSS Grid items, controls block (vertical) axis alignment of a grid item within its grid area. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -977,16 +1078,26 @@ pub enum AlignSelf { Auto, /// This item will be aligned with the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// This item will be aligned with the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// This item will be aligned with the start of the axis, unless the flex direction is reversed; /// then it will be aligned with the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// This item will be aligned with the end of the axis, unless the flex direction is reversed; /// then it will be aligned with the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// This item will be aligned along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// This item will be aligned at the baseline. Baseline, /// This item will be stretched to fill the container. @@ -995,6 +1106,46 @@ pub enum AlignSelf { impl AlignSelf { pub const DEFAULT: Self = Self::Auto; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + AlignSelf::StartSafe + | AlignSelf::CenterSafe + | AlignSelf::EndSafe + | AlignSelf::FlexStartSafe + | AlignSelf::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + AlignSelf::Start + | AlignSelf::Center + | AlignSelf::End + | AlignSelf::FlexStart + | AlignSelf::FlexEnd + | AlignSelf::Stretch + | AlignSelf::Auto + | AlignSelf::Baseline => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + AlignSelf::Start => AlignSelf::StartSafe, + AlignSelf::Center => AlignSelf::CenterSafe, + AlignSelf::End => AlignSelf::EndSafe, + AlignSelf::FlexStart => AlignSelf::FlexStartSafe, + AlignSelf::FlexEnd => AlignSelf::FlexEndSafe, + AlignSelf::StartSafe + | AlignSelf::EndSafe + | AlignSelf::CenterSafe + | AlignSelf::FlexStartSafe + | AlignSelf::FlexEndSafe + | AlignSelf::Stretch + | AlignSelf::Auto + | AlignSelf::Baseline => self, + } + } } impl Default for AlignSelf { @@ -1007,6 +1158,11 @@ impl Default for AlignSelf { /// - For children of flex nodes, this property has no effect. See `justify_content` for main axis alignment of flex items. /// - For CSS Grid items, controls inline (horizontal) axis alignment of a grid item within its grid area. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1020,10 +1176,16 @@ pub enum JustifySelf { Auto, /// This item will be aligned with the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// This item will be aligned with the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// This item will be aligned along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// This item will be aligned at the baseline. Baseline, /// This item will be stretched to fill the space it's given. @@ -1032,6 +1194,36 @@ pub enum JustifySelf { impl JustifySelf { pub const DEFAULT: Self = Self::Auto; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + JustifySelf::StartSafe | JustifySelf::CenterSafe | JustifySelf::EndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + JustifySelf::Start + | JustifySelf::Center + | JustifySelf::End + | JustifySelf::Auto + | JustifySelf::Stretch + | JustifySelf::Baseline => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + JustifySelf::Start => JustifySelf::StartSafe, + JustifySelf::Center => JustifySelf::CenterSafe, + JustifySelf::End => JustifySelf::EndSafe, + JustifySelf::StartSafe + | JustifySelf::EndSafe + | JustifySelf::CenterSafe + | JustifySelf::Auto + | JustifySelf::Stretch + | JustifySelf::Baseline => self, + } + } } impl Default for JustifySelf { @@ -1044,6 +1236,11 @@ impl Default for JustifySelf { /// - For Flexbox containers, controls alignment of lines if `flex_wrap` is set to [`FlexWrap::Wrap`] and there are multiple lines of items. /// - For CSS Grid containers, controls alignment of grid rows. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1057,16 +1254,26 @@ pub enum AlignContent { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed towards the start of the axis, unless the flex direction is reversed; /// then the items are packed towards the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// The items are packed towards the end of the axis, unless the flex direction is reversed; /// then the items are packed towards the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// The items are packed along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are stretched to fill the container along the axis. Stretch, /// The items are distributed such that the gap between any two items is equal. @@ -1079,6 +1286,50 @@ pub enum AlignContent { impl AlignContent { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + AlignContent::StartSafe + | AlignContent::CenterSafe + | AlignContent::EndSafe + | AlignContent::FlexStartSafe + | AlignContent::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + AlignContent::Default + | AlignContent::Start + | AlignContent::Center + | AlignContent::End + | AlignContent::FlexStart + | AlignContent::FlexEnd + | AlignContent::Stretch + | AlignContent::SpaceBetween + | AlignContent::SpaceEvenly + | AlignContent::SpaceAround => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + AlignContent::Start => AlignContent::StartSafe, + AlignContent::Center => AlignContent::CenterSafe, + AlignContent::End => AlignContent::EndSafe, + AlignContent::FlexStart => AlignContent::FlexStartSafe, + AlignContent::FlexEnd => AlignContent::FlexEndSafe, + AlignContent::Default + | AlignContent::StartSafe + | AlignContent::EndSafe + | AlignContent::CenterSafe + | AlignContent::FlexStartSafe + | AlignContent::FlexEndSafe + | AlignContent::Stretch + | AlignContent::SpaceBetween + | AlignContent::SpaceEvenly + | AlignContent::SpaceAround => self, + } + } } impl Default for AlignContent { @@ -1091,6 +1342,11 @@ impl Default for AlignContent { /// - For Flexbox containers, controls alignment of items in the main axis. /// - For CSS Grid containers, controls alignment of grid columns. /// +/// # Safe alignments +/// +/// Safe alignments will fall back to [`Self::Start`] if aligning the items would overflow the container, so +/// the start of the content stays visible. +/// /// #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect)] #[reflect(Default, PartialEq, Clone)] @@ -1104,16 +1360,26 @@ pub enum JustifyContent { Default, /// The items are packed towards the start of the axis. Start, + /// Like [`Start`](Self::Start) but safe [`safe`](Self#safe-alignments) + StartSafe, /// The items are packed towards the end of the axis. End, + /// Like [`End`](Self::End) but safe [`safe`](Self#safe-alignments) + EndSafe, /// The items are packed towards the start of the axis, unless the flex direction is reversed; /// then the items are packed towards the end of the axis. FlexStart, + /// Like [`FlexStart`](Self::FlexStart) but safe [`safe`](Self#safe-alignments) + FlexStartSafe, /// The items are packed towards the end of the axis, unless the flex direction is reversed; /// then the items are packed towards the start of the axis. FlexEnd, + /// Like [`FlexEnd`](Self::FlexEnd) but safe [`safe`](Self#safe-alignments) + FlexEndSafe, /// The items are packed along the center of the axis. Center, + /// Like [`Center`](Self::Center) but safe [`safe`](Self#safe-alignments) + CenterSafe, /// The items are stretched to fill the container along the axis. Stretch, /// The items are distributed such that the gap between any two items is equal. @@ -1126,6 +1392,50 @@ pub enum JustifyContent { impl JustifyContent { pub const DEFAULT: Self = Self::Default; + + /// Returns `true` is this alignment is considered [`safe`](Self#safe-alignments). + pub const fn is_safe(&self) -> bool { + match self { + JustifyContent::StartSafe + | JustifyContent::CenterSafe + | JustifyContent::EndSafe + | JustifyContent::FlexStartSafe + | JustifyContent::FlexEndSafe => true, + // Explicitly enumerate variants so we don't forget to extend this when changing them. + JustifyContent::Default + | JustifyContent::Start + | JustifyContent::Center + | JustifyContent::End + | JustifyContent::FlexStart + | JustifyContent::FlexEnd + | JustifyContent::Stretch + | JustifyContent::SpaceBetween + | JustifyContent::SpaceEvenly + | JustifyContent::SpaceAround => false, + } + } + + /// Converts `self` to a [`safe`](Self#safe-alignments) alignment if possible. + /// Returns `self` if there isn't a `safe` variant. + pub const fn to_safe(self) -> Self { + match self { + JustifyContent::Start => JustifyContent::StartSafe, + JustifyContent::Center => JustifyContent::CenterSafe, + JustifyContent::End => JustifyContent::EndSafe, + JustifyContent::FlexStart => JustifyContent::FlexStartSafe, + JustifyContent::FlexEnd => JustifyContent::FlexEndSafe, + JustifyContent::Default + | JustifyContent::StartSafe + | JustifyContent::EndSafe + | JustifyContent::CenterSafe + | JustifyContent::FlexStartSafe + | JustifyContent::FlexEndSafe + | JustifyContent::Stretch + | JustifyContent::SpaceBetween + | JustifyContent::SpaceEvenly + | JustifyContent::SpaceAround => self, + } + } } impl Default for JustifyContent {