vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--------------------------------------------------------------------------
-- MobileFrames.lua
--------------------------------------------------------------------------
--[[
Mobile Minimap Buttons

By: AnduinLothar    <KarlKFI@cosmosui.org>

Makes the Minimap Buttons draggable around the minimap with adjustable angle.
Control-Drag to change angle.
Control-Right-Click to bring up menu.
Menu: Reset, Reset All, Disable.

Possible ToDo: Shift-Ctrl-Drag to change radius.

Change Log:
v1.71
-Changed the radius calculation to make compatible with AddOns that allow changes to the radius setting of their buttons e.g. Gatherer, AlphaMap
-Updated the API.txt
v1.7
-Now automaticly makes mobile the following addon buttons: Soundtrack, Cirk's Blessings, CritLine, AlphaMap, and Natur EnemyCastBar.
v1.6
-Changed dragging and reset menu to control click to avoid conflict with battlegrounds button
-Fixed bug that wasn't saving posistions of icons unless you tapped them
v1.52
-Updated TOC to 11100
-Fixed Census button mask.
v1.51
-New Buttons are now Anchored when first made mobile. (Fixed OnLoad error with Atlas)
-Updated German Localization
v1.5 (1/15/06)
-Fixed Shift-OnClick option overridding to still work for clicks under half a second. (Fixes battleground minimap)
-Now automaticly makes mobile the following addon buttons: Atlas, CTRA, Wardrobe, Yatlas, Gatherer, Earth, IEF, CTA.
(Addon Buttons are only on English client until localized.)
v1.4 (1/4/06)
-Disabled OnDrag events of registered addon buttons (Wardrobe now correctly stops dragging)
-Fixed nil OnLoad bug by delaying frame loading until after PLAYER_ENTERING_WORLD on a fresh load
-Updated TOC to 10900
v1.3 (11/24/05)
-Dynamicly added buttons now save accross sessions
Demo additions:
/script MobileMinimapButtons_AddButton("AtlasButton","Atlas Button");
/script MobileMinimapButtons_AddButton("CT_RASets_Button","CT Raid Assist Button");
/script MobileMinimapButtons_AddButton("Wardrobe.IconFrame","Wardrobe Button");
/script MobileMinimapButtons_AddButton("TheYatlasButton","Yatlas Button");
/script MobileMinimapButtons_AddButton("GathererUI_IconFrame","Gatherer Button");
/script MobileMinimapButtons_AddButton("EarthMinimapButton","Earth Button");
/script MobileMinimapButtons_AddButton("IEFMinimapButton","Improved Error Frame Button");
/script MobileMinimapButtons_AddButton("CTA_MinimapIcon","Call To Arms Button");
v1.2 (10/27/05)
-Chnaged OnClick handling to allow for Casting via OnClick
-Implimented HasScript so that you no longer have to pass weather the frame is a button or not.
v1.11 (10/25/05)
-Fixed an obscure OnClick bug involving Khaos
v1.1 (10/18/05)
-Added dynamic button adding using MobileMinimapButtons_AddButton at any time.
-See API.txt for details on how to make your addon's button mobile.
v1.0 (9/30/05)
-Initial Release


        $Id: MobileMinimapButtons.lua 2025 2005-07-02 23:51:34Z KarlKFI $
        $Rev: 2025 $
        $LastChangedBy: KarlKFI $
        $Date: 2005-07-02 16:51:34 -0700 (Sat, 02 Jul 2005) $


]]--

--Update +1 if you change the list of frames in the localization!
local tempListVersion = MOBILE_MINIMAP_BUTTONS_LIST_VERSION;
local tempFrameList = MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS;

MobileMinimapButtons_Debug = false;
MobileMinimapButtons_Coords = {};
MobileMinimapButtons_Enabled = true;
MobileMinimapButtons_CurrentlyEnabled = {};
MobileMinimapButtons_NextClickDisabled = nil;

MobileMinimapButtons_FullSizeButtons = {
        --Fullsize buttons use the 1/2 width offset rather than the normal 1/4 width
        ["MiniMapTrackingFrame"] = true,
};

MobileMinimapButtons_MaskParentButtons = {
        --Parents that aren't attached hinder dragging, attach them.
        ["AtlasButton"] = "AtlasButtonFrame",
        ["CensusButton"] = "CensusButtonFrame",
        ["CT_RASets_Button"] = "CT_RASetsFrame",
        ["TheYatlasButton"] = "YatlasButtonFrame",
        ["AM_MinimapButton"] = "AM_MinimapFrame",
};

