Leatrix_Plus/Leatrix_Plus_Library.lua

3359 lines
108 KiB
Lua
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<<<<<<< HEAD
----------------------------------------------------------------------
-- L00: Leatrix Plus Library
----------------------------------------------------------------------
-- LibDBIcon 10.0.1:
-- 11: LibStub: (?s)-- LibStubStart\R?\K.*?(?=-- LibStubEnd)
-- 12: LibCallbackHandler: (?s)-- CallbackStart\R?\K.*?(?=-- CallbackEnd)
-- 13: LibDataBroker: (?s)-- DataBrokerStart\R?\K.*?(?=-- DataBrokerEnd)
-- 14: LibDBIcon: (?s)-- LibDBIconStart\R?\K.*?(?=-- LibDBIconEnd)
-- LibChatAnims 10.0.1:
-- 15: LibChatAnims: (?s)-- LibChatAnimsStart\R?\K.*?(?=-- LibChatAnimsEnd)
-- LibCandyBar 10.0.1:
-- 16: LibCandyBar: (?s)-- LibCandyBarStart\R?\K.*?(?=-- LibCandyBarEnd)
local void, Leatrix_Plus = ...
----------------------------------------------------------------------
-- L11: LibDBIcon: LibStub
----------------------------------------------------------------------
local function LeaLibStub()
-- LibStubStart
-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local LibStub = _G[LIBSTUB_MAJOR]
-- Check to see is this version of the stub is obsolete
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
-- LibStub:NewLibrary(major, minor)
-- major (string) - the major version of the library
-- minor (string or number ) - the minor version of the library
--
-- returns nil if a newer or same version of the lib is already present
-- returns empty library object or old library object if upgrade is needed
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
-- LibStub:GetLibrary(major, [silent])
-- major (string) - the major version of the library
-- silent (boolean) - if true, library is optional, silently return nil if its not found
--
-- throws an error if the library can not be found (except silent is set)
-- returns the library object if found
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
-- LibStub:IterateLibraries()
--
-- Returns an iterator for the currently registered libraries
function LibStub:IterateLibraries()
return pairs(self.libs)
end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
-- LibStubEnd
end
LeaLibStub()
----------------------------------------------------------------------
-- L12: LibDBIcon: CallbackHandler
----------------------------------------------------------------------
local function LeaCallbackHandler()
-- CallbackStart
--[[ $Id: CallbackHandler-1.0.lua 26 2022-12-12 15:09:39Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 8
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
if not CallbackHandler then return end -- No upgrade needed
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-- Lua APIs
local securecallfunction, error = securecallfunction, error
local setmetatable, rawget = setmetatable, rawget
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
local function Dispatch(handlers, ...)
local index, method = next(handlers)
if not method then return end
repeat
securecallfunction(method, ...)
index, method = next(handlers, index)
until not method
end
--------------------------------------------------------------------------
-- CallbackHandler:New
--
-- target - target object to embed public APIs in
-- RegisterName - name of the callback registration API, default "RegisterCallback"
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName)
RegisterName = RegisterName or "RegisterCallback"
UnregisterName = UnregisterName or "UnregisterCallback"
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
UnregisterAllName = "UnregisterAllCallbacks"
end
-- we declare all objects and exported APIs inside this closure to quickly gain access
-- to e.g. function names, the "target" parameter, etc
-- Create the registry object
local events = setmetatable({}, meta)
local registry = { recurse=0, events=events }
-- registry:Fire() - fires the given event/message into the registry
function registry:Fire(eventname, ...)
if not rawget(events, eventname) or not next(events[eventname]) then return end
local oldrecurse = registry.recurse
registry.recurse = oldrecurse + 1
Dispatch(events[eventname], eventname, ...)
registry.recurse = oldrecurse
if registry.insertQueue and oldrecurse==0 then
-- Something in one of our callbacks wanted to register more callbacks; they got queued
for event,callbacks in pairs(registry.insertQueue) do
local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten.
for object,func in pairs(callbacks) do
events[event][object] = func
-- fire OnUsed callback?
if first and registry.OnUsed then
registry.OnUsed(registry, target, event)
first = nil
end
end
end
registry.insertQueue = nil
end
end
-- Registration of a callback, handles:
-- self["method"], leads to self["method"](self, ...)
-- self with function ref, leads to functionref(...)
-- "addonId" (instead of self) with function ref, leads to functionref(...)
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
if type(eventname) ~= "string" then
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
end
method = method or eventname
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
if type(method) ~= "string" and type(method) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
end
local regfunc
if type(method) == "string" then
-- self["method"] calling style
if type(self) ~= "table" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
elseif self==target then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
elseif type(self[method]) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId" or self=thread
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(arg,...) end
else
regfunc = method
end
end
if events[eventname][self] or registry.recurse<1 then
-- if registry.recurse<1 then
-- we're overwriting an existing entry, or not currently recursing. just set it.
events[eventname][self] = regfunc
-- fire OnUsed callback?
if registry.OnUsed and first then
registry.OnUsed(registry, target, eventname)
end
else
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
registry.insertQueue[eventname][self] = regfunc
end
end
-- Unregister a callback
target[UnregisterName] = function(self, eventname)
if not self or self==target then
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
end
if type(eventname) ~= "string" then
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
end
if rawget(events, eventname) and events[eventname][self] then
events[eventname][self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(events[eventname]) then
registry.OnUnused(registry, target, eventname)
end
end
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
registry.insertQueue[eventname][self] = nil
end
end
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
if UnregisterAllName then
target[UnregisterAllName] = function(...)
if select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
for i=1,select("#",...) do
local self = select(i,...)
if registry.insertQueue then
for eventname, callbacks in pairs(registry.insertQueue) do
if callbacks[self] then
callbacks[self] = nil
end
end
end
for eventname, callbacks in pairs(events) do
if callbacks[self] then
callbacks[self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(callbacks) then
registry.OnUnused(registry, target, eventname)
end
end
end
end
end
end
return registry
end
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
-- try to upgrade old implicit embeds since the system is selfcontained and
-- relies on closures to work.
-- CallbackEnd
end
LeaCallbackHandler()
----------------------------------------------------------------------
-- L13: LibDBIcon: LibDataBroker
----------------------------------------------------------------------
local function LeaDataBroker()
-- DataBrokerStart
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
if not lib then return end
oldminor = oldminor or 0
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
if oldminor < 2 then
lib.domt = {
__metatable = "access denied",
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
}
end
if oldminor < 3 then
lib.domt.__newindex = function(self, key, value)
if not attributestorage[self] then attributestorage[self] = {} end
if attributestorage[self][key] == value then return end
attributestorage[self][key] = value
local name = namestorage[self]
if not name then return end
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
end
end
if oldminor < 2 then
function lib:NewDataObject(name, dataobj)
if self.proxystorage[name] then return end
if dataobj then
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
self.attributestorage[dataobj] = {}
for i,v in pairs(dataobj) do
self.attributestorage[dataobj][i] = v
dataobj[i] = nil
end
end
dataobj = setmetatable(dataobj or {}, self.domt)
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
return dataobj
end
end
if oldminor < 1 then
function lib:DataObjectIterator()
return pairs(self.proxystorage)
end
function lib:GetDataObjectByName(dataobjectname)
return self.proxystorage[dataobjectname]
end
function lib:GetNameByDataObject(dataobject)
return self.namestorage[dataobject]
end
end
if oldminor < 4 then
local next = pairs(attributestorage)
function lib:pairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
return next, attributestorage[dataobj], nil
end
local ipairs_iter = ipairs(attributestorage)
function lib:ipairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
return ipairs_iter, attributestorage[dataobj], 0
end
end
-- DataBrokerEnd
end
LeaDataBroker()
----------------------------------------------------------------------
-- L14: LibDBIcon: LibDBIcon
----------------------------------------------------------------------
local function LeaLibDBIcon()
-- LibDBIconStart
--@curseforge-project-slug: libdbicon-1-0@
-----------------------------------------------------------------------
-- LibDBIcon-1.0
--
-- Allows addons to easily create a lightweight minimap icon as an alternative to heavier LDB displays.
--
local DBICON10 = "LibDBIcon-1.0"
local DBICON10_MINOR = 45 -- Bump on changes
if not LibStub then error(DBICON10 .. " requires LibStub.") end
local ldb = LibStub("LibDataBroker-1.1", true)
if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
if not lib then return end
lib.objects = lib.objects or {}
lib.callbackRegistered = lib.callbackRegistered or nil
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
lib.notCreated = lib.notCreated or {}
lib.radius = lib.radius or 5
local next, Minimap, CreateFrame = next, Minimap, CreateFrame
lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate")
local isDraggingButton = false
function lib:IconCallback(event, name, key, value)
if lib.objects[name] then
if key == "icon" then
lib.objects[name].icon:SetTexture(value)
elseif key == "iconCoords" then
lib.objects[name].icon:UpdateCoord()
elseif key == "iconR" then
local _, g, b = lib.objects[name].icon:GetVertexColor()
lib.objects[name].icon:SetVertexColor(value, g, b)
elseif key == "iconG" then
local r, _, b = lib.objects[name].icon:GetVertexColor()
lib.objects[name].icon:SetVertexColor(r, value, b)
elseif key == "iconB" then
local r, g = lib.objects[name].icon:GetVertexColor()
lib.objects[name].icon:SetVertexColor(r, g, value)
end
end
end
if not lib.callbackRegistered then
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback")
lib.callbackRegistered = true
end
local function getAnchors(frame)
local x, y = frame:GetCenter()
if not x or not y then return "CENTER" end
local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
end
local function onEnter(self)
if isDraggingButton then return end
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
local obj = self.dataObject
if obj.OnTooltipShow then
lib.tooltip:SetOwner(self, "ANCHOR_NONE")
lib.tooltip:SetPoint(getAnchors(self))
obj.OnTooltipShow(lib.tooltip)
lib.tooltip:Show()
elseif obj.OnEnter then
obj.OnEnter(self)
end
end
local function onLeave(self)
lib.tooltip:Hide()
if not isDraggingButton then
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Play()
end
end
end
local obj = self.dataObject
if obj.OnLeave then
obj.OnLeave(self)
end
end
--------------------------------------------------------------------------------
local onDragStart, updatePosition
do
local minimapShapes = {
["ROUND"] = {true, true, true, true},
["SQUARE"] = {false, false, false, false},
["CORNER-TOPLEFT"] = {false, false, false, true},
["CORNER-TOPRIGHT"] = {false, false, true, false},
["CORNER-BOTTOMLEFT"] = {false, true, false, false},
["CORNER-BOTTOMRIGHT"] = {true, false, false, false},
["SIDE-LEFT"] = {false, true, false, true},
["SIDE-RIGHT"] = {true, false, true, false},
["SIDE-TOP"] = {false, false, true, true},
["SIDE-BOTTOM"] = {true, true, false, false},
["TRICORNER-TOPLEFT"] = {false, true, true, true},
["TRICORNER-TOPRIGHT"] = {true, false, true, true},
["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false},
}
local rad, cos, sin, sqrt, max, min = math.rad, math.cos, math.sin, math.sqrt, math.max, math.min
function updatePosition(button, position)
local angle = rad(position or 225)
local x, y, q = cos(angle), sin(angle), 1
if x < 0 then q = q + 1 end
if y > 0 then q = q + 2 end
local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
local quadTable = minimapShapes[minimapShape]
local w = (Minimap:GetWidth() / 2) + lib.radius
local h = (Minimap:GetHeight() / 2) + lib.radius
if quadTable[q] then
x, y = x*w, y*h
else
local diagRadiusW = sqrt(2*(w)^2)-10
local diagRadiusH = sqrt(2*(h)^2)-10
x = max(-w, min(x*diagRadiusW, w))
y = max(-h, min(y*diagRadiusH, h))
end
button:SetPoint("CENTER", Minimap, "CENTER", x, y)
end
end
local function onClick(self, b)
if self.dataObject.OnClick then
self.dataObject.OnClick(self, b)
end
end
local function onMouseDown(self)
self.isMouseDown = true
self.icon:UpdateCoord()
end
local function onMouseUp(self)
self.isMouseDown = false
self.icon:UpdateCoord()
end
do
local deg, atan2 = math.deg, math.atan2
local function onUpdate(self)
local mx, my = Minimap:GetCenter()
local px, py = GetCursorPosition()
local scale = Minimap:GetEffectiveScale()
px, py = px / scale, py / scale
local pos = 225
if self.db then
pos = deg(atan2(py - my, px - mx)) % 360
self.db.minimapPos = pos
else
pos = deg(atan2(py - my, px - mx)) % 360
self.minimapPos = pos
end
updatePosition(self, pos)
end
function onDragStart(self)
self:LockHighlight()
self.isMouseDown = true
self.icon:UpdateCoord()
self:SetScript("OnUpdate", onUpdate)
isDraggingButton = true
lib.tooltip:Hide()
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
end
end
local function onDragStop(self)
self:SetScript("OnUpdate", nil)
self.isMouseDown = false
self.icon:UpdateCoord()
self:UnlockHighlight()
isDraggingButton = false
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Play()
end
end
end
local defaultCoords = {0, 1, 0, 1}
local function updateCoord(self)
local coords = self:GetParent().dataObject.iconCoords or defaultCoords
local deltaX, deltaY = 0, 0
if not self:GetParent().isMouseDown then
deltaX = (coords[2] - coords[1]) * 0.05
deltaY = (coords[4] - coords[3]) * 0.05
end
self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY)
end
local function createButton(name, object, db)
local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
button.dataObject = object
button.db = db
button:SetFrameStrata("MEDIUM")
-- button:SetFixedFrameStrata(true)
button:SetFrameLevel(8)
-- button:SetFixedFrameLevel(true)
button:SetSize(31, 31)
button:RegisterForClicks("anyUp")
button:RegisterForDrag("LeftButton")
button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight"
if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
local overlay = button:CreateTexture(nil, "OVERLAY")
overlay:SetSize(50, 50)
overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
overlay:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
local background = button:CreateTexture(nil, "BACKGROUND")
background:SetSize(24, 24)
background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
background:SetPoint("CENTER", button, "CENTER", 0, 1)
local icon = button:CreateTexture(nil, "ARTWORK")
icon:SetSize(18, 18)
icon:SetTexture(object.icon)
icon:SetPoint("CENTER", button, "CENTER", 0, 1)
button.icon = icon
else
local overlay = button:CreateTexture(nil, "OVERLAY")
overlay:SetSize(53, 53)
overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
overlay:SetPoint("TOPLEFT")
local background = button:CreateTexture(nil, "BACKGROUND")
background:SetSize(20, 20)
background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
background:SetPoint("TOPLEFT", 7, -5)
local icon = button:CreateTexture(nil, "ARTWORK")
icon:SetSize(17, 17)
icon:SetTexture(object.icon)
icon:SetPoint("TOPLEFT", 7, -6)
button.icon = icon
end
button.isMouseDown = false
local r, g, b = button.icon:GetVertexColor()
button.icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b)
button.icon.UpdateCoord = updateCoord
button.icon:UpdateCoord()
button:SetScript("OnEnter", onEnter)
button:SetScript("OnLeave", onLeave)
button:SetScript("OnClick", onClick)
if not db or not db.lock then
button:SetScript("OnDragStart", onDragStart)
button:SetScript("OnDragStop", onDragStop)
end
button:SetScript("OnMouseDown", onMouseDown)
button:SetScript("OnMouseUp", onMouseUp)
button.fadeOut = button:CreateAnimationGroup()
local animOut = button.fadeOut:CreateAnimation("Alpha")
-- animOut:SetOrder(1)
-- animOut:SetDuration(0.2)
-- animOut:SetFromAlpha(1)
-- animOut:SetToAlpha(0)
-- animOut:SetStartDelay(1)
-- button.fadeOut:SetToFinalAlpha(true)
lib.objects[name] = button
if lib.loggedIn then
updatePosition(button, db and db.minimapPos)
if not db or not db.hide then
button:Show()
else
button:Hide()
end
end
lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback
end
-- We could use a metatable.__index on lib.objects, but then we'd create
-- the icons when checking things like :IsRegistered, which is not necessary.
local function check(name)
if lib.notCreated[name] then
createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
lib.notCreated[name] = nil
end
end
-- Wait a bit with the initial positioning to let any GetMinimapShape addons
-- load up.
if not lib.loggedIn then
local f = CreateFrame("Frame")
f:SetScript("OnEvent", function(f)
for _, button in next, lib.objects do
updatePosition(button, button.db and button.db.minimapPos)
if not button.db or not button.db.hide then
button:Show()
else
button:Hide()
end
end
lib.loggedIn = true
f:SetScript("OnEvent", nil)
end)
f:RegisterEvent("PLAYER_LOGIN")
end
local function getDatabase(name)
return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db
end
function lib:Register(name, object, db)
if not object.icon then error("Can't register LDB objects without icons set!") end
if lib.objects[name] or lib.notCreated[name] then error(DBICON10.. ": Object '".. name .."' is already registered.") end
if not db or not db.hide then
createButton(name, object, db)
else
lib.notCreated[name] = {object, db}
end
end
function lib:Lock(name)
if not lib:IsRegistered(name) then return end
if lib.objects[name] then
lib.objects[name]:SetScript("OnDragStart", nil)
lib.objects[name]:SetScript("OnDragStop", nil)
end
local db = getDatabase(name)
if db then
db.lock = true
end
end
function lib:Unlock(name)
if not lib:IsRegistered(name) then return end
if lib.objects[name] then
lib.objects[name]:SetScript("OnDragStart", onDragStart)
lib.objects[name]:SetScript("OnDragStop", onDragStop)
end
local db = getDatabase(name)
if db then
db.lock = nil
end
end
function lib:Hide(name)
if not lib.objects[name] then return end
lib.objects[name]:Hide()
end
function lib:Show(name)
check(name)
local button = lib.objects[name]
if button then
button:Show()
updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
end
end
function lib:IsRegistered(name)
return (lib.objects[name] or lib.notCreated[name]) and true or false
end
function lib:Refresh(name, db)
check(name)
local button = lib.objects[name]
if db then
button.db = db
end
updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
if not button.db or not button.db.hide then
button:Show()
else
button:Hide()
end
if not button.db or not button.db.lock then
button:SetScript("OnDragStart", onDragStart)
button:SetScript("OnDragStop", onDragStop)
else
button:SetScript("OnDragStart", nil)
button:SetScript("OnDragStop", nil)
end
end
function lib:GetMinimapButton(name)
return lib.objects[name]
end
do
local function OnMinimapEnter()
if isDraggingButton then return end
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
end
local function OnMinimapLeave()
if isDraggingButton then return end
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Play()
end
end
end
Minimap:HookScript("OnEnter", OnMinimapEnter)
Minimap:HookScript("OnLeave", OnMinimapLeave)
function lib:ShowOnEnter(name, value)
local button = lib.objects[name]
if button then
if value then
button.showOnMouseover = true
button.fadeOut:Stop()
button:SetAlpha(0)
else
button.showOnMouseover = false
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
end
end
function lib:GetButtonList()
local t = {}
for name in next, lib.objects do
t[#t+1] = name
end
return t
end
function lib:SetButtonRadius(radius)
if type(radius) == "number" then
lib.radius = radius
for _, button in next, lib.objects do
updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
end
end
end
function lib:SetButtonToPosition(button, position)
updatePosition(lib.objects[button] or button, position)
end
-- Upgrade!
for name, button in next, lib.objects do
local db = getDatabase(name)
if not db or not db.lock then
button:SetScript("OnDragStart", onDragStart)
button:SetScript("OnDragStop", onDragStop)
end
button:SetScript("OnEnter", onEnter)
button:SetScript("OnLeave", onLeave)
button:SetScript("OnClick", onClick)
button:SetScript("OnMouseDown", onMouseDown)
button:SetScript("OnMouseUp", onMouseUp)
if not button.fadeOut then -- Upgrade to 39
button.fadeOut = button:CreateAnimationGroup()
local animOut = button.fadeOut:CreateAnimation("Alpha")
animOut:SetOrder(1)
animOut:SetDuration(0.2)
animOut:SetFromAlpha(1)
animOut:SetToAlpha(0)
animOut:SetStartDelay(1)
button.fadeOut:SetToFinalAlpha(true)
end
end
lib:SetButtonRadius(lib.radius) -- Upgrade to 40
-- LibDBIconEnd
end
-- LeaLibDBIcon() -- disabled in 3.3.5, was causing red things
----------------------------------------------------------------------
-- L15: LibChatAnims (load on demand)
----------------------------------------------------------------------
function Leatrix_Plus:LeaPlusLCA()
-- LibChatAnimsStart
--@curseforge-project-slug: libchatanims@
local MAJOR, MINOR = "LibChatAnims", 4 -- Bump minor on changes
local LCA = LibStub:NewLibrary(MAJOR, MINOR)
if not LCA then return end -- No upgrade needed
LCA.animations = LCA.animations or {} -- Animation storage
LCA.alerting = LCA.alerting or {} -- Chat tab alerting storage
local anims = LCA.animations
local alerting = LCA.alerting
function LCA:IsAlerting(tab)
if alerting[tab] then
return true
end
end
----------------------------------------------------
-- Note, most of this code is simply replicated from
-- Blizzard's FloatingChatFrame.lua file.
-- The only real changes are the creation and use
-- of animations vs the use of UIFrameFlash.
--
--FCFDockOverflowButton_UpdatePulseState = function(self)
-- local dock = self:GetParent()
-- local shouldPulse = false
-- for _, chatFrame in pairs(FCFDock_GetChatFrames(dock)) do
-- local chatTab = _G[chatFrame:GetName().."Tab"]
-- if ( not chatFrame.isStaticDocked and chatTab.alerting) then
-- -- Make sure the rects are valid. (Not always the case when resizing the WoW client
-- if ( not chatTab:GetRight() or not dock.scrollFrame:GetRight() ) then
-- return false
-- end
-- -- Check if it's off the screen.
-- local DELTA = 3 -- Chosen through experimentation
-- if ( chatTab:GetRight() < (dock.scrollFrame:GetLeft() + DELTA) or chatTab:GetLeft() > (dock.scrollFrame:GetRight() - DELTA) ) then
-- shouldPulse = true
-- break
-- end
-- end
-- end
--
-- local tex = self:GetHighlightTexture()
-- if shouldPulse then
-- if not anims[tex] then
-- anims[tex] = tex:CreateAnimationGroup()
--
-- local fade1 = anims[tex]:CreateAnimation("Alpha")
-- fade1:SetDuration(1)
-- fade1:SetFromAlpha(0)
-- fade1:SetToAlpha(1)
-- fade1:SetOrder(1)
--
-- local fade2 = anims[tex]:CreateAnimation("Alpha")
-- fade2:SetDuration(1)
-- fade2:SetFromAlpha(1)
-- fade2:SetToAlpha(0)
-- fade2:SetOrder(2)
-- end
-- tex:Show()
-- tex:SetAlpha(0)
-- anims[tex]:SetLooping("REPEAT")
-- anims[tex]:Play()
--
-- self:LockHighlight()
-- self.alerting = true
-- else
-- if anims[tex] then
-- anims[tex]:Stop()
-- end
-- self:UnlockHighlight()
-- tex:SetAlpha(1)
-- tex:Show()
-- self.alerting = false
-- end
--
-- if self.list:IsShown() then
-- FCFDockOverflowList_Update(self.list, dock)
-- end
-- return true
--end
--FCFDockOverflowListButton_SetValue = function(button, chatFrame)
-- local chatTab = _G[chatFrame:GetName().."Tab"]
-- button.chatFrame = chatFrame
-- button:SetText(chatFrame.name)
--
-- local colorTable = chatTab.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE
--
-- if chatTab.selectedColorTable then
-- button:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b)
-- else
-- button:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
-- end
--
-- button.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b)
--
-- if chatTab.conversationIcon then
-- button.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b)
-- button.conversationIcon:Show()
-- else
-- button.conversationIcon:Hide()
-- end
--
-- if chatTab.alerting then
-- button.alerting = true
-- if not anims[button.glow] then
-- anims[button.glow] = button.glow:CreateAnimationGroup()
--
-- local fade1 = anims[button.glow]:CreateAnimation("Alpha")
-- fade1:SetDuration(1)
-- fade1:SetFromAlpha(0)
-- fade1:SetToAlpha(1)
-- fade1:SetOrder(1)
--
-- local fade2 = anims[button.glow]:CreateAnimation("Alpha")
-- fade2:SetDuration(1)
-- fade2:SetFromAlpha(1)
-- fade2:SetToAlpha(0)
-- fade2:SetOrder(2)
-- end
-- button.glow:Show()
-- button.glow:SetAlpha(0)
-- anims[button.glow]:SetLooping("REPEAT")
-- anims[button.glow]:Play()
-- else
-- button.alerting = false
-- if anims[button.glow] then
-- anims[button.glow]:Stop()
-- end
-- button.glow:Hide()
-- end
-- button:Show()
--end
FCF_StartAlertFlash = function(chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"]
if chatFrame.minFrame then
if not anims[chatFrame.minFrame] then
anims[chatFrame.minFrame] = chatFrame.minFrame.glow:CreateAnimationGroup()
local fade1 = anims[chatFrame.minFrame]:CreateAnimation("Alpha")
fade1:SetDuration(1)
fade1:SetFromAlpha(0)
fade1:SetToAlpha(1)
fade1:SetOrder(1)
local fade2 = anims[chatFrame.minFrame]:CreateAnimation("Alpha")
fade2:SetDuration(1)
fade2:SetFromAlpha(1)
fade2:SetToAlpha(0)
fade2:SetOrder(2)
end
chatFrame.minFrame.glow:Show()
chatFrame.minFrame.glow:SetAlpha(0)
anims[chatFrame.minFrame]:SetLooping("REPEAT")
anims[chatFrame.minFrame]:Play()
--chatFrame.minFrame.alerting = true
alerting[chatFrame.minFrame] = true
end
if not anims[chatTab.glow] then
anims[chatTab.glow] = chatTab.glow:CreateAnimationGroup()
local fade1 = anims[chatTab.glow]:CreateAnimation("Alpha")
fade1:SetDuration(1)
fade1:SetFromAlpha(0)
fade1:SetToAlpha(1)
fade1:SetOrder(1)
local fade2 = anims[chatTab.glow]:CreateAnimation("Alpha")
fade2:SetDuration(1)
fade2:SetFromAlpha(1)
fade2:SetToAlpha(0)
fade2:SetOrder(2)
end
chatTab.glow:Show()
chatTab.glow:SetAlpha(0)
anims[chatTab.glow]:SetLooping("REPEAT")
anims[chatTab.glow]:Play()
--chatTab.alerting = true
alerting[chatTab] = true
-- START function FCFTab_UpdateAlpha(chatFrame)
local mouseOverAlpha, noMouseAlpha = 0, 0
if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then
mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA
noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA
else
mouseOverAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_MOUSEOVER_ALPHA
noMouseAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_NOMOUSE_ALPHA
end
if chatFrame.hasBeenFaded then
chatTab:SetAlpha(mouseOverAlpha)
else
chatTab:SetAlpha(noMouseAlpha)
end
--END function FCFTab_UpdateAlpha(chatFrame)
--FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton)
end
FCF_StopAlertFlash = function(chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"]
if chatFrame.minFrame then
if anims[chatFrame.minFrame] then
anims[chatFrame.minFrame]:Stop()
end
chatFrame.minFrame.glow:Hide()
--chatFrame.minFrame.alerting = false
alerting[chatFrame.minFrame] = nil
end
if anims[chatTab.glow] then
anims[chatTab.glow]:Stop()
end
chatTab.glow:Hide()
--chatTab.alerting = false
alerting[chatTab] = nil
-- START function FCFTab_UpdateAlpha(chatFrame)
local mouseOverAlpha, noMouseAlpha = 0, 0
if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then
mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA
noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA
else
mouseOverAlpha = 0.6 --CHAT_FRAME_TAB_NORMAL_MOUSEOVER_ALPHA
noMouseAlpha = 0.2 --CHAT_FRAME_TAB_NORMAL_NOMOUSE_ALPHA
end
if chatFrame.hasBeenFaded then
chatTab:SetAlpha(mouseOverAlpha)
else
chatTab:SetAlpha(noMouseAlpha)
end
--END function FCFTab_UpdateAlpha(chatFrame)
--FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton)
end
-- LibChatAnimsEnd
end
----------------------------------------------------------------------
-- L16: LibDBIcon: LibCandyBar
----------------------------------------------------------------------
function Leatrix_Plus:LeaPlusCandyBar()
-- LibCandyBarStart
--@curseforge-project-slug: libcandybar-3-0@
--- **LibCandyBar-3.0** provides elegant timerbars with icons for use in addons.
-- It is based of the original ideas of the CandyBar and CandyBar-2.0 library.
-- In contrary to the earlier libraries LibCandyBar-3.0 provides you with a timerbar object with a simple API.
--
-- Creating a new timerbar using the ':New' function will return a new timerbar object. This timerbar object inherits all of the barPrototype functions listed here. \\
--
-- @usage
-- local candy = LibStub("LibCandyBar-3.0")
-- local texture = "Interface\\AddOns\\MyAddOn\\statusbar"
-- local mybar = candy:New(texture, 100, 16)
-- mybar:SetLabel("Yay!")
-- mybar:SetDuration(60)
-- mybar:Start()
-- @class file
-- @name LibCandyBar-3.0
local GetTime, floor, next = GetTime, floor, next
local CreateFrame, error, setmetatable, UIParent = CreateFrame, error, setmetatable, UIParent
if not LibStub then error("LibCandyBar-3.0 requires LibStub.") end
local cbh = LibStub:GetLibrary("CallbackHandler-1.0")
if not cbh then error("LibCandyBar-3.0 requires CallbackHandler-1.0") end
local lib = LibStub:NewLibrary("LibCandyBar-3.0", 100) -- Bump minor on changes
if not lib then return end
lib.callbacks = lib.callbacks or cbh:New(lib)
local cb = lib.callbacks
lib.dummyFrame = lib.dummyFrame or CreateFrame("Frame")
lib.barFrameMT = lib.barFrameMT or {__index = lib.dummyFrame}
lib.barPrototype = lib.barPrototype or setmetatable({}, lib.barFrameMT)
lib.barPrototype_mt = lib.barPrototype_mt or {__index = lib.barPrototype}
lib.barCache = lib.barCache or {}
local barPrototype = lib.barPrototype
local barPrototype_meta = lib.barPrototype_mt
local barCache = lib.barCache
local scripts = {
"OnUpdate", "OnDragStart", "OnDragStop",
"OnEnter", "OnLeave", "OnHide",
"OnShow", "OnMouseDown", "OnMouseUp",
"OnMouseWheel", "OnSizeChanged", "OnEvent"
}
local numScripts = #scripts
local GameFontHighlightSmallOutline = GameFontHighlightSmallOutline
local _fontName, _fontSize = GameFontHighlightSmallOutline:GetFont()
local _fontShadowX, _fontShadowY = GameFontHighlightSmallOutline:GetShadowOffset()
local _fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA = GameFontHighlightSmallOutline:GetShadowColor()
local SetWidth, SetHeight, SetSize = lib.dummyFrame.SetWidth, lib.dummyFrame.SetHeight, lib.dummyFrame.SetSize
local function stopBar(bar)
bar.updater:Stop()
bar.data = nil
bar.funcs = nil
bar.running = nil
bar.paused = nil
bar:Hide()
bar:SetParent(UIParent)
end
local tformat1 = "%d:%02d:%02d"
local tformat2 = "%d:%02d"
local tformat3 = "%.1f"
local tformat4 = "%.0f"
local function barUpdate(updater)
local bar = updater.parent
local t = GetTime()
if t >= bar.exp then
bar:Stop()
else
local time = bar.exp - t
bar.remaining = time
bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time)
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
bar.candyBarDuration:SetFormattedText(tformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
bar.candyBarDuration:SetFormattedText(tformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
bar.candyBarDuration:SetFormattedText(tformat3, time)
else -- 10 seconds to one minute
bar.candyBarDuration:SetFormattedText(tformat4, time)
end
if bar.funcs then
for i = 1, #bar.funcs do
bar.funcs[i](bar)
end
end
end
end
local atformat1 = "~%d:%02d:%02d"
local atformat2 = "~%d:%02d"
local atformat3 = "~%.1f"
local atformat4 = "~%.0f"
local function barUpdateApprox(updater)
local bar = updater.parent
local t = GetTime()
if t >= bar.exp then
bar:Stop()
else
local time = bar.exp - t
bar.remaining = time
bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time)
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
bar.candyBarDuration:SetFormattedText(atformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
bar.candyBarDuration:SetFormattedText(atformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
bar.candyBarDuration:SetFormattedText(atformat3, time)
else -- 10 seconds to one minute
bar.candyBarDuration:SetFormattedText(atformat4, time)
end
if bar.funcs then
for i = 1, #bar.funcs do
bar.funcs[i](bar)
end
end
end
end
-- ------------------------------------------------------------------------------
-- Bar functions
--
local function restyleBar(self)
if not self.running then return end
self.candyBarIconFrame:ClearAllPoints()
self.candyBarBar:ClearAllPoints()
-- In the past we used a :GetTexture check here, but as of WoW v5 it randomly returns nil, so use our own trustworthy variable.
if self.candyBarIconFrame.icon then
self.candyBarIconFrame:SetWidth(self.height)
if self.iconPosition == "RIGHT" then
self.candyBarIconFrame:SetPoint("TOPRIGHT", self)
self.candyBarIconFrame:SetPoint("BOTTOMRIGHT", self)
self.candyBarBar:SetPoint("TOPRIGHT", self.candyBarIconFrame, "TOPLEFT")
self.candyBarBar:SetPoint("BOTTOMRIGHT", self.candyBarIconFrame, "BOTTOMLEFT")
self.candyBarBar:SetPoint("TOPLEFT", self)
self.candyBarBar:SetPoint("BOTTOMLEFT", self)
else
self.candyBarIconFrame:SetPoint("TOPLEFT")
self.candyBarIconFrame:SetPoint("BOTTOMLEFT")
self.candyBarBar:SetPoint("TOPLEFT", self.candyBarIconFrame, "TOPRIGHT")
self.candyBarBar:SetPoint("BOTTOMLEFT", self.candyBarIconFrame, "BOTTOMRIGHT")
self.candyBarBar:SetPoint("TOPRIGHT", self)
self.candyBarBar:SetPoint("BOTTOMRIGHT", self)
end
self.candyBarIconFrame:Show()
else
self.candyBarBar:SetPoint("TOPLEFT", self)
self.candyBarBar:SetPoint("BOTTOMRIGHT", self)
self.candyBarIconFrame:Hide()
end
if self.showLabel and self.candyBarLabel.text then
self.candyBarLabel:Show()
else
self.candyBarLabel:Hide()
end
if self.showTime then
self.candyBarDuration:Show()
else
self.candyBarDuration:Hide()
end
end
--- Set whether the bar should drain (default) or fill up.
-- @param fill Boolean true/false
function barPrototype:SetFill(fill)
self.fill = fill
end
--- Adds a function to the timerbar. The function will run every update and will receive the bar as a parameter.
-- @param func Function to run every update.
-- @usage
-- -- The example below will print the time remaining to the chatframe every update. Yes, that's a whole lot of spam
-- mybar:AddUpdateFunction( function(bar) print(bar.remaining) end )
function barPrototype:AddUpdateFunction(func) if not self.funcs then self.funcs = {} end; self.funcs[#self.funcs+1] = func end
--- Sets user data in the timerbar object.
-- @param key Key to use for the data storage.
-- @param data Data to store.
function barPrototype:Set(key, data) if not self.data then self.data = {} end; self.data[key] = data end
--- Retrieves user data from the timerbar object.
-- @param key Key to retrieve
function barPrototype:Get(key) return self.data and self.data[key] end
--- Sets the color of the bar.
-- This is basically a wrapper to SetStatusBarColor.
-- @paramsig r, g, b, a
-- @param r Red component (0-1)
-- @param g Green component (0-1)
-- @param b Blue component (0-1)
-- @param a Alpha (0-1)
function barPrototype:SetColor(...) self.candyBarBar:SetStatusBarColor(...) end
--- Sets the color of the bar label and bar duration text.
-- @paramsig r, g, b, a
-- @param r Red component (0-1)
-- @param g Green component (0-1)
-- @param b Blue component (0-1)
-- @param a Alpha (0-1)
function barPrototype:SetTextColor(...)
self.candyBarLabel:SetTextColor(...)
self.candyBarDuration:SetTextColor(...)
end
--- Sets the shadow color of the bar label and bar duration text.
-- @paramsig r, g, b, a
-- @param r Red component (0-1)
-- @param g Green component (0-1)
-- @param b Blue component (0-1)
-- @param a Alpha (0-1)
function barPrototype:SetShadowColor(...)
self.candyBarLabel:SetShadowColor(...)
self.candyBarDuration:SetShadowColor(...)
end
--- Sets the texture of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param texture Path to the bar texture.
function barPrototype:SetTexture(texture)
self.candyBarBar:SetStatusBarTexture(texture)
self.candyBarBackground:SetTexture(texture)
end
--- Sets the width of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param width Width of the bar.
function barPrototype:SetWidth(width)
self.width = width
SetWidth(self, width)
end
--- Sets the height of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param height Height of the bar.
function barPrototype:SetHeight(height)
self.height = height
SetHeight(self, height)
restyleBar(self)
end
--- Sets the size of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param width Width of the bar.
-- @param height Height of the bar.
function barPrototype:SetSize(width, height)
self.width = width
self.height = height
SetSize(self, width, height)
restyleBar(self)
end
--- Returns the label (text) currently set on the bar.
function barPrototype:GetLabel()
return self.candyBarLabel.text
end
--- Sets the label on the bar.
-- @param text Label text.
function barPrototype:SetLabel(text)
self.candyBarLabel.text = text
self.candyBarLabel:SetText(text)
if text then
self.candyBarLabel:Show()
else
self.candyBarLabel:Hide()
end
end
--- Returns the icon texture path currently set on the bar, if it has an icon set.
function barPrototype:GetIcon()
return self.candyBarIconFrame.icon
end
--- Sets the icon next to the bar.
-- @param icon Path to the icon texture or nil to not display an icon.
-- @param ... Optional icon coordinates for texture trimming.
function barPrototype:SetIcon(icon, ...)
self.candyBarIconFrame.icon = icon
self.candyBarIconFrame:SetTexture(icon)
if ... then
self.candyBarIconFrame:SetTexCoord(...)
else
self.candyBarIconFrame:SetTexCoord(0.07, 0.93, 0.07, 0.93)
end
restyleBar(self)
end
--- Sets which side of the bar the icon should appear.
-- @param position Position of the icon according to the bar, either "LEFT" or "RIGHT" as a string. Set to "LEFT" by default.
function barPrototype:SetIconPosition(position)
self.iconPosition = position
restyleBar(self)
end
--- Sets wether or not the time indicator on the right of the bar should be shown.
-- Time is shown by default.
-- @param bool true to show the time, false/nil to hide the time.
function barPrototype:SetTimeVisibility(bool)
self.showTime = bool
if bool then
self.candyBarDuration:Show()
else
self.candyBarDuration:Hide()
end
end
--- Sets wether or not the label on the left of the bar should be shown.
-- label is shown by default.
-- @param bool true to show the label, false/nil to hide the label.
function barPrototype:SetLabelVisibility(bool)
self.showLabel = bool
if bool then
self.candyBarLabel:Show()
else
self.candyBarLabel:Hide()
end
end
--- Sets the duration of the bar.
-- This can also be used while the bar is running to adjust the time remaining, within the bounds of the original duration.
-- @param duration Duration of the bar in seconds.
-- @param isApprox Boolean. True if you wish the time display to be an approximate "~5" instead of "5"
function barPrototype:SetDuration(duration, isApprox) self.remaining = duration; self.isApproximate = isApprox end
--- Shows the bar and starts it.
-- @param maxValue Number. If you don't wish your bar to start full, you can set a max value. A maxValue of 10 on a bar with a duration of 5 would start it at 50%.
function barPrototype:Start(maxValue)
self.running = true
local time = self.remaining
self.gap = maxValue and maxValue-time or 0
restyleBar(self)
self.start = GetTime()
self.exp = self.start + time
self.candyBarBar:SetMinMaxValues(0, maxValue or time)
self.candyBarBar:SetValue(self.fill and 0 or time)
if self.isApproximate then
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
self.candyBarDuration:SetFormattedText(atformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
self.candyBarDuration:SetFormattedText(atformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
self.candyBarDuration:SetFormattedText(atformat3, time)
else -- 10 seconds to one minute
self.candyBarDuration:SetFormattedText(atformat4, time)
end
self.updater:SetScript("OnLoop", barUpdateApprox)
else
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
self.candyBarDuration:SetFormattedText(tformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
self.candyBarDuration:SetFormattedText(tformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
self.candyBarDuration:SetFormattedText(tformat3, time)
else -- 10 seconds to one minute
self.candyBarDuration:SetFormattedText(tformat4, time)
end
self.updater:SetScript("OnLoop", barUpdate)
end
self.updater:Play()
self:Show()
end
--- Pauses a running bar
function barPrototype:Pause()
if not self.paused then
self.updater:Pause()
self.paused = GetTime()
end
end
--- Resumes a paused bar
function barPrototype:Resume()
if self.paused then
local t = GetTime()
self.exp = t + self.remaining
self.start = self.start + (t-self.paused)
self.updater:Play()
self.paused = nil
end
end
--- Stops the bar.
-- This will stop the bar, fire the LibCandyBar_Stop callback, and recycle the bar into the candybar pool.
-- Note: make sure you remove all references to the bar in your addon upon receiving the LibCandyBar_Stop callback.
-- @usage
-- -- The example below shows the use of the LibCandyBar_Stop callback by printing the contents of the label in the chatframe
-- local function barstopped( callback, bar )
-- print( bar:GetLabel(), "stopped")
-- end
-- LibStub("LibCandyBar-3.0"):RegisterCallback(myaddonobject, "LibCandyBar_Stop", barstopped)
-- @param ... Optional args to pass across in the LibCandyBar_Stop callback.
function barPrototype:Stop(...)
cb:Fire("LibCandyBar_Stop", self, ...)
stopBar(self)
barCache[self] = true
end
-- ------------------------------------------------------------------------------
-- Library functions
--
--- Creates a new timerbar object and returns it. Don't forget to set the duration, label and :Start the timer bar after you get a hold of it!
-- @paramsig texture, width, height
-- @param texture Path to the texture used for the bar.
-- @param width Width of the bar.
-- @param height Height of the bar.
-- @usage
-- mybar = LibStub("LibCandyBar-3.0"):New("Interface\\AddOns\\MyAddOn\\media\\statusbar", 100, 16)
function lib:New(texture, width, height)
local bar = next(barCache)
if not bar then
local frame = CreateFrame("Frame", nil, UIParent)
bar = setmetatable(frame, barPrototype_meta)
local icon = bar:CreateTexture()
icon:SetPoint("TOPLEFT")
icon:SetPoint("BOTTOMLEFT")
icon:Show()
bar.candyBarIconFrame = icon
local statusbar = CreateFrame("StatusBar", nil, bar)
statusbar:SetPoint("TOPRIGHT")
statusbar:SetPoint("BOTTOMRIGHT")
bar.candyBarBar = statusbar
local bg = statusbar:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints()
bar.candyBarBackground = bg
local backdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops
backdrop:SetFrameLevel(0)
bar.candyBarBackdrop = backdrop
local iconBackdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops
iconBackdrop:SetFrameLevel(0)
bar.candyBarIconFrameBackdrop = iconBackdrop
local duration = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline")
duration:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0)
duration:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0)
bar.candyBarDuration = duration
local label = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline")
label:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0)
label:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0)
bar.candyBarLabel = label
local updater = bar:CreateAnimationGroup()
updater:SetLooping("REPEAT")
updater.parent = bar
local anim = updater:CreateAnimation()
anim:SetDuration(0.04)
bar.updater = updater
bar.repeater = anim
else
barCache[bar] = nil
end
bar:SetFrameStrata("MEDIUM")
bar:SetFrameLevel(100) -- Lots of room to create above or below this level
bar.candyBarBar:SetStatusBarTexture(texture)
bar.candyBarBackground:SetTexture(texture)
bar.width = width
bar.height = height
-- RESET ALL THE THINGS!
bar.fill = nil
bar.showTime = true
bar.showLabel = true
bar.iconPosition = nil
for i = 1, numScripts do -- Update if scripts table is changed, faster than doing #scripts
bar:SetScript(scripts[i], nil)
end
bar.candyBarBackground:SetVertexColor(0.5, 0.5, 0.5, 0.3)
bar.candyBarBar:SetStatusBarColor(0.5, 0.5, 0.5, 1)
bar:ClearAllPoints()
SetWidth(bar, width)
SetHeight(bar, height)
bar:SetMovable(1)
bar:SetScale(1)
bar:SetAlpha(1)
bar:SetClampedToScreen(false)
bar:EnableMouse(false)
bar.candyBarLabel:SetTextColor(1,1,1,1)
bar.candyBarLabel:SetJustifyH("LEFT")
bar.candyBarLabel:SetJustifyV("MIDDLE")
bar.candyBarLabel:SetFont(_fontName, _fontSize)
bar.candyBarLabel:SetShadowOffset(_fontShadowX, _fontShadowY)
bar.candyBarLabel:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA)
bar.candyBarDuration:SetTextColor(1,1,1,1)
bar.candyBarDuration:SetJustifyH("RIGHT")
bar.candyBarDuration:SetJustifyV("MIDDLE")
bar.candyBarDuration:SetFont(_fontName, _fontSize)
bar.candyBarDuration:SetShadowOffset(_fontShadowX, _fontShadowY)
bar.candyBarDuration:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA)
bar:SetLabel()
bar:SetIcon()
bar:SetDuration()
return bar
end
-- LibCandyBarEnd
end
-- L17: End
=======
----------------------------------------------------------------------
-- L00: Leatrix Plus Library
----------------------------------------------------------------------
-- LibDBIcon 10.0.1:
-- 11: LibStub: (?s)-- LibStubStart\R?\K.*?(?=-- LibStubEnd)
-- 12: LibCallbackHandler: (?s)-- CallbackStart\R?\K.*?(?=-- CallbackEnd)
-- 13: LibDataBroker: (?s)-- DataBrokerStart\R?\K.*?(?=-- DataBrokerEnd)
-- 14: LibDBIcon: (?s)-- LibDBIconStart\R?\K.*?(?=-- LibDBIconEnd)
-- LibChatAnims 10.0.1:
-- 15: LibChatAnims: (?s)-- LibChatAnimsStart\R?\K.*?(?=-- LibChatAnimsEnd)
-- LibCandyBar 10.0.1:
-- 16: LibCandyBar: (?s)-- LibCandyBarStart\R?\K.*?(?=-- LibCandyBarEnd)
local void, Leatrix_Plus = ...
----------------------------------------------------------------------
-- L11: LibDBIcon: LibStub
----------------------------------------------------------------------
local function LeaLibStub()
-- LibStubStart
-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local LibStub = _G[LIBSTUB_MAJOR]
-- Check to see is this version of the stub is obsolete
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
-- LibStub:NewLibrary(major, minor)
-- major (string) - the major version of the library
-- minor (string or number ) - the minor version of the library
--
-- returns nil if a newer or same version of the lib is already present
-- returns empty library object or old library object if upgrade is needed
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
-- LibStub:GetLibrary(major, [silent])
-- major (string) - the major version of the library
-- silent (boolean) - if true, library is optional, silently return nil if its not found
--
-- throws an error if the library can not be found (except silent is set)
-- returns the library object if found
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
-- LibStub:IterateLibraries()
--
-- Returns an iterator for the currently registered libraries
function LibStub:IterateLibraries()
return pairs(self.libs)
end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
-- LibStubEnd
end
LeaLibStub()
----------------------------------------------------------------------
-- L12: LibDBIcon: CallbackHandler
----------------------------------------------------------------------
local function LeaCallbackHandler()
-- CallbackStart
--[[ $Id: CallbackHandler-1.0.lua 26 2022-12-12 15:09:39Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 8
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
if not CallbackHandler then return end -- No upgrade needed
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-- Lua APIs
local securecallfunction, error = securecallfunction, error
local setmetatable, rawget = setmetatable, rawget
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
local function Dispatch(handlers, ...)
local index, method = next(handlers)
if not method then return end
repeat
securecallfunction(method, ...)
index, method = next(handlers, index)
until not method
end
--------------------------------------------------------------------------
-- CallbackHandler:New
--
-- target - target object to embed public APIs in
-- RegisterName - name of the callback registration API, default "RegisterCallback"
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName)
RegisterName = RegisterName or "RegisterCallback"
UnregisterName = UnregisterName or "UnregisterCallback"
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
UnregisterAllName = "UnregisterAllCallbacks"
end
-- we declare all objects and exported APIs inside this closure to quickly gain access
-- to e.g. function names, the "target" parameter, etc
-- Create the registry object
local events = setmetatable({}, meta)
local registry = { recurse=0, events=events }
-- registry:Fire() - fires the given event/message into the registry
function registry:Fire(eventname, ...)
if not rawget(events, eventname) or not next(events[eventname]) then return end
local oldrecurse = registry.recurse
registry.recurse = oldrecurse + 1
Dispatch(events[eventname], eventname, ...)
registry.recurse = oldrecurse
if registry.insertQueue and oldrecurse==0 then
-- Something in one of our callbacks wanted to register more callbacks; they got queued
for event,callbacks in pairs(registry.insertQueue) do
local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten.
for object,func in pairs(callbacks) do
events[event][object] = func
-- fire OnUsed callback?
if first and registry.OnUsed then
registry.OnUsed(registry, target, event)
first = nil
end
end
end
registry.insertQueue = nil
end
end
-- Registration of a callback, handles:
-- self["method"], leads to self["method"](self, ...)
-- self with function ref, leads to functionref(...)
-- "addonId" (instead of self) with function ref, leads to functionref(...)
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
if type(eventname) ~= "string" then
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
end
method = method or eventname
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
if type(method) ~= "string" and type(method) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
end
local regfunc
if type(method) == "string" then
-- self["method"] calling style
if type(self) ~= "table" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
elseif self==target then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
elseif type(self[method]) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId" or self=thread
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(arg,...) end
else
regfunc = method
end
end
if events[eventname][self] or registry.recurse<1 then
-- if registry.recurse<1 then
-- we're overwriting an existing entry, or not currently recursing. just set it.
events[eventname][self] = regfunc
-- fire OnUsed callback?
if registry.OnUsed and first then
registry.OnUsed(registry, target, eventname)
end
else
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
registry.insertQueue[eventname][self] = regfunc
end
end
-- Unregister a callback
target[UnregisterName] = function(self, eventname)
if not self or self==target then
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
end
if type(eventname) ~= "string" then
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
end
if rawget(events, eventname) and events[eventname][self] then
events[eventname][self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(events[eventname]) then
registry.OnUnused(registry, target, eventname)
end
end
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
registry.insertQueue[eventname][self] = nil
end
end
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
if UnregisterAllName then
target[UnregisterAllName] = function(...)
if select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
for i=1,select("#",...) do
local self = select(i,...)
if registry.insertQueue then
for eventname, callbacks in pairs(registry.insertQueue) do
if callbacks[self] then
callbacks[self] = nil
end
end
end
for eventname, callbacks in pairs(events) do
if callbacks[self] then
callbacks[self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(callbacks) then
registry.OnUnused(registry, target, eventname)
end
end
end
end
end
end
return registry
end
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
-- try to upgrade old implicit embeds since the system is selfcontained and
-- relies on closures to work.
-- CallbackEnd
end
LeaCallbackHandler()
----------------------------------------------------------------------
-- L13: LibDBIcon: LibDataBroker
----------------------------------------------------------------------
local function LeaDataBroker()
-- DataBrokerStart
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
if not lib then return end
oldminor = oldminor or 0
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
if oldminor < 2 then
lib.domt = {
__metatable = "access denied",
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
}
end
if oldminor < 3 then
lib.domt.__newindex = function(self, key, value)
if not attributestorage[self] then attributestorage[self] = {} end
if attributestorage[self][key] == value then return end
attributestorage[self][key] = value
local name = namestorage[self]
if not name then return end
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
end
end
if oldminor < 2 then
function lib:NewDataObject(name, dataobj)
if self.proxystorage[name] then return end
if dataobj then
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
self.attributestorage[dataobj] = {}
for i,v in pairs(dataobj) do
self.attributestorage[dataobj][i] = v
dataobj[i] = nil
end
end
dataobj = setmetatable(dataobj or {}, self.domt)
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
return dataobj
end
end
if oldminor < 1 then
function lib:DataObjectIterator()
return pairs(self.proxystorage)
end
function lib:GetDataObjectByName(dataobjectname)
return self.proxystorage[dataobjectname]
end
function lib:GetNameByDataObject(dataobject)
return self.namestorage[dataobject]
end
end
if oldminor < 4 then
local next = pairs(attributestorage)
function lib:pairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
return next, attributestorage[dataobj], nil
end
local ipairs_iter = ipairs(attributestorage)
function lib:ipairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
return ipairs_iter, attributestorage[dataobj], 0
end
end
-- DataBrokerEnd
end
LeaDataBroker()
----------------------------------------------------------------------
-- L14: LibDBIcon: LibDBIcon
----------------------------------------------------------------------
local function LeaLibDBIcon()
-- LibDBIconStart
--@curseforge-project-slug: libdbicon-1-0@
-----------------------------------------------------------------------
-- LibDBIcon-1.0
--
-- Allows addons to easily create a lightweight minimap icon as an alternative to heavier LDB displays.
--
local DBICON10 = "LibDBIcon-1.0"
local DBICON10_MINOR = 45 -- Bump on changes
if not LibStub then error(DBICON10 .. " requires LibStub.") end
local ldb = LibStub("LibDataBroker-1.1", true)
if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
if not lib then return end
lib.objects = lib.objects or {}
lib.callbackRegistered = lib.callbackRegistered or nil
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
lib.notCreated = lib.notCreated or {}
lib.radius = lib.radius or 5
local next, Minimap, CreateFrame = next, Minimap, CreateFrame
lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate")
local isDraggingButton = false
function lib:IconCallback(event, name, key, value)
if lib.objects[name] then
if key == "icon" then
lib.objects[name].icon:SetTexture(value)
elseif key == "iconCoords" then
lib.objects[name].icon:UpdateCoord()
elseif key == "iconR" then
local _, g, b = lib.objects[name].icon:GetVertexColor()
lib.objects[name].icon:SetVertexColor(value, g, b)
elseif key == "iconG" then
local r, _, b = lib.objects[name].icon:GetVertexColor()
lib.objects[name].icon:SetVertexColor(r, value, b)
elseif key == "iconB" then
local r, g = lib.objects[name].icon:GetVertexColor()
lib.objects[name].icon:SetVertexColor(r, g, value)
end
end
end
if not lib.callbackRegistered then
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback")
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback")
lib.callbackRegistered = true
end
local function getAnchors(frame)
local x, y = frame:GetCenter()
if not x or not y then return "CENTER" end
local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
end
local function onEnter(self)
if isDraggingButton then return end
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
local obj = self.dataObject
if obj.OnTooltipShow then
lib.tooltip:SetOwner(self, "ANCHOR_NONE")
lib.tooltip:SetPoint(getAnchors(self))
obj.OnTooltipShow(lib.tooltip)
lib.tooltip:Show()
elseif obj.OnEnter then
obj.OnEnter(self)
end
end
local function onLeave(self)
lib.tooltip:Hide()
if not isDraggingButton then
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Play()
end
end
end
local obj = self.dataObject
if obj.OnLeave then
obj.OnLeave(self)
end
end
--------------------------------------------------------------------------------
local onDragStart, updatePosition
do
local minimapShapes = {
["ROUND"] = {true, true, true, true},
["SQUARE"] = {false, false, false, false},
["CORNER-TOPLEFT"] = {false, false, false, true},
["CORNER-TOPRIGHT"] = {false, false, true, false},
["CORNER-BOTTOMLEFT"] = {false, true, false, false},
["CORNER-BOTTOMRIGHT"] = {true, false, false, false},
["SIDE-LEFT"] = {false, true, false, true},
["SIDE-RIGHT"] = {true, false, true, false},
["SIDE-TOP"] = {false, false, true, true},
["SIDE-BOTTOM"] = {true, true, false, false},
["TRICORNER-TOPLEFT"] = {false, true, true, true},
["TRICORNER-TOPRIGHT"] = {true, false, true, true},
["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false},
}
local rad, cos, sin, sqrt, max, min = math.rad, math.cos, math.sin, math.sqrt, math.max, math.min
function updatePosition(button, position)
local angle = rad(position or 225)
local x, y, q = cos(angle), sin(angle), 1
if x < 0 then q = q + 1 end
if y > 0 then q = q + 2 end
local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
local quadTable = minimapShapes[minimapShape]
local w = (Minimap:GetWidth() / 2) + lib.radius
local h = (Minimap:GetHeight() / 2) + lib.radius
if quadTable[q] then
x, y = x*w, y*h
else
local diagRadiusW = sqrt(2*(w)^2)-10
local diagRadiusH = sqrt(2*(h)^2)-10
x = max(-w, min(x*diagRadiusW, w))
y = max(-h, min(y*diagRadiusH, h))
end
button:SetPoint("CENTER", Minimap, "CENTER", x, y)
end
end
local function onClick(self, b)
if self.dataObject.OnClick then
self.dataObject.OnClick(self, b)
end
end
local function onMouseDown(self)
self.isMouseDown = true
self.icon:UpdateCoord()
end
local function onMouseUp(self)
self.isMouseDown = false
self.icon:UpdateCoord()
end
do
local deg, atan2 = math.deg, math.atan2
local function onUpdate(self)
local mx, my = Minimap:GetCenter()
local px, py = GetCursorPosition()
local scale = Minimap:GetEffectiveScale()
px, py = px / scale, py / scale
local pos = 225
if self.db then
pos = deg(atan2(py - my, px - mx)) % 360
self.db.minimapPos = pos
else
pos = deg(atan2(py - my, px - mx)) % 360
self.minimapPos = pos
end
updatePosition(self, pos)
end
function onDragStart(self)
self:LockHighlight()
self.isMouseDown = true
self.icon:UpdateCoord()
self:SetScript("OnUpdate", onUpdate)
isDraggingButton = true
lib.tooltip:Hide()
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
end
end
local function onDragStop(self)
self:SetScript("OnUpdate", nil)
self.isMouseDown = false
self.icon:UpdateCoord()
self:UnlockHighlight()
isDraggingButton = false
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Play()
end
end
end
local defaultCoords = {0, 1, 0, 1}
local function updateCoord(self)
local coords = self:GetParent().dataObject.iconCoords or defaultCoords
local deltaX, deltaY = 0, 0
if not self:GetParent().isMouseDown then
deltaX = (coords[2] - coords[1]) * 0.05
deltaY = (coords[4] - coords[3]) * 0.05
end
self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY)
end
local function createButton(name, object, db)
local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
button.dataObject = object
button.db = db
button:SetFrameStrata("MEDIUM")
-- button:SetFixedFrameStrata(true)
button:SetFrameLevel(8)
-- button:SetFixedFrameLevel(true)
button:SetSize(31, 31)
button:RegisterForClicks("anyUp")
button:RegisterForDrag("LeftButton")
button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight"
if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
local overlay = button:CreateTexture(nil, "OVERLAY")
overlay:SetSize(50, 50)
overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
overlay:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
local background = button:CreateTexture(nil, "BACKGROUND")
background:SetSize(24, 24)
background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
background:SetPoint("CENTER", button, "CENTER", 0, 1)
local icon = button:CreateTexture(nil, "ARTWORK")
icon:SetSize(18, 18)
icon:SetTexture(object.icon)
icon:SetPoint("CENTER", button, "CENTER", 0, 1)
button.icon = icon
else
local overlay = button:CreateTexture(nil, "OVERLAY")
overlay:SetSize(53, 53)
overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
overlay:SetPoint("TOPLEFT")
local background = button:CreateTexture(nil, "BACKGROUND")
background:SetSize(20, 20)
background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
background:SetPoint("TOPLEFT", 7, -5)
local icon = button:CreateTexture(nil, "ARTWORK")
icon:SetSize(17, 17)
icon:SetTexture(object.icon)
icon:SetPoint("TOPLEFT", 7, -6)
button.icon = icon
end
button.isMouseDown = false
local r, g, b = button.icon:GetVertexColor()
button.icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b)
button.icon.UpdateCoord = updateCoord
button.icon:UpdateCoord()
button:SetScript("OnEnter", onEnter)
button:SetScript("OnLeave", onLeave)
button:SetScript("OnClick", onClick)
if not db or not db.lock then
button:SetScript("OnDragStart", onDragStart)
button:SetScript("OnDragStop", onDragStop)
end
button:SetScript("OnMouseDown", onMouseDown)
button:SetScript("OnMouseUp", onMouseUp)
button.fadeOut = button:CreateAnimationGroup()
local animOut = button.fadeOut:CreateAnimation("Alpha")
-- animOut:SetOrder(1)
-- animOut:SetDuration(0.2)
-- animOut:SetFromAlpha(1)
-- animOut:SetToAlpha(0)
-- animOut:SetStartDelay(1)
-- button.fadeOut:SetToFinalAlpha(true)
lib.objects[name] = button
if lib.loggedIn then
updatePosition(button, db and db.minimapPos)
if not db or not db.hide then
button:Show()
else
button:Hide()
end
end
lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback
end
-- We could use a metatable.__index on lib.objects, but then we'd create
-- the icons when checking things like :IsRegistered, which is not necessary.
local function check(name)
if lib.notCreated[name] then
createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
lib.notCreated[name] = nil
end
end
-- Wait a bit with the initial positioning to let any GetMinimapShape addons
-- load up.
if not lib.loggedIn then
local f = CreateFrame("Frame")
f:SetScript("OnEvent", function(f)
for _, button in next, lib.objects do
updatePosition(button, button.db and button.db.minimapPos)
if not button.db or not button.db.hide then
button:Show()
else
button:Hide()
end
end
lib.loggedIn = true
f:SetScript("OnEvent", nil)
end)
f:RegisterEvent("PLAYER_LOGIN")
end
local function getDatabase(name)
return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db
end
function lib:Register(name, object, db)
if not object.icon then error("Can't register LDB objects without icons set!") end
if lib.objects[name] or lib.notCreated[name] then error(DBICON10.. ": Object '".. name .."' is already registered.") end
if not db or not db.hide then
createButton(name, object, db)
else
lib.notCreated[name] = {object, db}
end
end
function lib:Lock(name)
if not lib:IsRegistered(name) then return end
if lib.objects[name] then
lib.objects[name]:SetScript("OnDragStart", nil)
lib.objects[name]:SetScript("OnDragStop", nil)
end
local db = getDatabase(name)
if db then
db.lock = true
end
end
function lib:Unlock(name)
if not lib:IsRegistered(name) then return end
if lib.objects[name] then
lib.objects[name]:SetScript("OnDragStart", onDragStart)
lib.objects[name]:SetScript("OnDragStop", onDragStop)
end
local db = getDatabase(name)
if db then
db.lock = nil
end
end
function lib:Hide(name)
if not lib.objects[name] then return end
lib.objects[name]:Hide()
end
function lib:Show(name)
check(name)
local button = lib.objects[name]
if button then
button:Show()
updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
end
end
function lib:IsRegistered(name)
return (lib.objects[name] or lib.notCreated[name]) and true or false
end
function lib:Refresh(name, db)
check(name)
local button = lib.objects[name]
if db then
button.db = db
end
updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
if not button.db or not button.db.hide then
button:Show()
else
button:Hide()
end
if not button.db or not button.db.lock then
button:SetScript("OnDragStart", onDragStart)
button:SetScript("OnDragStop", onDragStop)
else
button:SetScript("OnDragStart", nil)
button:SetScript("OnDragStop", nil)
end
end
function lib:GetMinimapButton(name)
return lib.objects[name]
end
do
local function OnMinimapEnter()
if isDraggingButton then return end
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
end
local function OnMinimapLeave()
if isDraggingButton then return end
for _, button in next, lib.objects do
if button.showOnMouseover then
button.fadeOut:Play()
end
end
end
Minimap:HookScript("OnEnter", OnMinimapEnter)
Minimap:HookScript("OnLeave", OnMinimapLeave)
function lib:ShowOnEnter(name, value)
local button = lib.objects[name]
if button then
if value then
button.showOnMouseover = true
button.fadeOut:Stop()
button:SetAlpha(0)
else
button.showOnMouseover = false
button.fadeOut:Stop()
button:SetAlpha(1)
end
end
end
end
function lib:GetButtonList()
local t = {}
for name in next, lib.objects do
t[#t+1] = name
end
return t
end
function lib:SetButtonRadius(radius)
if type(radius) == "number" then
lib.radius = radius
for _, button in next, lib.objects do
updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
end
end
end
function lib:SetButtonToPosition(button, position)
updatePosition(lib.objects[button] or button, position)
end
-- Upgrade!
for name, button in next, lib.objects do
local db = getDatabase(name)
if not db or not db.lock then
button:SetScript("OnDragStart", onDragStart)
button:SetScript("OnDragStop", onDragStop)
end
button:SetScript("OnEnter", onEnter)
button:SetScript("OnLeave", onLeave)
button:SetScript("OnClick", onClick)
button:SetScript("OnMouseDown", onMouseDown)
button:SetScript("OnMouseUp", onMouseUp)
if not button.fadeOut then -- Upgrade to 39
button.fadeOut = button:CreateAnimationGroup()
local animOut = button.fadeOut:CreateAnimation("Alpha")
animOut:SetOrder(1)
animOut:SetDuration(0.2)
animOut:SetFromAlpha(1)
animOut:SetToAlpha(0)
animOut:SetStartDelay(1)
button.fadeOut:SetToFinalAlpha(true)
end
end
lib:SetButtonRadius(lib.radius) -- Upgrade to 40
-- LibDBIconEnd
end
-- LeaLibDBIcon() -- disabled in 3.3.5, was causing red things
----------------------------------------------------------------------
-- L15: LibChatAnims (load on demand)
----------------------------------------------------------------------
function Leatrix_Plus:LeaPlusLCA()
-- LibChatAnimsStart
--@curseforge-project-slug: libchatanims@
local MAJOR, MINOR = "LibChatAnims", 4 -- Bump minor on changes
local LCA = LibStub:NewLibrary(MAJOR, MINOR)
if not LCA then return end -- No upgrade needed
LCA.animations = LCA.animations or {} -- Animation storage
LCA.alerting = LCA.alerting or {} -- Chat tab alerting storage
local anims = LCA.animations
local alerting = LCA.alerting
function LCA:IsAlerting(tab)
if alerting[tab] then
return true
end
end
----------------------------------------------------
-- Note, most of this code is simply replicated from
-- Blizzard's FloatingChatFrame.lua file.
-- The only real changes are the creation and use
-- of animations vs the use of UIFrameFlash.
--
--FCFDockOverflowButton_UpdatePulseState = function(self)
-- local dock = self:GetParent()
-- local shouldPulse = false
-- for _, chatFrame in pairs(FCFDock_GetChatFrames(dock)) do
-- local chatTab = _G[chatFrame:GetName().."Tab"]
-- if ( not chatFrame.isStaticDocked and chatTab.alerting) then
-- -- Make sure the rects are valid. (Not always the case when resizing the WoW client
-- if ( not chatTab:GetRight() or not dock.scrollFrame:GetRight() ) then
-- return false
-- end
-- -- Check if it's off the screen.
-- local DELTA = 3 -- Chosen through experimentation
-- if ( chatTab:GetRight() < (dock.scrollFrame:GetLeft() + DELTA) or chatTab:GetLeft() > (dock.scrollFrame:GetRight() - DELTA) ) then
-- shouldPulse = true
-- break
-- end
-- end
-- end
--
-- local tex = self:GetHighlightTexture()
-- if shouldPulse then
-- if not anims[tex] then
-- anims[tex] = tex:CreateAnimationGroup()
--
-- local fade1 = anims[tex]:CreateAnimation("Alpha")
-- fade1:SetDuration(1)
-- fade1:SetFromAlpha(0)
-- fade1:SetToAlpha(1)
-- fade1:SetOrder(1)
--
-- local fade2 = anims[tex]:CreateAnimation("Alpha")
-- fade2:SetDuration(1)
-- fade2:SetFromAlpha(1)
-- fade2:SetToAlpha(0)
-- fade2:SetOrder(2)
-- end
-- tex:Show()
-- tex:SetAlpha(0)
-- anims[tex]:SetLooping("REPEAT")
-- anims[tex]:Play()
--
-- self:LockHighlight()
-- self.alerting = true
-- else
-- if anims[tex] then
-- anims[tex]:Stop()
-- end
-- self:UnlockHighlight()
-- tex:SetAlpha(1)
-- tex:Show()
-- self.alerting = false
-- end
--
-- if self.list:IsShown() then
-- FCFDockOverflowList_Update(self.list, dock)
-- end
-- return true
--end
--FCFDockOverflowListButton_SetValue = function(button, chatFrame)
-- local chatTab = _G[chatFrame:GetName().."Tab"]
-- button.chatFrame = chatFrame
-- button:SetText(chatFrame.name)
--
-- local colorTable = chatTab.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE
--
-- if chatTab.selectedColorTable then
-- button:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b)
-- else
-- button:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
-- end
--
-- button.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b)
--
-- if chatTab.conversationIcon then
-- button.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b)
-- button.conversationIcon:Show()
-- else
-- button.conversationIcon:Hide()
-- end
--
-- if chatTab.alerting then
-- button.alerting = true
-- if not anims[button.glow] then
-- anims[button.glow] = button.glow:CreateAnimationGroup()
--
-- local fade1 = anims[button.glow]:CreateAnimation("Alpha")
-- fade1:SetDuration(1)
-- fade1:SetFromAlpha(0)
-- fade1:SetToAlpha(1)
-- fade1:SetOrder(1)
--
-- local fade2 = anims[button.glow]:CreateAnimation("Alpha")
-- fade2:SetDuration(1)
-- fade2:SetFromAlpha(1)
-- fade2:SetToAlpha(0)
-- fade2:SetOrder(2)
-- end
-- button.glow:Show()
-- button.glow:SetAlpha(0)
-- anims[button.glow]:SetLooping("REPEAT")
-- anims[button.glow]:Play()
-- else
-- button.alerting = false
-- if anims[button.glow] then
-- anims[button.glow]:Stop()
-- end
-- button.glow:Hide()
-- end
-- button:Show()
--end
FCF_StartAlertFlash = function(chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"]
if chatFrame.minFrame then
if not anims[chatFrame.minFrame] then
anims[chatFrame.minFrame] = chatFrame.minFrame.glow:CreateAnimationGroup()
local fade1 = anims[chatFrame.minFrame]:CreateAnimation("Alpha")
fade1:SetDuration(1)
fade1:SetFromAlpha(0)
fade1:SetToAlpha(1)
fade1:SetOrder(1)
local fade2 = anims[chatFrame.minFrame]:CreateAnimation("Alpha")
fade2:SetDuration(1)
fade2:SetFromAlpha(1)
fade2:SetToAlpha(0)
fade2:SetOrder(2)
end
chatFrame.minFrame.glow:Show()
chatFrame.minFrame.glow:SetAlpha(0)
anims[chatFrame.minFrame]:SetLooping("REPEAT")
anims[chatFrame.minFrame]:Play()
--chatFrame.minFrame.alerting = true
alerting[chatFrame.minFrame] = true
end
if not anims[chatTab.glow] then
anims[chatTab.glow] = chatTab.glow:CreateAnimationGroup()
local fade1 = anims[chatTab.glow]:CreateAnimation("Alpha")
fade1:SetDuration(1)
fade1:SetFromAlpha(0)
fade1:SetToAlpha(1)
fade1:SetOrder(1)
local fade2 = anims[chatTab.glow]:CreateAnimation("Alpha")
fade2:SetDuration(1)
fade2:SetFromAlpha(1)
fade2:SetToAlpha(0)
fade2:SetOrder(2)
end
chatTab.glow:Show()
chatTab.glow:SetAlpha(0)
anims[chatTab.glow]:SetLooping("REPEAT")
anims[chatTab.glow]:Play()
--chatTab.alerting = true
alerting[chatTab] = true
-- START function FCFTab_UpdateAlpha(chatFrame)
local mouseOverAlpha, noMouseAlpha = 0, 0
if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then
mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA
noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA
else
mouseOverAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_MOUSEOVER_ALPHA
noMouseAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_NOMOUSE_ALPHA
end
if chatFrame.hasBeenFaded then
chatTab:SetAlpha(mouseOverAlpha)
else
chatTab:SetAlpha(noMouseAlpha)
end
--END function FCFTab_UpdateAlpha(chatFrame)
--FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton)
end
FCF_StopAlertFlash = function(chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"]
if chatFrame.minFrame then
if anims[chatFrame.minFrame] then
anims[chatFrame.minFrame]:Stop()
end
chatFrame.minFrame.glow:Hide()
--chatFrame.minFrame.alerting = false
alerting[chatFrame.minFrame] = nil
end
if anims[chatTab.glow] then
anims[chatTab.glow]:Stop()
end
chatTab.glow:Hide()
--chatTab.alerting = false
alerting[chatTab] = nil
-- START function FCFTab_UpdateAlpha(chatFrame)
local mouseOverAlpha, noMouseAlpha = 0, 0
if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then
mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA
noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA
else
mouseOverAlpha = 0.6 --CHAT_FRAME_TAB_NORMAL_MOUSEOVER_ALPHA
noMouseAlpha = 0.2 --CHAT_FRAME_TAB_NORMAL_NOMOUSE_ALPHA
end
if chatFrame.hasBeenFaded then
chatTab:SetAlpha(mouseOverAlpha)
else
chatTab:SetAlpha(noMouseAlpha)
end
--END function FCFTab_UpdateAlpha(chatFrame)
--FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton)
end
-- LibChatAnimsEnd
end
----------------------------------------------------------------------
-- L16: LibDBIcon: LibCandyBar
----------------------------------------------------------------------
function Leatrix_Plus:LeaPlusCandyBar()
-- LibCandyBarStart
--@curseforge-project-slug: libcandybar-3-0@
--- **LibCandyBar-3.0** provides elegant timerbars with icons for use in addons.
-- It is based of the original ideas of the CandyBar and CandyBar-2.0 library.
-- In contrary to the earlier libraries LibCandyBar-3.0 provides you with a timerbar object with a simple API.
--
-- Creating a new timerbar using the ':New' function will return a new timerbar object. This timerbar object inherits all of the barPrototype functions listed here. \\
--
-- @usage
-- local candy = LibStub("LibCandyBar-3.0")
-- local texture = "Interface\\AddOns\\MyAddOn\\statusbar"
-- local mybar = candy:New(texture, 100, 16)
-- mybar:SetLabel("Yay!")
-- mybar:SetDuration(60)
-- mybar:Start()
-- @class file
-- @name LibCandyBar-3.0
local GetTime, floor, next = GetTime, floor, next
local CreateFrame, error, setmetatable, UIParent = CreateFrame, error, setmetatable, UIParent
if not LibStub then error("LibCandyBar-3.0 requires LibStub.") end
local cbh = LibStub:GetLibrary("CallbackHandler-1.0")
if not cbh then error("LibCandyBar-3.0 requires CallbackHandler-1.0") end
local lib = LibStub:NewLibrary("LibCandyBar-3.0", 100) -- Bump minor on changes
if not lib then return end
lib.callbacks = lib.callbacks or cbh:New(lib)
local cb = lib.callbacks
lib.dummyFrame = lib.dummyFrame or CreateFrame("Frame")
lib.barFrameMT = lib.barFrameMT or {__index = lib.dummyFrame}
lib.barPrototype = lib.barPrototype or setmetatable({}, lib.barFrameMT)
lib.barPrototype_mt = lib.barPrototype_mt or {__index = lib.barPrototype}
lib.barCache = lib.barCache or {}
local barPrototype = lib.barPrototype
local barPrototype_meta = lib.barPrototype_mt
local barCache = lib.barCache
local scripts = {
"OnUpdate", "OnDragStart", "OnDragStop",
"OnEnter", "OnLeave", "OnHide",
"OnShow", "OnMouseDown", "OnMouseUp",
"OnMouseWheel", "OnSizeChanged", "OnEvent"
}
local numScripts = #scripts
local GameFontHighlightSmallOutline = GameFontHighlightSmallOutline
local _fontName, _fontSize = GameFontHighlightSmallOutline:GetFont()
local _fontShadowX, _fontShadowY = GameFontHighlightSmallOutline:GetShadowOffset()
local _fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA = GameFontHighlightSmallOutline:GetShadowColor()
local SetWidth, SetHeight, SetSize = lib.dummyFrame.SetWidth, lib.dummyFrame.SetHeight, lib.dummyFrame.SetSize
local function stopBar(bar)
bar.updater:Stop()
bar.data = nil
bar.funcs = nil
bar.running = nil
bar.paused = nil
bar:Hide()
bar:SetParent(UIParent)
end
local tformat1 = "%d:%02d:%02d"
local tformat2 = "%d:%02d"
local tformat3 = "%.1f"
local tformat4 = "%.0f"
local function barUpdate(updater)
local bar = updater.parent
local t = GetTime()
if t >= bar.exp then
bar:Stop()
else
local time = bar.exp - t
bar.remaining = time
bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time)
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
bar.candyBarDuration:SetFormattedText(tformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
bar.candyBarDuration:SetFormattedText(tformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
bar.candyBarDuration:SetFormattedText(tformat3, time)
else -- 10 seconds to one minute
bar.candyBarDuration:SetFormattedText(tformat4, time)
end
if bar.funcs then
for i = 1, #bar.funcs do
bar.funcs[i](bar)
end
end
end
end
local atformat1 = "~%d:%02d:%02d"
local atformat2 = "~%d:%02d"
local atformat3 = "~%.1f"
local atformat4 = "~%.0f"
local function barUpdateApprox(updater)
local bar = updater.parent
local t = GetTime()
if t >= bar.exp then
bar:Stop()
else
local time = bar.exp - t
bar.remaining = time
bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time)
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
bar.candyBarDuration:SetFormattedText(atformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
bar.candyBarDuration:SetFormattedText(atformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
bar.candyBarDuration:SetFormattedText(atformat3, time)
else -- 10 seconds to one minute
bar.candyBarDuration:SetFormattedText(atformat4, time)
end
if bar.funcs then
for i = 1, #bar.funcs do
bar.funcs[i](bar)
end
end
end
end
-- ------------------------------------------------------------------------------
-- Bar functions
--
local function restyleBar(self)
if not self.running then return end
self.candyBarIconFrame:ClearAllPoints()
self.candyBarBar:ClearAllPoints()
-- In the past we used a :GetTexture check here, but as of WoW v5 it randomly returns nil, so use our own trustworthy variable.
if self.candyBarIconFrame.icon then
self.candyBarIconFrame:SetWidth(self.height)
if self.iconPosition == "RIGHT" then
self.candyBarIconFrame:SetPoint("TOPRIGHT", self)
self.candyBarIconFrame:SetPoint("BOTTOMRIGHT", self)
self.candyBarBar:SetPoint("TOPRIGHT", self.candyBarIconFrame, "TOPLEFT")
self.candyBarBar:SetPoint("BOTTOMRIGHT", self.candyBarIconFrame, "BOTTOMLEFT")
self.candyBarBar:SetPoint("TOPLEFT", self)
self.candyBarBar:SetPoint("BOTTOMLEFT", self)
else
self.candyBarIconFrame:SetPoint("TOPLEFT")
self.candyBarIconFrame:SetPoint("BOTTOMLEFT")
self.candyBarBar:SetPoint("TOPLEFT", self.candyBarIconFrame, "TOPRIGHT")
self.candyBarBar:SetPoint("BOTTOMLEFT", self.candyBarIconFrame, "BOTTOMRIGHT")
self.candyBarBar:SetPoint("TOPRIGHT", self)
self.candyBarBar:SetPoint("BOTTOMRIGHT", self)
end
self.candyBarIconFrame:Show()
else
self.candyBarBar:SetPoint("TOPLEFT", self)
self.candyBarBar:SetPoint("BOTTOMRIGHT", self)
self.candyBarIconFrame:Hide()
end
if self.showLabel and self.candyBarLabel.text then
self.candyBarLabel:Show()
else
self.candyBarLabel:Hide()
end
if self.showTime then
self.candyBarDuration:Show()
else
self.candyBarDuration:Hide()
end
end
--- Set whether the bar should drain (default) or fill up.
-- @param fill Boolean true/false
function barPrototype:SetFill(fill)
self.fill = fill
end
--- Adds a function to the timerbar. The function will run every update and will receive the bar as a parameter.
-- @param func Function to run every update.
-- @usage
-- -- The example below will print the time remaining to the chatframe every update. Yes, that's a whole lot of spam
-- mybar:AddUpdateFunction( function(bar) print(bar.remaining) end )
function barPrototype:AddUpdateFunction(func) if not self.funcs then self.funcs = {} end; self.funcs[#self.funcs+1] = func end
--- Sets user data in the timerbar object.
-- @param key Key to use for the data storage.
-- @param data Data to store.
function barPrototype:Set(key, data) if not self.data then self.data = {} end; self.data[key] = data end
--- Retrieves user data from the timerbar object.
-- @param key Key to retrieve
function barPrototype:Get(key) return self.data and self.data[key] end
--- Sets the color of the bar.
-- This is basically a wrapper to SetStatusBarColor.
-- @paramsig r, g, b, a
-- @param r Red component (0-1)
-- @param g Green component (0-1)
-- @param b Blue component (0-1)
-- @param a Alpha (0-1)
function barPrototype:SetColor(...) self.candyBarBar:SetStatusBarColor(...) end
--- Sets the color of the bar label and bar duration text.
-- @paramsig r, g, b, a
-- @param r Red component (0-1)
-- @param g Green component (0-1)
-- @param b Blue component (0-1)
-- @param a Alpha (0-1)
function barPrototype:SetTextColor(...)
self.candyBarLabel:SetTextColor(...)
self.candyBarDuration:SetTextColor(...)
end
--- Sets the shadow color of the bar label and bar duration text.
-- @paramsig r, g, b, a
-- @param r Red component (0-1)
-- @param g Green component (0-1)
-- @param b Blue component (0-1)
-- @param a Alpha (0-1)
function barPrototype:SetShadowColor(...)
self.candyBarLabel:SetShadowColor(...)
self.candyBarDuration:SetShadowColor(...)
end
--- Sets the texture of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param texture Path to the bar texture.
function barPrototype:SetTexture(texture)
self.candyBarBar:SetStatusBarTexture(texture)
self.candyBarBackground:SetTexture(texture)
end
--- Sets the width of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param width Width of the bar.
function barPrototype:SetWidth(width)
self.width = width
SetWidth(self, width)
end
--- Sets the height of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param height Height of the bar.
function barPrototype:SetHeight(height)
self.height = height
SetHeight(self, height)
restyleBar(self)
end
--- Sets the size of the bar.
-- This should only be needed on running bars that get changed on the fly.
-- @param width Width of the bar.
-- @param height Height of the bar.
function barPrototype:SetSize(width, height)
self.width = width
self.height = height
SetSize(self, width, height)
restyleBar(self)
end
--- Returns the label (text) currently set on the bar.
function barPrototype:GetLabel()
return self.candyBarLabel.text
end
--- Sets the label on the bar.
-- @param text Label text.
function barPrototype:SetLabel(text)
self.candyBarLabel.text = text
self.candyBarLabel:SetText(text)
if text then
self.candyBarLabel:Show()
else
self.candyBarLabel:Hide()
end
end
--- Returns the icon texture path currently set on the bar, if it has an icon set.
function barPrototype:GetIcon()
return self.candyBarIconFrame.icon
end
--- Sets the icon next to the bar.
-- @param icon Path to the icon texture or nil to not display an icon.
-- @param ... Optional icon coordinates for texture trimming.
function barPrototype:SetIcon(icon, ...)
self.candyBarIconFrame.icon = icon
self.candyBarIconFrame:SetTexture(icon)
if ... then
self.candyBarIconFrame:SetTexCoord(...)
else
self.candyBarIconFrame:SetTexCoord(0.07, 0.93, 0.07, 0.93)
end
restyleBar(self)
end
--- Sets which side of the bar the icon should appear.
-- @param position Position of the icon according to the bar, either "LEFT" or "RIGHT" as a string. Set to "LEFT" by default.
function barPrototype:SetIconPosition(position)
self.iconPosition = position
restyleBar(self)
end
--- Sets wether or not the time indicator on the right of the bar should be shown.
-- Time is shown by default.
-- @param bool true to show the time, false/nil to hide the time.
function barPrototype:SetTimeVisibility(bool)
self.showTime = bool
if bool then
self.candyBarDuration:Show()
else
self.candyBarDuration:Hide()
end
end
--- Sets wether or not the label on the left of the bar should be shown.
-- label is shown by default.
-- @param bool true to show the label, false/nil to hide the label.
function barPrototype:SetLabelVisibility(bool)
self.showLabel = bool
if bool then
self.candyBarLabel:Show()
else
self.candyBarLabel:Hide()
end
end
--- Sets the duration of the bar.
-- This can also be used while the bar is running to adjust the time remaining, within the bounds of the original duration.
-- @param duration Duration of the bar in seconds.
-- @param isApprox Boolean. True if you wish the time display to be an approximate "~5" instead of "5"
function barPrototype:SetDuration(duration, isApprox) self.remaining = duration; self.isApproximate = isApprox end
--- Shows the bar and starts it.
-- @param maxValue Number. If you don't wish your bar to start full, you can set a max value. A maxValue of 10 on a bar with a duration of 5 would start it at 50%.
function barPrototype:Start(maxValue)
self.running = true
local time = self.remaining
self.gap = maxValue and maxValue-time or 0
restyleBar(self)
self.start = GetTime()
self.exp = self.start + time
self.candyBarBar:SetMinMaxValues(0, maxValue or time)
self.candyBarBar:SetValue(self.fill and 0 or time)
if self.isApproximate then
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
self.candyBarDuration:SetFormattedText(atformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
self.candyBarDuration:SetFormattedText(atformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
self.candyBarDuration:SetFormattedText(atformat3, time)
else -- 10 seconds to one minute
self.candyBarDuration:SetFormattedText(atformat4, time)
end
self.updater:SetScript("OnLoop", barUpdateApprox)
else
if time > 3599.9 then -- > 1 hour
local h = floor(time/3600)
local m = floor((time - (h*3600))/60)
local s = (time - (m*60)) - (h*3600)
self.candyBarDuration:SetFormattedText(tformat1, h, m, s)
elseif time > 59.9 then -- 1 minute to 1 hour
local m = floor(time/60)
local s = time - (m*60)
self.candyBarDuration:SetFormattedText(tformat2, m, s)
elseif time < 10 then -- 0 to 10 seconds
self.candyBarDuration:SetFormattedText(tformat3, time)
else -- 10 seconds to one minute
self.candyBarDuration:SetFormattedText(tformat4, time)
end
self.updater:SetScript("OnLoop", barUpdate)
end
self.updater:Play()
self:Show()
end
--- Pauses a running bar
function barPrototype:Pause()
if not self.paused then
self.updater:Pause()
self.paused = GetTime()
end
end
--- Resumes a paused bar
function barPrototype:Resume()
if self.paused then
local t = GetTime()
self.exp = t + self.remaining
self.start = self.start + (t-self.paused)
self.updater:Play()
self.paused = nil
end
end
--- Stops the bar.
-- This will stop the bar, fire the LibCandyBar_Stop callback, and recycle the bar into the candybar pool.
-- Note: make sure you remove all references to the bar in your addon upon receiving the LibCandyBar_Stop callback.
-- @usage
-- -- The example below shows the use of the LibCandyBar_Stop callback by printing the contents of the label in the chatframe
-- local function barstopped( callback, bar )
-- print( bar:GetLabel(), "stopped")
-- end
-- LibStub("LibCandyBar-3.0"):RegisterCallback(myaddonobject, "LibCandyBar_Stop", barstopped)
-- @param ... Optional args to pass across in the LibCandyBar_Stop callback.
function barPrototype:Stop(...)
cb:Fire("LibCandyBar_Stop", self, ...)
stopBar(self)
barCache[self] = true
end
-- ------------------------------------------------------------------------------
-- Library functions
--
--- Creates a new timerbar object and returns it. Don't forget to set the duration, label and :Start the timer bar after you get a hold of it!
-- @paramsig texture, width, height
-- @param texture Path to the texture used for the bar.
-- @param width Width of the bar.
-- @param height Height of the bar.
-- @usage
-- mybar = LibStub("LibCandyBar-3.0"):New("Interface\\AddOns\\MyAddOn\\media\\statusbar", 100, 16)
function lib:New(texture, width, height)
local bar = next(barCache)
if not bar then
local frame = CreateFrame("Frame", nil, UIParent)
bar = setmetatable(frame, barPrototype_meta)
local icon = bar:CreateTexture()
icon:SetPoint("TOPLEFT")
icon:SetPoint("BOTTOMLEFT")
icon:Show()
bar.candyBarIconFrame = icon
local statusbar = CreateFrame("StatusBar", nil, bar)
statusbar:SetPoint("TOPRIGHT")
statusbar:SetPoint("BOTTOMRIGHT")
bar.candyBarBar = statusbar
local bg = statusbar:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints()
bar.candyBarBackground = bg
local backdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops
backdrop:SetFrameLevel(0)
bar.candyBarBackdrop = backdrop
local iconBackdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops
iconBackdrop:SetFrameLevel(0)
bar.candyBarIconFrameBackdrop = iconBackdrop
local duration = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline")
duration:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0)
duration:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0)
bar.candyBarDuration = duration
local label = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline")
label:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0)
label:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0)
bar.candyBarLabel = label
local updater = bar:CreateAnimationGroup()
updater:SetLooping("REPEAT")
updater.parent = bar
local anim = updater:CreateAnimation()
anim:SetDuration(0.04)
bar.updater = updater
bar.repeater = anim
else
barCache[bar] = nil
end
bar:SetFrameStrata("MEDIUM")
bar:SetFrameLevel(100) -- Lots of room to create above or below this level
bar.candyBarBar:SetStatusBarTexture(texture)
bar.candyBarBackground:SetTexture(texture)
bar.width = width
bar.height = height
-- RESET ALL THE THINGS!
bar.fill = nil
bar.showTime = true
bar.showLabel = true
bar.iconPosition = nil
for i = 1, numScripts do -- Update if scripts table is changed, faster than doing #scripts
bar:SetScript(scripts[i], nil)
end
bar.candyBarBackground:SetVertexColor(0.5, 0.5, 0.5, 0.3)
bar.candyBarBar:SetStatusBarColor(0.5, 0.5, 0.5, 1)
bar:ClearAllPoints()
SetWidth(bar, width)
SetHeight(bar, height)
bar:SetMovable(1)
bar:SetScale(1)
bar:SetAlpha(1)
bar:SetClampedToScreen(false)
bar:EnableMouse(false)
bar.candyBarLabel:SetTextColor(1,1,1,1)
bar.candyBarLabel:SetJustifyH("LEFT")
bar.candyBarLabel:SetJustifyV("MIDDLE")
bar.candyBarLabel:SetFont(_fontName, _fontSize)
bar.candyBarLabel:SetShadowOffset(_fontShadowX, _fontShadowY)
bar.candyBarLabel:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA)
bar.candyBarDuration:SetTextColor(1,1,1,1)
bar.candyBarDuration:SetJustifyH("RIGHT")
bar.candyBarDuration:SetJustifyV("MIDDLE")
bar.candyBarDuration:SetFont(_fontName, _fontSize)
bar.candyBarDuration:SetShadowOffset(_fontShadowX, _fontShadowY)
bar.candyBarDuration:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA)
bar:SetLabel()
bar:SetIcon()
bar:SetDuration()
return bar
end
-- LibCandyBarEnd
end
-- L17: End
>>>>>>> 0f3757ee7b0a1d6b3ed73a1e639c617c3b5acfd0