Skip to content

Instantly share code, notes, and snippets.

@shakesoda
Created January 9, 2018 04:41
Show Gist options
  • Save shakesoda/6c14533a1b6b6efdaeaabf6a4c88444c to your computer and use it in GitHub Desktop.
Save shakesoda/6c14533a1b6b6efdaeaabf6a4c88444c to your computer and use it in GitHub Desktop.
flexible box layout prototype
local start_time = love.filesystem.getLastModified("main.lua")
function love.update(dt)
if (love.filesystem.getLastModified("main.lua") > start_time) then
love.event.quit("restart")
end
end
local function round(value, precision)
if precision then return round(value / precision) * precision end
return value >= 0 and math.floor(value+0.5) or ceil(value-0.5)
end
local widgets = {
layout = "row",
{ label = "asdf", height = 25 },
{
layout = "column",
label = "ghjk",
height = 25,
{ label = "OK", width = 100 },
{ label = "Cancel", width = 100 },
},
{
layout = "column",
height = 50,
{ label = "GGGG", width = 100 },
{ label = "Baby Baby", width = 100 },
{
layout = "column",
width = 100,
height = 50,
{ label = "OK", width = 100 },
{ label = "Cancel", width = 100 },
{
layout = "row",
width = 100,
height = 50,
{ label = "OK" },
{ label = "Cancel" },
}
}
}
}
local layout = {}
-- scale normalized ui layout to w*h, with care to fix gaps
function layout.scale(ui, w, h, do_rounding)
for _, item in ipairs(ui) do
if do_rounding then
item.x = item.x * w
item.y = item.y * h
-- fudge for floating point inaccuracy
item.x = (item.x + 0.01)
item.y = (item.y + 0.01)
-- carry adjusted item position into width
item.x_diff = item.x - math.floor(item.x)
item.y_diff = item.y - math.floor(item.y)
item.x = item.x - item.x_diff
item.y = item.y - item.y_diff
item.width = math.floor(item.width * w + item.x_diff)
item.height = math.floor(item.height * h + item.y_diff)
else
item.x = item.x * w
item.y = item.y * h
item.width = item.width * w
item.height = item.height * h
end
end
end
function layout.pack(widgets, ui, parent)
local ui = ui or {}
local total = 0
for i, v in ipairs(widgets) do
-- fill in default of 1
v.width = v.width or 1
v.height = v.height or 1
local size = v.width
if widgets.layout == "row" then
size = v.height
end
assert(size > 0)
total = total + size
end
local advance = 0
for i, v in ipairs(widgets) do
local item = {
label = v.label or string.format("<unknown %d>", i),
x = parent and parent.x or 0,
y = parent and parent.y or 0,
width = parent and parent.width or 1,
height = parent and parent.height or 1
}
if widgets.layout == "row" then
local height = v.height / total
item.y = item.y + item.height * advance
item.height = item.height * height
advance = advance + height
else
local width = v.width / total
item.x = item.x + item.width * advance
item.width = item.width * width
advance = advance + width
end
if #v > 0 then
layout.pack(v, ui, item)
else
table.insert(ui, item)
end
end
return ui
end
function love.draw()
local w, h = love.graphics.getDimensions()
local ui = layout.pack(widgets)
layout.scale(ui, w, h, true)
for i, v in ipairs(ui) do
local pad = 0
love.graphics.setColor(0, i*30, 255, 127)
love.graphics.rectangle("fill",
v.x + pad,
v.y + pad,
v.width - pad * 2,
v.height - pad * 2
)
love.graphics.setColor(255, 255, 255, 255)
love.graphics.print(
string.format("%d: %s", i, v.label),
v.x + pad,
v.y + pad
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment