aboutsummaryrefslogtreecommitdiff
path: root/src/ui/layout_base.hpp
blob: 527d9f986f2a400b007449fc235b97bb6c56dfca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#pragma once

// ReSharper disable once CppUnusedIncludeDirective
#include "pre.hpp"

#include "ui_base.hpp"

namespace cru::ui
{
    enum class Alignment
    {
        Center,
        Start,
        End
    };

    enum class MeasureMode
    {
        Exactly,
        Content,
        Stretch
    };

    enum class RectRange
    {
        Content, // content excluding padding, border and margin
        Padding, // only including content and padding
        HalfBorder, // including content, padding and half border
        FullBorder, // including content, padding and full border
        Margin // including content, padding, border and margin
    };

    struct LayoutSideParams final
    {
        constexpr static LayoutSideParams Exactly(const float length, const Alignment alignment = Alignment::Center)
        {
            return LayoutSideParams(MeasureMode::Exactly, length, alignment);
        }

        constexpr static LayoutSideParams Content(const Alignment alignment = Alignment::Center)
        {
            return LayoutSideParams(MeasureMode::Content, 0, alignment);
        }

        constexpr static LayoutSideParams Stretch(const Alignment alignment = Alignment::Center)
        {
            return LayoutSideParams(MeasureMode::Stretch, 0, alignment);
        }

        constexpr LayoutSideParams() = default;

        constexpr explicit LayoutSideParams(const MeasureMode mode, const float length, const Alignment alignment)
            : length(length), mode(mode), alignment(alignment)
        {

        }

        constexpr bool Validate() const
        {
            if (length < 0.0)
                return false;
            if (min.has_value() && min.value() < 0.0)
                return false;
            if (max.has_value() && max.value() < 0.0)
                return false;
            if (min.has_value() && max.has_value() && min.value() > max.value())
                return false;
            return true;
        }

        // only used in exactly mode, specify the exactly side length of content.
        float length = 0.0;
        MeasureMode mode = MeasureMode::Content;
        Alignment alignment = Alignment::Center;

        // min and max specify the min/max side length of content.
        // they are used as hint and respect the actual size that content needs.
        // when mode is exactly, length is coerced into the min-max range.
        std::optional<float> min = std::nullopt;
        std::optional<float> max = std::nullopt;
    };

    struct BasicLayoutParams final
    {
        BasicLayoutParams() = default;
        BasicLayoutParams(const BasicLayoutParams&) = default;
        BasicLayoutParams(BasicLayoutParams&&) = default;
        BasicLayoutParams& operator = (const BasicLayoutParams&) = default;
        BasicLayoutParams& operator = (BasicLayoutParams&&) = default;
        ~BasicLayoutParams() = default;

        bool Validate() const
        {
            return width.Validate() && height.Validate() && margin.Validate() && padding.Validate();
        }

        LayoutSideParams width;
        LayoutSideParams height;
        Thickness padding;
        Thickness margin;
    };
}