Skip to content

Commit

Permalink
Add flex and grid sizer elements
Browse files Browse the repository at this point in the history
  • Loading branch information
v-rob committed Jan 24, 2024
1 parent b033405 commit 0beb35f
Show file tree
Hide file tree
Showing 12 changed files with 829 additions and 18 deletions.
57 changes: 57 additions & 0 deletions builtin/ui/elem_defs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,60 @@ function ui.Root:_encode_fields()

return ui._encode("ZS", ui.Elem._encode_fields(self), ui._encode_flags(fl))
end

ui.Flex = ui._new_type(ui.Elem, "flex", 2)

function ui.Flex:new(props)
ui.Elem.new(self, props)

self._dir = props.dir
self._wrap = props.wrap
end

local dir_map = {left = 0, up = 1, right = 2, down = 3};
local wrap_map = {none = 0, forward = 1, backward = 2}

function ui.Flex:_encode_fields()
local fl = ui._make_flags()

if ui._shift_flag(fl, self._dir) then
ui._encode_flag(fl, "B", dir_map[self._dir])
end
if ui._shift_flag(fl, self._wrap) then
ui._encode_flag(fl, "B", wrap_map[self._wrap])
end

return ui._encode("ZS", ui.Elem._encode_fields(self), ui._encode_flags(fl))
end

ui.Grid = ui._new_type(ui.Elem, "grid", 3)

function ui.Grid:new(props)
ui.Elem.new(self, props)

self._hsizes = table.merge(props.hsizes or {})
self._vsizes = table.merge(props.vsizes or {})

self._hweights = table.merge(props.hweights or {})
self._vweights = table.merge(props.vweights or {})
end

function ui.Grid:_encode_fields()
local fl = ui._make_flags()

if ui._shift_flag(fl, #self._hsizes > 0) then
ui._encode_flag(fl, "Z", ui._encode_array("f", self._hsizes))
end
if ui._shift_flag(fl, #self._vsizes > 0) then
ui._encode_flag(fl, "Z", ui._encode_array("f", self._vsizes))
end

if ui._shift_flag(fl, #self._hweights > 0) then
ui._encode_flag(fl, "Z", ui._encode_array("f", self._hweights))
end
if ui._shift_flag(fl, #self._vweights > 0) then
ui._encode_flag(fl, "Z", ui._encode_array("f", self._vweights))
end

return ui._encode("ZS", ui.Elem._encode_fields(self), ui._encode_flags(fl))
end
24 changes: 24 additions & 0 deletions builtin/ui/style.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ function ui._cascade_props(add, props)
new.margin = add.margin or props.margin
new.padding = add.padding or props.padding

new.gap = add.gap or props.gap
new.weight = add.weight or props.weight
new.span = add.span or props.span

new.hspacing = add.hspacing or props.hspacing
new.vspacing = add.vspacing or props.vspacing

cascade_layer(new, add, props, "bg")
cascade_layer(new, add, props, "fg")

Expand Down Expand Up @@ -168,6 +175,23 @@ function ui._encode_props(props)
ui._encode_flag(fl, "ffff", unpack(props.padding))
end

if ui._shift_flag(fl, props.gap) then
ui._encode_flag(fl, "ff", unpack(props.gap))
end
if ui._shift_flag(fl, props.weight) then
ui._encode_flag(fl, "f", props.weight)
end
if ui._shift_flag(fl, props.span) then
ui._encode_flag(fl, "ii", unpack(props.span))
end

if ui._shift_flag(fl, props.hspacing) then
ui._encode_flag(fl, "B", spacing_map[props.hspacing])
end
if ui._shift_flag(fl, props.vspacing) then
ui._encode_flag(fl, "B", spacing_map[props.vspacing])
end

local bg_fl = encode_layer(props, "bg")
if ui._shift_flag(fl, bg_fl.flags ~= 0) then
ui._encode_flag(fl, "S", ui._encode_flags(bg_fl))
Expand Down
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(gui_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/manager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/modalMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/profilergraph.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sizer_elems.cpp
${CMAKE_CURRENT_SOURCE_DIR}/texture.cpp
${CMAKE_CURRENT_SOURCE_DIR}/window.cpp
${extra_gui_SRCS}
Expand Down
47 changes: 42 additions & 5 deletions src/gui/box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ namespace ui
margin = rf32(0.0f, 0.0f, 0.0f, 0.0f);
padding = rf32(0.0f, 0.0f, 0.0f, 0.0f);

gap = v2f32(0.0f, 0.0f);
weight = 0.0f;
span = v2s32(1, 1);

hspacing = Spacing::AFTER;
vspacing = Spacing::AFTER;

bg.reset();
fg.reset();

Expand Down Expand Up @@ -141,6 +148,19 @@ namespace ui
padding.LowerRightCorner = readV2F32(is);
}

if (testShift(set_mask))
gap = clamp_vec(readV2F32(is));
if (testShift(set_mask))
weight = std::max(readF32(is), 0.0f);
if (testShift(set_mask)) {
span = clamp_vec(readV2S32(is), v2s32(1, 1));
}

if (testShift(set_mask))
hspacing = toSpacing(readU8(is));
if (testShift(set_mask))
vspacing = toSpacing(readU8(is));

if (testShift(set_mask))
bg.read(is);
if (testShift(set_mask))
Expand Down Expand Up @@ -189,25 +209,42 @@ namespace ui
}
}

void Box::layout(const rf32 &parent_rect, const rf32 &parent_clip)
void Box::layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
{
// First, calculate the size of the element in absolute coordinates
// based on the normalized size.
d2f32 origin_size(
(m_style.rel_size.Width * parent_rect.getWidth()) + m_style.size.Width,
(m_style.rel_size.Height * parent_rect.getHeight()) + m_style.size.Height
(m_style.rel_size.Width * parent_rect.getWidth()),
(m_style.rel_size.Height * parent_rect.getHeight())
);

if (!sizer) {
// If this box is not in a sizer, then the "pos" and "size"
// attributes are absolute pixel amounts to offset the rect by.
origin_size.Width += m_style.size.Width;
origin_size.Height += m_style.size.Height;
} else {
// Otherwise, the "size" attribute is the minimum size of the box
// and the "pos" attribute is reserved for the sizer's use.
origin_size.Width = std::max(origin_size.Width, m_style.size.Width);
origin_size.Height = std::max(origin_size.Height, m_style.size.Height);
}

// Then, create the rect of the element relative to the origin by
// converting the normalized position absolute coordinates, while
// accounting for the anchor based on the previously calculated size.
v2f32 origin_pos(
(m_style.rel_pos.X * parent_rect.getWidth()) + m_style.pos.X -
(m_style.rel_pos.X * parent_rect.getWidth()) -
(m_style.rel_anchor.X * origin_size.Width),
(m_style.rel_pos.Y * parent_rect.getHeight()) + m_style.pos.Y -
(m_style.rel_pos.Y * parent_rect.getHeight()) -
(m_style.rel_anchor.Y * origin_size.Height)
);

if (!sizer) {
origin_pos.X += m_style.pos.X;
origin_pos.Y += m_style.pos.Y;
}

rf32 origin_rect(origin_pos, origin_size);

// The absolute rect of the element is made by shifting the origin to
Expand Down
9 changes: 8 additions & 1 deletion src/gui/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ namespace ui
rf32 margin;
rf32 padding;

v2f32 gap;
float weight;
d2s32 span;

Spacing hspacing;
Spacing vspacing;

Layer bg;
Layer fg;

Expand Down Expand Up @@ -169,7 +176,7 @@ namespace ui
void reset();
void read(std::istream &is);

void layout(const rf32 &parent_rect, const rf32 &parent_clip);
void layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
void draw(Canvas &parent);

private:
Expand Down
13 changes: 8 additions & 5 deletions src/gui/elem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,

// Include every element header for Elem::create()
#include "gui/generic_elems.h"
#include "gui/sizer_elems.h"

namespace ui
{
Expand All @@ -42,6 +43,8 @@ namespace ui
switch (type) {
CREATE(ELEM, Elem);
CREATE(ROOT, Root);
CREATE(FLEX, Flex);
CREATE(GRID, Grid);
default:
return nullptr;
}
Expand Down Expand Up @@ -88,9 +91,9 @@ namespace ui
m_main_box.setState(Box::STATE_NONE);
}

void Elem::layout(const rf32 &parent_rect, const rf32 &parent_clip)
void Elem::layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
{
layoutBoxes(parent_rect, parent_clip);
layoutBoxes(parent_rect, parent_clip, sizer);
layoutChildren();
}

Expand All @@ -103,15 +106,15 @@ namespace ui
}
}

void Elem::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip)
void Elem::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
{
m_main_box.layout(parent_rect, parent_clip);
m_main_box.layout(parent_rect, parent_clip, sizer);
}

