You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bastion/libs/StdUi/StdUiLayout.lua

211 lines
4.5 KiB

--- @type StdUi
local StdUi = LibStub and LibStub('StdUi', true);
if not StdUi then
return
end
local module, version = 'Layout', 3;
if not StdUi:UpgradeNeeded(module, version) then
return
end
local TableInsert = tinsert;
local TableRemove = tremove;
local pairs = pairs;
local MathMax = math.max;
local MathFloor = math.floor;
local defaultLayoutConfig = {
gutter = 10,
columns = 12,
padding = {
top = 0,
right = 10,
left = 10,
bottom = 10,
}
};
local defaultRowConfig = {
margin = {
top = 0,
right = 0,
bottom = 15,
left = 0
}
};
local defaultElementConfig = {
margin = {
top = 0,
right = 0,
bottom = 0,
left = 0
}
};
local EasyLayoutRow = {
AddElement = function(self, frame, config)
if not frame.layoutConfig then
frame.layoutConfig = StdUi.Util.tableMerge(defaultElementConfig, config or {});
elseif config then
frame.layoutConfig = StdUi.Util.tableMerge(frame.layoutConfig, config or {});
end
TableInsert(self.elements, frame);
end,
AddElements = function(self, ...)
local r = { ... };
local cfg = TableRemove(r, #r);
if cfg.column == 'even' then
cfg.column = MathFloor(self.parent.layout.columns / #r);
end
for i = 1, #r do
self:AddElement(r[i], StdUi.Util.tableMerge(defaultElementConfig, cfg));
end
end,
GetColumnsTaken = function(self)
local columnsTaken = 0;
local l = self.parent.layout;
for i = 1, #self.elements do
local lc = self.elements[i].layoutConfig;
local col = lc.column or l.columns;
columnsTaken = columnsTaken + col;
end
return columnsTaken;
end,
DrawRow = function(self, parentWidth, yOffset)
yOffset = yOffset or 0;
local l = self.parent.layout;
local g = l.gutter;
local rowMargin = self.config.margin;
local totalHeight = 0;
local columnsTaken = 0;
local x = g + l.padding.left + rowMargin.left;
-- if row has margins, cut down available width
parentWidth = parentWidth - rowMargin.left - rowMargin.right;
for i = 1, #self.elements do
local frame = self.elements[i];
frame:ClearAllPoints();
-- Frame layout config
local lc = frame.layoutConfig;
local m = lc.margin;
-- take full size
if lc.fullSize then
StdUi:GlueAcross(
frame,
self.parent,
l.padding.left,
-l.padding.top,
-l.padding.right,
l.padding.bottom
);
if frame.DoLayout then
frame:DoLayout();
end
totalHeight = MathMax(totalHeight, frame:GetHeight() + m.bottom + m.top + rowMargin.top + rowMargin.bottom);
return totalHeight;
end
local col = lc.column or l.columns;
local w = (parentWidth / (l.columns / col)) - 2 * g;
frame:SetWidth(w);
if columnsTaken + col > self.parent.layout.columns then
print('Element will not fit row capacity: ' .. l.columns);
return totalHeight;
end
-- move it down by rowMargin and element margin
frame:SetPoint('TOPLEFT', self.parent, 'TOPLEFT', x, yOffset - m.top - rowMargin.top);
if lc.fullHeight then
frame:SetPoint('BOTTOMLEFT', self.parent, 'BOTTOMLEFT', x, m.bottom + rowMargin.bottom);
end
--each element takes 1 gutter plus column * colWidth, while gutter is inclusive
x = x + w + 2 * g; -- double the gutter because width subtracts gutter
-- if that frame is container itself, do layout for it too
if frame.DoLayout then
frame:DoLayout();
end
totalHeight = MathMax(totalHeight, frame:GetHeight() + m.bottom + m.top + rowMargin.top + rowMargin.bottom);
columnsTaken = columnsTaken + col;
end
return totalHeight;
end
}
---EasyLayoutRow
---@param parent Frame
---@param config table
function StdUi:EasyLayoutRow(parent, config)
---@class EasyLayoutRow
local row = {
parent = parent,
config = self.Util.tableMerge(defaultRowConfig, config or {}),
elements = {}
};
for k, v in pairs(EasyLayoutRow) do
row[k] = v;
end
return row;
end
local EasyLayout = {
---@return EasyLayoutRow
AddRow = function(self, config)
if not self.rows then
self.rows = {};
end
local row = self.stdUi:EasyLayoutRow(self, config);
TableInsert(self.rows, row);
return row;
end,
DoLayout = function(self)
local l = self.layout;
local width = self:GetWidth() - l.padding.left - l.padding.right;
local y = -l.padding.top;
for i = 1, #self.rows do
local row = self.rows[i];
y = y - row:DrawRow(width, y);
end
end
};
function StdUi:EasyLayout(parent, config)
parent.stdUi = self;
parent.layout = self.Util.tableMerge(defaultLayoutConfig, config or {});
for k, v in pairs(EasyLayout) do
parent[k] = v;
end
end
StdUi:RegisterModule(module, version);