vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:

--[[ TrinketMenu 2.6 ]]--

--[[ SavedVariables ]]--

-- global settings
TrinketMenuOptions = {
        IconPos = -100,                         -- angle of initial minimap icon position
        CooldownCount = "OFF",          -- whether to display numerical cooldown counters
        TooltipFollow = "OFF",          -- whether tooltips follow the mouse
        KeepOpen = "OFF",                       -- whether menu hides after use
        ShowIcon = "ON",                        -- whether to show the minimap button
        KeepDocked = "ON",                      -- whether to keep menu docked at all times
        Notify = "OFF",                         -- whether a message appears when a trinket is ready
        DisableToggle="OFF",            -- whether minimap button toggles trinkets
        NotifyUsedOnly="OFF",           -- whether notify happens only on trinkets used
        NotifyChatAlso="OFF",           -- whether to send notify to chat also
        Locked = "OFF",                         -- whether windows can be moved/scaled/rotated
        ShowTooltips = "ON",            -- whether to display tooltips at all
        NotifyThirty = "OFF",           -- whether to notify cooldowns at 30 seconds instead of 0
        SquareMinimap = "OFF",          -- whether the minimap is square instead of circular
        MenuOnShift = "OFF"                     -- whether menu requires Shift to display
}

-- per-character settings
TrinketMenuPerOptions = {
        MainDock = "BOTTOMRIGHT",       -- corner of main window docked to
        MenuDock = "BOTTOMLEFT",        -- corner menu window is docked from
        MainOrient = "HORIZONTAL",      -- direction of main window
        MenuOrient = "VERTICAL",        -- direction of menu window
        XPos = 400,                                     -- left edge of main window
        YPos = 400,                                     -- top edge of main window
        MainScale = 1,                          -- scaling of main window
        MenuScale = 1,                          -- scaling of menu window
        Visible="ON",                           -- whether to display the trinkets
        FirstUse = true                         -- whether this is the first time this user has used the mod
}

--[[ Misc Variables ]]--

TrinketMenu_Version = 2.7
BINDING_HEADER_TRINKETMENU = "TrinketMenu"

TrinketMenu = {}

TrinketMenu.MaxTrinkets = 30 -- add more to TrinketMenu_MenuFrame if this changes

TrinketMenu.BaggedTrinkets = {} -- indexed by number, 1-30 of trinkets in the menu
TrinketMenu.NumberOfTrinkets = 0 -- number of trinkets in the menu
TrinketMenu.Swapping = false -- true if a swap in progress

TrinketMenu.ScalingTime = 0 -- time since last scaling OnUpdate
TrinketMenu.ScalingUpdateTimer = .1 -- frequency (in seconds) of scaling OnUpdates
TrinketMenu.FrameToScale = nil -- handle to the frame (_MainFrame or _MenuFrame) being scaled
TrinketMenu.ScalingWidth = 0 -- width of the frame being scaled

TrinketMenu.DockingTime = 0 -- time since last docking OnUpdate
TrinketMenu.DockingUpdateTimer = .2 -- frequency (in seconds) of docking OnUpdates

TrinketMenu.InventoryTime = 0 -- time since last inventory/bag change
TrinketMenu.InventoryUpdateTimer = .25 -- time after last inventory/bag change before doing an update

TrinketMenu.MenuFrameTime = 0 -- time since last MenuFrame OnUpdate
TrinketMenu.MenuFrameUpdateTimer = .25 -- time before menu disappears after leaving main/menu frames

TrinketMenu.TooltipTime = 0 -- time since last tooltip OnUpdate
TrinketMenu.TooltipUpdateTimer = 1 -- frequency (in seconds) of updating tooltip
TrinketMenu.TooltipOwner = nil -- (this) when tooltip created
TrinketMenu.TooltipType = nil -- "BAG" or "INVENTORY"
TrinketMenu.TooltipBag = nil -- bag number
TrinketMenu.TooltipSlot = nil -- bag or inventory slot number

TrinketMenu.CooldownCountTime = 0 -- time since last cooldown numbers update
TrinketMenu.CooldownCountUpdateTimer = 1 -- frequency (in seconds) of updating cooldown numbers
TrinketMenu.CurrentTime = 0 -- time when a cooldown pass begins

TrinketMenu.Queue = {} -- [0] or [1] = name of trinket queued for slot 0 or 1
TrinketMenu.NotifyList = {} -- name of trinkets used to be notified when cooldown expires

-- option labels, tooltips and variables
TrinketMenu.OptInfo = {
        ["TrinketMenuOptShowIcon"] = { text="Minimap Button", tooltip="Check this to show a gear button along the minimap edge to access TrinketMenu.\n\n/trinket opt : display options", info="ShowIcon" },
        ["TrinketMenuOptLocked"] = { text="Lock Windows", tooltip="Check this to lock the windows to prevent moving, scaling or rotating.", info="Locked" },
        ["TrinketMenuOptCooldownCount"] = { text="Cooldown Numbers", tooltip="Check this to show numerical cooldowns remaining on trinkets.", info="CooldownCount" },
        ["TrinketMenuOptShowTooltips"] = { text="Show Tooltips", tooltip="Check this to show tooltips for trinkets and options.", info="ShowTooltips" },
        ["TrinketMenuOptTooltipFollow"] = { text="Tooltips at Mouse", tooltip="Check this to show trinket tooltips at the pointer instead of the default position.", info="TooltipFollow" },
        ["TrinketMenuOptKeepOpen"] = { text="Keep Menu Open", tooltip="Check this to keep the trinket menu open at all times.", info="KeepOpen" },
        ["TrinketMenuOptKeepDocked"] = { text="Keep Menu Docked", tooltip="Check this to keep the trinket menu docked to the equipped trinkets.\n\nRecommended: On\n\nIf you undock and move the menu far away from equipped trinkets, you may not be able to move the mouse to the menu before it disappears.  If this happens, hold Shift to keep the menu open or check this option to redock the window.", info="KeepDocked" },
        ["TrinketMenuOptNotify"] = { text="Notify When Ready", tooltip="Check this to display a message when a trinket's cooldown is expiring.", info="Notify" },
        ["TrinketMenuOptDisableToggle"] = { text="Disable Toggle", tooltip="Check this to prevent clicking the minimap button from toggling the trinkets on/off.", info="DisableToggle" },
        ["TrinketMenuOptNotifyUsedOnly"] = { text="Notify Used Only", tooltip="Check this to show cooldown notifications only if you actually used the trinket.  So that equip cooldowns and shared timers will not notify on expiring.", info="NotifyUsedOnly" },
        ["TrinketMenuOptNotifyChatAlso"] = { text="Notify Chat Also", tooltip="Check this to send cooldown notifications to the chat window also.", info="NotifyChatAlso" },
        ["TrinketMenuOptNotifyThirty"] = { text="Notify at 30 sec", tooltip="Check this to send cooldown notifications when a trinket is at 30 seconds.", info="NotifyThirty" },
        ["TrinketMenuOptSquareMinimap"] = { text="Square Minimap", tooltip="Check this to position the minimap button on a square minimap.", info="SquareMinimap" },
        ["TrinketMenuOptMenuOnShift"] = { text="Menu On Shift Only", tooltip="Check this to prevent the trinket menu from showing unless you hold Shift.", info="MenuOnShift" }
}