function MobileMinimapButtons_OnLoad()
        this:RegisterEvent("VARIABLES_LOADED");
        this:RegisterEvent("PLAYER_ENTERING_WORLD");
        if (Khaos) then
                MobileMinimapButtons_RegisterForKhaos();
        end
end

function MobileMinimapButtons_OnEvent(event)
        if (event == "VARIABLES_LOADED") then
                --Make sure list has new frames, but don't remove added ones
                if (MOBILE_MINIMAP_BUTTONS_LIST_VERSION) and (tempListVersion > MOBILE_MINIMAP_BUTTONS_LIST_VERSION) then
                        for frameName, localizedFrameName in tempFrameList do
                                if (not MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName]) then
                                        MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName] = localizedFrameName;
                                end
                        end
                        MOBILE_MINIMAP_BUTTONS_LIST_VERSION = tempListVersion;
                end
                tempFrameList = nil;
                tempListVersion = nil
                MobileMinimapButtons_EnteringWorldFromFullLoad = true;

        elseif (event == "PLAYER_ENTERING_WORLD") then
                if (MobileMinimapButtons_EnteringWorldFromFullLoad) then
                        --Loop Through Minimap Buttons
                        for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
                                if (Sea.util.getValue(frameName)) then
                                        MobileMinimapButtons_MakeMobile(frameName, localizedFrameName);
                                end
                        end
                        MobileMinimapButtons_EnteringWorldFromFullLoad = nil;
                        MobileMinimapButtons_FramesLoaded = true;
                end
        end
end

function MobileMinimapButtons_AddButton(frameName, localizedFrameName)
        if (not frameName) or (not Sea.util.getValue(frameName)) then
                Sea.io.print("MobileMinimapButtons Error: Cannot add ", frameName, " (", localizedFrameName, ") called from ", this:GetName(), ". The button does not exist.");
                return;
        elseif (MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName]) then
                if (MobileMinimapButtons_FramesLoaded) then
                        Sea.io.print("MobileMinimapButtons Error: Cannot add ", frameName, " (", localizedFrameName, ") called from ", this:GetName(), ". Duplicate already registered.");
                end
                return;
        end
        MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName] = localizedFrameName;
        if (MobileMinimapButtons_FramesLoaded) then
                MobileMinimapButtons_MakeMobile(frameName, localizedFrameName);
                if (not MobileMinimapButtons_Enabled) then
                        --Override Disable to redisable
                        MobileMinimapButtons_Enabled = true;
                        MobileMinimapButtons_Disable();
                end
        end
end


function MobileMinimapButtons_MakeMobile(frameName, localizedFrameName)
        if (MobileMinimapButtons_CurrentlyEnabled[frameName]) then
                -- Already Mobile
                return;
        end

        local frame = Sea.util.getValue(frameName);

        --Store the current position as the reset coords
        MobileMinimapButtons_StoreResetPosition(frameName);

        --Load Frame Script Element Hooks
        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnEvent", "replace", "OnEvent" );
        if (frame:HasScript("OnClick")) then
                --Enable Click events
                --frame:RegisterForClicks("LeftButton", "RightButton");
                Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnClick", "replace", "OnClick" );
        end
        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseDown", "replace", "OnMouseDown" );
        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseUp", "replace", "OnMouseUp" );
        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnHide", "replace", "OnHide" );
        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnUpdate", "replace", "OnUpdate" );

        --Make sure all the Buttons are Mobile
        if (not frame:IsMovable()) then
                frame:SetMovable(1);
        end

        --Disable OnDrag events by passing no arguments
        frame:RegisterForDrag();

        --Reposition Buttons to Saved Coords
        local coords = MobileMinimapButtons_Coords[frameName];
        frame:ClearAllPoints();
        if (coords) and (coords.x) and (coords.y) then
                frame:SetPoint("CENTER", "Minimap", "CENTER", coords.x, coords.y);
        else
                frame:SetPoint("CENTER", "Minimap", "CENTER", frame.resetX, frame.resetY);
        end

        --Set as enabled for this session
        MobileMinimapButtons_CurrentlyEnabled[frameName] = localizedFrameName;
        --Save for later
        MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[frameName] = localizedFrameName;

        --Elevate Buttons Above the MiniMap
        frame:SetFrameLevel(frame:GetFrameLevel()+1);

        --Attach Parent Buttons
        local maskFrame = Sea.util.getValue(MobileMinimapButtons_MaskParentButtons[frameName])
        if (maskFrame) then
                maskFrame:SetAllPoints(frame);
        end
