 08bf1a6c2e
			
		
	
	
		08bf1a6c2e
		
			
		
	
	
	
	
		
			
			# Objective - Simplify API and make authoring styles easier See: https://github.com/bevyengine/bevy/issues/8540#issuecomment-1536177102 ## Solution - The `size`, `min_size`, `max_size`, and `gap` properties have been replaced by `width`, `height`, `min_width`, `min_height`, `max_width`, `max_height`, `row_gap`, and `column_gap` properties --- ## Changelog - Flattened `Style` properties that have a `Size` value directly into `Style` ## Migration Guide - The `size`, `min_size`, `max_size`, and `gap` properties have been replaced by the `width`, `height`, `min_width`, `min_height`, `max_width`, `max_height`, `row_gap`, and `column_gap` properties. Use the new properties instead. --------- Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
		
			
				
	
	
		
			1805 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			1805 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::UiRect;
 | |
| use bevy_asset::Handle;
 | |
| use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
 | |
| use bevy_math::{Rect, Vec2};
 | |
| use bevy_reflect::prelude::*;
 | |
| use bevy_reflect::ReflectFromReflect;
 | |
| use bevy_render::{
 | |
|     color::Color,
 | |
|     texture::{Image, DEFAULT_IMAGE_HANDLE},
 | |
| };
 | |
| use bevy_transform::prelude::GlobalTransform;
 | |
| use serde::{Deserialize, Serialize};
 | |
| use smallvec::SmallVec;
 | |
| use std::ops::{Div, DivAssign, Mul, MulAssign};
 | |
| use thiserror::Error;
 | |
| 
 | |
| /// Describes the size of a UI node
 | |
| #[derive(Component, Debug, Copy, Clone, Reflect)]
 | |
| #[reflect(Component, Default)]
 | |
| pub struct Node {
 | |
|     /// The size of the node as width and height in logical pixels
 | |
|     /// automatically calculated by [`super::layout::ui_layout_system`]
 | |
|     pub(crate) calculated_size: Vec2,
 | |
| }
 | |
| 
 | |
