maycoon_core/
layout.rs

1use nalgebra::Vector2;
2pub use taffy::{
3    AlignContent, AlignItems, AlignSelf, Dimension, Display, FlexDirection, FlexWrap, GridAutoFlow,
4    GridPlacement, JustifyContent, JustifyItems, JustifySelf, Layout, LengthPercentage,
5    LengthPercentageAuto, Line, NodeId, Overflow, Position, Rect, TaffyError, TaffyResult,
6    TaffyTree,
7};
8
9/// Defines different aspects and properties of a widget layout.
10#[derive(Clone, PartialEq, Debug)]
11pub struct LayoutStyle {
12    /// What layout strategy should be used?
13    pub display: Display,
14
15    /// How children overflowing their container should affect layout.
16    pub overflow: (Overflow, Overflow),
17
18    /// How much space (in points) should be reserved for scrollbars.
19    pub scrollbar_width: f32,
20
21    /// What should the position value of this struct use as a base offset?
22    pub position: Position,
23
24    /// How should the position of this element be tweaked relative to the layout defined?
25    pub inset: Rect<LengthPercentageAuto>,
26
27    /// Sets the initial size of the item.
28    pub size: Vector2<Dimension>,
29
30    /// Controls the minimum size of the item.
31    pub min_size: Vector2<Dimension>,
32
33    /// Controls the maximum size of the item.
34    pub max_size: Vector2<Dimension>,
35
36    /// Sets the preferred aspect ratio for the item
37    ///
38    /// The ratio is calculated as width divided by height.
39    pub aspect_ratio: Option<f32>,
40
41    /// How large should the margin be on each side?
42    pub margin: Rect<LengthPercentageAuto>,
43
44    /// How large should the padding be on each side?
45    pub padding: Rect<LengthPercentage>,
46
47    /// How large should the border be on each side?
48    pub border: Rect<LengthPercentage>,
49
50    /// How this node's children aligned in the cross/block axis?
51    pub align_items: Option<AlignItems>,
52
53    /// How this node should be aligned in the cross/block axis
54    /// Falls back to the parents [AlignItems] if not set.
55    pub align_self: Option<AlignSelf>,
56
57    /// How this node's children should be aligned in the inline axis.
58    pub justify_items: Option<AlignItems>,
59
60    /// How this node should be aligned in the inline axis
61    /// Falls back to the parents [JustifyItems] if not set.
62    pub justify_self: Option<AlignSelf>,
63
64    /// How should content contained within this item be aligned in the cross/block axis?
65    pub align_content: Option<AlignContent>,
66
67    /// How should content contained within this item be aligned in the main/inline axis?
68    pub justify_content: Option<JustifyContent>,
69
70    /// How large should the gaps between items in a grid or flex container be?
71    pub gap: Vector2<LengthPercentage>,
72
73    /// Which direction does the main axis flow in?
74    pub flex_direction: FlexDirection,
75
76    /// Should elements wrap, or stay in a single line?
77    pub flex_wrap: FlexWrap,
78
79    /// Sets the initial main axis size of the item.
80    pub flex_basis: Dimension,
81
82    /// The relative rate at which this item grows when it is expanding to fill space.
83    ///
84    /// 0.0 is the default value, and this value must be positive.
85    pub flex_grow: f32,
86
87    /// The relative rate at which this item shrinks when it is contracting to fit into space.
88    ///
89    /// 1.0 is the default value, and this value must be positive.
90    pub flex_shrink: f32,
91
92    /// Controls how items get placed into the grid for auto-placed items.
93    pub grid_auto_flow: GridAutoFlow,
94
95    /// Defines which row in the grid the item should start and end at.
96    pub grid_row: Line<GridPlacement>,
97
98    /// Defines which column in the grid the item should start and end at.
99    pub grid_column: Line<GridPlacement>,
100}
101
102impl Default for LayoutStyle {
103    fn default() -> Self {
104        LayoutStyle {
105            display: Display::default(),
106            overflow: (Overflow::Visible, Overflow::Visible),
107            scrollbar_width: 0.0,
108            position: Position::Relative,
109            inset: Rect::auto(),
110            margin: Rect::zero(),
111            padding: Rect::zero(),
112            border: Rect::zero(),
113            size: Vector2::new(Dimension::auto(), Dimension::auto()),
114            min_size: Vector2::new(Dimension::auto(), Dimension::auto()),
115            max_size: Vector2::new(Dimension::auto(), Dimension::auto()),
116            aspect_ratio: None,
117            gap: Vector2::new(LengthPercentage::length(0.0), LengthPercentage::length(0.0)),
118            align_items: None,
119            align_self: None,
120            justify_items: None,
121            justify_self: None,
122            align_content: None,
123            justify_content: None,
124            flex_direction: FlexDirection::Row,
125            flex_wrap: FlexWrap::NoWrap,
126            flex_grow: 0.0,
127            flex_shrink: 1.0,
128            flex_basis: Dimension::auto(),
129            grid_auto_flow: GridAutoFlow::Row,
130            grid_row: Line {
131                start: GridPlacement::Auto,
132                end: GridPlacement::Auto,
133            },
134            grid_column: Line {
135                start: GridPlacement::Auto,
136                end: GridPlacement::Auto,
137            },
138        }
139    }
140}
141
142impl From<LayoutStyle> for taffy::Style {
143    fn from(value: LayoutStyle) -> Self {
144        taffy::Style {
145            display: value.display,
146            overflow: taffy::Point {
147                x: value.overflow.0,
148                y: value.overflow.1,
149            },
150            scrollbar_width: value.scrollbar_width,
151            position: value.position,
152            inset: value.inset,
153            margin: value.margin,
154            padding: value.padding,
155            border: value.border,
156            size: taffy::Size {
157                width: value.size.x,
158                height: value.size.y,
159            },
160            min_size: taffy::Size {
161                width: value.min_size.x,
162                height: value.min_size.y,
163            },
164            max_size: taffy::Size {
165                width: value.max_size.x,
166                height: value.max_size.y,
167            },
168            aspect_ratio: value.aspect_ratio,
169            gap: taffy::Size {
170                width: value.gap.x,
171                height: value.gap.y,
172            },
173            align_items: value.align_items,
174            align_self: value.align_self,
175            justify_items: value.justify_items,
176            justify_self: value.justify_self,
177            align_content: value.align_content,
178            justify_content: value.justify_content,
179            flex_direction: value.flex_direction,
180            flex_wrap: value.flex_wrap,
181            flex_grow: value.flex_grow,
182            flex_shrink: value.flex_shrink,
183            flex_basis: value.flex_basis,
184            grid_auto_flow: value.grid_auto_flow,
185            grid_row: value.grid_row,
186            grid_column: value.grid_column,
187            ..Default::default()
188        }
189    }
190}
191
192/// The computed layout with children nodes.
193#[derive(Debug)]
194pub struct LayoutNode {
195    /// The computed layout of this node.
196    pub layout: Layout,
197    /// The children of this node.
198    pub children: Vec<LayoutNode>,
199}
200
201/// The raw layout styles with children nodes.
202pub struct StyleNode {
203    /// The layout style of this node.
204    pub style: LayoutStyle,
205    /// The children of this node.
206    pub children: Vec<StyleNode>,
207}