azul_layout/
style.rs

1#![allow(dead_code)]
2
3// MIT License
4//
5// Copyright (c) 2018 Visly Inc.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25use crate::{
26    geometry::{Offsets, DEFAULT_OFFSETS, DEFAULT_SIZE, Size},
27    number::Number,
28};
29use azul_css::PixelValue;
30
31#[derive(Copy, Clone, PartialEq, Debug)]
32pub enum AlignItems {
33    FlexStart,
34    FlexEnd,
35    Center,
36    Baseline,
37    Stretch,
38}
39
40impl AlignItems {
41    pub(crate) const DEFAULT: AlignItems = AlignItems::FlexStart;
42}
43
44impl Default for AlignItems {
45    fn default() -> AlignItems {
46        AlignItems::DEFAULT
47    }
48}
49
50#[derive(Copy, Clone, PartialEq, Debug)]
51pub enum AlignSelf {
52    Auto,
53    FlexStart,
54    FlexEnd,
55    Center,
56    Baseline,
57    Stretch,
58}
59
60impl AlignSelf {
61    pub(crate) const DEFAULT: AlignSelf = AlignSelf::Auto;
62}
63
64impl Default for AlignSelf {
65    fn default() -> AlignSelf {
66        AlignSelf::DEFAULT
67    }
68}
69
70#[derive(Copy, Clone, PartialEq, Debug)]
71pub enum AlignContent {
72    FlexStart,
73    FlexEnd,
74    Center,
75    Stretch,
76    SpaceBetween,
77    SpaceAround,
78}
79
80impl AlignContent {
81    pub(crate) const DEFAULT: AlignContent = AlignContent::Stretch;
82}
83
84impl Default for AlignContent {
85    fn default() -> AlignContent {
86        AlignContent::DEFAULT
87    }
88}
89
90#[derive(Copy, Clone, PartialEq, Debug)]
91pub enum Direction {
92    Inherit,
93    LTR,
94    RTL,
95}
96
97impl Direction {
98    const DEFAULT: Direction = Direction::Inherit;
99}
100
101impl Default for Direction {
102    fn default() -> Direction {
103        Direction::DEFAULT
104    }
105}
106
107#[derive(Copy, Clone, PartialEq, Debug)]
108pub enum Display {
109    Flex,
110    Block,
111    InlineBlock,
112    None,
113}
114
115impl Display {
116    const DEFAULT: Display = Display::Block;
117}
118
119impl Default for Display {
120    fn default() -> Display {
121        Display::DEFAULT
122    }
123}
124
125#[derive(Copy, Clone, PartialEq, Debug)]
126pub enum FlexDirection {
127    Row,
128    Column,
129    RowReverse,
130    ColumnReverse,
131}
132
133impl FlexDirection {
134    pub(crate) const DEFAULT: FlexDirection = FlexDirection::Row;
135}
136
137impl Default for FlexDirection {
138    fn default() -> FlexDirection {
139        FlexDirection::DEFAULT
140    }
141}
142
143impl FlexDirection {
144    pub(crate) fn is_row(self) -> bool {
145        self == FlexDirection::Row || self == FlexDirection::RowReverse
146    }
147
148    pub(crate) fn is_column(self) -> bool {
149        self == FlexDirection::Column || self == FlexDirection::ColumnReverse
150    }
151
152    pub(crate) fn is_reverse(self) -> bool {
153        self == FlexDirection::RowReverse || self == FlexDirection::ColumnReverse
154    }
155}
156
157#[derive(Copy, Clone, PartialEq, Debug)]
158pub enum JustifyContent {
159    FlexStart,
160    FlexEnd,
161    Center,
162    SpaceBetween,
163    SpaceAround,
164    SpaceEvenly,
165}
166
167impl JustifyContent {
168    pub(crate) const DEFAULT: JustifyContent = JustifyContent::FlexStart;
169}
170
171impl Default for JustifyContent {
172    fn default() -> JustifyContent {
173        JustifyContent::DEFAULT
174    }
175}
176
177#[derive(Copy, Clone, PartialEq, Debug)]
178pub enum Overflow {
179    Auto,
180    Visible,
181    Hidden,
182    Scroll,
183}
184
185impl Overflow {
186    pub(crate) const DEFAULT: Overflow = Overflow::Scroll;
187}
188
189impl Default for Overflow {
190    fn default() -> Overflow {
191        Overflow::DEFAULT
192    }
193}
194
195impl Overflow {
196    pub fn allows_horizontal_overflow(&self) -> bool {
197        use self::Overflow::*;
198        match self {
199            Auto => false,
200            Visible => true,
201            Hidden => true,
202            Scroll => false,
203        }
204    }
205
206    pub fn allows_vertical_overflow(&self) -> bool {
207        true
208    }
209}
210
211#[derive(Copy, Clone, PartialEq, Debug)]
212pub enum PositionType {
213    Relative,
214    Absolute,
215    Static,
216    Fixed,
217}
218
219impl PositionType {
220    pub(crate) const DEFAULT: PositionType = PositionType::Relative;
221}
222
223impl Default for PositionType {
224    fn default() -> PositionType {
225        PositionType::Relative
226    }
227}
228
229#[derive(Copy, Clone, PartialEq, Debug)]
230pub enum FlexWrap {
231    NoWrap,
232    Wrap,
233    WrapReverse,
234}
235
236impl FlexWrap {
237    pub(crate) const DEFAULT: FlexWrap = FlexWrap::Wrap;
238}
239
240impl Default for FlexWrap {
241    fn default() -> FlexWrap {
242        FlexWrap::DEFAULT
243    }
244}
245
246#[derive(Copy, Clone, PartialEq, Debug)]
247pub enum Dimension {
248    Undefined,
249    Auto,
250    Pixels(f32),
251    Percent(f32),
252}
253
254impl Dimension {
255    pub(crate) const DEFAULT: Dimension = Dimension::Undefined;
256}
257
258impl Default for Dimension {
259    #[inline]
260    fn default() -> Dimension {
261        Dimension::DEFAULT
262    }
263}
264
265impl Dimension {
266    pub(crate) fn resolve(self, parent_width: Number) -> Number {
267        match self {
268            Dimension::Pixels(pixels) => Number::Defined(pixels),
269            Dimension::Percent(percent) => parent_width * (percent / 100.0),
270            _ => Number::Undefined,
271        }
272    }
273
274    pub(crate) fn is_defined(self) -> bool {
275        match self {
276            Dimension::Pixels(_) => true,
277            Dimension::Percent(_) => true,
278            _ => false,
279        }
280    }
281}
282
283impl Default for Offsets<Dimension> {
284    #[inline]
285    fn default() -> Offsets<Dimension> {
286        DEFAULT_OFFSETS
287    }
288}
289
290impl Default for Size<Dimension> {
291    #[inline]
292    fn default() -> Size<Dimension> {
293        DEFAULT_SIZE
294    }
295}
296
297#[derive(Copy, Clone, PartialEq, Debug)]
298pub enum BoxSizing {
299    ContentBox,
300    BorderBox,
301}
302
303impl BoxSizing {
304    pub(crate) const DEFAULT: BoxSizing = BoxSizing::ContentBox;
305}
306
307impl Default for BoxSizing {
308    #[inline]
309    fn default() -> BoxSizing {
310        BoxSizing::DEFAULT
311    }
312}
313
314#[derive(Copy, Clone, Debug)]
315pub struct Style {pub display: Display,
316    pub box_sizing: BoxSizing,
317    pub position_type: PositionType,
318    pub direction: Direction,
319    pub flex_direction: FlexDirection,
320    pub flex_wrap: FlexWrap,
321    pub overflow: Overflow,
322    pub align_items: AlignItems,
323    pub align_self: AlignSelf,
324    pub align_content: AlignContent,
325    pub justify_content: JustifyContent,
326    pub position: Offsets<Dimension>,
327    pub margin: Offsets<Dimension>,
328    pub padding: Offsets<Dimension>,
329    pub border: Offsets<Dimension>,
330    pub flex_grow: f32,
331    pub flex_shrink: f32,
332    pub flex_basis: Dimension,
333    pub size: Size<Dimension>,
334    pub min_size: Size<Dimension>,
335    pub max_size: Size<Dimension>,
336    pub aspect_ratio: Number,
337    pub font_size_px: PixelValue,
338    pub letter_spacing: Option<PixelValue>,
339    pub word_spacing: Option<PixelValue>,
340    pub line_height: Option<f32>,
341    pub tab_width: Option<f32>,
342}
343
344impl Style {
345    pub(crate) const DEFAULT: Style = Style {
346        display: Display::DEFAULT,
347        box_sizing: BoxSizing::DEFAULT,
348        position_type: PositionType::DEFAULT,
349        direction: Direction::DEFAULT,
350        flex_direction: FlexDirection::DEFAULT,
351        flex_wrap: FlexWrap::DEFAULT,
352        overflow: Overflow::DEFAULT,
353        align_items: AlignItems::DEFAULT,
354        align_self: AlignSelf::DEFAULT,
355        align_content: AlignContent::DEFAULT,
356        justify_content: JustifyContent::DEFAULT,
357        position: DEFAULT_OFFSETS,
358        margin: DEFAULT_OFFSETS,
359        padding: DEFAULT_OFFSETS,
360        border: DEFAULT_OFFSETS,
361        flex_grow: 0.0,
362        flex_shrink: 1.0,
363        flex_basis: Dimension::Auto,
364        size: DEFAULT_SIZE,
365        min_size: DEFAULT_SIZE,
366        max_size: DEFAULT_SIZE,
367        aspect_ratio: Number::Undefined,
368        font_size_px: PixelValue::const_px(10),
369        letter_spacing: None,
370        line_height: None,
371        word_spacing: None,
372        tab_width: None,
373    };
374}
375
376pub(crate) static DEFAULT_STYLE: Style = Style::DEFAULT;
377
378impl Default for Style {
379    fn default() -> Style {
380        Style::DEFAULT
381    }
382}
383
384impl Style {
385    pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
386        match direction {
387            FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
388            FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.height,
389        }
390    }
391
392    pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
393        match direction {
394            FlexDirection::Row | FlexDirection::RowReverse => self.max_size.width,
395            FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.height,
396        }
397    }
398
399    pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
400        match direction {
401            FlexDirection::Row | FlexDirection::RowReverse => self.margin.left,
402            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.top,
403        }
404    }
405
406    pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
407        match direction {
408            FlexDirection::Row | FlexDirection::RowReverse => self.margin.right,
409            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.bottom,
410        }
411    }
412
413    pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
414        match direction {
415            FlexDirection::Row | FlexDirection::RowReverse => self.size.height,
416            FlexDirection::Column | FlexDirection::ColumnReverse => self.size.width,
417        }
418    }
419
420    pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
421        match direction {
422            FlexDirection::Row | FlexDirection::RowReverse => self.min_size.height,
423            FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.width,
424        }
425    }
426
427    pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
428        match direction {
429            FlexDirection::Row | FlexDirection::RowReverse => self.max_size.height,
430            FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.width,
431        }
432    }
433
434    pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
435        match direction {
436            FlexDirection::Row | FlexDirection::RowReverse => self.margin.top,
437            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.left,
438        }
439    }
440
441    pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
442        match direction {
443            FlexDirection::Row | FlexDirection::RowReverse => self.margin.bottom,
444            FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.right,
445        }
446    }
447
448    pub(crate) fn align_self(&self, parent: &Style) -> AlignSelf {
449        if self.align_self == AlignSelf::Auto {
450            match parent.align_items {
451                AlignItems::FlexStart => AlignSelf::FlexStart,
452                AlignItems::FlexEnd => AlignSelf::FlexEnd,
453                AlignItems::Center => AlignSelf::Center,
454                AlignItems::Baseline => AlignSelf::Baseline,
455                AlignItems::Stretch => AlignSelf::Stretch,
456            }
457        } else {
458            self.align_self
459        }
460    }
461}