vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[
        Infield.lua
                A library of functions to keep frames within the UIParent's bounds
--]]

--constants
local VERSION = 60814;

if Infield and Infield.version >= VERSION then return; end

local UPDATE_INTERVAL = 1;

--[[ Local Functions ]]--

local function RegisterScaleEvents()
        --set the onupdate function
        InfieldUpdater:SetScript("OnEvent", function()
                local uiScale = UIParent:GetScale();
                if this.currentScale ~= uiScale then
                        for _, action in pairs(Infield.rescaleList) do
                                action();
                        end     
                        this.currentScale = uiScale;
                end
        end);
        InfieldUpdater:RegisterEvent("PLAYER_ENTERING_WORLD");
        InfieldUpdater:RegisterEvent("CVAR_UPDATE");
end

--returns the adjusted x and y coordinates for a frame when scaled, keeping the topleft of the frame in the same relative spot
local function GetAdjustedCoords(frame, nScale)
        if(not ( frame:GetLeft() and frame:GetTop() ) ) then
                return nil;
        end
        return frame:GetLeft() * frame:GetScale() / nScale, frame:GetTop() * frame:GetScale() / nScale;
end

--[[ Update or Load Infield's Functions ]]--

--create a new infield instance
if not Infield then
        Infield = { rescaleList = {} };
--do stuff needed to be done on a version change
else
        InfieldUpdater:Hide();
        local resList = Infield.rescaleList;
        Infield = { rescaleList = resList };

        if InfieldUpdater and InfieldUpdater:GetScript("OnUpdate") then
                InfieldUpdater:SetScript("OnUpdate", nil);
                InfieldUpdater.elapsed = nil;
                RegisterScaleEvents();
        end
end
Infield.version = VERSION;

--Add a function to execute when the UI scale changes
--This must be added before the PLAYER_LOGIN event takes place to detect the startup rescale.
Infield.AddRescaleAction = function(funct)
        table.insert(Infield.rescaleList, funct);
end

--Sets <frame>'s scale <scale>, and repositions the frame if its out of the viewable screen area
Infield.Scale = function(frame, scale)
        local x, y = GetAdjustedCoords(frame, scale);
        
        frame:SetScale(scale);
        if(x) then
                Infield.Place(frame, "TOPLEFT", UIParent, "BOTTOMLEFT", x, y);
        end
end

--Places a frame at a location and repositions it so that it is not outside of the UIParent
--Syntax is similar to Frame:SetScale()
Infield.Place = function(frame, point, parent, relPoint, x, y)
        frame:ClearAllPoints();
        frame:SetPoint(point, parent, relPoint, x, y);
        Infield.Reposition(frame, UIParent);
end

--Moves a frame within the bounds of parent if its out of bounds
Infield.Reposition = function(frame, parent)
        if( frame:GetBottom() and frame:GetTop() and frame:GetLeft() and frame:GetRight() ) then
                local xoff = 0;
                local yoff = 0;
                local ratio = frame:GetScale();
                
                --check and see if the frame is off the screen
                --Y bounds checking
                if (  frame:GetBottom() < 0) then
                        yoff = 0 - frame:GetBottom();
                elseif ( frame:GetTop()  > (parent:GetTop() / ratio ) ) then
                        yoff = (parent:GetTop() / ratio) - frame:GetTop();
                end

                --X bounds checking
                if ( frame:GetLeft() < 0 ) then
                        xoff = 0  - frame:GetLeft();
                elseif ( frame:GetRight()  > ( parent:GetRight() / ratio )  ) then
                        xoff = (parent:GetRight() / ratio) - frame:GetRight();
                end
                
                --Reposition if anything was out of bounds
                if( xoff ~= 0 or yoff ~= 0) then
                        local x = frame:GetLeft() + xoff;
                        local y = frame:GetTop() + yoff;
                        
                        frame:ClearAllPoints();
                        frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", x , y);
                end
        end
end

--create the frame
if not InfieldUpdater then 
        CreateFrame("Frame", "InfieldUpdater");
        RegisterScaleEvents();
end

Generated by GNU Enscript 1.6.5.90.