--[[ Local functions ]]--

-- dock-dependant offset and directions: MainDock..MenuDock
-- x/yoff   = offset MenuFrame is positioned to MainFrame
-- x/ydir   = direction trinkets are added to menu
-- x/ystart = starting offset when building a menu, relativePoint MenuDock
local dock_stats = { ["TOPRIGHTTOPLEFT"] =               { xoff=-4, yoff=0,  xdir=1,  ydir=-1, xstart=8,   ystart=-8 },
                                         ["BOTTOMRIGHTBOTTOMLEFT"] = { xoff=-4, yoff=0,  xdir=1,  ydir=1,  xstart=8,   ystart=44 },
                                         ["TOPLEFTTOPRIGHT"] =           { xoff=4,  yoff=0,  xdir=-1, ydir=-1, xstart=-44, ystart=-8 },
                                         ["BOTTOMLEFTBOTTOMRIGHT"] = { xoff=4,  yoff=0,  xdir=-1, ydir=1,  xstart=-44, ystart=44 },
                                         ["TOPRIGHTBOTTOMRIGHT"] =   { xoff=0,  yoff=-4, xdir=-1, ydir=1,  xstart=-44,  ystart=44 },
                                         ["BOTTOMRIGHTTOPRIGHT"] =   { xoff=0,  yoff=4,  xdir=-1, ydir=-1, xstart=-44,  ystart=-8 },
                                         ["TOPLEFTBOTTOMLEFT"] =         { xoff=0,  yoff=-4, xdir=1,  ydir=1,  xstart=8,   ystart=44 },
                                         ["BOTTOMLEFTTOPLEFT"] =         { xoff=0,  yoff=4,  xdir=1,  ydir=-1, xstart=8,   ystart=-8 } }

-- returns offset and direction depending on current docking. ie: dock_info("xoff")
local function dock_info(arg1)

        local anchor = TrinketMenuPerOptions.MainDock..TrinketMenuPerOptions.MenuDock

        if dock_stats[anchor] and arg1 and dock_stats[anchor][arg1] then
                return dock_stats[anchor][arg1]
        else
                return 0
        end
end

-- hide the docking markers
local function clear_docking()

        local corners,i = { "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT" }

        for i=1,4 do
                getglobal("TrinketMenu_MainDock_"..corners[i]):Hide()
                getglobal("TrinketMenu_MenuDock_"..corners[i]):Hide()
        end
end

-- returns true if the two values are close to each other
local function near(arg1,arg2)

    local isnear = false

    if (math.max(arg1,arg2)-math.min(arg1,arg2)) < 15 then
                isnear = true
    end

    return isnear
end

-- returns true if windows unlocked
local function unlocked()
        return TrinketMenuOptions.Locked=="OFF"
end

-- moves the MenuFrame to the dock position against MainFrame
local function dock_windows()

        clear_docking()

        if TrinketMenuOptions.KeepDocked=="ON" then
        
                TrinketMenu_MenuFrame:ClearAllPoints()
                if TrinketMenuOptions.Locked=="OFF" then
                        TrinketMenu_MenuFrame:SetPoint(TrinketMenuPerOptions.MenuDock,"TrinketMenu_MainFrame",TrinketMenuPerOptions.MainDock,dock_info("xoff"),dock_info("yoff"))
                else
                        TrinketMenu_MenuFrame:SetPoint(TrinketMenuPerOptions.MenuDock,"TrinketMenu_MainFrame",TrinketMenuPerOptions.MainDock,dock_info("xoff")*3,dock_info("yoff")*3)
                end
        end
end

-- displays windows vertically or horizontally
local function orient_windows()

        if TrinketMenuPerOptions.MainOrient=="HORIZONTAL" then
                TrinketMenu_MainFrame:SetWidth(90)
                TrinketMenu_MainFrame:SetHeight(52)
        else
                TrinketMenu_MainFrame:SetWidth(52)
                TrinketMenu_MainFrame:SetHeight(90)
        end

        TrinketMenu.InventoryTime = 10 -- immediate update
        TrinketMenu_InventoryFrame:Show()

end

-- redisplay menu cooldowns only if they're on screen
local function update_menu_cooldowns()

        -- set cooldown timers on menu trinkets
        local start, duration, enable
        for i=1,TrinketMenu.NumberOfTrinkets do
                start,duration,enable = GetContainerItemCooldown(TrinketMenu.BaggedTrinkets[i].bag,TrinketMenu.BaggedTrinkets[i].slot)
                CooldownFrame_SetTimer(getglobal("TrinketMenu_Menu"..i.."Cooldown"), start, duration, enable)
        end
end

-- update equipped trinkets cooldowns
local function update_cooldowns()

        local start, duration, enable

        start, duration, enable = GetInventoryItemCooldown("player",13)
        CooldownFrame_SetTimer(TrinketMenu_Trinket0Cooldown, start, duration, enable)

        start, duration, enable = GetInventoryItemCooldown("player",14)
        CooldownFrame_SetTimer(TrinketMenu_Trinket1Cooldown, start, duration, enable)

        if TrinketMenu_MenuFrame:IsVisible() and TrinketMenu.NumberOfTrinkets>0 then
                update_menu_cooldowns()
        end
end

-- call this when any action can change the 'Cooldown Numbers' or 'Notify When Ready' options
-- both share the same OnUpdate frame, but either should work independently of other.
local function cooldown_opts_changed()

        local i

        if TrinketMenuOptions.CooldownCount=="OFF" then
                TrinketMenu_Trinket0Time:Hide("")
                TrinketMenu_Trinket1Time:Hide("")
                for i=1,TrinketMenu.MaxTrinkets do
                        getglobal("TrinketMenu_Menu"..i.."Time"):Hide("")
                end
        else
                TrinketMenu_Trinket0Time:Show()
                TrinketMenu_Trinket1Time:Show()
                for i=1,TrinketMenu.MaxTrinkets do
                        getglobal("TrinketMenu_Menu"..i.."Time"):Show()
                end
        end
end