end

function MobileMinimapButtons_StoreResetPosition(frameName)
        local frame = Sea.util.getValue(frameName);
        local centerX, centerY = Minimap:GetCenter();
        local thisX, thisY = frame:GetCenter();
        local radius;

        local diffX = centerX - thisX;
        local diffY = centerY - thisY;
        local dist = (diffX * diffX) + (diffY * diffY);
        radius = math.sqrt(dist);

        local x = math.abs(thisX - centerX);
        local y = math.abs(thisY - centerY);
        local xSign = 1;
        local ySign = 1;
        if not (thisX >= centerX) then
                xSign = -1;
        end
        if not (thisY >= centerY) then
                ySign = -1;
        end
        --Sea.io.print(xSign*x,", ",ySign*y);
        local angle = math.atan(x/y);
        x = math.sin(angle)*radius;
        y = math.cos(angle)*radius;
        frame.resetX = xSign*x;
        frame.resetY = ySign*y;
end

function MobileMinimapButtons_Reset(frame)
        if (frame) then
                frame.isMoving = false;
                frame:ClearAllPoints();
                frame:SetPoint("CENTER", "Minimap", "CENTER", frame.resetX, frame.resetY);
                frame:SetUserPlaced(false);
                MobileMinimapButtons_Coords[frame:GetName()] = nil;
        end
end

function MobileMinimapButtons_ResetAll()
        for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
                local frame = Sea.util.getValue(frameName);
                MobileMinimapButtons_Reset(frame);
        end
end

function MobileMinimapButtons_Disable()
        if (not MobileMinimapButtons_Enabled) then
                return;
        end
        for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
                --Reset Location without forgetting coords
                local frame = Sea.util.getValue(frameName);
                if (frame) then
                        frame.isMoving = false;
                        frame:ClearAllPoints();
                        frame:SetPoint("CENTER", "Minimap", "CENTER", frame.resetX, frame.resetY);
                        frame:SetUserPlaced(false);

                        --Unload Frame Script Element Hooks
                        Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnEvent", "replace", "OnEvent" );
                        if (frame:HasScript("OnClick")) then
                                Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnClick", "replace", "OnClick" );
                        end
                        Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnMouseDown", "replace", "OnMouseDown" );
                        Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnMouseUp", "replace", "OnMouseUp" );
                        Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnHide", "replace", "OnHide" );
                        Sea.util.unhook( frameName, "MobileMinimapButtons_Master_OnUpdate", "replace", "OnUpdate" );
                end
        end
        MobileMinimapButtons_Enabled = nil;
end

function MobileMinimapButtons_ReEnable()
        if (MobileMinimapButtons_Enabled) then
                return;
        end
        for frameName, localizedFrameName in MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS do
                --Load Frame Script Element Hooks
                local frame = Sea.util.getValue(frameName);
                if (frame) then
                        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnEvent", "replace", "OnEvent" );
                        if (frame:HasScript("OnClick")) then
                                Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnClick", "replace", "OnClick" );
                        end
                        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseDown", "replace", "OnMouseDown" );
                        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnMouseUp", "replace", "OnMouseUp" );
                        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnHide", "replace", "OnHide" );
                        Sea.util.hook( frameName, "MobileMinimapButtons_Master_OnUpdate", "replace", "OnUpdate" );

                        --Reposition Buttons to Saved Coords
                        local coords = MobileMinimapButtons_Coords[frameName];
                        if (coords) and (coords.x) and (coords.y) then
                                local frame = Sea.util.getValue(frameName);
                                frame:ClearAllPoints();
                                frame:SetPoint("CENTER", "Minimap", "CENTER", coords.x, coords.y);
                        end
                end
        end
        MobileMinimapButtons_Enabled = true;
end

function MobileMinimapButtons_Master_OnMouseDown()
        Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnMouseDown(", arg1, ")");
        if (IsControlKeyDown()) then
                if (arg1 == "LeftButton") then
                        this.isMoving = 0;
                        local centerX, centerY = Minimap:GetCenter();
                        local thisX, thisY = this:GetCenter();                          
                        local diffX = centerX - thisX;
                        local diffY = centerY - thisY;
                        local dist = (diffX * diffX) + (diffY * diffY);
                        this.radius = math.sqrt(dist);
                end
        else
                return true;
        end
