--[[ FlyPaper Functionality for sticking one frome to another frame Methods: FlyPaper.Stick(frame, otherFrame, tolerance, xOff, yOff) - Attempts to attach to tolerance - how close the frames need to be to attach xOff - how close, horizontally, the frames should be attached yOff - how close, vertically, the frames should be attached FlyPaper.StickToPoint(frame, otherFrame, point, xOff, yOff) - attempts to anchor to a specific point on point - any non nil return value of FlyPaper.Stick; Version History: 6.7.19: Fixed a bug causing a frame to think it was still stuck to another frame when it really wasn't Added FlyPaper.StickToPoint for reloading settings --]] local VERSION = "6.7.19"; if(FlyPaper and FlyPaper.version >= VERSION) then return; end --returns true if , or one of the frames that is dependent on, is anchored to . Returns false otherwise. local function FrameIsDependentOnFrame(frame, otherFrame) if(not (otherFrame and frame) ) then return false; end if(frame == otherFrame) then return true; end local parent = frame.stuckTo; while parent do if(parent == otherFrame) then return true; end parent = parent.stuckTo; end return false end --returns true if its actually possible to attach the two frames without error local function CanAttach(frame, otherFrame) if( not (frame and otherFrame) ) then return false; elseif(frame:GetNumPoints() == 0 or otherFrame:GetNumPoints() == 0 ) then return false; elseif(frame:GetWidth() == 0 or frame:GetHeight() == 0 or otherFrame:GetWidth() == 0 or otherFrame:GetHeight() == 0) then return false; elseif( FrameIsDependentOnFrame(otherFrame, frame) ) then return false; end return true; end --[[ Attachment Functions ]]-- local function AttachToTop(frame, otherFrame, distLeft, distRight, distCenter, offset) frame:ClearAllPoints(); --closest to the left if(distLeft < distCenter and distLeft < distRight) then frame:SetPoint("BOTTOMLEFT", otherFrame, "TOPLEFT", 0, offset); return "TL"; --closest to the right elseif(distRight < distCenter and distRight < distLeft ) then frame:SetPoint("BOTTOMRIGHT", otherFrame, "TOPRIGHT", 0, offset); return "TR"; --closest to the center else frame:SetPoint("BOTTOM", otherFrame, "TOP", 0, offset); return "TC"; end end local function AttachToBottom(frame, otherFrame, distLeft, distRight, distCenter, offset) frame:ClearAllPoints(); --bottomleft if(distLeft < distCenter and distLeft < distRight) then frame:SetPoint("TOPLEFT", otherFrame, "BOTTOMLEFT", 0, -offset); return "BL"; --bottomright elseif(distRight < distCenter and distRight < distLeft) then frame:SetPoint("TOPRIGHT", otherFrame, "BOTTOMRIGHT", 0, -offset); return "BR"; --bottom else frame:SetPoint("TOP", otherFrame, "BOTTOM", 0, -offset); return "BC"; end end local function AttachToLeft(frame, otherFrame, distTop, distBottom, distCenter, offset) frame:ClearAllPoints(); --bottomleft if(distBottom < distTop and distBottom < distCenter) then frame:SetPoint("BOTTOMRIGHT", otherFrame, "BOTTOMLEFT", -offset, 0); return "LB"; --topleft elseif(distTop < distBottom and distTop < distCenter) then frame:SetPoint("TOPRIGHT", otherFrame, "TOPLEFT", -offset, 0); return "LT"; --left else frame:SetPoint("RIGHT", otherFrame, "LEFT", -offset, 0); return "LC"; end end local function AttachToRight(frame, otherFrame, distTop, distBottom, distCenter, offset) frame:ClearAllPoints(); --bottomright if(distBottom < distTop and distBottom < distCenter) then frame:SetPoint("BOTTOMLEFT", otherFrame, "BOTTOMRIGHT", offset, 0); return "RB"; --topright elseif(distTop < distBottom and distTop < distCenter) then frame:SetPoint("TOPLEFT", otherFrame, "TOPRIGHT", offset, 0); return "RT"; --right else frame:SetPoint("LEFT", otherFrame, "RIGHT", offset, 0); return "RC"; end end --[[ Usable Functions ]]-- FlyPaper = { version = VERSION, Stick = function(frame, otherFrame, tolerance, xOff, yOff) if(not xOff) then xOff = 0; end if(not yOff) then yOff = 0; end if(not CanAttach(frame, otherFrame) ) then if(frame) then frame.stuckTo = nil; end return false; end --get anchoring points local left = frame:GetLeft(); local right = frame:GetRight(); local top = frame:GetTop(); local bottom = frame:GetBottom(); local centerX, centerY = frame:GetCenter(); if(left and right and top and bottom and centerX) then local oScale = otherFrame:GetScale(); left = left / oScale; right = right / oScale; top = top / oScale; bottom = bottom /oScale; centerX = centerX / oScale; centerY = centerY / oScale; else frame.stuckTo = nil; return false; end local oLeft = otherFrame:GetLeft(); local oRight = otherFrame:GetRight(); local oTop = otherFrame:GetTop(); local oBottom = otherFrame:GetBottom(); local oCenterX, oCenterY = otherFrame:GetCenter(); if(oLeft and oRight and oTop and oBottom and oCenterX) then local scale = frame:GetScale(); oCenterX = oCenterX / scale; oCenterY = oCenterY / scale; oLeft = oLeft / scale; oRight = oRight / scale; oTop = oTop / scale; oBottom = oBottom / scale; else frame.stuckTo = nil; return false; end --[[ Start Attempting to Anchor to ]]-- if( (oLeft - tolerance <= left and oRight + tolerance >= right) or (left - tolerance <= oLeft and right + tolerance >= oRight) ) then local distCenter = math.abs(oCenterX - centerX); local distLeft = math.abs(oLeft - left); local distRight = math.abs(right - oRight); --try to stick to the top if the distance is under the threshold distance to stick frames to each other (tolerance) if( math.abs(oTop - bottom) <= tolerance ) then local point = AttachToTop(frame, otherFrame, distLeft, distRight, distCenter, yOff); frame.stuckTo = otherFrame; return point; --to the bottom elseif( math.abs(oBottom - top) <= tolerance ) then local point = AttachToBottom(frame, otherFrame, distLeft, distRight, distCenter, yOff); frame.stuckTo = otherFrame; return point; end end if ( (oTop + tolerance >= top and oBottom - tolerance <= bottom) or (top + tolerance >= oTop and bottom - tolerance <= oBottom) ) then local distCenter = math.abs(oCenterY - centerY); local distTop = math.abs(oTop - top); local distBottom = math.abs(oBottom - bottom); --to the left if(math.abs(oLeft - right) <= tolerance ) then local point = AttachToLeft(frame, otherFrame, distTop, distBottom, distCenter, xOff); frame.stuckTo = otherFrame; return point; end --to the right if(math.abs(oRight - left) <= tolerance ) then local point = AttachToRight(frame, otherFrame, distTop, distBottom, distCenter, xOff); frame.stuckTo = otherFrame; return point; end end frame.stuckTo = nil; return false; end, StickToPoint = function(frame, otherFrame, point, xOff, yOff) if(not xOff) then xOff = 0; end if(not yOff) then yOff = 0; end --[[ Check to make sure we can anchor ]]-- --check to make sure its actually possible to attach the frames if(not (point and CanAttach(frame, otherFrame)) ) then if(frame) then frame.stuckTo = nil; end return nil; end --check to make sure all anchoring points are valid local left = frame:GetLeft(); local right = frame:GetRight(); local top = frame:GetTop(); local bottom = frame:GetBottom(); local centerX = frame:GetCenter(); if( not (left and right and top and bottom and centerX) ) then frame.stuckTo = nil; return nil; end local oLeft = otherFrame:GetLeft(); local oRight = otherFrame:GetRight(); local oTop = otherFrame:GetTop(); local oBottom = otherFrame:GetBottom(); local oCenterX = otherFrame:GetCenter(); if(not (oLeft and oRight and oTop and oBottom and oCenterX) ) then frame.stuckTo = nil; return nil; end --[[ Start Attempting to Anchor to ]]-- frame:ClearAllPoints(); if( point == "TL" ) then frame:SetPoint("BOTTOMLEFT", otherFrame, "TOPLEFT", 0, yOff); frame.stuckTo = otherFrame; return point; elseif(point == "TC") then frame:SetPoint("BOTTOM", otherFrame, "TOP", 0, yOff); frame.stuckTo = otherFrame; return point; elseif(point == "TR") then frame:SetPoint("BOTTOMRIGHT", otherFrame, "TOPRIGHT", 0, yOff); frame.stuckTo = otherFrame; return point; end if( point == "BL" ) then frame:SetPoint("TOPLEFT", otherFrame, "BOTTOMLEFT", 0, -yOff); frame.stuckTo = otherFrame; return point; elseif(point == "BC") then frame:SetPoint("TOP", otherFrame, "BOTTOM", 0, -yOff); frame.stuckTo = otherFrame; return point; elseif(point == "BR") then frame:SetPoint("TOPRIGHT", otherFrame, "BOTTOMRIGHT", 0, -yOff); frame.stuckTo = otherFrame; return point; end --to the left if( point == "LB" ) then frame:SetPoint("BOTTOMRIGHT", otherFrame, "BOTTOMLEFT", -xOff, 0); frame.stuckTo = otherFrame; return point; elseif(point == "LC") then frame:SetPoint("RIGHT", otherFrame, "LEFT", -xOff, 0); frame.stuckTo = otherFrame; return point; elseif(point == "LT") then frame:SetPoint("TOPRIGHT", otherFrame, "TOPLEFT", -xOff, 0); frame.stuckTo = otherFrame; return point; end --to the right if( point == "RB" ) then frame:SetPoint("BOTTOMLEFT", otherFrame, "BOTTOMRIGHT", xOff, 0); frame.stuckTo = otherFrame; return point; elseif(point == "RC") then frame:SetPoint("LEFT", otherFrame, "RIGHT", xOff, 0); frame.stuckTo = otherFrame; return point; elseif(point == "RT") then frame:SetPoint("TOPLEFT", otherFrame, "TOPRIGHT", xOff, 0); frame.stuckTo = otherFrame; return point; end frame.stuckTo = nil; return nil; end, }