Skip to main content

gpui_engine/
style.rs

1//! The engine's layout vocabulary: the layout-affecting style fields and the
2//! enums that describe them.
3//!
4//! These enums are copies of `taffy`'s style enums so this crate can derive
5//! `JsonSchema` and stay independent of `taffy` itself.
6
7use gpui_types::{AbsoluteLength, DefiniteLength, Edges, GridLocation, Length, Point, Size};
8use refineable::Refineable;
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11
12/// The layout-affecting subset of an element's style.
13///
14/// The facade resolves its `Style` into this before handing it to a layout
15/// engine, so the engine never sees paint-only properties.
16#[derive(Clone, Debug)]
17pub struct EngineLayoutStyle {
18    /// The layout algorithm used for this node's children.
19    pub display: Display,
20    /// How overflowing children affect this node's scrollable area.
21    pub overflow: Point<Overflow>,
22    /// Space reserved for the scrollbars of `Overflow::Scroll` nodes.
23    pub scrollbar_width: AbsoluteLength,
24    /// The positioning strategy for this node.
25    pub position: Position,
26    /// Offsets applied relative to the layout position.
27    pub inset: Edges<Length>,
28    /// The preferred size.
29    pub size: Size<Length>,
30    /// The minimum size.
31    pub min_size: Size<Length>,
32    /// The maximum size.
33    pub max_size: Size<Length>,
34    /// The preferred aspect ratio, calculated as width divided by height.
35    pub aspect_ratio: Option<f32>,
36    /// Space around this node.
37    pub margin: Edges<Length>,
38    /// Space inside this node.
39    pub padding: Edges<DefiniteLength>,
40    /// Border widths.
41    pub border_widths: Edges<AbsoluteLength>,
42    /// How this node's children are aligned in the cross/block axis.
43    pub align_items: Option<AlignItems>,
44    /// How this node is aligned in the cross/block axis.
45    pub align_self: Option<AlignSelf>,
46    /// How this node's content is aligned in the cross/block axis.
47    pub align_content: Option<AlignContent>,
48    /// How this node's content is aligned in the main/inline axis.
49    pub justify_content: Option<JustifyContent>,
50    /// Space between this node's children.
51    pub gap: Size<DefiniteLength>,
52    /// Which direction the flex main axis flows in.
53    pub flex_direction: FlexDirection,
54    /// Whether flex children wrap or stay on a single line.
55    pub flex_wrap: FlexWrap,
56    /// The initial main-axis size of this node.
57    pub flex_basis: Length,
58    /// The rate at which this node grows when expanding to fill space.
59    pub flex_grow: f32,
60    /// The rate at which this node shrinks when contracting.
61    pub flex_shrink: f32,
62    /// The grid column template.
63    pub grid_cols: Option<GridTemplate>,
64    /// The grid row template.
65    pub grid_rows: Option<GridTemplate>,
66    /// This node's location within its parent's grid.
67    pub grid_location: Option<GridLocation>,
68}
69
70/// The minimum size of a column or row in a grid layout
71#[derive(
72    Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, JsonSchema, Serialize, Deserialize,
73)]
74pub enum GridTemplateMinSize {
75    /// The column or row size may be 0
76    #[default]
77    Zero,
78    /// The column or row size can be determined by the min content
79    MinContent,
80    /// The column or row size can be determined by the max content
81    MaxContent,
82}
83
84/// A simplified representation of the grid-template-* value
85#[derive(
86    Copy,
87    Clone,
88    Refineable,
89    PartialEq,
90    Eq,
91    PartialOrd,
92    Ord,
93    Debug,
94    Default,
95    JsonSchema,
96    Serialize,
97    Deserialize,
98)]
99pub struct GridTemplate {
100    /// How this template directive should be repeated
101    pub repeat: u16,
102    /// The minimum size in the repeat(<>, minmax(_, 1fr)) equation
103    pub min_size: GridTemplateMinSize,
104}
105
106/// Used to control how child nodes are aligned.
107/// For Flexbox it controls alignment in the cross axis
108/// For Grid it controls alignment in the block axis
109///
110/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)
111#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
112// Copy of taffy::style type of the same name, to derive JsonSchema.
113pub enum AlignItems {
114    /// Items are packed toward the start of the axis
115    Start,
116    /// Items are packed toward the end of the axis
117    End,
118    /// Items are packed towards the flex-relative start of the axis.
119    ///
120    /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
121    /// to End. In all other cases it is equivalent to Start.
122    FlexStart,
123    /// Items are packed towards the flex-relative end of the axis.
124    ///
125    /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
126    /// to Start. In all other cases it is equivalent to End.
127    FlexEnd,
128    /// Items are packed along the center of the cross axis
129    Center,
130    /// Items are aligned such as their baselines align
131    Baseline,
132    /// Stretch to fill the container
133    Stretch,
134}
135/// Used to control how child nodes are aligned.
136/// Does not apply to Flexbox, and will be ignored if specified on a flex container
137/// For Grid it controls alignment in the inline axis
138///
139/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items)
140pub type JustifyItems = AlignItems;
141/// Used to control how the specified nodes is aligned.
142/// Overrides the parent Node's `AlignItems` property.
143/// For Flexbox it controls alignment in the cross axis
144/// For Grid it controls alignment in the block axis
145///
146/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self)
147pub type AlignSelf = AlignItems;
148/// Used to control how the specified nodes is aligned.
149/// Overrides the parent Node's `JustifyItems` property.
150/// Does not apply to Flexbox, and will be ignored if specified on a flex child
151/// For Grid it controls alignment in the inline axis
152///
153/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self)
154pub type JustifySelf = AlignItems;
155
156/// Sets the distribution of space between and around content items
157/// For Flexbox it controls alignment in the cross axis
158/// For Grid it controls alignment in the block axis
159///
160/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content)
161#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)]
162// Copy of taffy::style type of the same name, to derive JsonSchema.
163pub enum AlignContent {
164    /// Items are packed toward the start of the axis
165    Start,
166    /// Items are packed toward the end of the axis
167    End,
168    /// Items are packed towards the flex-relative start of the axis.
169    ///
170    /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
171    /// to End. In all other cases it is equivalent to Start.
172    FlexStart,
173    /// Items are packed towards the flex-relative end of the axis.
174    ///
175    /// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
176    /// to Start. In all other cases it is equivalent to End.
177    FlexEnd,
178    /// Items are centered around the middle of the axis
179    Center,
180    /// Items are stretched to fill the container
181    Stretch,
182    /// The first and last items are aligned flush with the edges of the container (no gap)
183    /// The gap between items is distributed evenly.
184    SpaceBetween,
185    /// The gap between the first and last items is exactly THE SAME as the gap between items.
186    /// The gaps are distributed evenly
187    SpaceEvenly,
188    /// The gap between the first and last items is exactly HALF the gap between items.
189    /// The gaps are distributed evenly in proportion to these ratios.
190    SpaceAround,
191}
192
193/// Sets the distribution of space between and around content items
194/// For Flexbox it controls alignment in the main axis
195/// For Grid it controls alignment in the inline axis
196///
197/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)
198pub type JustifyContent = AlignContent;
199
200/// Sets the layout used for the children of this node
201///
202/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
203#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)]
204// Copy of taffy::style type of the same name, to derive JsonSchema.
205pub enum Display {
206    /// The children will follow the block layout algorithm
207    Block,
208    /// The children will follow the flexbox layout algorithm
209    #[default]
210    Flex,
211    /// The children will follow the CSS Grid layout algorithm
212    Grid,
213    /// The children will not be laid out, and will follow absolute positioning
214    None,
215}
216
217/// Controls whether flex items are forced onto one line or can wrap onto multiple lines.
218///
219/// Defaults to [`FlexWrap::NoWrap`]
220///
221/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-wrap-property)
222#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)]
223// Copy of taffy::style type of the same name, to derive JsonSchema.
224pub enum FlexWrap {
225    /// Items will not wrap and stay on a single line
226    #[default]
227    NoWrap,
228    /// Items will wrap according to this item's [`FlexDirection`]
229    Wrap,
230    /// Items will wrap in the opposite direction to this item's [`FlexDirection`]
231    WrapReverse,
232}
233
234/// The direction of the flexbox layout main axis.
235///
236/// There are always two perpendicular layout axes: main (or primary) and cross (or secondary).
237/// Adding items will cause them to be positioned adjacent to each other along the main axis.
238/// By varying this value throughout your tree, you can create complex axis-aligned layouts.
239///
240/// Items are always aligned relative to the cross axis, and justified relative to the main axis.
241///
242/// The default behavior is [`FlexDirection::Row`].
243///
244/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-direction-property)
245#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)]
246// Copy of taffy::style type of the same name, to derive JsonSchema.
247pub enum FlexDirection {
248    /// Defines +x as the main axis
249    ///
250    /// Items will be added from left to right in a row.
251    #[default]
252    Row,
253    /// Defines +y as the main axis
254    ///
255    /// Items will be added from top to bottom in a column.
256    Column,
257    /// Defines -x as the main axis
258    ///
259    /// Items will be added from right to left in a row.
260    RowReverse,
261    /// Defines -y as the main axis
262    ///
263    /// Items will be added from bottom to top in a column.
264    ColumnReverse,
265}
266
267/// How children overflowing their container should affect layout
268///
269/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
270/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
271/// the main ones being:
272///
273///   - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
274///   - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
275///
276/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
277/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
278///
279/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
280#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)]
281// Copy of taffy::style type of the same name, to derive JsonSchema.
282pub enum Overflow {
283    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
284    /// Content that overflows this node *should* contribute to the scroll region of its parent.
285    #[default]
286    Visible,
287    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
288    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
289    Clip,
290    /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
291    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
292    Hidden,
293    /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
294    /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
295    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
296    Scroll,
297}
298
299/// The positioning strategy for this item.
300///
301/// This controls both how the origin is determined for the [`Style::position`] field,
302/// and whether or not the item will be controlled by flexbox's layout algorithm.
303///
304/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
305/// which can be unintuitive.
306///
307/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
308#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, JsonSchema)]
309// Copy of taffy::style type of the same name, to derive JsonSchema.
310pub enum Position {
311    /// The offset is computed relative to the final position given by the layout algorithm.
312    /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
313    #[default]
314    Relative,
315    /// The offset is computed relative to this item's closest positioned ancestor, if any.
316    /// Otherwise, it is placed relative to the origin.
317    /// No space is created for the item in the page layout, and its size will not be altered.
318    ///
319    /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
320    Absolute,
321}