| impl Node {
 | |
|     /// The calculated node size as width and height in logical pixels
 | |
|     /// automatically calculated by [`super::layout::ui_layout_system`]
 | |
|     pub const fn size(&self) -> Vec2 {
 | |
|         self.calculated_size
 | |
|     }
 | |
| 
 | |
|     /// Returns the size of the node in physical pixels based on the given scale factor.
 | |
|     #[inline]
 | |
|     pub fn physical_size(&self, scale_factor: f64) -> Vec2 {
 | |
|         Vec2::new(
 | |
|             (self.calculated_size.x as f64 * scale_factor) as f32,
 | |
|             (self.calculated_size.y as f64 * scale_factor) as f32,
 | |
|         )
 | |
|     }
 | |
| 
 | |
|     /// Returns the logical pixel coordinates of the UI node, based on its [`GlobalTransform`].
 | |
|     #[inline]
 | |
|     pub fn logical_rect(&self, transform: &GlobalTransform) -> Rect {
 | |
|         Rect::from_center_size(transform.translation().truncate(), self.size())
 | |
|     }
 | |
| 
 | |
|     /// Returns the physical pixel coordinates of the UI node, based on its [`GlobalTransform`] and the scale factor.
 | |
|     #[inline]
 | |
|     pub fn physical_rect(&self, transform: &GlobalTransform, scale_factor: f64) -> Rect {
 | |
|         let rect = self.logical_rect(transform);
 | |
|         Rect {
 | |
|             min: Vec2::new(
 | |
|                 (rect.min.x as f64 * scale_factor) as f32,
 | |
|                 (rect.min.y as f64 * scale_factor) as f32,
 | |
|             ),
 | |
|             max: Vec2::new(
 | |
|                 (rect.max.x as f64 * scale_factor) as f32,
 | |
|                 (rect.max.y as f64 * scale_factor) as f32,
 | |
|             ),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Node {
 | |
|     pub const DEFAULT: Self = Self {
 | |
|         calculated_size: Vec2::ZERO,
 | |
|     };
 | |
| }
 | |
| 
 | |
| impl Default for Node {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Represents the possible value types for layout properties.
 | |
| ///
 | |
| /// This enum allows specifying values for various [`Style`] properties in different units,
 | |
| /// such as logical pixels, percentages, or automatically determined values.
 | |
| #[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum Val {
 | |
|     /// Automatically determine the value based on the context and other `Style` properties.
 | |
|     Auto,
 | |
|     /// Set this value in logical pixels.
 | |
|     Px(f32),
 | |
|     /// Set the value as a percentage of its parent node's length along a specific axis.
 | |
|     ///
 | |
|     /// If the UI node has no parent, the percentage is calculated based on the window's length
 | |
|     /// along the corresponding axis.
 | |
|     ///
 | |
|     /// The chosen axis depends on the `Style` field set:
 | |
|     /// * For `flex_basis`, the percentage is relative to the main-axis length determined by the `flex_direction`.
 | |
|     /// * For `gap`, `min_size`, `size`, and `max_size`:
 | |
|     ///   - `width` is relative to the parent's width.
 | |
|     ///   - `height` is relative to the parent's height.
 | |
|     /// * For `margin`, `padding`, and `border` values: the percentage is relative to the parent node's width.
 | |
|     /// * For positions, `left` and `right` are relative to the parent's width, while `bottom` and `top` are relative to the parent's height.
 | |
|     Percent(f32),
 | |
|     /// Set this value in percent of the viewport width
 | |
|     Vw(f32),
 | |
|     /// Set this value in percent of the viewport height
 | |
|     Vh(f32),
 | |
|     /// Set this value in percent of the viewport's smaller dimension.
 | |
|     VMin(f32),
 | |
|     /// Set this value in percent of the viewport's larger dimension.
 | |
|     VMax(f32),
 | |
| }
 | |
| 
 | |
| impl Val {
 | |
|     pub const DEFAULT: Self = Self::Auto;
 | |
| }
 | |
| 
 | |
| impl Default for Val {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Mul<f32> for Val {
 | |
|     type Output = Val;
 | |
| 
 | |
|     fn mul(self, rhs: f32) -> Self::Output {
 | |
|         match self {
 | |
|             Val::Auto => Val::Auto,
 | |
|             Val::Px(value) => Val::Px(value * rhs),
 | |
|             Val::Percent(value) => Val::Percent(value * rhs),
 | |
|             Val::Vw(value) => Val::Vw(value * rhs),
 | |
|             Val::Vh(value) => Val::Vh(value * rhs),
 | |
|             Val::VMin(value) => Val::VMin(value * rhs),
 | |
|             Val::VMax(value) => Val::VMax(value * rhs),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl MulAssign<f32> for Val {
 | |
|     fn mul_assign(&mut self, rhs: f32) {
 | |
|         match self {
 | |
|             Val::Auto => {}
 | |
|             Val::Px(value)
 | |
|             | Val::Percent(value)
 | |
|             | Val::Vw(value)
 | |
|             | Val::Vh(value)
 | |
|             | Val::VMin(value)
 | |
|             | Val::VMax(value) => *value *= rhs,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Div<f32> for Val {
 | |
|     type Output = Val;
 | |
| 
 | |
|     fn div(self, rhs: f32) -> Self::Output {
 | |
|         match self {
 | |
|             Val::Auto => Val::Auto,
 | |
|             Val::Px(value) => Val::Px(value / rhs),
 | |
|             Val::Percent(value) => Val::Percent(value / rhs),
 | |
|             Val::Vw(value) => Val::Vw(value / rhs),
 | |
|             Val::Vh(value) => Val::Vh(value / rhs),
 | |
|             Val::VMin(value) => Val::VMin(value / rhs),
 | |
|             Val::VMax(value) => Val::VMax(value / rhs),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl DivAssign<f32> for Val {
 | |
|     fn div_assign(&mut self, rhs: f32) {
 | |
|         match self {
 | |
|             Val::Auto => {}
 | |
|             Val::Px(value)
 | |
|             | Val::Percent(value)
 | |
|             | Val::Vw(value)
 | |
|             | Val::Vh(value)
 | |
|             | Val::VMin(value)
 | |
|             | Val::VMax(value) => *value /= rhs,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Debug, Eq, PartialEq, Clone, Copy, Error)]
 | |
| pub enum ValArithmeticError {
 | |
|     #[error("the variants of the Vals don't match")]
 | |
|     NonIdenticalVariants,
 | |
|     #[error("the given variant of Val is not evaluateable (non-numeric)")]
 | |
|     NonEvaluateable,
 | |
| }
 | |
| 
 | |
| impl Val {
 | |
|     /// Tries to add the values of two [`Val`]s.
 | |
|     /// Returns [`ValArithmeticError::NonIdenticalVariants`] if two [`Val`]s are of different variants.
 | |
|     /// When adding non-numeric [`Val`]s, it returns the value unchanged.
 | |
|     pub fn try_add(&self, rhs: Val) -> Result<Val, ValArithmeticError> {
 | |
|         match (self, rhs) {
 | |
|             (Val::Auto, Val::Auto) => Ok(*self),
 | |
|             (Val::Px(value), Val::Px(rhs_value)) => Ok(Val::Px(value + rhs_value)),
 | |
|             (Val::Percent(value), Val::Percent(rhs_value)) => Ok(Val::Percent(value + rhs_value)),
 | |
|             _ => Err(ValArithmeticError::NonIdenticalVariants),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Adds `rhs` to `self` and assigns the result to `self` (see [`Val::try_add`])
 | |
|     pub fn try_add_assign(&mut self, rhs: Val) -> Result<(), ValArithmeticError> {
 | |
|         *self = self.try_add(rhs)?;
 | |
|         Ok(())
 | |
|     }
 | |
| 
 | |
|     /// Tries to subtract the values of two [`Val`]s.
 | |
|     /// Returns [`ValArithmeticError::NonIdenticalVariants`] if two [`Val`]s are of different variants.
 | |
|     /// When adding non-numeric [`Val`]s, it returns the value unchanged.
 | |
|     pub fn try_sub(&self, rhs: Val) -> Result<Val, ValArithmeticError> {
 | |
|         match (self, rhs) {
 | |
|             (Val::Auto, Val::Auto) => Ok(*self),
 | |
|             (Val::Px(value), Val::Px(rhs_value)) => Ok(Val::Px(value - rhs_value)),
 | |
|             (Val::Percent(value), Val::Percent(rhs_value)) => Ok(Val::Percent(value - rhs_value)),
 | |
|             _ => Err(ValArithmeticError::NonIdenticalVariants),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Subtracts `rhs` from `self` and assigns the result to `self` (see [`Val::try_sub`])
 | |
|     pub fn try_sub_assign(&mut self, rhs: Val) -> Result<(), ValArithmeticError> {
 | |
|         *self = self.try_sub(rhs)?;
 | |
|         Ok(())
 | |
|     }
 | |
| 
 | |
|     /// A convenience function for simple evaluation of [`Val::Percent`] variant into a concrete [`Val::Px`] value.
 | |
|     /// Returns a [`ValArithmeticError::NonEvaluateable`] if the [`Val`] is impossible to evaluate into [`Val::Px`].
 | |
|     /// Otherwise it returns an [`f32`] containing the evaluated value in pixels.
 | |
|     ///
 | |
|     /// **Note:** If a [`Val::Px`] is evaluated, it's inner value returned unchanged.
 | |
|     pub fn evaluate(&self, size: f32) -> Result<f32, ValArithmeticError> {
 | |
|         match self {
 | |
|             Val::Percent(value) => Ok(size * value / 100.0),
 | |
|             Val::Px(value) => Ok(*value),
 | |
|             _ => Err(ValArithmeticError::NonEvaluateable),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Similar to [`Val::try_add`], but performs [`Val::evaluate`] on both values before adding.
 | |
|     /// Returns an [`f32`] value in pixels.
 | |
|     pub fn try_add_with_size(&self, rhs: Val, size: f32) -> Result<f32, ValArithmeticError> {
 | |
|         let lhs = self.evaluate(size)?;
 | |
|         let rhs = rhs.evaluate(size)?;
 | |
| 
 | |
|         Ok(lhs + rhs)
 | |
|     }
 | |
| 
 | |
|     /// Similar to [`Val::try_add_assign`], but performs [`Val::evaluate`] on both values before adding.
 | |
|     /// The value gets converted to [`Val::Px`].
 | |
|     pub fn try_add_assign_with_size(
 | |
|         &mut self,
 | |
|         rhs: Val,
 | |
|         size: f32,
 | |
|     ) -> Result<(), ValArithmeticError> {
 | |
|         *self = Val::Px(self.evaluate(size)? + rhs.evaluate(size)?);
 | |
|         Ok(())
 | |
|     }
 | |
| 
 | |
|     /// Similar to [`Val::try_sub`], but performs [`Val::evaluate`] on both values before subtracting.
 | |
|     /// Returns an [`f32`] value in pixels.
 | |
|     pub fn try_sub_with_size(&self, rhs: Val, size: f32) -> Result<f32, ValArithmeticError> {
 | |
|         let lhs = self.evaluate(size)?;
 | |
|         let rhs = rhs.evaluate(size)?;
 | |
| 
 | |
|         Ok(lhs - rhs)
 | |
|     }
 | |
| 
 | |
|     /// Similar to [`Val::try_sub_assign`], but performs [`Val::evaluate`] on both values before adding.
 | |
|     /// The value gets converted to [`Val::Px`].
 | |
|     pub fn try_sub_assign_with_size(
 | |
|         &mut self,
 | |
|         rhs: Val,
 | |
|         size: f32,
 | |
|     ) -> Result<(), ValArithmeticError> {
 | |
|         *self = Val::Px(self.try_add_with_size(rhs, size)?);
 | |
|         Ok(())
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Describes the style of a UI container node
 | |
| ///
 | |
| /// Node's can be laid out using either Flexbox or CSS Grid Layout.<br />
 | |
| /// See below for general learning resources and for documentation on the individual style properties.
 | |
| ///
 | |
| /// ### Flexbox
 | |
| ///
 | |
| /// - [MDN: Basic Concepts of Grid Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout)
 | |
| /// - [A Complete Guide To Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) by CSS Tricks. This is detailed guide with illustrations and comphrehensive written explanation of the different Flexbox properties and how they work.
 | |
| /// - [Flexbox Froggy](https://flexboxfroggy.com/). An interactive tutorial/game that teaches the essential parts of Flebox in a fun engaging way.
 | |
| ///
 | |
| /// ### CSS Grid
 | |
| ///
 | |
| /// - [MDN: Basic Concepts of Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox)
 | |
| /// - [A Complete Guide To CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) by CSS Tricks. This is detailed guide with illustrations and comphrehensive written explanation of the different CSS Grid properties and how they work.
 | |
| /// - [CSS Grid Garden](https://cssgridgarden.com/). An interactive tutorial/game that teaches the essential parts of CSS Grid in a fun engaging way.
 | |
| 
 | |
| #[derive(Component, Clone, PartialEq, Debug, Reflect, FromReflect)]
 | |
| #[reflect(Component, FromReflect, Default, PartialEq)]
 | |
| pub struct Style {
 | |
|     /// Which layout algorithm to use when laying out this node's contents:
 | |
|     ///   - [`Display::Flex`]: Use the Flexbox layout algorithm
 | |
|     ///   - [`Display::Grid`]: Use the CSS Grid layout algorithm
 | |
|     ///   - [`Display::None`]: Hide this node and perform layout as if it does not exist.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/display>
 | |
|     pub display: Display,
 | |
| 
 | |
|     /// Whether a node should be laid out in-flow with, or independently of it's siblings:
 | |
|     ///  - [`PositionType::Relative`]: Layout this node in-flow with other nodes using the usual (flexbox/grid) layout algorithm.
 | |
|     ///  - [`PositionType::Absolute`]: Layout this node on top and independently of other nodes.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/position>
 | |
|     pub position_type: PositionType,
 | |
| 
 | |
|     /// Whether overflowing content should be displayed or clipped.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
 | |
|     pub overflow: Overflow,
 | |
| 
 | |
|     /// Defines the text direction. For example English is written LTR (left-to-right) while Arabic is written RTL (right-to-left).
 | |
|     ///
 | |
|     /// Note: the corresponding CSS property also affects box layout order, but this isn't yet implemented in bevy.
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/direction>
 | |
|     pub direction: Direction,
 | |
| 
 | |
|     /// The horizontal position of the left edge of the node.
 | |
|     ///  - For relatively positioned nodes, this is relative to the node's position as computed during regular layout.
 | |
|     ///  - For absolutely positioned nodes, this is relative to the *parent* node's bounding box.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/left>
 | |
|     pub left: Val,
 | |
| 
 | |
|     /// The horizontal position of the right edge of the node.
 | |
|     ///  - For relatively positioned nodes, this is relative to the node's position as computed during regular layout.
 | |
|     ///  - For absolutely positioned nodes, this is relative to the *parent* node's bounding box.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/right>
 | |
|     pub right: Val,
 | |
| 
 | |
|     /// The vertical position of the top edge of the node.
 | |
|     ///  - For relatively positioned nodes, this is relative to the node's position as computed during regular layout.
 | |
|     ///  - For absolutely positioned nodes, this is relative to the *parent* node's bounding box.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/top>
 | |
|     pub top: Val,
 | |
| 
 | |
|     /// The vertical position of the bottom edge of the node.
 | |
|     ///  - For relatively positioned nodes, this is relative to the node's position as computed during regular layout.
 | |
|     ///  - For absolutely positioned nodes, this is relative to the *parent* node's bounding box.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/bottom>
 | |
|     pub bottom: Val,
 | |
| 
 | |
|     /// The ideal width of the node. `width` is used when it is within the bounds defined by `min_width` and `max_width`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/width>
 | |
|     pub width: Val,
 | |
| 
 | |
|     /// The ideal height of the node. `height` is used when it is within the bounds defined by `min_height` and `max_height`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/height>
 | |
|     pub height: Val,
 | |
| 
 | |
|     /// The minimum width of the node. `min_width` is used if it is greater than either `width` and/or `max_width`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/min-width>
 | |
|     pub min_width: Val,
 | |
| 
 | |
|     /// The minimum height of the node. `min_height` is used if it is greater than either `height` and/or `max_height`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/min-height>
 | |
|     pub min_height: Val,
 | |
| 
 | |
|     /// The maximum width of the node. `max_width` is used if it is within the bounds defined by `min_width` and `width`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/max-width>
 | |
|     pub max_width: Val,
 | |
| 
 | |
|     /// The maximum height of the node. `max_height` is used if it is within the bounds defined by `min_height` and `height`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/max-height>
 | |
|     pub max_height: Val,
 | |
| 
 | |
|     /// The aspect ratio of the node (defined as `width / height`)
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio>
 | |
|     pub aspect_ratio: Option<f32>,
 | |
| 
 | |
|     /// 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
 | |
|     ///
 | |
|     /// This value is overriden [`JustifySelf`] on the child node is set.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>
 | |
|     pub align_items: 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
 | |
|     ///
 | |
|     /// This value is overriden [`JustifySelf`] on the child node is set.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>
 | |
|     pub justify_items: 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 it's grid area
 | |
|     ///
 | |
|     /// If set to `Auto`, alignment is inherited from the value of [`AlignItems`] set on the parent node.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/align-self>
 | |
|     pub align_self: AlignSelf,
 | |
| 
 | |
|     /// For Flexbox items:
 | |
|     ///   - 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 it's grid area.
 | |
|     ///
 | |
|     /// If set to `Auto`, alignment is inherited from the value of [`JustifyItems`] set on the parent node.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>
 | |
|     pub justify_self: 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 container:
 | |
|     ///   - Controls alignment of grid rows
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/align-content>
 | |
|     pub align_content: AlignContent,
 | |
| 
 | |
|     /// For Flexbox containers:
 | |
|     ///   - Controls alignment of items in the main axis
 | |
|     /// For CSS Grid containers:
 | |
|     ///   - Controls alignment of grid columns
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content>
 | |
|     pub justify_content: JustifyContent,
 | |
| 
 | |
|     /// The amount of space around a node outside its border.
 | |
|     ///
 | |
|     /// If a percentage value is used, the percentage is calculated based on the width of the parent node.
 | |
|     ///
 | |
|     /// # Example
 | |
|     /// ```
 | |
|     /// # use bevy_ui::{Style, UiRect, Val};
 | |
|     /// let style = Style {
 | |
|     ///     margin: UiRect {
 | |
|     ///         left: Val::Percent(10.),
 | |
|     ///         right: Val::Percent(10.),
 | |
|     ///         top: Val::Percent(15.),
 | |
|     ///         bottom: Val::Percent(15.)
 | |
|     ///     },
 | |
|     ///     ..Default::default()
 | |
|     /// };
 | |
|     /// ```
 | |
|     /// A node with this style and a parent with dimensions of 100px by 300px, will have calculated margins of 10px on both left and right edges, and 15px on both top and bottom edges.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/margin>
 | |
|     pub margin: UiRect,
 | |
| 
 | |
|     /// The amount of space between the edges of a node and its contents.
 | |
|     ///
 | |
|     /// If a percentage value is used, the percentage is calculated based on the width of the parent node.
 | |
|     ///
 | |
|     /// # Example
 | |
|     /// ```
 | |
|     /// # use bevy_ui::{Style, UiRect, Val};
 | |
|     /// let style = Style {
 | |
|     ///     padding: UiRect {
 | |
|     ///         left: Val::Percent(1.),
 | |
|     ///         right: Val::Percent(2.),
 | |
|     ///         top: Val::Percent(3.),
 | |
|     ///         bottom: Val::Percent(4.)
 | |
|     ///     },
 | |
|     ///     ..Default::default()
 | |
|     /// };
 | |
|     /// ```
 | |
|     /// A node with this style and a parent with dimensions of 300px by 100px, will have calculated padding of 3px on the left, 6px on the right, 9px on the top and 12px on the bottom.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/padding>
 | |
|     pub padding: UiRect,
 | |
| 
 | |
|     /// The amount of space between the margins of a node and its padding.
 | |
|     ///
 | |
|     /// If a percentage value is used, the percentage is calculated based on the width of the parent node.
 | |
|     ///
 | |
|     /// The size of the node will be expanded if there are constraints that prevent the layout algorithm from placing the border within the existing node boundary.
 | |
|     ///
 | |
|     /// Rendering for borders is not yet implemented.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width>
 | |
|     pub border: UiRect,
 | |
| 
 | |
|     /// Whether a Flexbox container should be a row or a column. This property has no effect of Grid nodes.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction>
 | |
|     pub flex_direction: FlexDirection,
 | |
| 
 | |
|     /// Whether a Flexbox container should wrap it's contents onto multiple line wrap if they overflow. This property has no effect of Grid nodes.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap>
 | |
|     pub flex_wrap: FlexWrap,
 | |
| 
 | |
|     /// Defines how much a flexbox item should grow if there's space available. Defaults to 0 (don't grow at all).
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow>
 | |
|     pub flex_grow: f32,
 | |
| 
 | |
|     /// Defines how much a flexbox item should shrink if there's not enough space available. Defaults to 1.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink>
 | |
|     pub flex_shrink: f32,
 | |
| 
 | |
|     /// The initial length of a flexbox in the main axis, before flex growing/shrinking properties are applied.
 | |
|     ///
 | |
|     /// `flex_basis` overrides `size` on the main axis if both are set,  but it obeys the bounds defined by `min_size` and `max_size`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis>
 | |
|     pub flex_basis: Val,
 | |
| 
 | |
|     /// The size of the gutters between items in a vertical flexbox layout or between rows in a grid layout
 | |
|     ///
 | |
|     /// Note: Values of `Val::Auto` are not valid and are treated as zero.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap>
 | |
|     pub row_gap: Val,
 | |
| 
 | |
|     /// The size of the gutters between items in a horizontal flexbox layout or between column in a grid layout
 | |
|     ///
 | |
|     /// Note: Values of `Val::Auto` are not valid and are treated as zero.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap>
 | |
|     pub column_gap: Val,
 | |
| 
 | |
|     /// Controls whether automatically placed grid items are placed row-wise or column-wise. And whether the sparse or dense packing algorithm is used.
 | |
|     /// Only affect Grid layouts
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow>
 | |
|     pub grid_auto_flow: GridAutoFlow,
 | |
| 
 | |
|     /// Defines the number of rows a grid has and the sizes of those rows. If grid items are given explicit placements then more rows may
 | |
|     /// be implicitly generated by items that are placed out of bounds. The sizes of those rows are controlled by `grid_auto_rows` property.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows>
 | |
|     pub grid_template_rows: Vec<RepeatedGridTrack>,
 | |
| 
 | |
|     /// Defines the number of columns a grid has and the sizes of those columns. If grid items are given explicit placements then more columns may
 | |
|     /// be implicitly generated by items that are placed out of bounds. The sizes of those columns are controlled by `grid_auto_columns` property.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
 | |
|     pub grid_template_columns: Vec<RepeatedGridTrack>,
 | |
| 
 | |
|     /// Defines the size of implicitly created rows. Rows are created implicitly when grid items are given explicit placements that are out of bounds
 | |
|     /// of the rows explicitly created using `grid_template_rows`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows>
 | |
|     pub grid_auto_rows: Vec<GridTrack>,
 | |
|     /// Defines the size of implicitly created columns. Columns are created implicitly when grid items are given explicit placements that are out of bounds
 | |
|     /// of the columns explicitly created using `grid_template_columms`.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
 | |
|     pub grid_auto_columns: Vec<GridTrack>,
 | |
| 
 | |
|     /// The row in which a grid item starts and how many rows it spans.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row>
 | |
|     pub grid_row: GridPlacement,
 | |
| 
 | |
|     /// The column in which a grid item starts and how many columns it spans.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column>
 | |
|     pub grid_column: GridPlacement,
 | |
| }
 | |
| 
 | |
| impl Style {
 | |
|     pub const DEFAULT: Self = Self {
 | |
|         display: Display::DEFAULT,
 | |
|         position_type: PositionType::DEFAULT,
 | |
|         left: Val::Auto,
 | |
|         right: Val::Auto,
 | |
|         top: Val::Auto,
 | |
|         bottom: Val::Auto,
 | |
|         direction: Direction::DEFAULT,
 | |
|         flex_direction: FlexDirection::DEFAULT,
 | |
|         flex_wrap: FlexWrap::DEFAULT,
 | |
|         align_items: AlignItems::DEFAULT,
 | |
|         justify_items: JustifyItems::DEFAULT,
 | |
|         align_self: AlignSelf::DEFAULT,
 | |
|         justify_self: JustifySelf::DEFAULT,
 | |
|         align_content: AlignContent::DEFAULT,
 | |
|         justify_content: JustifyContent::DEFAULT,
 | |
|         margin: UiRect::DEFAULT,
 | |
|         padding: UiRect::DEFAULT,
 | |
|         border: UiRect::DEFAULT,
 | |
|         flex_grow: 0.0,
 | |
|         flex_shrink: 1.0,
 | |
|         flex_basis: Val::Auto,
 | |
|         width: Val::Auto,
 | |
|         height: Val::Auto,
 | |
|         min_width: Val::Auto,
 | |
|         min_height: Val::Auto,
 | |
|         max_width: Val::Auto,
 | |
|         max_height: Val::Auto,
 | |
|         aspect_ratio: None,
 | |
|         overflow: Overflow::DEFAULT,
 | |
|         row_gap: Val::Px(0.0),
 | |
|         column_gap: Val::Px(0.0),
 | |
|         grid_auto_flow: GridAutoFlow::DEFAULT,
 | |
|         grid_template_rows: Vec::new(),
 | |
|         grid_template_columns: Vec::new(),
 | |
|         grid_auto_rows: Vec::new(),
 | |
|         grid_auto_columns: Vec::new(),
 | |
|         grid_column: GridPlacement::DEFAULT,
 | |
|         grid_row: GridPlacement::DEFAULT,
 | |
|     };
 | |
| }
 | |
| 
 | |
| impl Default for Style {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// How items are aligned according to the cross axis
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum AlignItems {
 | |
|     /// The items are packed in their default position as if no alignment was applied
 | |
|     Default,
 | |
|     /// Items are packed towards the start of the axis.
 | |
|     Start,
 | |
|     /// Items are packed towards the end of the axis.
 | |
|     End,
 | |
|     /// 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,
 | |
|     /// 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,
 | |
|     /// Items are aligned at the center.
 | |
|     Center,
 | |
|     /// Items are aligned at the baseline.
 | |
|     Baseline,
 | |
|     /// Items are stretched across the whole cross axis.
 | |
|     Stretch,
 | |
| }
 | |
| 
 | |
| impl AlignItems {
 | |
|     pub const DEFAULT: Self = Self::Default;
 | |
| }
 | |
| 
 | |
| impl Default for AlignItems {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// How items are aligned according to the cross axis
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum JustifyItems {
 | |
|     /// The items are packed in their default position as if no alignment was applied
 | |
|     Default,
 | |
|     /// Items are packed towards the start of the axis.
 | |
|     Start,
 | |
|     /// Items are packed towards the end of the axis.
 | |
|     End,
 | |
|     /// Items are aligned at the center.
 | |
|     Center,
 | |
|     /// Items are aligned at the baseline.
 | |
|     Baseline,
 | |
|     /// Items are stretched across the whole cross axis.
 | |
|     Stretch,
 | |
| }
 | |
| 
 | |
| impl JustifyItems {
 | |
|     pub const DEFAULT: Self = Self::Default;
 | |
| }
 | |
| 
 | |
| impl Default for JustifyItems {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// How this item is aligned according to the cross axis.
 | |
| /// Overrides [`AlignItems`].
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum AlignSelf {
 | |
|     /// Use the parent node's [`AlignItems`] value to determine how this item should be aligned.
 | |
|     Auto,
 | |
|     /// This item will be aligned with the start of the axis.
 | |
|     Start,
 | |
|     /// This item will be aligned with the end of the axis.
 | |
|     End,
 | |
|     /// 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,
 | |
|     /// 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,
 | |
|     /// This item will be aligned at the center.
 | |
|     Center,
 | |
|     /// This item will be aligned at the baseline.
 | |
|     Baseline,
 | |
|     /// This item will be stretched across the whole cross axis.
 | |
|     Stretch,
 | |
| }
 | |
| 
 | |
| impl AlignSelf {
 | |
|     pub const DEFAULT: Self = Self::Auto;
 | |
| }
 | |
| 
 | |
| impl Default for AlignSelf {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// How this item is aligned according to the cross axis.
 | |
| /// Overrides [`AlignItems`].
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum JustifySelf {
 | |
|     /// Use the parent node's [`AlignItems`] value to determine how this item should be aligned.
 | |
|     Auto,
 | |
|     /// This item will be aligned with the start of the axis.
 | |
|     Start,
 | |
|     /// This item will be aligned with the end of the axis.
 | |
|     End,
 | |
|     /// This item will be aligned at the center.
 | |
|     Center,
 | |
|     /// This item will be aligned at the baseline.
 | |
|     Baseline,
 | |
|     /// This item will be stretched across the whole cross axis.
 | |
|     Stretch,
 | |
| }
 | |
| 
 | |
| impl JustifySelf {
 | |
|     pub const DEFAULT: Self = Self::Auto;
 | |
| }
 | |
| 
 | |
| impl Default for JustifySelf {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Defines how each line is aligned within the flexbox.
 | |
| ///
 | |
| /// It only applies if [`FlexWrap::Wrap`] is present and if there are multiple lines of items.
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum AlignContent {
 | |
|     /// The items are packed in their default position as if no alignment was applied
 | |
|     Default,
 | |
|     /// Each line moves towards the start of the cross axis.
 | |
|     Start,
 | |
|     /// Each line moves towards the end of the cross axis.
 | |
|     End,
 | |
|     /// Each line moves towards the start of the cross axis, unless the flex direction is reversed; then the line moves towards the end of the cross axis.
 | |
|     FlexStart,
 | |
|     /// Each line moves towards the end of the cross axis, unless the flex direction is reversed; then the line moves towards the start of the cross axis.
 | |
|     FlexEnd,
 | |
|     /// Each line moves towards the center of the cross axis.
 | |
|     Center,
 | |
|     /// Each line will stretch to fill the remaining space.
 | |
|     Stretch,
 | |
|     /// Each line fills the space it needs, putting the remaining space, if any
 | |
|     /// inbetween the lines.
 | |
|     SpaceBetween,
 | |
|     /// The gap between the first and last items is exactly THE SAME as the gap between items.
 | |
|     /// The gaps are distributed evenly.
 | |
|     SpaceEvenly,
 | |
|     /// Each line fills the space it needs, putting the remaining space, if any
 | |
|     /// around the lines.
 | |
|     SpaceAround,
 | |
| }
 | |
| 
 | |
| impl AlignContent {
 | |
|     pub const DEFAULT: Self = Self::Default;
 | |
| }
 | |
| 
 | |
| impl Default for AlignContent {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Defines how items are aligned according to the main axis
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum JustifyContent {
 | |
|     /// The items are packed in their default position as if no alignment was applied
 | |
|     Default,
 | |
|     /// Items are packed toward the start of the axis.
 | |
|     Start,
 | |
|     /// Items are packed toward the end of the axis.
 | |
|     End,
 | |
|     /// Pushed towards the start, unless the flex direction is reversed; then pushed towards the end.
 | |
|     FlexStart,
 | |
|     /// Pushed towards the end, unless the flex direction is reversed; then pushed towards the start.
 | |
|     FlexEnd,
 | |
|     /// Centered along the main axis.
 | |
|     Center,
 | |
|     /// Remaining space is distributed between the items.
 | |
|     SpaceBetween,
 | |
|     /// Remaining space is distributed around the items.
 | |
|     SpaceAround,
 | |
|     /// Like [`JustifyContent::SpaceAround`] but with even spacing between items.
 | |
|     SpaceEvenly,
 | |
| }
 | |
| 
 | |
| impl JustifyContent {
 | |
|     pub const DEFAULT: Self = Self::Default;
 | |
| }
 | |
| 
 | |
| impl Default for JustifyContent {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Defines the text direction
 | |
| ///
 | |
| /// For example English is written LTR (left-to-right) while Arabic is written RTL (right-to-left).
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum Direction {
 | |
|     /// Inherit from parent node.
 | |
|     Inherit,
 | |
|     /// Text is written left to right.
 | |
|     LeftToRight,
 | |
|     /// Text is written right to left.
 | |
|     RightToLeft,
 | |
| }
 | |
| 
 | |
| impl Direction {
 | |
|     pub const DEFAULT: Self = Self::Inherit;
 | |
| }
 | |
| 
 | |
| impl Default for Direction {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Whether to use a Flexbox layout model.
 | |
| ///
 | |
| /// Part of the [`Style`] component.
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum Display {
 | |
|     /// Use Flexbox layout model to determine the position of this [`Node`].
 | |
|     Flex,
 | |
|     /// Use CSS Grid layout model to determine the position of this [`Node`].
 | |
|     Grid,
 | |
|     /// Use no layout, don't render this node and its children.
 | |
|     ///
 | |
|     /// If you want to hide a node and its children,
 | |
|     /// but keep its layout in place, set its [`Visibility`](bevy_render::view::Visibility) component instead.
 | |
|     None,
 | |
| }
 | |
| 
 | |
| impl Display {
 | |
|     pub const DEFAULT: Self = Self::Flex;
 | |
| }
 | |
| 
 | |
| impl Default for Display {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Defines how flexbox items are ordered within a flexbox
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum FlexDirection {
 | |
|     /// Same way as text direction along the main axis.
 | |
|     Row,
 | |
|     /// Flex from top to bottom.
 | |
|     Column,
 | |
|     /// Opposite way as text direction along the main axis.
 | |
|     RowReverse,
 | |
|     /// Flex from bottom to top.
 | |
|     ColumnReverse,
 | |
| }
 | |
| 
 | |
| impl FlexDirection {
 | |
|     pub const DEFAULT: Self = Self::Row;
 | |
| }
 | |
| 
 | |
| impl Default for FlexDirection {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Whether to show or hide overflowing items
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect, Serialize, Deserialize, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub struct Overflow {
 | |
|     /// Whether to show or clip overflowing items on the x axis        
 | |
|     pub x: OverflowAxis,
 | |
|     /// Whether to show or clip overflowing items on the y axis
 | |
|     pub y: OverflowAxis,
 | |
| }
 | |
| 
 | |
| impl Overflow {
 | |
|     pub const DEFAULT: Self = Self {
 | |
|         x: OverflowAxis::DEFAULT,
 | |
|         y: OverflowAxis::DEFAULT,
 | |
|     };
 | |
| 
 | |
|     /// Show overflowing items on both axes
 | |
|     pub const fn visible() -> Self {
 | |
|         Self {
 | |
|             x: OverflowAxis::Visible,
 | |
|             y: OverflowAxis::Visible,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Clip overflowing items on both axes
 | |
|     pub const fn clip() -> Self {
 | |
|         Self {
 | |
|             x: OverflowAxis::Clip,
 | |
|             y: OverflowAxis::Clip,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Clip overflowing items on the x axis
 | |
|     pub const fn clip_x() -> Self {
 | |
|         Self {
 | |
|             x: OverflowAxis::Clip,
 | |
|             y: OverflowAxis::Visible,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Clip overflowing items on the y axis
 | |
|     pub const fn clip_y() -> Self {
 | |
|         Self {
 | |
|             x: OverflowAxis::Visible,
 | |
|             y: OverflowAxis::Clip,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Overflow is visible on both axes
 | |
|     pub const fn is_visible(&self) -> bool {
 | |
|         self.x.is_visible() && self.y.is_visible()
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Default for Overflow {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Whether to show or hide overflowing items
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Reflect, FromReflect, Serialize, Deserialize)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum OverflowAxis {
 | |
|     /// Show overflowing items.
 | |
|     Visible,
 | |
|     /// Hide overflowing items.
 | |
|     Clip,
 | |
| }
 | |
| 
 | |
| impl OverflowAxis {
 | |
|     pub const DEFAULT: Self = Self::Visible;
 | |
| 
 | |
|     /// Overflow is visible on this axis
 | |
|     pub const fn is_visible(&self) -> bool {
 | |
|         matches!(self, Self::Visible)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Default for OverflowAxis {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// The strategy used to position this node
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum PositionType {
 | |
|     /// Relative to all other nodes with the [`PositionType::Relative`] value.
 | |
|     Relative,
 | |
|     /// Independent of all other nodes.
 | |
|     ///
 | |
|     /// As usual, the `Style.position` field of this node is specified relative to its parent node.
 | |
|     Absolute,
 | |
| }
 | |
| 
 | |
| impl PositionType {
 | |
|     const DEFAULT: Self = Self::Relative;
 | |
| }
 | |
| 
 | |
| impl Default for PositionType {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Defines if flexbox items appear on a single line or on multiple lines
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum FlexWrap {
 | |
|     /// Single line, will overflow if needed.
 | |
|     NoWrap,
 | |
|     /// Multiple lines, if needed.
 | |
|     Wrap,
 | |
|     /// Same as [`FlexWrap::Wrap`] but new lines will appear before the previous one.
 | |
|     WrapReverse,
 | |
| }
 | |
| 
 | |
| impl FlexWrap {
 | |
|     const DEFAULT: Self = Self::NoWrap;
 | |
| }
 | |
| 
 | |
| impl Default for FlexWrap {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Controls whether grid items are placed row-wise or column-wise. And whether the sparse or dense packing algorithm is used.
 | |
| ///
 | |
| /// The "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items.
 | |
| ///
 | |
| /// Defaults to [`GridAutoFlow::Row`]
 | |
| ///
 | |
| /// <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow>
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum GridAutoFlow {
 | |
|     /// Items are placed by filling each row in turn, adding new rows as necessary
 | |
|     Row,
 | |
|     /// Items are placed by filling each column in turn, adding new columns as necessary.
 | |
|     Column,
 | |
|     /// Combines `Row` with the dense packing algorithm.
 | |
|     RowDense,
 | |
|     /// Combines `Column` with the dense packing algorithm.
 | |
|     ColumnDense,
 | |
| }
 | |
| 
 | |
| impl GridAutoFlow {
 | |
|     const DEFAULT: Self = Self::Row;
 | |
| }
 | |
| 
 | |
| impl Default for GridAutoFlow {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect_value(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum MinTrackSizingFunction {
 | |
|     /// Track minimum size should be a fixed pixel value
 | |
|     Px(f32),
 | |
|     /// Track minimum size should be a percentage value
 | |
|     Percent(f32),
 | |
|     /// Track minimum size should be content sized under a min-content constraint
 | |
|     MinContent,
 | |
|     /// Track minimum size should be content sized under a max-content constraint
 | |
|     MaxContent,
 | |
|     /// Track minimum size should be automatically sized
 | |
|     Auto,
 | |
| }
 | |
| 
 | |
| #[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect_value(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub enum MaxTrackSizingFunction {
 | |
|     /// Track maximum size should be a fixed pixel value
 | |
|     Px(f32),
 | |
|     /// Track maximum size should be a percentage value
 | |
|     Percent(f32),
 | |
|     /// Track maximum size should be content sized under a min-content constraint
 | |
|     MinContent,
 | |
|     /// Track maximum size should be content sized under a max-content constraint
 | |
|     MaxContent,
 | |
|     /// Track maximum size should be sized according to the fit-content formula with a fixed pixel limit
 | |
|     FitContentPx(f32),
 | |
|     /// Track maximum size should be sized according to the fit-content formula with a percentage limit
 | |
|     FitContentPercent(f32),
 | |
|     /// Track maximum size should be automatically sized
 | |
|     Auto,
 | |
|     /// The dimension as a fraction of the total available grid space (`fr` units in CSS)
 | |
|     /// Specified value is the numerator of the fraction. Denominator is the sum of all fractions specified in that grid dimension
 | |
|     /// Spec: <https://www.w3.org/TR/css3-grid-layout/#fr-unit>
 | |
|     Fraction(f32),
 | |
| }
 | |
| 
 | |
| /// A [`GridTrack`] is a Row or Column of a CSS Grid. This struct specifies what size the track should be.
 | |
| /// See below for the different "track sizing functions" you can specify.
 | |
| #[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub struct GridTrack {
 | |
|     pub(crate) min_sizing_function: MinTrackSizingFunction,
 | |
|     pub(crate) max_sizing_function: MaxTrackSizingFunction,
 | |
| }
 | |
| 
 | |
| impl GridTrack {
 | |
|     const DEFAULT: Self = Self {
 | |
|         min_sizing_function: MinTrackSizingFunction::Auto,
 | |
|         max_sizing_function: MaxTrackSizingFunction::Auto,
 | |
|     };
 | |
| 
 | |
|     /// Create a grid track with a fixed pixel size
 | |
|     pub fn px<T: From<Self>>(value: f32) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Px(value),
 | |
|             max_sizing_function: MaxTrackSizingFunction::Px(value),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a grid track with a percentage size
 | |
|     pub fn percent<T: From<Self>>(value: f32) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Percent(value),
 | |
|             max_sizing_function: MaxTrackSizingFunction::Percent(value),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a grid track with an `fr` size.
 | |
|     /// Note that this will give the track a content-based minimum size.
 | |
|     /// Usually you are best off using `GridTrack::flex` instead which uses a zero minimum size
 | |
|     pub fn fr<T: From<Self>>(value: f32) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Auto,
 | |
|             max_sizing_function: MaxTrackSizingFunction::Fraction(value),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a grid track with an `minmax(0, Nfr)` size.
 | |
|     pub fn flex<T: From<Self>>(value: f32) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Px(0.0),
 | |
|             max_sizing_function: MaxTrackSizingFunction::Fraction(value),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a grid track which is automatically sized to fit it's contents, and then
 | |
|     pub fn auto<T: From<Self>>() -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Auto,
 | |
|             max_sizing_function: MaxTrackSizingFunction::Auto,
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a grid track which is automatically sized to fit it's contents when sized at their "min-content" sizes
 | |
|     pub fn min_content<T: From<Self>>() -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::MinContent,
 | |
|             max_sizing_function: MaxTrackSizingFunction::MinContent,
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a grid track which is automatically sized to fit it's contents when sized at their "max-content" sizes
 | |
|     pub fn max_content<T: From<Self>>() -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::MaxContent,
 | |
|             max_sizing_function: MaxTrackSizingFunction::MaxContent,
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a fit-content() grid track with fixed pixel limit
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content_function>
 | |
|     pub fn fit_content_px<T: From<Self>>(limit: f32) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Auto,
 | |
|             max_sizing_function: MaxTrackSizingFunction::FitContentPx(limit),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a fit-content() grid track with percentage limit
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content_function>
 | |
|     pub fn fit_content_percent<T: From<Self>>(limit: f32) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: MinTrackSizingFunction::Auto,
 | |
|             max_sizing_function: MaxTrackSizingFunction::FitContentPercent(limit),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a minmax() grid track
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/minmax>
 | |
|     pub fn minmax<T: From<Self>>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> T {
 | |
|         Self {
 | |
|             min_sizing_function: min,
 | |
|             max_sizing_function: max,
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Default for GridTrack {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| /// How many times to repeat a repeated grid track
 | |
| ///
 | |
| /// <https://developer.mozilla.org/en-US/docs/Web/CSS/repeat>
 | |
| pub enum GridTrackRepetition {
 | |
|     /// Repeat the track fixed number of times
 | |
|     Count(u16),
 | |
|     /// Repeat the track to fill available space
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/repeat#auto-fill>
 | |
|     AutoFill,
 | |
|     /// Repeat the track to fill available space but collapse any tracks that do not end up with
 | |
|     /// an item placed in them.
 | |
|     ///
 | |
|     /// <https://developer.mozilla.org/en-US/docs/Web/CSS/repeat#auto-fit>
 | |
|     AutoFit,
 | |
| }
 | |
| 
 | |
| impl From<u16> for GridTrackRepetition {
 | |
|     fn from(count: u16) -> Self {
 | |
|         Self::Count(count)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<i32> for GridTrackRepetition {
 | |
|     fn from(count: i32) -> Self {
 | |
|         Self::Count(count as u16)
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<usize> for GridTrackRepetition {
 | |
|     fn from(count: usize) -> Self {
 | |
|         Self::Count(count as u16)
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Represents a *possibly* repeated [`GridTrack`].
 | |
| ///
 | |
| /// The repetition parameter can either be:
 | |
| ///   - The integer `1`, in which case the track is non-repeated.
 | |
| ///   - a `u16` count to repeat the track N times
 | |
| ///   - A `GridTrackRepetition::AutoFit` or `GridTrackRepetition::AutoFill`
 | |
| ///
 | |
| /// Note: that in the common case you want a non-repeating track (repetition count 1), you may use the constructor methods on [`GridTrack`]
 | |
| /// to create a `RepeatedGridTrack`. i.e. `GridTrack::px(10.0)` is equivalent to `RepeatedGridTrack::px(1, 10.0)`.
 | |
| ///
 | |
| /// You may only use one auto-repetition per track list. And if your track list contains an auto repetition
 | |
| /// then all track (in and outside of the repetition) must be fixed size (px or percent). Integer repetitions are just shorthand for writing out
 | |
| /// N tracks longhand and are not subject to the same limitations.
 | |
| #[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| pub struct RepeatedGridTrack {
 | |
|     pub(crate) repetition: GridTrackRepetition,
 | |
|     pub(crate) tracks: SmallVec<[GridTrack; 1]>,
 | |
| }
 | |
| 
 | |
| impl RepeatedGridTrack {
 | |
|     /// Create a repeating set of grid tracks with a fixed pixel size
 | |
|     pub fn px<T: From<Self>>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T {
 | |
|         Self {
 | |
|             repetition: repetition.into(),
 | |
|             tracks: SmallVec::from_buf([GridTrack::px(value)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of grid tracks with a percentage size
 | |
|     pub fn percent<T: From<Self>>(repetition: impl Into<GridTrackRepetition>, value: f32) -> T {
 | |
|         Self {
 | |
|             repetition: repetition.into(),
 | |
|             tracks: SmallVec::from_buf([GridTrack::percent(value)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of grid tracks with automatic size
 | |
|     pub fn auto<T: From<Self>>(repetition: u16) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::auto()]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of grid tracks with an `fr` size.
 | |
|     /// Note that this will give the track a content-based minimum size.
 | |
|     /// Usually you are best off using `GridTrack::flex` instead which uses a zero minimum size
 | |
|     pub fn fr<T: From<Self>>(repetition: u16, value: f32) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::fr(value)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of grid tracks with an `minmax(0, Nfr)` size.
 | |
|     pub fn flex<T: From<Self>>(repetition: u16, value: f32) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::flex(value)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of grid tracks with min-content size
 | |
|     pub fn min_content<T: From<Self>>(repetition: u16) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::min_content()]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of grid tracks with max-content size
 | |
|     pub fn max_content<T: From<Self>>(repetition: u16) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::max_content()]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of fit-content() grid tracks with fixed pixel limit
 | |
|     pub fn fit_content_px<T: From<Self>>(repetition: u16, limit: f32) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::fit_content_px(limit)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of fit-content() grid tracks with percentage limit
 | |
|     pub fn fit_content_percent<T: From<Self>>(repetition: u16, limit: f32) -> T {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(repetition),
 | |
|             tracks: SmallVec::from_buf([GridTrack::fit_content_percent(limit)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repeating set of minmax() grid track
 | |
|     pub fn minmax<T: From<Self>>(
 | |
|         repetition: impl Into<GridTrackRepetition>,
 | |
|         min: MinTrackSizingFunction,
 | |
|         max: MaxTrackSizingFunction,
 | |
|     ) -> T {
 | |
|         Self {
 | |
|             repetition: repetition.into(),
 | |
|             tracks: SmallVec::from_buf([GridTrack::minmax(min, max)]),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| 
 | |
|     /// Create a repetition of a set of tracks
 | |
|     pub fn repeat_many<T: From<Self>>(
 | |
|         repetition: impl Into<GridTrackRepetition>,
 | |
|         tracks: impl Into<Vec<GridTrack>>,
 | |
|     ) -> T {
 | |
|         Self {
 | |
|             repetition: repetition.into(),
 | |
|             tracks: SmallVec::from_vec(tracks.into()),
 | |
|         }
 | |
|         .into()
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<GridTrack> for RepeatedGridTrack {
 | |
|     fn from(track: GridTrack) -> Self {
 | |
|         Self {
 | |
|             repetition: GridTrackRepetition::Count(1),
 | |
|             tracks: SmallVec::from_buf([track]),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<GridTrack> for Vec<GridTrack> {
 | |
|     fn from(track: GridTrack) -> Self {
 | |
|         vec![GridTrack {
 | |
|             min_sizing_function: track.min_sizing_function,
 | |
|             max_sizing_function: track.max_sizing_function,
 | |
|         }]
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<GridTrack> for Vec<RepeatedGridTrack> {
 | |
|     fn from(track: GridTrack) -> Self {
 | |
|         vec![RepeatedGridTrack {
 | |
|             repetition: GridTrackRepetition::Count(1),
 | |
|             tracks: SmallVec::from_buf([track]),
 | |
|         }]
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<RepeatedGridTrack> for Vec<RepeatedGridTrack> {
 | |
|     fn from(track: RepeatedGridTrack) -> Self {
 | |
|         vec![track]
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, PartialEq, Serialize, Deserialize)]
 | |
| /// Represents the position of a grid item in a single axis.
 | |
| ///
 | |
| /// There are 3 fields which may be set:
 | |
| ///   - `start`: which grid line the item should start at
 | |
| ///   - `end`: which grid line the item should end at
 | |
| ///   - `span`: how many tracks the item should span
 | |
| ///
 | |
| /// The default `span` is 1. If neither `start` or `end` is set then the item will be placed automatically.
 | |
| ///
 | |
| /// Generally, at most two fields should be set. If all three fields are specifed then `span` will be ignored. If `end` specifies an earlier
 | |
| /// grid line than `start` then `end` will be ignored and the item will have a span of 1.
 | |
| ///
 | |
| /// <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Line-based_Placement_with_CSS_Grid>
 | |
| pub struct GridPlacement {
 | |
|     /// The grid line at which the item should start. Lines are 1-indexed. Negative indexes count backwards from the end of the grid. Zero is not a valid index.
 | |
|     pub(crate) start: Option<i16>,
 | |
|     /// How many grid tracks the item should span. Defaults to 1.
 | |
|     pub(crate) span: Option<u16>,
 | |
|     /// The grid line at which the node should end. Lines are 1-indexed. Negative indexes count backwards from the end of the grid. Zero is not a valid index.
 | |
|     pub(crate) end: Option<i16>,
 | |
| }
 | |
| 
 | |
| impl GridPlacement {
 | |
|     const DEFAULT: Self = Self {
 | |
|         start: None,
 | |
|         span: Some(1),
 | |
|         end: None,
 | |
|     };
 | |
| 
 | |
|     /// Place the grid item automatically (letting the `span` default to `1`).
 | |
|     pub fn auto() -> Self {
 | |
|         Self {
 | |
|             start: None,
 | |
|             end: None,
 | |
|             span: Some(1),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Place the grid item automatically, specifying how many tracks it should `span`.
 | |
|     pub fn span(span: u16) -> Self {
 | |
|         Self {
 | |
|             start: None,
 | |
|             end: None,
 | |
|             span: Some(span),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Place the grid item specifying the `start` grid line (letting the `span` default to `1`).
 | |
|     pub fn start(start: i16) -> Self {
 | |
|         Self {
 | |
|             start: Some(start),
 | |
|             end: None,
 | |
|             span: Some(1),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Place the grid item specifying the `end` grid line (letting the `span` default to `1`).
 | |
|     pub fn end(end: i16) -> Self {
 | |
|         Self {
 | |
|             start: None,
 | |
|             end: Some(end),
 | |
|             span: Some(1),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Place the grid item specifying the `start` grid line and how many tracks it should `span`.
 | |
|     pub fn start_span(start: i16, span: u16) -> Self {
 | |
|         Self {
 | |
|             start: Some(start),
 | |
|             end: None,
 | |
|             span: Some(span),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Place the grid item specifying `start` and `end` grid lines (`span` will be inferred)
 | |
|     pub fn start_end(start: i16, end: i16) -> Self {
 | |
|         Self {
 | |
|             start: Some(start),
 | |
|             end: Some(end),
 | |
|             span: None,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Place the grid item specifying the `end` grid line and how many tracks it should `span`.
 | |
|     pub fn end_span(end: i16, span: u16) -> Self {
 | |
|         Self {
 | |
|             start: None,
 | |
|             end: Some(end),
 | |
|             span: Some(span),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Mutate the item, setting the `start` grid line
 | |
|     pub fn set_start(mut self, start: i16) -> Self {
 | |
|         self.start = Some(start);
 | |
|         self
 | |
|     }
 | |
| 
 | |
|     /// Mutate the item, setting the `end` grid line
 | |
|     pub fn set_end(mut self, end: i16) -> Self {
 | |
|         self.end = Some(end);
 | |
|         self
 | |
|     }
 | |
| 
 | |
|     /// Mutate the item, setting the number of tracks the item should `span`
 | |
|     pub fn set_span(mut self, span: u16) -> Self {
 | |
|         self.span = Some(span);
 | |
|         self
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Default for GridPlacement {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// The background color of the node
 | |
| ///
 | |
| /// This serves as the "fill" color.
 | |
| /// When combined with [`UiImage`], tints the provided texture.
 | |
| #[derive(Component, Copy, Clone, Debug, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, Component, Default)]
 | |
| pub struct BackgroundColor(pub Color);
 | |
| 
 | |
| impl BackgroundColor {
 | |
|     pub const DEFAULT: Self = Self(Color::WHITE);
 | |
| }
 | |
| 
 | |
| impl Default for BackgroundColor {
 | |
|     fn default() -> Self {
 | |
|         Self::DEFAULT
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<Color> for BackgroundColor {
 | |
|     fn from(color: Color) -> Self {
 | |
|         Self(color)
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// The 2D texture displayed for this UI node
 | |
| #[derive(Component, Clone, Debug, Reflect)]
 | |
| #[reflect(Component, Default)]
 | |
| pub struct UiImage {
 | |
|     /// Handle to the texture
 | |
|     pub texture: Handle<Image>,
 | |
|     /// Whether the image should be flipped along its x-axis
 | |
|     pub flip_x: bool,
 | |
|     /// Whether the image should be flipped along its y-axis
 | |
|     pub flip_y: bool,
 | |
| }
 | |
| 
 | |
| impl Default for UiImage {
 | |
|     fn default() -> UiImage {
 | |
|         UiImage {
 | |
|             texture: DEFAULT_IMAGE_HANDLE.typed(),
 | |
|             flip_x: false,
 | |
|             flip_y: false,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl UiImage {
 | |
|     pub fn new(texture: Handle<Image>) -> Self {
 | |
|         Self {
 | |
|             texture,
 | |
|             ..Default::default()
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// flip the image along its x-axis
 | |
|     #[must_use]
 | |
|     pub const fn with_flip_x(mut self) -> Self {
 | |
|         self.flip_x = true;
 | |
|         self
 | |
|     }
 | |
| 
 | |
|     /// flip the image along its y-axis
 | |
|     #[must_use]
 | |
|     pub const fn with_flip_y(mut self) -> Self {
 | |
|         self.flip_y = true;
 | |
|         self
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl From<Handle<Image>> for UiImage {
 | |
|     fn from(texture: Handle<Image>) -> Self {
 | |
|         Self::new(texture)
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// The calculated clip of the node
 | |
| #[derive(Component, Default, Copy, Clone, Debug, Reflect, FromReflect)]
 | |
| #[reflect(FromReflect, Component)]
 | |
| pub struct CalculatedClip {
 | |
|     /// The rect of the clip
 | |
|     pub clip: Rect,
 | |
| }
 | |
| 
 | |
| /// Indicates that this [`Node`] entity's front-to-back ordering is not controlled solely
 | |
| /// by its location in the UI hierarchy. A node with a higher z-index will appear on top
 | |
| /// of other nodes with a lower z-index.
 | |
| ///
 | |
| /// UI nodes that have the same z-index will appear according to the order in which they
 | |
| /// appear in the UI hierarchy. In such a case, the last node to be added to its parent
 | |
| /// will appear in front of this parent's other children.
 | |
| ///
 | |
| /// Internally, nodes with a global z-index share the stacking context of root UI nodes
 | |
| /// (nodes that have no parent). Because of this, there is no difference between using
 | |
| /// [`ZIndex::Local(n)`] and [`ZIndex::Global(n)`] for root nodes.
 | |
| ///
 | |
| /// Nodes without this component will be treated as if they had a value of [`ZIndex::Local(0)`].
 | |
| #[derive(Component, Copy, Clone, Debug, Reflect, FromReflect)]
 | |
| #[reflect(Component, FromReflect)]
 | |
| pub enum ZIndex {
 | |
|     /// Indicates the order in which this node should be rendered relative to its siblings.
 | |
|     Local(i32),
 | |
|     /// Indicates the order in which this node should be rendered relative to root nodes and
 | |
|     /// all other nodes that have a global z-index.
 | |
|     Global(i32),
 | |
| }
 | |
| 
 | |
| impl Default for ZIndex {
 | |
|     fn default() -> Self {
 | |
|         Self::Local(0)
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod tests {
 | |
|     use crate::ValArithmeticError;
 | |
| 
 | |
|     use super::Val;
 | |
| 
 | |
|     #[test]
 | |
|     fn val_try_add() {
 | |
|         let auto_sum = Val::Auto.try_add(Val::Auto).unwrap();
 | |
|         let px_sum = Val::Px(20.).try_add(Val::Px(22.)).unwrap();
 | |
|         let percent_sum = Val::Percent(50.).try_add(Val::Percent(50.)).unwrap();
 | |
| 
 | |
|         assert_eq!(auto_sum, Val::Auto);
 | |
|         assert_eq!(px_sum, Val::Px(42.));
 | |
|         assert_eq!(percent_sum, Val::Percent(100.));
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_try_add_to_self() {
 | |
|         let mut val = Val::Px(5.);
 | |
| 
 | |
|         val.try_add_assign(Val::Px(3.)).unwrap();
 | |
| 
 | |
|         assert_eq!(val, Val::Px(8.));
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_try_sub() {
 | |
|         let auto_sum = Val::Auto.try_sub(Val::Auto).unwrap();
 | |
|         let px_sum = Val::Px(72.).try_sub(Val::Px(30.)).unwrap();
 | |
|         let percent_sum = Val::Percent(100.).try_sub(Val::Percent(50.)).unwrap();
 | |
| 
 | |
|         assert_eq!(auto_sum, Val::Auto);
 | |
|         assert_eq!(px_sum, Val::Px(42.));
 | |
|         assert_eq!(percent_sum, Val::Percent(50.));
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn different_variant_val_try_add() {
 | |
|         let different_variant_sum_1 = Val::Px(50.).try_add(Val::Percent(50.));
 | |
|         let different_variant_sum_2 = Val::Percent(50.).try_add(Val::Auto);
 | |
| 
 | |
|         assert_eq!(
 | |
|             different_variant_sum_1,
 | |
|             Err(ValArithmeticError::NonIdenticalVariants)
 | |
|         );
 | |
|         assert_eq!(
 | |
|             different_variant_sum_2,
 | |
|             Err(ValArithmeticError::NonIdenticalVariants)
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn different_variant_val_try_sub() {
 | |
|         let different_variant_diff_1 = Val::Px(50.).try_sub(Val::Percent(50.));
 | |
|         let different_variant_diff_2 = Val::Percent(50.).try_sub(Val::Auto);
 | |
| 
 | |
|         assert_eq!(
 | |
|             different_variant_diff_1,
 | |
|             Err(ValArithmeticError::NonIdenticalVariants)
 | |
|         );
 | |
|         assert_eq!(
 | |
|             different_variant_diff_2,
 | |
|             Err(ValArithmeticError::NonIdenticalVariants)
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_evaluate() {
 | |
|         let size = 250.;
 | |
|         let result = Val::Percent(80.).evaluate(size).unwrap();
 | |
| 
 | |
|         assert_eq!(result, size * 0.8);
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_evaluate_px() {
 | |
|         let size = 250.;
 | |
|         let result = Val::Px(10.).evaluate(size).unwrap();
 | |
| 
 | |
|         assert_eq!(result, 10.);
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_invalid_evaluation() {
 | |
|         let size = 250.;
 | |
|         let evaluate_auto = Val::Auto.evaluate(size);
 | |
| 
 | |
|         assert_eq!(evaluate_auto, Err(ValArithmeticError::NonEvaluateable));
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_try_add_with_size() {
 | |
|         let size = 250.;
 | |
| 
 | |
|         let px_sum = Val::Px(21.).try_add_with_size(Val::Px(21.), size).unwrap();
 | |
|         let percent_sum = Val::Percent(20.)
 | |
|             .try_add_with_size(Val::Percent(30.), size)
 | |
|             .unwrap();
 | |
|         let mixed_sum = Val::Px(20.)
 | |
|             .try_add_with_size(Val::Percent(30.), size)
 | |
|             .unwrap();
 | |
| 
 | |
|         assert_eq!(px_sum, 42.);
 | |
|         assert_eq!(percent_sum, 0.5 * size);
 | |
|         assert_eq!(mixed_sum, 20. + 0.3 * size);
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_try_sub_with_size() {
 | |
|         let size = 250.;
 | |
| 
 | |
|         let px_sum = Val::Px(60.).try_sub_with_size(Val::Px(18.), size).unwrap();
 | |
|         let percent_sum = Val::Percent(80.)
 | |
|             .try_sub_with_size(Val::Percent(30.), size)
 | |
|             .unwrap();
 | |
|         let mixed_sum = Val::Percent(50.)
 | |
|             .try_sub_with_size(Val::Px(30.), size)
 | |
|             .unwrap();
 | |
| 
 | |
|         assert_eq!(px_sum, 42.);
 | |
|         assert_eq!(percent_sum, 0.5 * size);
 | |
|         assert_eq!(mixed_sum, 0.5 * size - 30.);
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_try_add_non_numeric_with_size() {
 | |
|         let size = 250.;
 | |
| 
 | |
|         let percent_sum = Val::Auto.try_add_with_size(Val::Auto, size);
 | |
| 
 | |
|         assert_eq!(percent_sum, Err(ValArithmeticError::NonEvaluateable));
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn val_arithmetic_error_messages() {
 | |
|         assert_eq!(
 | |
|             format!("{}", ValArithmeticError::NonIdenticalVariants),
 | |
|             "the variants of the Vals don't match"
 | |
|         );
 | |
|         assert_eq!(
 | |
|             format!("{}", ValArithmeticError::NonEvaluateable),
 | |
|             "the given variant of Val is not evaluateable (non-numeric)"
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     #[test]
 | |
|     fn default_val_equals_const_default_val() {
 | |
|         assert_eq!(Val::default(), Val::DEFAULT);
 | |
|     }
 | |
| }
 |