forked from Bastion/Bastion
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.
211 lines
4.5 KiB
211 lines
4.5 KiB
2 years ago
|
--- @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);
|