end

function MobileMinimapButtons_Master_OnMouseUp()
        Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnMouseUp(", arg1, ")");
        local frameName = this:GetName();
        if (this.isMoving) then
                if (MouseIsOver(this)) and (this.isMoving > GetFramerate()) then
                        --Only disable OnClick if it was dragging longer than 1 second (accounts for shift-OnClicking)
                        MobileMinimapButtons_NextClickDisabled = true;
                end
                if (not MobileMinimapButtons_Coords[frameName]) then
                        MobileMinimapButtons_Coords[frameName] = {};
                end
                MobileMinimapButtons_Coords[frameName].x = this.currentX;
                MobileMinimapButtons_Coords[frameName].y = this.currentY;
                this.isMoving = false;
                this.radius = nil;
        elseif (MouseIsOver(this)) then
                if (IsControlKeyDown()) and (arg1 == "RightButton") then
                        --MobileMinimapButtons_Reset(this);
                        MobileMinimapButtonsDropDown.displayMode = "MENU";
                        ToggleDropDownMenu(1, frameName, MobileMinimapButtonsDropDown, frameName);
                        --MobileMinimapButtonsDropDown_Reposition(frameName);
                        MobileMinimapButtons_NextClickDisabled = true;
                else
                        --MobileMinimapButtons_NextClickDisabled = nil;
                        return true;
                end
        else
                return true;
        end
end

function MobileMinimapButtons_Master_OnClick()
        if (not MobileMinimapButtons_NextClickDisabled) then
                Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnClick(", arg1, ") Orig Called.");
                return true;
        else
                Sea.io.dprint("MobileMinimapButtons_Debug", "MobileMinimapButtons_Master_OnClick(", arg1, ") Orig Not Called.");
                MobileMinimapButtons_NextClickDisabled = nil;
        end
end

function MobileMinimapButtons_Master_OnHide()
        this.isMoving = false;
        return true;
end

function MobileMinimapButtons_Master_OnUpdate()
        if (this.isMoving) then
                this.isMoving = this.isMoving+1;
                local mouseX, mouseY = GetCursorPosition();
                local centerX, centerY = Minimap:GetCenter();
                local scale = Minimap:GetEffectiveScale();
                mouseX = mouseX / scale;
                mouseY = mouseY / scale;
                local radius;

                if ( not this.radius ) then
                        if (MobileMinimapButtons_FullSizeButtons[this:GetName()]) then
                                radius = ((Minimap:GetRight()-Minimap:GetLeft())/2) + ((this:GetRight()-this:GetLeft())/2);
                        else
                                radius = ((Minimap:GetRight()-Minimap:GetLeft())/2) + ((this:GetRight()-this:GetLeft())/4);
                        end
                else
                        radius = this.radius;
                end

                local x = math.abs(mouseX - centerX);
                local y = math.abs(mouseY - centerY);
                local xSign = 1;
                local ySign = 1;
                if not (mouseX >= centerX) then
                        xSign = -1;
                end
                if not (mouseY >= centerY) then
                        ySign = -1;
                end
                --Sea.io.print(xSign*x,", ",ySign*y);
                local angle = math.atan(x/y);
                x = math.sin(angle)*radius;
                y = math.cos(angle)*radius;
                this.currentX = xSign*x;
                this.currentY = ySign*y;
                this:ClearAllPoints();
                this:SetPoint("CENTER", "Minimap", "CENTER", this.currentX, this.currentY);
        else
                return true;
        end
end

-- <= == == == == == == == == == == == == =>
-- => Menu
-- <= == == == == == == == == == == == == =>

function MobileMinimapButtons_LoadDropDownMenu()
        --Title
        local info = {};
        info.text = MOBILE_MINIMAP_BUTTONS_DESCRIPTIONS[UIDROPDOWNMENU_MENU_VALUE];
        info.notClickable = 1;
        info.isTitle = 1;
        UIDropDownMenu_AddButton(info, 1);

        --Reset
        local info = {};
        info.text = RESET;
        info.value = "Reset";
        info.func = function() MobileMinimapButtons_Reset(Sea.util.getValue(UIDROPDOWNMENU_MENU_VALUE)) end;
        --info.notCheckable = 1;
        UIDropDownMenu_AddButton(info, 1);

        --Reset All
        local info = {};
        info.text = RESET_ALL;
        info.value = "ResetAll";
        info.func = MobileMinimapButtons_ResetAll;
        --info.notCheckable = 1;
        UIDropDownMenu_AddButton(info, 1);

        MobileMinimapButtonsDropDown_Reposition(UIDROPDOWNMENU_MENU_VALUE);