-- scan inventory and build MenuFrame
function TrinketMenu_BuildMenu()

        local idx,i,j,k,texture = 1
        local itemLink,itemID,itemName,equipSlot,itemTexture

        -- go through bags and gather trinkets into .BaggedTrinkets
        for i=0,4 do
                for j=1,GetContainerNumSlots(i) do
                        itemLink = GetContainerItemLink(i,j)
                        
                        if itemLink then
                                _,_,itemID,itemName = string.find(GetContainerItemLink(i,j) or "","item:(%d+).+%[(.+)%]")
                                _,_,_,_,_,_,_,equipSlot,itemTexture = GetItemInfo(itemID or "")
                                if equipSlot=="INVTYPE_TRINKET" then
                                        if not TrinketMenu.BaggedTrinkets[idx] then
                                                TrinketMenu.BaggedTrinkets[idx] = {}
                                        end
                                        TrinketMenu.BaggedTrinkets[idx].bag = i
                                        TrinketMenu.BaggedTrinkets[idx].slot = j
                                        TrinketMenu.BaggedTrinkets[idx].name = itemName
                                        TrinketMenu.BaggedTrinkets[idx].texture = itemTexture
                                        idx = idx + 1
                                end
                        end
                end
        end
        TrinketMenu.NumberOfTrinkets = math.min(idx-1,TrinketMenu.MaxTrinkets)

        if TrinketMenu.NumberOfTrinkets<1 then
                -- user has no bagged trinkets :(
                TrinketMenu_MenuFrame:Hide()
        else
                -- display trinkets outward from docking point
                local col,row,xpos,ypos = 0,0,dock_info("xstart"),dock_info("ystart")
                local max_cols = 1

                if TrinketMenu.NumberOfTrinkets>24 then
                        max_cols = 5
                elseif TrinketMenu.NumberOfTrinkets>18 then
                        max_cols = 4
                elseif TrinketMenu.NumberOfTrinkets>12 then
                        max_cols = 3
                elseif TrinketMenu.NumberOfTrinkets>4 then
                        max_cols = 2
                end

                for i=1,TrinketMenu.NumberOfTrinkets do
                        local item = getglobal("TrinketMenu_Menu"..i)
                        getglobal("TrinketMenu_Menu"..i.."Icon"):SetTexture(TrinketMenu.BaggedTrinkets[i].texture)
                        item:SetPoint("TOPLEFT","TrinketMenu_MenuFrame",TrinketMenuPerOptions.MenuDock,xpos,ypos)

                        if TrinketMenuPerOptions.MenuOrient=="VERTICAL" then
                                xpos = xpos + dock_info("xdir")*40
                                col = col + 1
                                if col==max_cols then
                                        xpos = dock_info("xstart")
                                        col = 0
                                        ypos = ypos + dock_info("ydir")*40
                                        row = row + 1
                                end
                                item:Show()
                        else
                                ypos = ypos + dock_info("ydir")*40
                                col = col + 1
                                if col==max_cols then
                                        ypos = dock_info("ystart")
                                        col = 0
                                        xpos = xpos + dock_info("xdir")*40
                                        row = row + 1
                                end
                                item:Show()
                        end
                end
                for i=(TrinketMenu.NumberOfTrinkets+1),TrinketMenu.MaxTrinkets do
                        getglobal("TrinketMenu_Menu"..i):Hide()
                end
                if col==0 then
                        row = row-1
                end

                if TrinketMenuPerOptions.MenuOrient=="VERTICAL" then
                        TrinketMenu_MenuFrame:SetWidth(12+(max_cols*40))
                        TrinketMenu_MenuFrame:SetHeight(12+((row+1)*40))
                else
                        TrinketMenu_MenuFrame:SetWidth(12+((row+1)*40))
                        TrinketMenu_MenuFrame:SetHeight(12+(max_cols*40))
                end

                update_menu_cooldowns()
        end

end

-- sets window lock "ON" or "OFF"
local function set_lock(arg1)

        TrinketMenuOptions.Locked = arg1

        if arg1=="ON" then
                TrinketMenu_MainFrame:SetBackdropColor(0,0,0,0)
                TrinketMenu_MainFrame:SetBackdropBorderColor(0,0,0,0)
                TrinketMenu_MainResizeButton:Hide()
                TrinketMenu_MenuFrame:SetBackdropColor(0,0,0,0)
                TrinketMenu_MenuFrame:SetBackdropBorderColor(0,0,0,0)
                TrinketMenu_MenuResizeButton:Hide()
        else
                TrinketMenu_MainFrame:SetBackdropColor(1,1,1,1)
                TrinketMenu_MainFrame:SetBackdropBorderColor(1,1,1,1)
                TrinketMenu_MainResizeButton:Show()
                TrinketMenu_MenuFrame:SetBackdropColor(1,1,1,1)
                TrinketMenu_MenuFrame:SetBackdropBorderColor(1,1,1,1)
                TrinketMenu_MenuResizeButton:Show()
        end
        dock_windows()
end

local function move_icon()

        local xpos,ypos

        if TrinketMenuOptions.SquareMinimap=="ON" then
                -- brute force method until trig solution figured out - min/max a point on a circle beyond square
                xpos = 110 * cos(TrinketMenuOptions.IconPos or 0)
                ypos = 110 * sin(TrinketMenuOptions.IconPos or 0)
                xpos = math.max(-82,math.min(xpos,84))
                ypos = math.max(-86,math.min(ypos,82))
        else
                xpos = 80*cos(TrinketMenuOptions.IconPos or 0)
                ypos = 80*sin(TrinketMenuOptions.IconPos or 0)
        end

        TrinketMenu_IconFrame:SetPoint("TOPLEFT","Minimap","TOPLEFT",52-xpos,ypos-52)

end

local function show_icon()
        if TrinketMenuOptions.ShowIcon=="ON" then
                TrinketMenu_IconFrame:Show()
        else
                TrinketMenu_IconFrame:Hide()
        end
end

local function check_state(arg1)

        if arg1=="ON" then
                return 1
        else
                return 0
        end
end

-- for use with main/menu frames with UIParent parent when relocated by the mod, to register for layout-cache.txt
local function really_setpoint(frame,point,relativeTo,relativePoint,xoff,yoff)
        frame:SetPoint(point,relativeTo,relativePoint,xoff,yoff)
end

-- enable/disable subopt (arg2) arg1->arg2
local function subopt_enable(arg1,arg2)

        if arg1 and arg2 and TrinketMenuOptions[arg1]=="ON" then
                getglobal("TrinketMenuOpt"..arg2):Enable()
                getglobal("TrinketMenuOpt"..arg2.."Text"):SetTextColor(1,.82,0)
        elseif arg1 and arg2 then
                getglobal("TrinketMenuOpt"..arg2):Disable()
                getglobal("TrinketMenuOpt"..arg2.."Text"):SetTextColor(.6,.6,.6)
        end
end

-- returns the name of the trinket in slot 0 or 1
local function trinket_name(slot)
        local _,_,name = string.find(GetInventoryItemLink("player",tonumber(slot)+13) or "","^.*%[(.*)%].*$")
        return name
end

-- sets initial display
local function initialize_display()

        if TrinketMenuPerOptions.FirstUse then
                -- if this is first use for this user
                local i
                for i in TrinketMenuPerOptions do
                        -- go through and see if any PerOptions are in Options from previous versions
                        if TrinketMenuOptions[i] then
                                -- copy those Options to PerOptions
                                TrinketMenuPerOptions[i] = TrinketMenuOptions[i]
                        end
                end
                TrinketMenuPerOptions.FirstUse = nil
        end

        TrinketMenuOptions.KeepDocked = TrinketMenuOptions.KeepDocked or "ON" -- new option for 2.1
        TrinketMenuOptions.Notify = TrinketMenuOptions.Notify or "OFF" -- 2.1
        TrinketMenuOptions.DisableToggle = TrinketMenuOptions.DisableToggle or "OFF" -- new option for 2.2
        TrinketMenuOptions.NotifyUsedOnly = TrinketMenuOptions.NotifyUsedOnly or "OFF" -- 2.2
        TrinketMenuOptions.NotifyChatAlso = TrinketMenuOptions.NotifyChatAlso or "OFF" -- 2.2
        TrinketMenuOptions.ShowTooltips = TrinketMenuOptions.ShowTooltips or "ON" -- 2.3
        TrinketMenuOptions.NotifyThirty = TrinketMenuOptions.NotifyThirty or "OFF" -- 2.5
        TrinketMenuOptions.SquareMinimap = TrinketMenuOptions.SquareMinimap or "OFF" -- 2.6
        TrinketMenuOptions.MenuOnShift = TrinketMenuOptions.MenuOnShift or "OFF" -- 2.6

        if TrinketMenuPerOptions.XPos and TrinketMenuPerOptions.YPos then
                really_setpoint(TrinketMenu_MainFrame,"TOPLEFT","UIParent","BOTTOMLEFT",TrinketMenuPerOptions.XPos,TrinketMenuPerOptions.YPos)
        end
        if TrinketMenuPerOptions.MainScale then
                TrinketMenu_MainFrame:SetScale(TrinketMenuPerOptions.MainScale)
        end
        if TrinketMenuPerOptions.MenuScale then
                TrinketMenu_MenuFrame:SetScale(TrinketMenuPerOptions.MenuScale)
        end

        TrinketMenu_Title:SetText("TrinketMenu "..TrinketMenu_Version)

        move_icon()
        show_icon()
        set_lock(TrinketMenuOptions.Locked)
        orient_windows()
        dock_windows()
        local _,texture = GetInventorySlotInfo("Trinket0Slot")
        TrinketMenu_Trinket0Icon:SetTexture(texture)
        _,texture = GetInventorySlotInfo("Trinket1Slot")
        TrinketMenu_Trinket1Icon:SetTexture(texture)

        -- initialize options
        for i in TrinketMenu.OptInfo do
                getglobal(i.."Text"):SetText(TrinketMenu.OptInfo[i].text)
                getglobal(i):SetChecked(check_state(TrinketMenuOptions[TrinketMenu.OptInfo[i].info]))
        end

        if TrinketMenuOptions.KeepOpen=="ON" then
                TrinketMenu_MenuFrame:Show()
        end

        if TrinketMenuPerOptions.Visible=="OFF" then
                TrinketMenu_MainFrame:Hide()
                TrinketMenu_MenuFrame:Hide()
        end

        cooldown_opts_changed()
        subopt_enable("ShowIcon","DisableToggle")
        subopt_enable("Notify","NotifyUsedOnly")
        subopt_enable("Notify","NotifyChatAlso")
        subopt_enable("Notify","NotifyThirty")
        subopt_enable("ShowTooltips","TooltipFollow")
        subopt_enable("ShowIcon","SquareMinimap")
end

local function cursor_empty()
        return not (CursorHasItem() or CursorHasMoney() or CursorHasSpell())
end

-- swap trinket named 'name' into trinket slot 'which' (0 or 1)
local function swap_by_name(which,name)

        local i

        if TrinketMenu.Queue[which] and cursor_empty() then
                for i=1,TrinketMenu.NumberOfTrinkets do
                        if TrinketMenu.BaggedTrinkets[i].name==TrinketMenu.Queue[which] then
                                PickupInventoryItem(which+13)
                                PickupContainerItem(TrinketMenu.BaggedTrinkets[i].bag,TrinketMenu.BaggedTrinkets[i].slot)
                                getglobal("TrinketMenu_Trinket"..which.."Icon"):SetVertexColor(0.4,0.4,0.4)
                                TrinketMenu.Swapping = true
                        end
                end
        end
end

-- returns true if the player is really dead or ghost, not merely FD
local function player_really_dead()
        local dead,i = UnitIsDeadOrGhost("player")

        for i=1,16 do
                if UnitBuff("player",i)=="Interface\\Icons\\Ability_Rogue_FeignDeath" then
                        dead = nil -- player is just FD, not really dead
                end
        end

        return dead
end

--[[ Frame Scripts ]]--

function TrinketMenu_OnLoad()

        SlashCmdList["TrinketMenuCOMMAND"] = TrinketMenu_SlashHandler
        SLASH_TrinketMenuCOMMAND1 = "/trinketmenu";
        SLASH_TrinketMenuCOMMAND2 = "/trinket";
        
        this:RegisterEvent("PLAYER_LOGIN")
end

function TrinketMenu_OnEvent(event)

        if event=="UNIT_INVENTORY_CHANGED" or event=="BAG_UPDATE" then
                TrinketMenu.InventoryTime = 0 -- reset time of last update
                TrinketMenu_InventoryFrame:Show()

        elseif (event=="PLAYER_REGEN_ENABLED" or event=="PLAYER_UNGHOST" or event=="PLAYER_ALIVE") and not player_really_dead() then
                -- trinkets can now be swapped after combat/death
                if TrinketMenu.Queue[0] or TrinketMenu.Queue[1] then
                        TrinketMenu_BuildMenu()
                        swap_by_name(0,TrinketMenu.Queue[0])
                        swap_by_name(1,TrinketMenu.Queue[1])
                        TrinketMenu.Queue[0] = nil
                        TrinketMenu.Queue[1] = nil
                        TrinketMenu_Trinket0Queue:Hide()
                        TrinketMenu_Trinket1Queue:Hide()
                end

        elseif event=="PLAYER_ENTERING_WORLD" then
                this:RegisterEvent("UNIT_INVENTORY_CHANGED")
                this:RegisterEvent("BAG_UPDATE")
                this:RegisterEvent("PLAYER_LEAVING_WORLD")
                TrinketMenu_OnEvent("BAG_UPDATE") -- force an update

        elseif event=="PLAYER_LEAVING_WORLD" then
                this:UnregisterEvent("UNIT_INVENTORY_CHANGED")
                this:UnregisterEvent("BAG_UPDATE")
                this:RegisterEvent("PLAYER_ENTERING_WORLD")

        elseif event=="PLAYER_LOGIN" then
                table.insert(UISpecialFrames,"TrinketMenu_OptFrame") -- make options window ESCable

                initialize_display()

                -- hook UseInventoryItem
                oldTrinketMenu_UseInventoryItem = UseInventoryItem
                UseInventoryItem = newTrinketMenu_UseInventoryItem

                this:RegisterEvent("PLAYER_REGEN_ENABLED")
                this:RegisterEvent("PLAYER_UNGHOST")
                this:RegisterEvent("PLAYER_ALIVE")
                this:RegisterEvent("PLAYER_ENTERING_WORLD")
        end             
end

function TrinketMenu_SlashHandler(arg1)

        arg1 = string.lower(arg1)

        if not arg1 or arg1=="" then
                TrinketMenu_Toggle()
        elseif arg1=="reset" then
                TrinketMenu_Opt_Reset()
        elseif string.find(arg1,"^opt") or string.find(arg1,"^config") then
                TrinketMenu_OptFrame:Show()
        elseif arg1=="lock" then
                set_lock("ON")
        elseif arg1=="unlock" then
                set_lock("OFF")
        elseif arg1=="debug" then
                DEFAULT_CHAT_FRAME:AddMessage("Trinkets: "..tostring(TrinketMenu.NumberOfTrinkets))
                DEFAULT_CHAT_FRAME:AddMessage("Version: "..tostring(TrinketMenu_Version))
                local function o(info)
                        local i=TrinketMenuOptions[info]
                        return ((i=="ON") and "1") or ((i=="OFF") and "0") or ","
                end
                local opts = { "CooldownCount","TooltipFollow","KeepOpen","ShowIcon","",
                                           "KeepDocked","Notify", "DisableToggle", "NotifyUsedOnly","",
                                           "NotifyChatAlso","Locked", "ShowTooltips", "NotifyThirty","",
                                           "SquareMinimap","MenuOnShift" }
                local txt = ""
                for i=1,table.getn(opts) do
                        txt=txt..o(opts[i])
                end
                DEFAULT_CHAT_FRAME:AddMessage("Opts: "..txt)
        elseif string.find(arg1,"scale") then
                local _,_,menuscale = string.find(arg1,"scale menu (.+)")
                if tonumber(menuscale) then
                        TrinketMenu.FrameToScale = TrinketMenu_MenuFrame
                        TrinketMenu_ScaleFrame(menuscale)
                end
                local _,_,mainscale = string.find(arg1,"scale main (.+)")
                if tonumber(mainscale) then
                        TrinketMenu.FrameToScale = TrinketMenu_MainFrame
                        TrinketMenu_ScaleFrame(mainscale)
                end
                if not tonumber(menuscale) and not tonumber(mainscale) then
                        DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu scale:")
                        DEFAULT_CHAT_FRAME:AddMessage("/trinket scale main (number) : set exact main scale")
                        DEFAULT_CHAT_FRAME:AddMessage("/trinket scale menu (number) : set exact menu scale")
                        DEFAULT_CHAT_FRAME:AddMessage("ie, /trinket scale menu 0.85")
                        DEFAULT_CHAT_FRAME:AddMessage("Note: You can drag the lower-right corner of either window to scale.  This slash command is for those who want to set an exact scale.")
                end
                TrinketMenu.FrameToScale = nil
                TrinketMenuPerOptions.MainScale = TrinketMenu_MainFrame:GetScale()
                TrinketMenuPerOptions.MenuScale = TrinketMenu_MenuFrame:GetScale()
                update_cooldowns()
        else
                DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu useage:")
                DEFAULT_CHAT_FRAME:AddMessage("/trinket or /trinketmenu : toggle the window")
                DEFAULT_CHAT_FRAME:AddMessage("/trinket reset : reset window")
                DEFAULT_CHAT_FRAME:AddMessage("/trinket opt : summon options window")
                DEFAULT_CHAT_FRAME:AddMessage("/trinket lock|unlock : toggles window lock")
                DEFAULT_CHAT_FRAME:AddMessage("/trinket scale main|menu (number) : sets an exact scale")
        end

end

--[[ Window Movement ]]--

function TrinketMenu_MainFrame_OnMouseUp(arg1)
        if arg1=="LeftButton" then
                update_cooldowns()
                this:StopMovingOrSizing()
                TrinketMenuPerOptions.XPos = TrinketMenu_MainFrame:GetLeft()
                TrinketMenuPerOptions.YPos = TrinketMenu_MainFrame:GetTop()
        elseif unlocked() then
                if TrinketMenuPerOptions.MainOrient=="VERTICAL" then
                        TrinketMenuPerOptions.MainOrient = "HORIZONTAL"
                else
                        TrinketMenuPerOptions.MainOrient = "VERTICAL"
                end
                orient_windows()
        end

end

function TrinketMenu_MainFrame_OnMouseDown(arg1)
        if arg1=="LeftButton" and unlocked() then
                this:StartMoving()
        end
end

--[[ MainFrame and MenuFrame Scaling ]]--

function TrinketMenu_StartScaling(arg1)
        if arg1=="LeftButton" and unlocked() then
                this:LockHighlight()
                TrinketMenu.FrameToScale = this:GetParent()
                TrinketMenu.ScalingWidth = this:GetParent():GetWidth()
                TrinketMenu_ScalingFrame:Show()
        end
end

function TrinketMenu_StopScaling(arg1)
        if arg1=="LeftButton" then
                TrinketMenu_ScalingFrame:Hide()
                TrinketMenu.FrameToScale = nil
                this:UnlockHighlight()
                if this:GetParent():GetName() == "TrinketMenu_MainFrame" then
                        TrinketMenuPerOptions.MainScale = TrinketMenu_MainFrame:GetScale()
                else
                        TrinketMenuPerOptions.MenuScale = TrinketMenu_MenuFrame:GetScale()
                end
                update_cooldowns()
        end
end

function TrinketMenu_ScaleFrame(scale)
        local frame = TrinketMenu.FrameToScale
        local oldscale = frame:GetScale() or 1
        local framex = (frame:GetLeft() or TrinketMenuPerOptions.XPos)* oldscale
        local framey = (frame:GetTop() or TrinketMenuPerOptions.YPos)* oldscale

        frame:SetScale(scale)
        if frame:GetName() == "TrinketMenu_MainFrame" then
                really_setpoint(TrinketMenu_MainFrame,"TOPLEFT","UIParent","BOTTOMLEFT",framex/scale,framey/scale)
                TrinketMenuPerOptions.XPos = TrinketMenu_MainFrame:GetLeft()
                TrinketMenuPerOptions.YPos = TrinketMenu_MainFrame:GetTop()
        elseif TrinketMenuOptions.KeepDocked=="OFF" then
                TrinketMenu_MenuFrame:ClearAllPoints()
                really_setpoint(TrinketMenu_MenuFrame,"TOPLEFT","UIParent","BOTTOMLEFT",framex/scale,framey/scale)
        end
end

function TrinketMenu_ScalingFrame_OnUpdate(arg1)

        TrinketMenu.ScalingTime = TrinketMenu.ScalingTime + arg1
        if TrinketMenu.ScalingTime > TrinketMenu.ScalingUpdateTimer then
                TrinketMenu.ScalingTime = 0

                local frame = TrinketMenu.FrameToScale
                local oldscale = frame:GetEffectiveScale()
                local framex, framey, cursorx, cursory = frame:GetLeft()*oldscale, frame:GetTop()*oldscale, GetCursorPosition()

                if (cursorx-framex)>32 then
                        local newscale = (cursorx-framex)/TrinketMenu.ScalingWidth
                        TrinketMenu_ScaleFrame(newscale)
                end

        end
end

--[[ Menu docking ]]--

function TrinketMenu_MenuFrame_OnMouseUp(arg1)
        if arg1=="LeftButton" then
                update_cooldowns()
                TrinketMenu_DockingFrame:Hide()
                TrinketMenu_MenuFrame:StopMovingOrSizing()
                if TrinketMenuOptions.KeepDocked=="ON" then
                        dock_windows()
                end
                TrinketMenu.InventoryTime = 1 -- reset time of last update
                TrinketMenu_InventoryFrame:Show()
        elseif unlocked() then
                if TrinketMenuPerOptions.MenuOrient=="VERTICAL" then
                        TrinketMenuPerOptions.MenuOrient="HORIZONTAL"
                else
                        TrinketMenuPerOptions.MenuOrient="VERTICAL"
                end
                orient_windows()
        end
end

function TrinketMenu_MenuFrame_OnMouseDown(arg1)
        if arg1=="LeftButton" and unlocked() then
                TrinketMenu_MenuFrame:StartMoving()

                if TrinketMenuOptions.KeepDocked=="ON" then
                        TrinketMenu_DockingFrame:Show()
                end
        end
end

function TrinketMenu_DockingFrame_OnUpdate(arg1)

        TrinketMenu.DockingTime = TrinketMenu.DockingTime + arg1
        if TrinketMenu.DockingTime > TrinketMenu.DockingUpdateTimer then
                TrinketMenu.DockingTime = 0

                local main = TrinketMenu_MainFrame
                local menu = TrinketMenu_MenuFrame
                local mainscale = TrinketMenu_MainFrame:GetScale()
                local menuscale = TrinketMenu_MenuFrame:GetScale()

                if near(main:GetRight()*mainscale,menu:GetLeft()*menuscale) then
                        if near(main:GetTop()*mainscale,menu:GetTop()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "TOPRIGHT"
                                TrinketMenuPerOptions.MenuDock = "TOPLEFT"
                        elseif near(main:GetBottom()*mainscale,menu:GetBottom()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "BOTTOMRIGHT"
                                TrinketMenuPerOptions.MenuDock = "BOTTOMLEFT"
                        end
                elseif near(main:GetLeft()*mainscale,menu:GetRight()*menuscale) then
                        if near(main:GetTop()*mainscale,menu:GetTop()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "TOPLEFT"
                                TrinketMenuPerOptions.MenuDock = "TOPRIGHT"
                        elseif near(main:GetBottom()*mainscale,menu:GetBottom()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "BOTTOMLEFT"
                                TrinketMenuPerOptions.MenuDock = "BOTTOMRIGHT"
                        end
                elseif near(main:GetRight()*mainscale,menu:GetRight()*menuscale) then
                        if near(main:GetTop()*mainscale,menu:GetBottom()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "TOPRIGHT"
                                TrinketMenuPerOptions.MenuDock = "BOTTOMRIGHT"
                        elseif near(main:GetBottom()*mainscale,menu:GetTop()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "BOTTOMRIGHT"
                                TrinketMenuPerOptions.MenuDock = "TOPRIGHT"
                        end
                elseif near(main:GetLeft()*mainscale,menu:GetLeft()*menuscale) then
                        if near(main:GetTop()*mainscale,menu:GetBottom()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "TOPLEFT"
                                TrinketMenuPerOptions.MenuDock = "BOTTOMLEFT"
                        elseif near(main:GetBottom()*mainscale,menu:GetTop()*menuscale) then
                                TrinketMenuPerOptions.MainDock = "BOTTOMLEFT"
                                TrinketMenuPerOptions.MenuDock = "TOPLEFT"
                        end
                end

                clear_docking()
                getglobal("TrinketMenu_MainDock_"..TrinketMenuPerOptions.MainDock):Show()
                getglobal("TrinketMenu_MenuDock_"..TrinketMenuPerOptions.MenuDock):Show()

        end
end

--[[ Inventory ]]--

-- after a period of no inventory/bag updates since one happens, update
function TrinketMenu_InventoryFrame_OnUpdate(arg1)

        TrinketMenu.InventoryTime = TrinketMenu.InventoryTime + arg1
        if TrinketMenu.InventoryTime>TrinketMenu.InventoryUpdateTimer then
                TrinketMenu_InventoryFrame:Hide()
                TrinketMenu.InventoryTime = 0

                local t0texture, t1texture = GetInventoryItemTexture("player",13), GetInventoryItemTexture("player",14)

                TrinketMenu.Swapping = false

                TrinketMenu_Trinket0Icon:SetTexture(t0texture or "Interface\\PaperDoll\\UI-PaperDoll-Slot-Trinket")
                TrinketMenu_Trinket1Icon:SetTexture(t1texture or "Interface\\PaperDoll\\UI-PaperDoll-Slot-Trinket")
                TrinketMenu_Trinket0:SetChecked(0)
                TrinketMenu_Trinket1:SetChecked(0)
                TrinketMenu_Trinket0Icon:SetVertexColor(1,1,1,1)
                TrinketMenu_Trinket1Icon:SetVertexColor(1,1,1,1)
                TrinketMenu.CooldownCountTime = TrinketMenu.CooldownCountUpdateTimer -- immediate update of cooldown counters
                update_cooldowns()

                if not t0texture and not t1texture and TrinketMenu.NumberOfTrinkets<1 then
                        -- user has no trinkets at all. :( poor guy.  hide window
--                      TrinketMenuPerOptions.Visible = "OFF"
                        TrinketMenu_MainFrame:Hide()
                end

                TrinketMenu_BuildMenu()

        end
end

--[[ Menu popup ]]--

function TrinketMenu_ResetMenuTimer()
        TrinketMenu.MenuFrameTime = 0
end

function TrinketMenu_MenuFrame_OnUpdate(arg1)

        TrinketMenu.MenuFrameTime = TrinketMenu.MenuFrameTime + arg1
        if TrinketMenu.MenuFrameTime>TrinketMenu.MenuFrameUpdateTimer then
                TrinketMenu.MenuFrameTime = 0
                if (not MouseIsOver(TrinketMenu_MainFrame)) and (not MouseIsOver(TrinketMenu_MenuFrame)) and (not TrinketMenu_ScalingFrame:IsVisible()) and not IsShiftKeyDown() and (TrinketMenuOptions.KeepOpen=="OFF") then
                        TrinketMenu_MenuFrame:Hide()
                end
        end

end

function TrinketMenu_ShowMenu()

        if IsShiftKeyDown() or TrinketMenuOptions.MenuOnShift=="OFF" then
                TrinketMenu_BuildMenu()
                if TrinketMenu.NumberOfTrinkets>0 then
                        TrinketMenu.MenuFrameTime = 0
                        TrinketMenu_MenuFrame:Show()
                end
        end
end

function TrinketMenu_Toggle()

        if TrinketMenu_MainFrame:IsVisible() then
                TrinketMenuPerOptions.Visible = "OFF"
                TrinketMenu_MainFrame:Hide()
                TrinketMenu_MenuFrame:Hide()
                TrinketMenu_OptFrame:Hide()
        else
                TrinketMenuPerOptions.Visible = "ON"
                TrinketMenu_MainFrame:Show()
                if TrinketMenuOptions.KeepOpen=="ON" then
                        TrinketMenu_MenuFrame:Show()
                end
        end
end

--[[ Trinket clicks ]]--

-- hooked UseInventoryItem - updates trinketmenu when slot 13 or 14 are used
function newTrinketMenu_UseInventoryItem(arg1)

        oldTrinketMenu_UseInventoryItem(arg1)

        if arg1==13 or arg1==14 then
                getglobal("TrinketMenu_Trinket"..(arg1-13)):SetChecked(1)

                local name = trinket_name(arg1-13)
                if name then
                        TrinketMenu.NotifyList[name] = 1 -- add this trinket's name to notify list
                end
                update_cooldowns()

                TrinketMenu.InventoryTime = -1.25
                TrinketMenu_InventoryFrame:Show()
        end
end

-- can be used in key binding also, arg1==13 or 14
function TrinketMenu_UseTrinket(arg1)

        if (arg1==13 or arg1==14) and not MerchantFrame:IsVisible() then
                UseInventoryItem(arg1)
        end
end

-- called from Trinket0/1's OnClick
function TrinketMenu_Trinket_OnClick(arg1)

        local id = this:GetID()
        this:SetChecked(0)

        if arg1=="LeftButton" and IsShiftKeyDown() and ChatFrameEditBox:IsVisible() then
                -- link to chat instead of use
                ChatFrameEditBox:Insert(GetInventoryItemLink("player",id))
        else
                TrinketMenu_UseTrinket(id)
        end
end

-- called from Menu1-30's OnClick
function TrinketMenu_SwapTrinket(arg1)

        local id = this:GetID()
        this:SetChecked(0)

        if UnitAffectingCombat("player") or player_really_dead() then
                -- if in combat, put the chosen trinket(id) into queue

                local which = arg1=="LeftButton" and 0 or 1 -- which==which trinket, 0(left) or 1(right)

                if TrinketMenu.Queue[which]==TrinketMenu.BaggedTrinkets[id].name then
                        -- if already queued for this slot, remove from queue
                        TrinketMenu.Queue[which] = nil
                        getglobal("TrinketMenu_Trinket"..which.."Queue"):Hide()
                else
                        if TrinketMenu.Queue[1-which]==TrinketMenu.BaggedTrinkets[id].name then
                                -- if this was queued for other slot, move to this one
                                TrinketMenu.Queue[1-which] = nil
                                getglobal("TrinketMenu_Trinket"..(1-which).."Queue"):Hide()
                        end

                        getglobal("TrinketMenu_Trinket"..which.."Queue"):SetTexture(TrinketMenu.BaggedTrinkets[id].texture)
                        TrinketMenu.Queue[which] = TrinketMenu.BaggedTrinkets[id].name
                        getglobal("TrinketMenu_Trinket"..which.."Queue"):Show()
                end

        elseif not TrinketMenu.Swapping then

                if arg1=="LeftButton" and IsShiftKeyDown() and ChatFrameEditBox:IsVisible() then
                        -- link to chat instead of swap
                        ChatFrameEditBox:Insert(GetContainerItemLink(TrinketMenu.BaggedTrinkets[id].bag,TrinketMenu.BaggedTrinkets[id].slot))
                elseif cursor_empty() then
                        PickupContainerItem(TrinketMenu.BaggedTrinkets[id].bag,TrinketMenu.BaggedTrinkets[id].slot)
                        if arg1=="LeftButton" then
                                PickupInventoryItem(13)
                                TrinketMenu_Trinket0Icon:SetVertexColor(0.4, 0.4, 0.4)
                        else
                                PickupInventoryItem(14)
                                TrinketMenu_Trinket1Icon:SetVertexColor(0.4, 0.4, 0.4)
                        end
                        TrinketMenu.Swapping = true
                end
        end

        if not IsShiftKeyDown() and TrinketMenuOptions.KeepOpen=="OFF" then
                TrinketMenu_MenuFrame:Hide()
        end
end

--[[ Tooltips ]]--

function TrinketMenu_InventoryTooltip()

        local id = this:GetID()

        if TrinketMenu_ScalingFrame:IsVisible() or TrinketMenuOptions.ShowTooltips=="OFF" then
                return
        end

        TrinketMenu.TooltipOwner = this
        TrinketMenu.TooltipType = "INVENTORY"
        TrinketMenu.TooltipSlot = id

        TrinketMenu.TooltipBag = TrinketMenu.Queue[id-13]

        TrinketMenu.TooltipTime = 10 -- immediate update
        TrinketMenu_TooltipFrame:Show()
end

function TrinketMenu_BagTooltip()

        local id = this:GetID()

        if TrinketMenu_ScalingFrame:IsVisible() or TrinketMenuOptions.ShowTooltips=="OFF" then
                return
        end

        TrinketMenu.TooltipOwner = this
        TrinketMenu.TooltipType = "BAG"
        TrinketMenu.TooltipBag = TrinketMenu.BaggedTrinkets[id].bag
        TrinketMenu.TooltipSlot = TrinketMenu.BaggedTrinkets[id].slot

        TrinketMenu.TooltipTime = 10 -- immediate update
        TrinketMenu_TooltipFrame:Show()
end

function TrinketMenu_ClearTooltip()

        GameTooltip:Hide()
        TrinketMenu.TooltipType = nil
        TrinketMenu_TooltipFrame:Hide()
end

-- updates the tooltip created in the functions above
function TrinketMenu_TooltipFrame_OnUpdate(arg1)

        TrinketMenu.TooltipTime = TrinketMenu.TooltipTime + arg1
        if TrinketMenu.TooltipTime > TrinketMenu.TooltipUpdateTimer then
                TrinketMenu.TooltipTime = 0

                if TrinketMenu.TooltipType then

                        local cooldown

                        if TrinketMenuOptions.TooltipFollow=="ON" then
                                if TrinketMenu.TooltipOwner:GetLeft()<400 then
                                        GameTooltip:SetOwner(TrinketMenu.TooltipOwner,"ANCHOR_RIGHT")
                                else
                                        GameTooltip:SetOwner(TrinketMenu.TooltipOwner,"ANCHOR_LEFT")
                                end
                        else
                                GameTooltip_SetDefaultAnchor(GameTooltip,TrinketMenu.TooltipOwner)
                        end
                        if TrinketMenu.TooltipType=="BAG" then
                                GameTooltip:SetBagItem(TrinketMenu.TooltipBag,TrinketMenu.TooltipSlot)
                                cooldown = GetContainerItemCooldown(TrinketMenu.TooltipBag,TrinketMenu.TooltipSlot)
                        else
                                GameTooltip:SetInventoryItem("player",TrinketMenu.TooltipSlot)
                                cooldown = GetInventoryItemCooldown("player",TrinketMenu.TooltipSlot)
                                if TrinketMenu.TooltipBag then
                                        GameTooltip:AddLine("Queued: "..TrinketMenu.TooltipBag)
                                end
                        end
                        GameTooltip:Show()
                        if cooldown==0 then
                                -- stop updates if this trinket has no cooldown
                                TrinketMenu.TooltipType = nil
                                TrinketMenu_TooltipFrame:Hide()
                        end
                end

        end

end

-- normal tooltip for options
function TrinketMenu_OnTooltip(arg1,arg2)

        if TrinketMenuOptions.ShowTooltips=="ON" then
                GameTooltip_SetDefaultAnchor(GameTooltip,this)
                GameTooltip:AddLine(arg1)
                GameTooltip:AddLine(arg2,.8,.8,.8,1)
                GameTooltip:Show()
        end
end

--[[ Minimap Icon ]]--

function TrinketMenu_IconDraggingFrame_OnUpdate(arg1)
        local xpos,ypos = GetCursorPosition()
        local xmin,ymin = Minimap:GetLeft() or 400, Minimap:GetBottom() or 400

        xpos = xmin-xpos/Minimap:GetEffectiveScale()+70
        ypos = ypos/Minimap:GetEffectiveScale()-ymin-70

        TrinketMenuOptions.IconPos = math.deg(math.atan2(ypos,xpos))
        move_icon()
end

function TrinketMenu_IconFrame_OnClick(arg1)

        if arg1=="LeftButton" and TrinketMenuOptions.DisableToggle=="OFF" then
                TrinketMenu_Toggle()
        else
                if TrinketMenu_OptFrame:IsVisible() then
                        TrinketMenu_OptFrame:Hide()
                else
                        TrinketMenu_OptFrame:Show()
                end
        end
end

--[[ Options ]]--

function TrinketMenu_Opt_OnEnter()

        local id = this:GetName()

        if TrinketMenu.OptInfo[id] then
                TrinketMenu_OnTooltip(TrinketMenu.OptInfo[id].text,TrinketMenu.OptInfo[id].tooltip)
        end
end

function TrinketMenu_Opt_OnClick()

        local id_name = this:GetName()
        local id_var = TrinketMenu.OptInfo[id_name].info

        if this:GetChecked()==1 then
                TrinketMenuOptions[id_var] = "ON"
        else
                TrinketMenuOptions[id_var] = "OFF"
        end

        if id_var=="Locked" then
                set_lock(TrinketMenuOptions.Locked)
        elseif id_var=="KeepOpen" then
                TrinketMenu_MenuFrame:Show()
        elseif id_var=="ShowIcon" then
                show_icon()
        elseif id_var=="CooldownCount" then
                TrinketMenu.CooldownCountTime = TrinketMenu.CooldownCountUpdateTimer -- immediate update
                cooldown_opts_changed()
        elseif id_var=="KeepDocked" then
                if TrinketMenuOptions.KeepDocked=="ON" then
                        dock_windows()
                else
                        TrinketMenu.FrameToScale = TrinketMenu_MenuFrame
                        TrinketMenu_ScaleFrame(TrinketMenu_MenuFrame:GetScale())
                end

                TrinketMenu.FrameToScale = this:GetParent()
                TrinketMenu.ScalingWidth = this:GetParent():GetWidth()
        elseif id_var=="Notify" then
                cooldown_opts_changed()
        elseif id_var=="SquareMinimap" then
                move_icon()
        end

        subopt_enable("ShowIcon","DisableToggle")
        subopt_enable("Notify","NotifyUsedOnly")
        subopt_enable("Notify","NotifyChatAlso")
        subopt_enable("Notify","NotifyThirty")
        subopt_enable("ShowTooltips","TooltipFollow")
        subopt_enable("ShowIcon","SquareMinimap")
end

function TrinketMenu_Opt_Reset()

        TrinketMenuOptions = {
                CooldownCount="OFF", TooltipFollow="OFF", KeepOpen="OFF", ShowIcon="ON",
                IconPos=-100, Locked="OFF", 
                KeepDocked="ON", Notify="OFF", -- 2.1
                DisableToggle="OFF", NotifyUsedOnly="OFF", NotifyChatAlso="OFF" -- 2.2
        }
        TrinketMenuPerOptions = {
                MainDock="BOTTOMRIGHT", MenuDock="BOTTOMLEFT", MainOrient="HORIZONTAL", MenuOrient="VERTICAL",
                XPos=400, YPos=400, MainScale=1.0, MenuScale=1.0,
                Visible="ON" 
        }

        TrinketMenu_OptFrame:ClearAllPoints()
        TrinketMenu_OptFrame:SetPoint("CENTER","UIParent","CENTER")
        initialize_display()

end

--[[ Cooldown Counters ]]--


local function format_time(seconds)

        if seconds<60 then
                return math.floor(seconds+.5).." s"
        else
                if seconds < 3600 then 
                        return math.ceil((seconds/60)).." m"
                else
                        return math.ceil((seconds/3600)).." h"
                end
        end

end

-- indexed by TrinketMenuOptions.NotifyThirty
local ready_text = { ["ON"] = " ready soon!", ["OFF"] = " ready!" }

-- sends a message "(trinket) ready!"
local function notify(trinket)

        if trinket and ((TrinketMenu.NotifyList[trinket] and TrinketMenuOptions.NotifyUsedOnly=="ON") or TrinketMenuOptions.NotifyUsedOnly=="OFF") then
                if SCT_CmdDisplay then
                        -- send via SCT if it exists
                        SCT_CmdDisplay("'"..string.gsub(trinket,"'","")..ready_text[TrinketMenuOptions.NotifyThirty].."' 2 7 9")
                else
                        -- send vis UIErrorsFrame if SCT doesn't exit
                        UIErrorsFrame:AddMessage(trinket..ready_text[TrinketMenuOptions.NotifyThirty],.2,.7,.9,1,UIERRORS_HOLD_TIME)
                end

                if TrinketMenuOptions.NotifyChatAlso=="ON" then
                        DEFAULT_CHAT_FRAME:AddMessage("|cff33b2e5"..trinket..ready_text[TrinketMenuOptions.NotifyThirty])
                end
                TrinketMenu.NotifyList[trinket] = nil
                PlaySound("GnomeExploration")
        end
end

local function write_cooldown(where,start,duration)

        local cooldown = duration - (TrinketMenu.CurrentTime - start)

        if start==0 then
                where:SetText("")
        elseif cooldown<3 and not where:GetText() then
                -- this is a global cooldown. don't display it. not accurate but at least not annoying
        else
                where:SetText(format_time(cooldown))

                -- placed here because we don't want to be notified on global cooldowns
                if TrinketMenuOptions.Notify=="ON" and ((TrinketMenuOptions.NotifyThirty=="OFF" and cooldown<1) or (TrinketMenuOptions.NotifyThirty=="ON" and (cooldown>30 and cooldown<=31))) then
                        local _,_,id = string.find(where:GetName(),"TrinketMenu_Menu(%d+)Time")
                        if id then
                                notify(TrinketMenu.BaggedTrinkets[tonumber(id)].name)
                        else
                                if where==TrinketMenu_Trinket0Time then
                                        id = trinket_name(0)
                                        if id then
                                                notify(id)
                                        end
                                else
                                        id = trinket_name(1)
                                        if id then
                                                notify(id)
                                        end
                                end
                        end
                end
        end
end

function TrinketMenu_CooldownCountFrame_OnUpdate(arg1)

        TrinketMenu.CooldownCountTime = TrinketMenu.CooldownCountTime + arg1
        if TrinketMenu.CooldownCountTime > TrinketMenu.CooldownCountUpdateTimer then
                -- update cooldowns
                TrinketMenu.CooldownCountTime = 0

                if TrinketMenuOptions.CooldownCount=="ON" or TrinketMenuOptions.Notify=="ON" then

                        local i,start,duration
                        TrinketMenu.CurrentTime = GetTime()

                        if TrinketMenu_MainFrame:IsVisible() then
                                start, duration = GetInventoryItemCooldown("player",13)
                                write_cooldown(TrinketMenu_Trinket0Time,start,duration)
                                start, duration = GetInventoryItemCooldown("player",14)
                                write_cooldown(TrinketMenu_Trinket1Time,start,duration)
                        end

                        if TrinketMenu_MenuFrame:IsVisible() or TrinketMenuOptions.Notify=="ON" then
                                for i=1,TrinketMenu.NumberOfTrinkets do
                                        start, duration = GetContainerItemCooldown(TrinketMenu.BaggedTrinkets[i].bag,TrinketMenu.BaggedTrinkets[i].slot)
                                        write_cooldown(getglobal("TrinketMenu_Menu"..i.."Time"),start,duration)
                                end
                        end
                end

        end

end

function TrinketMenu_CooldownCountFrame_OnHide()

        local i

        TrinketMenu_Trinket0Time:SetText("")
        TrinketMenu_Trinket1Time:SetText("")

        for i=1,TrinketMenu.MaxTrinkets do
                getglobal("TrinketMenu_Menu"..i.."Time"):SetText("")
        end
end