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.
263 lines
7.7 KiB
263 lines
7.7 KiB
-- Neuron is a World of Warcraft® user interface addon.
|
|
-- Copyright (c) 2017-2021 Britt W. Yazel
|
|
-- Copyright (c) 2006-2014 Connor H. Chenoweth
|
|
-- This code is licensed under the MIT license (see LICENSE for details)
|
|
|
|
local _, addonTable = ...
|
|
local Neuron = addonTable.Neuron
|
|
|
|
local Bar = Neuron.Bar
|
|
|
|
local function frameIsDependentOnFrame(frame, otherFrame)
|
|
|
|
if frame and otherFrame then
|
|
|
|
if frame == otherFrame then return true end
|
|
|
|
local points = frame:GetNumPoints()
|
|
|
|
for i=1,points do
|
|
local parent = select(2, frame:GetPoint(i))
|
|
if frameIsDependentOnFrame(parent, otherFrame) then return true end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function canAttach(frame, otherFrame)
|
|
if not frame and otherFrame then
|
|
return
|
|
elseif frame:GetNumPoints() == 0 or otherFrame:GetNumPoints() == 0 then
|
|
return
|
|
elseif frame:GetWidth() == 0 or frame:GetHeight() == 0 or otherFrame:GetWidth() == 0 or otherFrame:GetHeight() == 0 then
|
|
return
|
|
elseif frameIsDependentOnFrame(otherFrame, frame) then
|
|
return
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
--[[ Attachment Functions ]]--
|
|
|
|
local function attachToTop(frame, otherFrame, distLeft, distRight, distCenter, offset)
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
if distLeft < distCenter and distLeft < distRight then
|
|
|
|
frame:SetPoint("BOTTOMLEFT", otherFrame, "TOPLEFT", 0, offset); return "TL"
|
|
|
|
elseif distRight < distCenter and distRight < distLeft then
|
|
|
|
frame:SetPoint("BOTTOMRIGHT", otherFrame, "TOPRIGHT", 0, offset); return "TR"
|
|
else
|
|
frame:SetPoint("BOTTOM", otherFrame, "TOP", 0, offset); return "TC"
|
|
end
|
|
end
|
|
|
|
local function attachToBottom(frame, otherFrame, distLeft, distRight, distCenter, offset)
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
if distLeft < distCenter and distLeft < distRight then
|
|
|
|
frame:SetPoint("TOPLEFT", otherFrame, "BOTTOMLEFT", 0, -offset); return "BL"
|
|
|
|
elseif distRight < distCenter and distRight < distLeft then
|
|
|
|
frame:SetPoint("TOPRIGHT", otherFrame, "BOTTOMRIGHT", 0, -offset); return "BR"
|
|
|
|
else
|
|
frame:SetPoint("TOP", otherFrame, "BOTTOM", 0, -offset); return "BC"
|
|
end
|
|
end
|
|
|
|
local function attachToLeft(frame, otherFrame, distTop, distBottom, distCenter, offset)
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
if distBottom < distTop and distBottom < distCenter then
|
|
|
|
frame:SetPoint("BOTTOMRIGHT", otherFrame, "BOTTOMLEFT", -offset, 0); return "LB"
|
|
|
|
elseif distTop < distBottom and distTop < distCenter then
|
|
|
|
frame:SetPoint("TOPRIGHT", otherFrame, "TOPLEFT", -offset, 0); return "LT"
|
|
|
|
else
|
|
frame:SetPoint("RIGHT", otherFrame, "LEFT", -offset, 0); return "LC"
|
|
end
|
|
end
|
|
|
|
local function attachToRight(frame, otherFrame, distTop, distBottom, distCenter, offset)
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
if distBottom < distTop and distBottom < distCenter then
|
|
|
|
frame:SetPoint("BOTTOMLEFT", otherFrame, "BOTTOMRIGHT", offset, 0); return "RB"
|
|
|
|
elseif distTop < distBottom and distTop < distCenter then
|
|
|
|
frame:SetPoint("TOPLEFT", otherFrame, "TOPRIGHT", offset, 0); return "RT"
|
|
|
|
else
|
|
frame:SetPoint("LEFT", otherFrame, "RIGHT", offset, 0); return "RC"
|
|
end
|
|
end
|
|
|
|
local function attachToCenter(frame, otherFrame)
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
frame:SetPoint("CENTER", otherFrame, "CENTER", 0, 0); return "CT"
|
|
end
|
|
|
|
|
|
--[[ Usable Functions ]]--
|
|
|
|
|
|
function Bar:StickToEdge()
|
|
|
|
local point, x, y= self:GetPosition()
|
|
local changed
|
|
local w, h, rTol = self:GetWidth()/2, self:GetHeight()/2, Neuron.SNAPTO_TOLERANCE
|
|
|
|
local function calcX(opt)
|
|
if opt == 1 then if x <= w+rTol then x = w; changed = true end
|
|
elseif opt == 2 then if x >= -(w+rTol) then x = -(w); changed = true end
|
|
elseif opt == 3 then if math.abs(x) <= rTol then x = 0; changed = true end
|
|
end
|
|
end
|
|
|
|
local function calcY(opt)
|
|
if opt == 1 then if y <= h+rTol then y = h; changed = true end
|
|
elseif opt == 2 then if y >= -(h+rTol) then y = -(h); changed = true end
|
|
elseif opt == 3 then if math.abs(y) <= rTol then y = 0; changed = true end
|
|
end
|
|
end
|
|
|
|
if point == "CENTER" then calcX(3); calcY(3) end
|
|
|
|
if point:find("LEFT") then calcX(1); calcY(3) end
|
|
|
|
if point:find("RIGHT") then calcX(2); calcY(3) end
|
|
|
|
if not changed and point:find("BOTTOM") then calcX(3); calcY(1) end
|
|
|
|
if not changed and point:find("TOP") then calcX(3); calcY(2) end
|
|
|
|
if changed then
|
|
self.data.point = point; self:SetXAxis(x); self:SetYAxis(y)
|
|
self:SetPosition()
|
|
end
|
|
end
|
|
|
|
function Bar:Stick(oFrame, tolerance, xOff, yOff)
|
|
|
|
xOff, yOff = xOff or 0, yOff or 0
|
|
|
|
if not canAttach(self, oFrame) then return end
|
|
|
|
local left, right, top, bottom = self:GetLeft(), self:GetRight(), self:GetTop(), self:GetBottom()
|
|
local centerX, centerY = self:GetCenter()
|
|
|
|
if left and right and top and bottom and centerX then
|
|
|
|
local oScale = oFrame:GetScale()
|
|
|
|
left = left/oScale; right = right/oScale; top = top/oScale; bottom = bottom/oScale
|
|
|
|
centerX = centerX/oScale; centerY = centerY/oScale
|
|
|
|
else return end
|
|
|
|
|
|
local oLeft, oRight, oTop, oBottom = oFrame:GetLeft(), oFrame:GetRight(), oFrame:GetTop(), oFrame:GetBottom()
|
|
local oCenterX, oCenterY = oFrame:GetCenter()
|
|
|
|
if oLeft and oRight and oTop and oBottom and oCenterX then
|
|
|
|
local scale = self:GetScale()
|
|
|
|
oLeft = oLeft/scale; oRight = oRight/scale; oTop = oTop/scale; oBottom = oBottom/scale
|
|
|
|
oCenterX = oCenterX/scale; oCenterY = oCenterY/scale
|
|
|
|
else return end
|
|
|
|
if (oLeft - tolerance <= left and oRight + tolerance >= right) or (left - tolerance <= oLeft and right + tolerance >= oRight) then
|
|
|
|
local distCenter, distLeft, distRight = math.abs(oCenterX - centerX), math.abs(oLeft - left), math.abs(right - oRight)
|
|
|
|
if math.abs(oTop - bottom) <= tolerance then
|
|
return attachToTop(self, oFrame, distLeft, distRight, distCenter, yOff)
|
|
elseif math.abs(oBottom - top) <= tolerance then
|
|
return attachToBottom(self, oFrame, distLeft, distRight, distCenter, yOff)
|
|
end
|
|
end
|
|
|
|
if (oTop + tolerance >= top and oBottom - tolerance <= bottom) or (top + tolerance >= oTop and bottom - tolerance <= oBottom) then
|
|
|
|
local distCenter, distTop, distBottom = math.abs(oCenterY - centerY), math.abs(oTop - top), math.abs(oBottom - bottom)
|
|
|
|
if math.abs(oLeft - right) <= tolerance then
|
|
return attachToLeft(self, oFrame, distTop, distBottom, distCenter, xOff)
|
|
end
|
|
|
|
if math.abs(oRight - left) <= tolerance then
|
|
return attachToRight(self, oFrame, distTop, distBottom, distCenter, xOff)
|
|
end
|
|
end
|
|
|
|
if oCenterX > centerX - tolerance/2 and oCenterX < centerX + tolerance/2 and oCenterY > centerY - tolerance/2 and oCenterY < centerY + tolerance/2 then
|
|
return attachToCenter(self, oFrame)
|
|
end
|
|
end
|
|
|
|
function Bar:StickToPoint(oFrame, point, xOff, yOff)
|
|
|
|
xOff, yOff = xOff or 0, yOff or 0
|
|
|
|
if not (point and canAttach(self, oFrame)) then return end
|
|
|
|
self:ClearAllPoints()
|
|
|
|
if point == "TL" then
|
|
self:SetPoint("BOTTOMLEFT", oFrame, "TOPLEFT", 0, yOff); return point
|
|
elseif point == "TC" then
|
|
self:SetPoint("BOTTOM", oFrame, "TOP", 0, yOff); return point
|
|
elseif point == "TR" then
|
|
self:SetPoint("BOTTOMRIGHT", oFrame, "TOPRIGHT", 0, yOff); return point
|
|
end
|
|
|
|
if point == "BL" then
|
|
self:SetPoint("TOPLEFT", oFrame, "BOTTOMLEFT", 0, -yOff); return point
|
|
elseif point == "BC" then
|
|
self:SetPoint("TOP", oFrame, "BOTTOM", 0, -yOff); return point
|
|
elseif point == "BR" then
|
|
self:SetPoint("TOPRIGHT", oFrame, "BOTTOMRIGHT", 0, -yOff); return point
|
|
end
|
|
|
|
if point == "LB" then
|
|
self:SetPoint("BOTTOMRIGHT", oFrame, "BOTTOMLEFT", -xOff, 0); return point
|
|
elseif point == "LC" then
|
|
self:SetPoint("RIGHT", oFrame, "LEFT", -xOff, 0); return point
|
|
elseif point == "LT" then
|
|
self:SetPoint("TOPRIGHT", oFrame, "TOPLEFT", -xOff, 0); return point
|
|
end
|
|
|
|
if point == "RB" then
|
|
self:SetPoint("BOTTOMLEFT", oFrame, "BOTTOMRIGHT", xOff, 0); return point
|
|
elseif point == "RC" then
|
|
self:SetPoint("LEFT", oFrame, "RIGHT", xOff, 0); return point
|
|
elseif point == "RT" then
|
|
self:SetPoint("TOPLEFT", oFrame, "TOPRIGHT", xOff, 0); return point
|
|
end
|
|
|
|
if point == "CT" then
|
|
self:SetPoint("CENTER", oFrame, "CENTER", 0, 0); return point
|
|
end
|
|
end
|
|
|