Skip to content

Commit 1814ebf

Browse files
committed
Add flex and grid sizer elements
1 parent 3266e6b commit 1814ebf

12 files changed

+829
-18
lines changed

builtin/ui/elem_defs.lua

+57
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,60 @@ function ui.Root:_encode_fields()
3232

3333
return ui._encode("ZS", ui.Elem._encode_fields(self), ui._encode_flags(fl))
3434
end
35+
36+
ui.Flex = ui._new_type(ui.Elem, "flex", 2)
37+
38+
function ui.Flex:new(props)
39+
ui.Elem.new(self, props)
40+
41+
self._dir = props.dir
42+
self._wrap = props.wrap
43+
end
44+
45+
local dir_map = {left = 0, up = 1, right = 2, down = 3};
46+
local wrap_map = {none = 0, forward = 1, backward = 2}
47+
48+
function ui.Flex:_encode_fields()
49+
local fl = ui._make_flags()
50+
51+
if ui._shift_flag(fl, self._dir) then
52+
ui._encode_flag(fl, "B", dir_map[self._dir])
53+
end
54+
if ui._shift_flag(fl, self._wrap) then
55+
ui._encode_flag(fl, "B", wrap_map[self._wrap])
56+
end
57+
58+
return ui._encode("ZS", ui.Elem._encode_fields(self), ui._encode_flags(fl))
59+
end
60+
61+
ui.Grid = ui._new_type(ui.Elem, "grid", 3)
62+
63+
function ui.Grid:new(props)
64+
ui.Elem.new(self, props)
65+
66+
self._hsizes = table.merge(props.hsizes or {})
67+
self._vsizes = table.merge(props.vsizes or {})
68+
69+
self._hweights = table.merge(props.hweights or {})
70+
self._vweights = table.merge(props.vweights or {})
71+
end
72+
73+
function ui.Grid:_encode_fields()
74+
local fl = ui._make_flags()
75+
76+
if ui._shift_flag(fl, #self._hsizes > 0) then
77+
ui._encode_flag(fl, "Z", ui._encode_array("f", self._hsizes))
78+
end
79+
if ui._shift_flag(fl, #self._vsizes > 0) then
80+
ui._encode_flag(fl, "Z", ui._encode_array("f", self._vsizes))
81+
end
82+
83+
if ui._shift_flag(fl, #self._hweights > 0) then
84+
ui._encode_flag(fl, "Z", ui._encode_array("f", self._hweights))
85+
end
86+
if ui._shift_flag(fl, #self._vweights > 0) then
87+
ui._encode_flag(fl, "Z", ui._encode_array("f", self._vweights))
88+
end
89+
90+
return ui._encode("ZS", ui.Elem._encode_fields(self), ui._encode_flags(fl))
91+
end

builtin/ui/style.lua

+24
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ function ui._cascade_props(add, props)
8080
new.margin = add.margin or props.margin
8181
new.padding = add.padding or props.padding
8282

83+
new.gap = add.gap or props.gap
84+
new.weight = add.weight or props.weight
85+
new.span = add.span or props.span
86+
87+
new.hspacing = add.hspacing or props.hspacing
88+
new.vspacing = add.vspacing or props.vspacing
89+
8390
cascade_layer(new, add, props, "bg")
8491
cascade_layer(new, add, props, "fg")
8592

@@ -168,6 +175,23 @@ function ui._encode_props(props)
168175
ui._encode_flag(fl, "ffff", unpack(props.padding))
169176
end
170177

178+
if ui._shift_flag(fl, props.gap) then
179+
ui._encode_flag(fl, "ff", unpack(props.gap))
180+
end
181+
if ui._shift_flag(fl, props.weight) then
182+
ui._encode_flag(fl, "f", props.weight)
183+
end
184+
if ui._shift_flag(fl, props.span) then
185+
ui._encode_flag(fl, "ii", unpack(props.span))
186+
end
187+
188+
if ui._shift_flag(fl, props.hspacing) then
189+
ui._encode_flag(fl, "B", spacing_map[props.hspacing])
190+
end
191+
if ui._shift_flag(fl, props.vspacing) then
192+
ui._encode_flag(fl, "B", spacing_map[props.vspacing])
193+
end
194+
171195
local bg_fl = encode_layer(props, "bg")
172196
if ui._shift_flag(fl, bg_fl.flags ~= 0) then
173197
ui._encode_flag(fl, "S", ui._encode_flags(bg_fl))

src/gui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ set(gui_SRCS
3333
${CMAKE_CURRENT_SOURCE_DIR}/manager.cpp
3434
${CMAKE_CURRENT_SOURCE_DIR}/modalMenu.cpp
3535
${CMAKE_CURRENT_SOURCE_DIR}/profilergraph.cpp
36+
${CMAKE_CURRENT_SOURCE_DIR}/sizer_elems.cpp
3637
${CMAKE_CURRENT_SOURCE_DIR}/texture.cpp
3738
${CMAKE_CURRENT_SOURCE_DIR}/window.cpp
3839
${extra_gui_SRCS}

src/gui/box.cpp

+42-5
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ namespace ui
103103
margin = rf32(0.0f, 0.0f, 0.0f, 0.0f);
104104
padding = rf32(0.0f, 0.0f, 0.0f, 0.0f);
105105

106+
gap = v2f32(0.0f, 0.0f);
107+
weight = 0.0f;
108+
span = v2s32(1, 1);
109+
110+
hspacing = Spacing::AFTER;
111+
vspacing = Spacing::AFTER;
112+
106113
bg.reset();
107114
fg.reset();
108115

@@ -141,6 +148,19 @@ namespace ui
141148
padding.LowerRightCorner = readV2F32(is);
142149
}
143150

151+
if (testShift(set_mask))
152+
gap = clamp_vec(readV2F32(is));
153+
if (testShift(set_mask))
154+
weight = std::max(readF32(is), 0.0f);
155+
if (testShift(set_mask)) {
156+
span = clamp_vec(readV2S32(is), v2s32(1, 1));
157+
}
158+
159+
if (testShift(set_mask))
160+
hspacing = toSpacing(readU8(is));
161+
if (testShift(set_mask))
162+
vspacing = toSpacing(readU8(is));
163+
144164
if (testShift(set_mask))
145165
bg.read(is);
146166
if (testShift(set_mask))
@@ -189,25 +209,42 @@ namespace ui
189209
}
190210
}
191211

192-
void Box::layout(const rf32 &parent_rect, const rf32 &parent_clip)
212+
void Box::layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
193213
{
194214
// First, calculate the size of the element in absolute coordinates
195215
// based on the normalized size.
196216
d2f32 origin_size(
197-
(m_style.rel_size.Width * parent_rect.getWidth()) + m_style.size.Width,
198-
(m_style.rel_size.Height * parent_rect.getHeight()) + m_style.size.Height
217+
(m_style.rel_size.Width * parent_rect.getWidth()),
218+
(m_style.rel_size.Height * parent_rect.getHeight())
199219
);
200220

221+
if (!sizer) {
222+
// If this box is not in a sizer, then the "pos" and "size"
223+
// attributes are absolute pixel amounts to offset the rect by.
224+
origin_size.Width += m_style.size.Width;
225+
origin_size.Height += m_style.size.Height;
226+
} else {
227+
// Otherwise, the "size" attribute is the minimum size of the box
228+
// and the "pos" attribute is reserved for the sizer's use.
229+
origin_size.Width = std::max(origin_size.Width, m_style.size.Width);
230+
origin_size.Height = std::max(origin_size.Height, m_style.size.Height);
231+
}
232+
201233
// Then, create the rect of the element relative to the origin by
202234
// converting the normalized position absolute coordinates, while
203235
// accounting for the anchor based on the previously calculated size.
204236
v2f32 origin_pos(
205-
(m_style.rel_pos.X * parent_rect.getWidth()) + m_style.pos.X -
237+
(m_style.rel_pos.X * parent_rect.getWidth()) -
206238
(m_style.rel_anchor.X * origin_size.Width),
207-
(m_style.rel_pos.Y * parent_rect.getHeight()) + m_style.pos.Y -
239+
(m_style.rel_pos.Y * parent_rect.getHeight()) -
208240
(m_style.rel_anchor.Y * origin_size.Height)
209241
);
210242

243+
if (!sizer) {
244+
origin_pos.X += m_style.pos.X;
245+
origin_pos.Y += m_style.pos.Y;
246+
}
247+
211248
rf32 origin_rect(origin_pos, origin_size);
212249

213250
// The absolute rect of the element is made by shifting the origin to

src/gui/box.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ namespace ui
9090
rf32 margin;
9191
rf32 padding;
9292

93+
v2f32 gap;
94+
float weight;
95+
d2s32 span;
96+
97+
Spacing hspacing;
98+
Spacing vspacing;
99+
93100
Layer bg;
94101
Layer fg;
95102

@@ -169,7 +176,7 @@ namespace ui
169176
void reset();
170177
void read(std::istream &is);
171178

172-
void layout(const rf32 &parent_rect, const rf32 &parent_clip);
179+
void layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
173180
void draw(Canvas &parent);
174181

175182
private:

src/gui/elem.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2727

2828
// Include every element header for Elem::create()
2929
#include "gui/generic_elems.h"
30+
#include "gui/sizer_elems.h"
3031

3132
namespace ui
3233
{
@@ -42,6 +43,8 @@ namespace ui
4243
switch (type) {
4344
CREATE(ELEM, Elem);
4445
CREATE(ROOT, Root);
46+
CREATE(FLEX, Flex);
47+
CREATE(GRID, Grid);
4548
default:
4649
return nullptr;
4750
}
@@ -88,9 +91,9 @@ namespace ui
8891
m_main_box.setState(Box::STATE_NONE);
8992
}
9093

91-
void Elem::layout(const rf32 &parent_rect, const rf32 &parent_clip)
94+
void Elem::layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
9295
{
93-
layoutBoxes(parent_rect, parent_clip);
96+
layoutBoxes(parent_rect, parent_clip, sizer);
9497
layoutChildren();
9598
}
9699

@@ -103,15 +106,15 @@ namespace ui
103106
}
104107
}
105108

106-
void Elem::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip)
109+
void Elem::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
107110
{
108-
m_main_box.layout(parent_rect, parent_clip);
111+
m_main_box.layout(parent_rect, parent_clip, sizer);
109112
}
110113