void Elem::layoutChildren()
{
for (Elem *child : m_children) {
child->layout(m_main_box.getChildRect(), m_main_box.getChildClip());
child->layout(m_main_box.getChildRect(), m_main_box.getChildClip(), false);
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/gui/elem.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ namespace ui
{
ELEM,
ROOT,
FLEX,
GRID,
};

private:
Expand Down Expand Up @@ -77,12 +79,12 @@ namespace ui
virtual void reset();
virtual void read(std::istream &is);

void layout(const rf32 &parent_rect, const rf32 &parent_clip);
void layout(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
void drawAll(Canvas &canvas);

protected:
virtual void layoutBoxes(
const rf32 &parent_rect, const rf32 &parent_clip);
const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);
virtual void layoutChildren();

virtual void draw(Canvas &canvas);
Expand Down
6 changes: 3 additions & 3 deletions src/gui/generic_elems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ namespace ui
m_backdrop_box.setState(Box::STATE_NONE);
}

void Root::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip)
void Root::layoutBoxes(const rf32 &parent_rect, const rf32 &parent_clip, bool sizer)
{
m_backdrop_box.layout(parent_rect, parent_clip);
m_backdrop_box.layout(parent_rect, parent_clip, false);

Elem::layoutBoxes(
m_backdrop_box.getChildRect(), m_backdrop_box.getChildClip());
m_backdrop_box.getChildRect(), m_backdrop_box.getChildClip(), sizer);
}

void Root::draw(Canvas &canvas)
Expand Down
2 changes: 1 addition & 1 deletion src/gui/generic_elems.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace ui

protected:
virtual void layoutBoxes(
const rf32 &parent_rect, const rf32 &parent_clip);
const rf32 &parent_rect, const rf32 &parent_clip, bool sizer);

virtual void draw(Canvas &canvas);
};
Expand Down
Loading

0 comments on commit 0beb35f

Please sign in to comment.