1mod alignment;
3mod dimension;
4
5#[cfg(feature = "flexbox")]
6mod flex;
7
8pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
9pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto};
10
11#[cfg(feature = "flexbox")]
12pub use self::flex::{FlexDirection, FlexWrap};
13
14#[cfg(feature = "grid")]
15mod grid;
16#[cfg(feature = "grid")]
17pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement};
18#[cfg(feature = "grid")]
19pub use self::grid::{
20 GridAutoFlow, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction,
21 NonRepeatedTrackSizingFunction, TrackSizingFunction,
22};
23use crate::geometry::{Point, Rect, Size};
24
25#[cfg(feature = "grid")]
26use crate::geometry::Line;
27#[cfg(feature = "serde")]
28use crate::style_helpers;
29#[cfg(feature = "grid")]
30use crate::util::sys::GridTrackVec;
31
32#[derive(Copy, Clone, PartialEq, Eq, Debug)]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37pub enum Display {
38 #[cfg(feature = "block_layout")]
40 Block,
41 #[cfg(feature = "flexbox")]
43 Flex,
44 #[cfg(feature = "grid")]
46 Grid,
47 None,
49}
50
51impl Display {
52 #[cfg(feature = "flexbox")]
54 pub const DEFAULT: Display = Display::Flex;
55
56 #[cfg(all(feature = "grid", not(feature = "flexbox")))]
58 pub const DEFAULT: Display = Display::Grid;
59
60 #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
62 pub const DEFAULT: Display = Display::Block;
63
64 #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
66 pub const DEFAULT: Display = Display::None;
67}
68
69impl core::fmt::Display for Display {
70 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
71 match self {
72 Display::None => write!(f, "NONE"),
73 #[cfg(feature = "block_layout")]
74 Display::Block => write!(f, "BLOCK"),
75 #[cfg(feature = "flexbox")]
76 Display::Flex => write!(f, "FLEX"),
77 #[cfg(feature = "grid")]
78 Display::Grid => write!(f, "GRID"),
79 }
80 }
81}
82
83impl Default for Display {
84 fn default() -> Self {
85 Self::DEFAULT
86 }
87}
88
89#[derive(Copy, Clone, PartialEq, Eq, Debug)]
99#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
100pub enum Position {
101 Relative,
104 Absolute,
110}
111
112impl Default for Position {
113 fn default() -> Self {
114 Self::Relative
115 }
116}
117
118#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub enum Overflow {
134 #[default]
137 Visible,
138 Clip,
141 Hidden,
144 Scroll,
148}
149
150impl Overflow {
151 #[inline(always)]
154 pub(crate) fn is_scroll_container(self) -> bool {
155 match self {
156 Self::Visible | Self::Clip => false,
157 Self::Hidden | Self::Scroll => true,
158 }
159 }
160
161 #[inline(always)]
164 pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
165 match self.is_scroll_container() {
166 true => Some(0.0),
167 false => None,
168 }
169 }
170}
171
172#[derive(Clone, PartialEq, Debug)]
187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188#[cfg_attr(feature = "serde", serde(default))]
189pub struct Style {
190 pub display: Display,
192
193 pub overflow: Point<Overflow>,
196 pub scrollbar_width: f32,
198
199 pub position: Position,
202 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
204 pub inset: Rect<LengthPercentageAuto>,
205
206 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
209 pub size: Size<Dimension>,
210 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
212 pub min_size: Size<Dimension>,
213 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
215 pub max_size: Size<Dimension>,
216 pub aspect_ratio: Option<f32>,
220
221 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
224 pub margin: Rect<LengthPercentageAuto>,
225 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
227 pub padding: Rect<LengthPercentage>,
228 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
230 pub border: Rect<LengthPercentage>,
231
232 #[cfg(any(feature = "flexbox", feature = "grid"))]
235 pub align_items: Option<AlignItems>,
236 #[cfg(any(feature = "flexbox", feature = "grid"))]
239 pub align_self: Option<AlignSelf>,
240 #[cfg(feature = "grid")]
242 pub justify_items: Option<AlignItems>,
243 #[cfg(feature = "grid")]
246 pub justify_self: Option<AlignSelf>,
247 #[cfg(any(feature = "flexbox", feature = "grid"))]
249 pub align_content: Option<AlignContent>,
250 #[cfg(any(feature = "flexbox", feature = "grid"))]
252 pub justify_content: Option<JustifyContent>,
253 #[cfg(any(feature = "flexbox", feature = "grid"))]
255 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
256 pub gap: Size<LengthPercentage>,
257
258 #[cfg(feature = "flexbox")]
261 pub flex_direction: FlexDirection,
262 #[cfg(feature = "flexbox")]
264 pub flex_wrap: FlexWrap,
265 #[cfg(feature = "flexbox")]
267 pub flex_basis: Dimension,
268 #[cfg(feature = "flexbox")]
272 pub flex_grow: f32,
273 #[cfg(feature = "flexbox")]
277 pub flex_shrink: f32,
278
279 #[cfg(feature = "grid")]
282 pub grid_template_rows: GridTrackVec<TrackSizingFunction>,
283 #[cfg(feature = "grid")]
285 pub grid_template_columns: GridTrackVec<TrackSizingFunction>,
286 #[cfg(feature = "grid")]
288 pub grid_auto_rows: GridTrackVec<NonRepeatedTrackSizingFunction>,
289 #[cfg(feature = "grid")]
291 pub grid_auto_columns: GridTrackVec<NonRepeatedTrackSizingFunction>,
292 #[cfg(feature = "grid")]
294 pub grid_auto_flow: GridAutoFlow,
295
296 #[cfg(feature = "grid")]
299 pub grid_row: Line<GridPlacement>,
300 #[cfg(feature = "grid")]
302 pub grid_column: Line<GridPlacement>,
303}
304
305impl Style {
306 pub const DEFAULT: Style = Style {
308 display: Display::DEFAULT,
309 overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
310 scrollbar_width: 0.0,
311 position: Position::Relative,
312 inset: Rect::auto(),
313 margin: Rect::zero(),
314 padding: Rect::zero(),
315 border: Rect::zero(),
316 size: Size::auto(),
317 min_size: Size::auto(),
318 max_size: Size::auto(),
319 aspect_ratio: None,
320 #[cfg(any(feature = "flexbox", feature = "grid"))]
321 gap: Size::zero(),
322 #[cfg(any(feature = "flexbox", feature = "grid"))]
324 align_items: None,
325 #[cfg(any(feature = "flexbox", feature = "grid"))]
326 align_self: None,
327 #[cfg(feature = "grid")]
328 justify_items: None,
329 #[cfg(feature = "grid")]
330 justify_self: None,
331 #[cfg(any(feature = "flexbox", feature = "grid"))]
332 align_content: None,
333 #[cfg(any(feature = "flexbox", feature = "grid"))]
334 justify_content: None,
335 #[cfg(feature = "flexbox")]
337 flex_direction: FlexDirection::Row,
338 #[cfg(feature = "flexbox")]
339 flex_wrap: FlexWrap::NoWrap,
340 #[cfg(feature = "flexbox")]
341 flex_grow: 0.0,
342 #[cfg(feature = "flexbox")]
343 flex_shrink: 1.0,
344 #[cfg(feature = "flexbox")]
345 flex_basis: Dimension::Auto,
346 #[cfg(feature = "grid")]
348 grid_template_rows: GridTrackVec::new(),
349 #[cfg(feature = "grid")]
350 grid_template_columns: GridTrackVec::new(),
351 #[cfg(feature = "grid")]
352 grid_auto_rows: GridTrackVec::new(),
353 #[cfg(feature = "grid")]
354 grid_auto_columns: GridTrackVec::new(),
355 #[cfg(feature = "grid")]
356 grid_auto_flow: GridAutoFlow::Row,
357 #[cfg(feature = "grid")]
358 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
359 #[cfg(feature = "grid")]
360 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
361 };
362}
363
364impl Default for Style {
365 fn default() -> Self {
366 Style::DEFAULT
367 }
368}
369
370#[cfg(test)]
371mod tests {
372 use super::Style;
373 use crate::geometry::*;
374
375 #[test]
376 fn defaults_match() {
377 #[cfg(feature = "grid")]
378 use super::GridPlacement;
379
380 let old_defaults = Style {
381 display: Default::default(),
382 overflow: Default::default(),
383 scrollbar_width: 0.0,
384 position: Default::default(),
385 #[cfg(feature = "flexbox")]
386 flex_direction: Default::default(),
387 #[cfg(feature = "flexbox")]
388 flex_wrap: Default::default(),
389 #[cfg(any(feature = "flexbox", feature = "grid"))]
390 align_items: Default::default(),
391 #[cfg(any(feature = "flexbox", feature = "grid"))]
392 align_self: Default::default(),
393 #[cfg(feature = "grid")]
394 justify_items: Default::default(),
395 #[cfg(feature = "grid")]
396 justify_self: Default::default(),
397 #[cfg(any(feature = "flexbox", feature = "grid"))]
398 align_content: Default::default(),
399 #[cfg(any(feature = "flexbox", feature = "grid"))]
400 justify_content: Default::default(),
401 inset: Rect::auto(),
402 margin: Rect::zero(),
403 padding: Rect::zero(),
404 border: Rect::zero(),
405 gap: Size::zero(),
406 #[cfg(feature = "flexbox")]
407 flex_grow: 0.0,
408 #[cfg(feature = "flexbox")]
409 flex_shrink: 1.0,
410 #[cfg(feature = "flexbox")]
411 flex_basis: super::Dimension::Auto,
412 size: Size::auto(),
413 min_size: Size::auto(),
414 max_size: Size::auto(),
415 aspect_ratio: Default::default(),
416 #[cfg(feature = "grid")]
417 grid_template_rows: Default::default(),
418 #[cfg(feature = "grid")]
419 grid_template_columns: Default::default(),
420 #[cfg(feature = "grid")]
421 grid_auto_rows: Default::default(),
422 #[cfg(feature = "grid")]
423 grid_auto_columns: Default::default(),
424 #[cfg(feature = "grid")]
425 grid_auto_flow: Default::default(),
426 #[cfg(feature = "grid")]
427 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
428 #[cfg(feature = "grid")]
429 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
430 };
431
432 assert_eq!(Style::DEFAULT, Style::default());
433 assert_eq!(Style::DEFAULT, old_defaults);
434 }
435
436 #[test]
439 fn style_sizes() {
440 use super::*;
441
442 fn assert_type_size<T>(expected_size: usize) {
443 let name = ::core::any::type_name::<T>();
444 let name = name.replace("taffy::geometry::", "");
445 let name = name.replace("taffy::style::dimension::", "");
446 let name = name.replace("taffy::style::alignment::", "");
447 let name = name.replace("taffy::style::flex::", "");
448 let name = name.replace("taffy::style::grid::", "");
449
450 assert_eq!(
451 ::core::mem::size_of::<T>(),
452 expected_size,
453 "Expected {} for be {} byte(s) but it was {} byte(s)",
454 name,
455 expected_size,
456 ::core::mem::size_of::<T>(),
457 );
458 }
459
460 assert_type_size::<Display>(1);
462 assert_type_size::<Position>(1);
463 assert_type_size::<Overflow>(1);
464
465 assert_type_size::<f32>(4);
467 assert_type_size::<LengthPercentage>(8);
468 assert_type_size::<LengthPercentageAuto>(8);
469 assert_type_size::<Dimension>(8);
470 assert_type_size::<Size<LengthPercentage>>(16);
471 assert_type_size::<Size<LengthPercentageAuto>>(16);
472 assert_type_size::<Size<Dimension>>(16);
473 assert_type_size::<Rect<LengthPercentage>>(32);
474 assert_type_size::<Rect<LengthPercentageAuto>>(32);
475 assert_type_size::<Rect<Dimension>>(32);
476
477 assert_type_size::<AlignContent>(1);
479 assert_type_size::<AlignItems>(1);
480 assert_type_size::<Option<AlignItems>>(1);
481
482 assert_type_size::<FlexDirection>(1);
484 assert_type_size::<FlexWrap>(1);
485
486 assert_type_size::<GridAutoFlow>(1);
488 assert_type_size::<MinTrackSizingFunction>(8);
489 assert_type_size::<MaxTrackSizingFunction>(12);
490 assert_type_size::<NonRepeatedTrackSizingFunction>(20);
491 assert_type_size::<TrackSizingFunction>(32);
492 assert_type_size::<Vec<NonRepeatedTrackSizingFunction>>(24);
493 assert_type_size::<Vec<TrackSizingFunction>>(24);
494
495 assert_type_size::<GridPlacement>(4);
497 assert_type_size::<Line<GridPlacement>>(8);
498
499 assert_type_size::<Style>(352);
501 }
502}