--- @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);