Serenity Operating System
1/*
2 * Copyright (c) 2022, Martin Falisse <mfalisse@outlook.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/Vector.h>
10#include <LibWeb/CSS/Length.h>
11#include <LibWeb/CSS/Percentage.h>
12
13namespace Web::CSS {
14
15class GridSize {
16public:
17 enum class Type {
18 Length,
19 Percentage,
20 FlexibleLength,
21 MaxContent,
22 MinContent,
23 };
24
25 GridSize(Length);
26 GridSize(Percentage);
27 GridSize(float);
28 GridSize(Type);
29 GridSize();
30 ~GridSize();
31
32 static GridSize make_auto();
33
34 Type type() const { return m_type; }
35
36 bool is_length() const { return m_type == Type::Length; }
37 bool is_percentage() const { return m_type == Type::Percentage; }
38 bool is_flexible_length() const { return m_type == Type::FlexibleLength; }
39 bool is_max_content() const { return m_type == Type::MaxContent; }
40 bool is_min_content() const { return m_type == Type::MinContent; }
41
42 Length length() const;
43 Percentage percentage() const { return m_percentage; }
44 float flexible_length() const { return m_flexible_length; }
45
46 // https://www.w3.org/TR/css-grid-2/#layout-algorithm
47 // An intrinsic sizing function (min-content, max-content, auto, fit-content()).
48 // FIXME: Add missing properties once implemented.
49 bool is_intrinsic_track_sizing() const
50 {
51 return (m_type == Type::Length && m_length.is_auto()) || m_type == Type::MaxContent || m_type == Type::MinContent;
52 }
53
54 bool is_definite() const
55 {
56 return (m_type == Type::Length && !m_length.is_auto()) || is_percentage();
57 }
58
59 ErrorOr<String> to_string() const;
60 bool operator==(GridSize const& other) const
61 {
62 return m_type == other.type()
63 && m_length == other.length()
64 && m_percentage == other.percentage()
65 && m_flexible_length == other.flexible_length();
66 }
67
68private:
69 Type m_type;
70 // Length includes a RefPtr<CalculatedStyleValue> member, but we can't include the header StyleValue.h as it includes
71 // this file already. To break the cyclic dependency, we must initialize m_length in the constructor.
72 Length m_length;
73 Percentage m_percentage { Percentage(0) };
74 float m_flexible_length { 0 };
75};
76
77class GridMinMax {
78public:
79 GridMinMax(CSS::GridSize min_grid_size, CSS::GridSize max_grid_size);
80 GridMinMax() = default;
81
82 GridSize min_grid_size() const& { return m_min_grid_size; }
83 GridSize max_grid_size() const& { return m_max_grid_size; }
84
85 ErrorOr<String> to_string() const;
86 bool operator==(GridMinMax const& other) const
87 {
88 return m_min_grid_size == other.min_grid_size()
89 && m_max_grid_size == other.max_grid_size();
90 }
91
92private:
93 GridSize m_min_grid_size;
94 GridSize m_max_grid_size;
95};
96
97class GridTrackSizeList {
98public:
99 GridTrackSizeList(Vector<CSS::ExplicitGridTrack> track_list, Vector<Vector<String>> line_names);
100 GridTrackSizeList();
101
102 static GridTrackSizeList make_auto();
103
104 Vector<CSS::ExplicitGridTrack> track_list() const { return m_track_list; }
105 Vector<Vector<String>> line_names() const { return m_line_names; }
106
107 ErrorOr<String> to_string() const;
108 bool operator==(GridTrackSizeList const& other) const
109 {
110 return m_line_names == other.line_names() && m_track_list == other.track_list();
111 }
112
113private:
114 Vector<CSS::ExplicitGridTrack> m_track_list;
115 Vector<Vector<String>> m_line_names;
116};
117
118class GridRepeat {
119public:
120 enum class Type {
121 AutoFit,
122 AutoFill,
123 Default,
124 };
125 GridRepeat(GridTrackSizeList, int repeat_count);
126 GridRepeat(GridTrackSizeList, Type);
127 GridRepeat();
128
129 bool is_auto_fill() const { return m_type == Type::AutoFill; }
130 bool is_auto_fit() const { return m_type == Type::AutoFit; }
131 bool is_default() const { return m_type == Type::Default; }
132 int repeat_count() const
133 {
134 VERIFY(is_default());
135 return m_repeat_count;
136 }
137 GridTrackSizeList grid_track_size_list() const& { return m_grid_track_size_list; }
138 Type type() const& { return m_type; }
139
140 ErrorOr<String> to_string() const;
141 bool operator==(GridRepeat const& other) const
142 {
143 if (m_type != other.type())
144 return false;
145 if (m_type == Type::Default && m_repeat_count != other.repeat_count())
146 return false;
147 return m_grid_track_size_list == other.grid_track_size_list();
148 }
149
150private:
151 Type m_type;
152 GridTrackSizeList m_grid_track_size_list;
153 int m_repeat_count { 0 };
154};
155
156class ExplicitGridTrack {
157public:
158 enum class Type {
159 MinMax,
160 Repeat,
161 Default,
162 };
163 ExplicitGridTrack(CSS::GridRepeat);
164 ExplicitGridTrack(CSS::GridMinMax);
165 ExplicitGridTrack(CSS::GridSize);
166
167 bool is_repeat() const { return m_type == Type::Repeat; }
168 GridRepeat repeat() const
169 {
170 VERIFY(is_repeat());
171 return m_grid_repeat;
172 }
173
174 bool is_minmax() const { return m_type == Type::MinMax; }
175 GridMinMax minmax() const
176 {
177 VERIFY(is_minmax());
178 return m_grid_minmax;
179 }
180
181 bool is_default() const { return m_type == Type::Default; }
182 GridSize grid_size() const
183 {
184 VERIFY(is_default());
185 return m_grid_size;
186 }
187
188 Type type() const { return m_type; }
189
190 ErrorOr<String> to_string() const;
191 bool operator==(ExplicitGridTrack const& other) const
192 {
193 if (is_repeat() && other.is_repeat())
194 return m_grid_repeat == other.repeat();
195 if (is_minmax() && other.is_minmax())
196 return m_grid_minmax == other.minmax();
197 if (is_default() && other.is_default())
198 return m_grid_size == other.grid_size();
199 return false;
200 }
201
202private:
203 Type m_type;
204 GridRepeat m_grid_repeat;
205 GridMinMax m_grid_minmax;
206 GridSize m_grid_size;
207};
208
209}