end

function MobileMinimapButtonsDropDown_OnLoad()
        UIDropDownMenu_Initialize(this, MobileMinimapButtons_LoadDropDownMenu, "MENU");
end

function MobileMinimapButtonsDropDown_Reposition(anchorName)
        local customPoint = "TOPLEFT";   --Default Anchor
        local offscreenY, offscreenX, anchorPoint, relativePoint, offsetX, offsetY;
        local listFrame = getglobal("DropDownList"..UIDROPDOWNMENU_MENU_LEVEL);
        -- Determine whether the menu is off the screen or not
        local offscreenY, offscreenX;
        --Hack for built in bug
        if ( not listFrame:GetRight() ) then
                return;
        end

        if ( listFrame:GetBottom() < WorldFrame:GetBottom() ) then
                offscreenY = 1;
        end
        if ( listFrame:GetRight() > WorldFrame:GetRight() ) then
                offscreenX = 1;
        end

        local anchorPoint, relativePoint, offsetX, offsetY;
        if ( offscreenY == 1 ) then
                if ( offscreenX == 1 ) then
                        anchorPoint = string.gsub(customPoint, "TOP(.*)", "BOTTOM%1");
                        anchorPoint = string.gsub(anchorPoint, "(.*)LEFT", "%1RIGHT");
                        relativePoint = "TOPRIGHT";
                        offsetX = 0;
                        offsetY = 14;
                else
                        anchorPoint = string.gsub(customPoint, "TOP(.*)", "BOTTOM%1");
                        relativePoint = "TOPLEFT";
                        offsetX = 0;
                        offsetY = 14;
                end
        else
                if ( offscreenX == 1 ) then
                        anchorPoint = string.gsub(customPoint, "(.*)LEFT", "%1RIGHT");
                        relativePoint = "BOTTOMRIGHT";
                        offsetX = 0;
                        offsetY = -14;
                else
                        anchorPoint = customPoint;
                        relativePoint = "BOTTOMLEFT";
                        offsetX = 0;
                        offsetY = -14;
                end
        end
        listFrame:ClearAllPoints();
        listFrame:SetPoint(anchorPoint, anchorName, relativePoint, offsetX, offsetY);

        -- Reshow the "MENU" border
        getglobal(listFrame:GetName().."Backdrop"):Hide();
        getglobal(listFrame:GetName().."MenuBackdrop"):Show();
        --getglobal(listFrame:GetName().."Backdrop"):Show();
        --getglobal(listFrame:GetName().."MenuBackdrop"):Hide();
end

-- <= == == == == == == == == == == == == =>
-- => Khaos Registration
-- <= == == == == == == == == == == == == =>

function MobileMinimapButtons_RegisterForKhaos()
        local optionSet = {
                id="MobileMinimapButtons";
                text=MOBILE_MINIMAP_BUTTONS_HEADER;
                helptext=MOBILE_MINIMAP_BUTTONS_HEADER_INFO;
                difficulty=1;
                default = {checked = true};
                callback = function(checked)
                        if (checked) then
                                MobileMinimapButtons_ReEnable();
                        else
                                MobileMinimapButtons_Disable();
                        end
                end;
                options={
                        {
                                id="Header";
                                text=MOBILE_MINIMAP_BUTTONS_HEADER;
                                helptext=MOBILE_MINIMAP_BUTTONS_HEADER_INFO;
                                type=K_HEADER;
                        };
                        {
                                id="ResetAll";
                                type=K_BUTTON;
                                text=MOBILE_MINIMAP_BUTTONS_RESET_ALL_TEXT;
                                helptext=MOBILE_MINIMAP_BUTTONS_RESET_ALL_TEXT_INFO;
                                callback=MobileMinimapButtons_ResetAll;
                                setup={buttonText=RESET_ALL};
                        };
                };
        };
        Khaos.registerOptionSet(
                "frames",
                optionSet
        );
end