1use crate::geometry::{Rect, Size};
2use crate::number::Number;
3
4#[derive(Copy, Clone, PartialEq, Debug)]
5#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
7#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
8pub enum AlignItems {
9 FlexStart,
10 FlexEnd,
11 Center,
12 Baseline,
13 Stretch,
14}
15
16impl Default for AlignItems {
17 fn default() -> AlignItems {
18 AlignItems::Stretch
19 }
20}
21
22#[derive(Copy, Clone, PartialEq, Debug)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
25#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
26pub enum AlignSelf {
27 Auto,
28 FlexStart,
29 FlexEnd,
30 Center,
31 Baseline,
32 Stretch,
33}
34
35impl Default for AlignSelf {
36 fn default() -> AlignSelf {
37 AlignSelf::Auto
38 }
39}
40
41#[derive(Copy, Clone, PartialEq, Debug)]
42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
44#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
45pub enum AlignContent {
46 FlexStart,
47 FlexEnd,
48 Center,
49 Stretch,
50 SpaceBetween,
51 SpaceAround,
52}
53
54impl Default for AlignContent {
55 fn default() -> AlignContent {
56 AlignContent::Stretch
57 }
58}
59
60#[derive(Copy, Clone, PartialEq, Debug)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
63#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
64pub enum Direction {
65 Inherit,
66 #[cfg_attr(feature = "serde", serde(rename = "ltr"))]
67 LTR,
68 #[cfg_attr(feature = "serde", serde(rename = "rtl"))]
69 RTL,
70}
71
72impl Default for Direction {
73 fn default() -> Direction {
74 Direction::Inherit
75 }
76}
77
78#[derive(Copy, Clone, PartialEq, Debug)]
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
81#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
82pub enum Display {
83 #[cfg_attr(feature = "serde", serde(rename = "flex"))]
84 Flex,
85 #[cfg_attr(feature = "serde", serde(rename = "none"))]
86 None,
87}
88
89impl Default for Display {
90 fn default() -> Display {
91 Display::Flex
92 }
93}
94
95#[derive(Copy, Clone, PartialEq, Debug)]
96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
98#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
99pub enum FlexDirection {
100 Row,
101 Column,
102 RowReverse,
103 ColumnReverse,
104}
105
106impl Default for FlexDirection {
107 fn default() -> FlexDirection {
108 FlexDirection::Row
109 }
110}
111
112impl FlexDirection {
113 pub(crate) fn is_row(self) -> bool {
114 self == FlexDirection::Row || self == FlexDirection::RowReverse
115 }
116
117 pub(crate) fn is_column(self) -> bool {
118 self == FlexDirection::Column || self == FlexDirection::ColumnReverse
119 }
120
121 pub(crate) fn is_reverse(self) -> bool {
122 self == FlexDirection::RowReverse || self == FlexDirection::ColumnReverse
123 }
124}
125
126#[derive(Copy, Clone, PartialEq, Debug)]
127#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
128#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
129#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
130pub enum JustifyContent {
131 FlexStart,
132 FlexEnd,
133 Center,
134 SpaceBetween,
135 SpaceAround,
136 SpaceEvenly,
137}
138
139impl Default for JustifyContent {
140 fn default() -> JustifyContent {
141 JustifyContent::FlexStart
142 }
143}
144
145#[derive(Copy, Clone, PartialEq, Debug)]
146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
147#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
148#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
149pub enum Overflow {
150 Visible,
151 Hidden,
152 Scroll,
153}
154
155impl Default for Overflow {
156 fn default() -> Overflow {
157 Overflow::Visible
158 }
159}
160
161#[derive(Copy, Clone, PartialEq, Debug)]
162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
163#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
164#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
165pub enum PositionType {
166 Relative,
167 Absolute,
168}
169
170impl Default for PositionType {
171 fn default() -> PositionType {
172 PositionType::Relative
173 }
174}
175
176#[derive(Copy, Clone, PartialEq, Debug)]
177#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
178#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
179#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
180pub enum FlexWrap {
181 NoWrap,
182 Wrap,
183 WrapReverse,
184}
185
186impl Default for FlexWrap {
187 fn default() -> FlexWrap {
188 FlexWrap::NoWrap
189 }
190}
191
192#[derive(Copy, Clone, PartialEq, Debug)]
193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
195#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
196pub enum Dimension {
197 Undefined,
198 Auto,
199 Points(f32),
200 Percent(f32),
201}
202
203impl Default for Dimension {
204 fn default() -> Dimension {
205 Dimension::Undefined
206 }
207}
208
209impl Dimension {
210 pub(crate) fn resolve(self, parent_width: Number) -> Number {
211 match self {
212 Dimension::Points(points) => Number::Defined(points),
213 Dimension::Percent(percent) => parent_width * percent,
214 _ => Number::Undefined,
215 }
216 }
217
218 pub(crate) fn is_defined(self) -> bool {
219 match self {
220 Dimension::Points(_) => true,
221 Dimension::Percent(_) => true,
222 _ => false,
223 }
224 }
225}
226
227impl Default for Rect<Dimension> {
228 fn default() -> Rect<Dimension> {
229 Rect { start: Default::default(), end: Default::default(), top: Default::default(), bottom: Default::default() }
230 }
231}
232
233impl Default for Size<Dimension> {
234 fn default() -> Size<Dimension> {
235 Size { width: Dimension::Auto, height: Dimension::Auto }
236 }
237}
238
239#[derive(Copy, Clone, PartialEq, Debug)]
240#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
241#[cfg_attr(feature = "serde", serde(default))]
242#[cfg_attr(all(feature = "serde", feature = "serde_kebab_case"), serde(rename_all = "kebab-case"))]
243#[cfg_attr(all(feature = "serde", feature = "serde_camel_case"), serde(rename_all = "camelCase"))]
244pub struct Style {
245 pub display: Display,
246 pub position_type: PositionType,
247 pub direction: Direction,
248 pub flex_direction: FlexDirection,
249 pub flex_wrap: FlexWrap,
250 pub overflow: Overflow,
251 pub align_items: AlignItems,
252 pub align_self: AlignSelf,
253 pub align_content: AlignContent,
254 pub justify_content: JustifyContent,
255 pub position: Rect<Dimension>,
256 pub margin: Rect<Dimension>,
257 pub padding: Rect<Dimension>,
258 pub border: Rect<Dimension>,
259 pub flex_grow: f32,
260 pub flex_shrink: f32,
261 pub flex_basis: Dimension,
262 pub size: Size<Dimension>,
263 pub min_size: Size<Dimension>,
264 pub max_size: Size<Dimension>,
265 pub aspect_ratio: Number,
266}
267
268impl Default for Style {
269 fn default() -> Style {
270 Style {
271 display: Default::default(),
272 position_type: Default::default(),
273 direction: Default::default(),
274 flex_direction: Default::default(),
275 flex_wrap: Default::default(),
276 overflow: Default::default(),
277 align_items: Default::default(),
278 align_self: Default::default(),
279 align_content: Default::default(),
280 justify_content: Default::default(),
281 position: Default::default(),
282 margin: Default::default(),
283 padding: Default::default(),
284 border: Default::default(),
285 flex_grow: 0.0,
286 flex_shrink: 1.0,
287 flex_basis: Dimension::Auto,
288 size: Default::default(),
289 min_size: Default::default(),
290 max_size: Default::default(),
291 aspect_ratio: Default::default(),
292 }
293 }
294}
295
296impl Style {
297 pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
298 match direction {
299 FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
300 FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.height,
301 }
302 }
303
304 pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
305 match direction {
306 FlexDirection::Row | FlexDirection::RowReverse => self.max_size.width,
307 FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.height,
308 }
309 }
310
311 pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
312 match direction {
313 FlexDirection::Row | FlexDirection::RowReverse => self.margin.start,
314 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.top,
315 }
316 }
317
318 pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
319 match direction {
320 FlexDirection::Row | FlexDirection::RowReverse => self.margin.end,
321 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.bottom,
322 }
323 }
324
325 pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
326 match direction {
327 FlexDirection::Row | FlexDirection::RowReverse => self.size.height,
328 FlexDirection::Column | FlexDirection::ColumnReverse => self.size.width,
329 }
330 }
331
332 pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
333 match direction {
334 FlexDirection::Row | FlexDirection::RowReverse => self.min_size.height,
335 FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.width,
336 }
337 }
338
339 pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
340 match direction {
341 FlexDirection::Row | FlexDirection::RowReverse => self.max_size.height,
342 FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.width,
343 }
344 }
345
346 pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
347 match direction {
348 FlexDirection::Row | FlexDirection::RowReverse => self.margin.top,
349 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.start,
350 }
351 }
352
353 pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
354 match direction {
355 FlexDirection::Row | FlexDirection::RowReverse => self.margin.bottom,
356 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.end,
357 }
358 }
359
360 pub(crate) fn align_self(&self, parent: &Style) -> AlignSelf {
361 if self.align_self == AlignSelf::Auto {
362 match parent.align_items {
363 AlignItems::FlexStart => AlignSelf::FlexStart,
364 AlignItems::FlexEnd => AlignSelf::FlexEnd,
365 AlignItems::Center => AlignSelf::Center,
366 AlignItems::Baseline => AlignSelf::Baseline,
367 AlignItems::Stretch => AlignSelf::Stretch,
368 }
369 } else {
370 self.align_self
371 }
372 }
373}