111114
void Elem::layoutChildren()
112115
{
113116
for (Elem *child : m_children) {
114-
child->layout(m_main_box.getChildRect(), m_main_box.getChildClip());
117+
child->layout(m_main_box.getChildRect(), m_main_box.getChildClip(), false);
115118
}
116119
}
117120

src/gui/elem.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ namespace ui
3939
{
4040
ELEM,
4141
ROOT,
42+
FLEX,
43+
GRID,
4244
};
4345

4446
private:
@@ -77,12 +79,12 @@ namespace ui
7779
virtual void reset();
7880
virtual void read(std::istream &is);
7981

80-
void layout(const rf32 &parent_rect, const rf32 &parent_clip);
82+
void layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
8183
void drawAll(Canvas &canvas);
8284

8385
protected:
8486
virtual void layoutBoxes(
85-
const rf32 &parent_rect, const rf32 &parent_clip);
87+
const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
8688
virtual void layoutChildren();
8789

8890
virtual void draw(Canvas &canvas);

src/gui/generic_elems.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ namespace ui
5151
m_backdrop_box.setState(Box::STATE_NONE);
5252
}
5353

54-
void Root::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip)
54+
void Root::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
5555
{
56-
m_backdrop_box.layout(parent_rect, parent_clip);
56+
m_backdrop_box.layout(parent_rect, parent_clip, false);
5757

5858
Elem::layoutBoxes(
59-
m_backdrop_box.getChildRect(), m_backdrop_box.getChildClip());
59+
m_backdrop_box.getChildRect(), m_backdrop_box.getChildClip(), sizer);
6060
}
6161

6262
void Root::draw(Canvas &canvas)

src/gui/generic_elems.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace ui
4343

4444
protected:
4545
virtual void layoutBoxes(
46-
const rf32 &parent_rect, const rf32 &parent_clip);
46+
const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
4747

4848
virtual void draw(Canvas &canvas);
4949
};

0 commit comments

Comments
 (0)