diff --git a/api/api.lua b/api/api.lua index f4eb6c1f..2d70f34d 100644 --- a/api/api.lua +++ b/api/api.lua @@ -765,7 +765,12 @@ function pfUI.api.LoadMovable(frame, init) for id, point in pairs(frame.posdata.pos) do local a, b, c, d, e = unpack(point) - if a and b then frame:SetPoint(a,b,c,d,e) end + -- skip if anchoring to itself (would cause WoW error) + if a and b and b ~= frame and b ~= frame:GetName() then + frame:SetPoint(a,b,c,d,e) + elseif a and (not b or b == frame or b == frame:GetName()) then + frame:SetPoint(a,d,e) + end end end end @@ -1197,10 +1202,28 @@ end -- returns: array of options as strings for pfUI.gui.bar function pfUI.api.BarLayoutOptions(barsize) assert(barsize > 0 and barsize <= NUM_ACTIONBAR_BUTTONS,"BarLayoutOptions: barsize "..tostring(barsize).." is invalid") - local options = {} - for i,layout in ipairs(pfGridmath[barsize]) do - options[i] = string.format("%d x %d",layout[1],layout[2]) + local options, seen = {}, {} + local function add(option) + if not seen[option] then table.insert(options, option); seen[option] = true end end + for i,layout in ipairs(pfGridmath[barsize]) do + add(string.format("%d x %d",layout[1],layout[2])) + end + for _, option in ipairs({ + "1 x 12", "1 x 10", "2 x 10", "2 x 5", "3 x 10", "3 x 5", "3 x 3", + "5 x 3", "10 x 3", "5 x 2", "10 x 2", "10 x 1", "12 x 1" + }) do add(option) end + table.sort(options, function(a, b) + local _, _, ac, ar = string.find(a, "(%d+)%s*x%s*(%d+)") + local _, _, bc, br = string.find(b, "(%d+)%s*x%s*(%d+)") + ac, ar = tonumber(ac) or 1, tonumber(ar) or 1 + bc, br = tonumber(bc) or 1, tonumber(br) or 1 + local ah = ac >= ar and 0 or 1 + local bh = bc >= br and 0 or 1 + if ah ~= bh then return ah < bh end + if ah == 0 then if ac ~= bc then return ac > bc end; return ar < br + else if ar ~= br then return ar > br end; return ac < bc end + end) return options end @@ -1225,17 +1248,39 @@ function pfUI.api.BarLayoutFormfactor(option) end end +local function ResolveBarLayout(barsize, formfactor, uneven) + local layout = tostring(formfactor or "") + local _, _, a, b = string.find(layout, "(%d+)%s*x%s*(%d+)") + if a and b then + local cols, rows = tonumber(a), tonumber(b) + cols = math.min(NUM_ACTIONBAR_BUTTONS, math.max(1, cols)) + rows = math.min(NUM_ACTIONBAR_BUTTONS, math.max(1, rows)) + local orientation = string.upper(uneven or "DOWN") + local mode = (orientation == "LEFT" or orientation == "RIGHT") and "cols" or "rows" + if mode == "rows" then + cols = math.max(1, math.min(cols, barsize)) + rows = math.max(1, math.ceil(barsize / cols)) + else + rows = math.max(1, math.min(rows, barsize)) + cols = math.max(1, math.ceil(barsize / rows)) + end + return cols, rows, mode, orientation + end + local index = pfUI.api.BarLayoutFormfactor(layout) + if not index then return nil end + local cols, rows = unpack(pfGridmath[barsize][index]) + return cols, rows, "rows", "DOWN" +end + -- [ Bar Layout Size ] -- -- 'bar' frame reference, -- 'barsize' integer number of buttons, -- 'formfactor' string formfactor in cols x rows, -- 'padding' the spacing between buttons -function pfUI.api.BarLayoutSize(bar,barsize,formfactor,iconsize,bordersize,padding) +function pfUI.api.BarLayoutSize(bar,barsize,formfactor,iconsize,bordersize,padding,uneven) assert(barsize > 0 and barsize <= NUM_ACTIONBAR_BUTTONS,"BarLayoutSize: barsize "..tostring(barsize).." is invalid") - local formfactor = pfUI.api.BarLayoutFormfactor(formfactor) - local layout = pfGridmath[barsize] and pfGridmath[barsize][formfactor or 1] - if not layout then layout = pfGridmath[barsize] and pfGridmath[barsize][1] or {1,1} end - local cols, rows = unpack(layout) + local cols, rows = ResolveBarLayout(barsize, formfactor, uneven) + if not cols or not rows then cols, rows = unpack(pfGridmath[barsize][1]) end local width = (iconsize + bordersize*2+padding) * cols + padding local height = (iconsize + bordersize*2+padding) * rows + padding bar._size = {width,height} @@ -1250,18 +1295,56 @@ end -- 'iconsize' size of the button -- 'bordersize' default bordersize -- 'padding' the spacing between buttons -function pfUI.api.BarButtonAnchor(button,basename,buttonindex,barsize,formfactor,iconsize,bordersize,padding) +function pfUI.api.BarButtonAnchor(button,basename,buttonindex,barsize,formfactor,iconsize,bordersize,padding,uneven) assert(barsize > 0 and barsize <= NUM_ACTIONBAR_BUTTONS,"BarButtonAnchor: barsize "..tostring(barsize).." is invalid") - local formfactor = pfUI.api.BarLayoutFormfactor(formfactor) + local cols, rows, mode, orientation = ResolveBarLayout(barsize, formfactor, uneven) + if not cols or not rows then + cols, rows, mode, orientation = unpack(pfGridmath[barsize][1]), "rows", "DOWN" + end local parent = button:GetParent() - local layout = pfGridmath[barsize] and pfGridmath[barsize][formfactor or 1] - if not layout then layout = pfGridmath[barsize] and pfGridmath[barsize][1] or {1,1} end - local cols, rows = unpack(layout) - if buttonindex == 1 then - button._anchor = {"TOPLEFT", parent, "TOPLEFT", bordersize+padding, -bordersize-padding} + local step = iconsize + bordersize*2 + padding + local row, col + if mode == "cols" then + col = math.ceil(buttonindex / rows) + row = buttonindex - ((col-1) * rows) else - local col = buttonindex-((math.ceil(buttonindex/cols)-1)*cols) - button._anchor = col==1 and {"TOP",_G[basename..(buttonindex-cols)],"BOTTOM",0,-(bordersize*2+padding)} or {"LEFT",_G[basename..(buttonindex-1)],"RIGHT",(bordersize*2+padding),0} + row = math.ceil(buttonindex / cols) + col = buttonindex - ((row-1) * cols) + end + if mode == "cols" and orientation == "LEFT" then + local final_col = math.ceil(barsize / rows) + local count = barsize - (final_col - 1) * rows + if count > 0 and count < rows then + if col == final_col then col = 1 else col = col + 1 end + end + elseif mode == "rows" and orientation == "UP" then + local final_row = math.ceil(barsize / cols) + local count = barsize - (final_row - 1) * cols + if count > 0 and count < cols then + if row == final_row then row = 1 else row = row + 1 end + end + end + local x = bordersize + padding + (col - 1) * step + local y = -bordersize - padding - (row - 1) * step + if buttonindex == 1 then + button._anchor = {"TOPLEFT", parent, "TOPLEFT", x, y} + else + button._anchor = {"TOPLEFT", parent, "TOPLEFT", x, y} + if mode == "cols" then + local final_col = math.ceil(barsize / rows) + local count = barsize - (final_col - 1) * rows + local target_col = (orientation == "LEFT") and 1 or cols + if count > 0 and count < rows and col == target_col and row == 1 then + button._anchor[5] = button._anchor[5] - (rows - count) * step / 2 + end + else + local final_row = math.ceil(barsize / cols) + local count = barsize - (final_row - 1) * cols + local target_row = (orientation == "UP") and 1 or rows + if count > 0 and count < cols and row == target_row and col == 1 then + button._anchor[4] = button._anchor[4] + (cols - count) * step / 2 + end + end end return button._anchor end @@ -1444,7 +1527,6 @@ function pfUI.api.GetNoNameObject(frame, objtype, layer, arg1, arg2) local arg2 = arg2 and gsub(arg2, "([%+%-%*%(%)%?%[%]%^])", "%%%1") local objects - if not frame or not frame.GetRegions then return end if objtype == "Texture" or objtype == "FontString" then objects = {frame:GetRegions()} else