diff --git a/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua index 39e265d..c802e4c 100644 --- a/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua +++ b/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua @@ -1,10 +1,15 @@ ---[[ $Id: CallbackHandler-1.0.lua 22 2018-07-21 14:17:22Z nevcairiel $ ]] -local MAJOR, MINOR = "CallbackHandler-1.0", 7 +--[[ $Id: CallbackHandler-1.0.lua 22 2018-07-21 14:17:22Z nevcairiel $ ]] local + MAJOR, MINOR = "CallbackHandler-1.0", 7 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} +local meta = { + __index = function(tbl, key) + tbl[key] = {} + return tbl[key] + end +} -- Lua APIs local tconcat = table.concat @@ -18,17 +23,15 @@ local next, select, pairs, type, tostring = next, select, pairs, type, tostring local xpcall = xpcall -local function errorhandler(err) - return geterrorhandler()(err) -end +local function errorhandler(err) return geterrorhandler()(err) end local function Dispatch(handlers, ...) - local index, method = next(handlers) - if not method then return end - repeat - xpcall(method, errorhandler, ...) - index, method = next(handlers, index) - until not method + local index, method = next(handlers) + if not method then return end + repeat + xpcall(method, errorhandler, ...) + index, method = next(handlers, index) + until not method end -------------------------------------------------------------------------- @@ -39,173 +42,199 @@ end -- 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(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 eventname,callbacks in pairs(registry.insertQueue) do - 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. - for self,func in pairs(callbacks) do - events[eventname][self] = func - -- fire OnUsed callback? - if first and registry.OnUsed then - registry.OnUsed(registry, target, eventname) - 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 +function CallbackHandler:New(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 eventname, callbacks in pairs(registry.insertQueue) do + 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. + for self, func in pairs(callbacks) do + events[eventname][self] = func + -- fire OnUsed callback? + if first and registry.OnUsed then + registry.OnUsed(registry, target, eventname) + 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. diff --git a/libs/LibDBIcon-1.0/LibDBIcon-1.0.lua b/libs/LibDBIcon-1.0/LibDBIcon-1.0.lua index e865bdf..6e1adff 100644 --- a/libs/LibDBIcon-1.0/LibDBIcon-1.0.lua +++ b/libs/LibDBIcon-1.0/LibDBIcon-1.0.lua @@ -1,10 +1,8 @@ - ----------------------------------------------------------------------- -- 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 = 43 -- Bump on changes if not LibStub then error(DBICON10 .. " requires LibStub.") end @@ -18,81 +16,86 @@ 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 -lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate") +lib.tooltip = lib.tooltip or + CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, + "GameTooltipTemplate") local next, Minimap = next, Minimap 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 + 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 + 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 + 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 + 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 + 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 -------------------------------------------------------------------------------- @@ -100,371 +103,365 @@ 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 + 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 + if self.dataObject.OnClick then self.dataObject.OnClick(self, b) end end local function onMouseDown(self) - self.isMouseDown = true - self.icon:UpdateCoord() + self.isMouseDown = true + self.icon:UpdateCoord() end local function onMouseUp(self) - self.isMouseDown = false - self.icon:UpdateCoord() + 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 + 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 + 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) + 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:SetSize(31, 31) - button:SetFrameLevel(8) - button:RegisterForClicks("anyUp") - button:RegisterForDrag("LeftButton") - button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight" - 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 - button.isMouseDown = false - - local r, g, b = icon:GetVertexColor() - icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b) - - icon.UpdateCoord = updateCoord - 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 + local button = CreateFrame("Button", "LibDBIcon10_" .. name, Minimap) + button.dataObject = object + button.db = db + button:SetFrameStrata("MEDIUM") + button:SetSize(31, 31) + button:SetFrameLevel(8) + button:RegisterForClicks("anyUp") + button:RegisterForDrag("LeftButton") + button:SetHighlightTexture(136477) -- "Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight" + 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 + button.isMouseDown = false + + local r, g, b = icon:GetVertexColor() + icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b) + + icon.UpdateCoord = updateCoord + 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 + 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") + 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 + 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 + 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 + 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 + 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() + 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 + 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 + 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 + 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 +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 + 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 + 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 + 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) + 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 + 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 diff --git a/libs/LibDataBroker-1.1/LibDataBroker-1.1.lua b/libs/LibDataBroker-1.1/LibDataBroker-1.1.lua index f47c0cd..b5e3e29 100644 --- a/libs/LibDataBroker-1.1/LibDataBroker-1.1.lua +++ b/libs/LibDataBroker-1.1/LibDataBroker-1.1.lua @@ -1,90 +1,100 @@ - assert(LibStub, "LibDataBroker-1.1 requires LibStub") -assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0") +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 +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, - } + 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 + 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 + 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:DataObjectIterator() return pairs(self.proxystorage) end - function lib:GetDataObjectByName(dataobjectname) - return self.proxystorage[dataobjectname] - end + function lib:GetDataObjectByName(dataobjectname) + return self.proxystorage[dataobjectname] + end - function lib:GetNameByDataObject(dataobject) - return self.namestorage[dataobject] - 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 + 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 diff --git a/libs/LibDewdrop-3.0/LibDewdrop-3.0.lua b/libs/LibDewdrop-3.0/LibDewdrop-3.0.lua index e796faa..44ecb99 100644 --- a/libs/LibDewdrop-3.0/LibDewdrop-3.0.lua +++ b/libs/LibDewdrop-3.0/LibDewdrop-3.0.lua @@ -15,74 +15,69 @@ Dependencies: AceLibrary License: LGPL v2.1 ]] -local Dewdrop = LibStub:NewLibrary( "LibDewdrop-3.0", 1 ) +local Dewdrop = LibStub:NewLibrary("LibDewdrop-3.0", 1) Dewdrop.scrollListSize = 33 if not Dewdrop then - return -- already loaded and no upgrade necessary + return -- already loaded and no upgrade necessary end -local function new( ... ) - local t = { } - for i = 1, select( '#', ... ), 2 do - local k = select( i, ... ) - if k then - t[k] = select( i + 1, ... ) - else - break - end - end - return t +local function new(...) + local t = {} + for i = 1, select('#', ...), 2 do + local k = select(i, ...) + if k then + t[k] = select(i + 1, ...) + else + break + end + end + return t end local tmp do - local t = { } - function tmp( ... ) - for k in pairs( t ) do - t[k] = nil - end - for i = 1, select( '#', ... ), 2 do - local k = select( i, ... ) - if k then - t[k] = select( i + 1, ... ) - else - break - end - end - return t - end + local t = {} + function tmp(...) + for k in pairs(t) do t[k] = nil end + for i = 1, select('#', ...), 2 do + local k = select(i, ...) + if k then + t[k] = select(i + 1, ...) + else + break + end + end + return t + end end local tmp2 do - local t = { } - function tmp2( ... ) - for k in pairs( t ) do - t[k] = nil - end - for i = 1, select( '#', ... ), 2 do - local k = select( i, ... ) - if k then - t[k] = select( i + 1, ... ) - else - break - end - end - return t - end + local t = {} + function tmp2(...) + for k in pairs(t) do t[k] = nil end + for i = 1, select('#', ...), 2 do + local k = select(i, ...) + if k then + t[k] = select(i + 1, ...) + else + break + end + end + return t + end end - -local TOC = select( 4, GetBuildInfo( ) ) or 0 - +local TOC = select(4, GetBuildInfo()) or 0 local CLOSE = "Close" local CLOSE_DESC = "Close the menu." local VALIDATION_ERROR = "Validation error." local USAGE_TOOLTIP = "Usage: %s." -local RANGE_TOOLTIP = "Note that you can scroll your mouse wheel while over the slider to step by one." +local RANGE_TOOLTIP = + "Note that you can scroll your mouse wheel while over the slider to step by one." local RESET_KEYBINDING_DESC = "Hit escape to clear the keybinding." local KEY_BUTTON1 = "Left Mouse" local KEY_BUTTON2 = "Right Mouse" @@ -90,82 +85,93 @@ local DISABLED = "Disabled" local DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" if GetLocale() == "deDE" then - CLOSE = "Schlie\195\159en" - CLOSE_DESC = "Men\195\188 schlie\195\159en." - VALIDATION_ERROR = "Validierungsfehler." - USAGE_TOOLTIP = "Benutzung: %s." - RANGE_TOOLTIP = "Beachte das du mit dem Mausrad scrollen kannst solange du mit dem Mauszeiger \195\188ber dem Schieberegler bist, um feinere Spr\195\188nge zu machen." - RESET_KEYBINDING_DESC = "Escape dr\195\188cken, um die Tastenbelegung zu l\195\182schen." - KEY_BUTTON1 = "Linke Maustaste" - KEY_BUTTON2 = "Rechte Maustaste" - DISABLED = "Deaktiviert" - DEFAULT_CONFIRM_MESSAGE = "Bist du sicher das du `%s' machen willst?" + CLOSE = "Schlie\195\159en" + CLOSE_DESC = "Men\195\188 schlie\195\159en." + VALIDATION_ERROR = "Validierungsfehler." + USAGE_TOOLTIP = "Benutzung: %s." + RANGE_TOOLTIP = + "Beachte das du mit dem Mausrad scrollen kannst solange du mit dem Mauszeiger \195\188ber dem Schieberegler bist, um feinere Spr\195\188nge zu machen." + RESET_KEYBINDING_DESC = + "Escape dr\195\188cken, um die Tastenbelegung zu l\195\182schen." + KEY_BUTTON1 = "Linke Maustaste" + KEY_BUTTON2 = "Rechte Maustaste" + DISABLED = "Deaktiviert" + DEFAULT_CONFIRM_MESSAGE = "Bist du sicher das du `%s' machen willst?" elseif GetLocale() == "koKR" then - CLOSE = "닫기" - CLOSE_DESC = "메뉴를 닫습니다." - VALIDATION_ERROR = "오류 확인." - USAGE_TOOLTIP = "사용법: %s." - RANGE_TOOLTIP = "알림 : 슬라이더 위에서 마우스 휠을 사용하면 한단계씩 조절할 수 있습니다." - RESET_KEYBINDING_DESC = "단축키를 해제하려면 ESC키를 누르세요." - KEY_BUTTON1 = "왼쪽 마우스" - KEY_BUTTON2 = "오른쪽 마우스" - DISABLED = "비활성화됨" - DEFAULT_CONFIRM_MESSAGE = "정말로 `%s' 실행을 하시겠습니까 ?" + CLOSE = "닫기" + CLOSE_DESC = "메뉴를 닫습니다." + VALIDATION_ERROR = "오류 확인." + USAGE_TOOLTIP = "사용법: %s." + RANGE_TOOLTIP = + "알림 : 슬라이더 위에서 마우스 휠을 사용하면 한단계씩 조절할 수 있습니다." + RESET_KEYBINDING_DESC = + "단축키를 해제하려면 ESC키를 누르세요." + KEY_BUTTON1 = "왼쪽 마우스" + KEY_BUTTON2 = "오른쪽 마우스" + DISABLED = "비활성화됨" + DEFAULT_CONFIRM_MESSAGE = "정말로 `%s' 실행을 하시겠습니까 ?" elseif GetLocale() == "frFR" then - CLOSE = "Fermer" - CLOSE_DESC = "Ferme le menu." - VALIDATION_ERROR = "Erreur de validation." - USAGE_TOOLTIP = "Utilisation : %s." - RANGE_TOOLTIP = "Vous pouvez aussi utiliser la molette de la souris pour pour modifier progressivement." - RESET_KEYBINDING_DESC = "Appuyez sur la touche Echappement pour effacer le raccourci." - KEY_BUTTON1 = "Clic gauche" - KEY_BUTTON2 = "Clic droit" - DISABLED = "D\195\169sactiv\195\169" - DEFAULT_CONFIRM_MESSAGE = "\195\138tes-vous s\195\187r de vouloir effectuer '%s' ?" + CLOSE = "Fermer" + CLOSE_DESC = "Ferme le menu." + VALIDATION_ERROR = "Erreur de validation." + USAGE_TOOLTIP = "Utilisation : %s." + RANGE_TOOLTIP = + "Vous pouvez aussi utiliser la molette de la souris pour pour modifier progressivement." + RESET_KEYBINDING_DESC = + "Appuyez sur la touche Echappement pour effacer le raccourci." + KEY_BUTTON1 = "Clic gauche" + KEY_BUTTON2 = "Clic droit" + DISABLED = "D\195\169sactiv\195\169" + DEFAULT_CONFIRM_MESSAGE = + "\195\138tes-vous s\195\187r de vouloir effectuer '%s' ?" elseif GetLocale() == "esES" then - CLOSE = "Cerrar" - CLOSE_DESC = "Cierra el menú." - VALIDATION_ERROR = "Error de validación." - USAGE_TOOLTIP = "Uso: %s." - RANGE_TOOLTIP = "Puedes desplazarte verticalmente con la rueda del ratón sobre el desplazador." - RESET_KEYBINDING_DESC = "Pulsa Escape para borrar la asignación de tecla." - KEY_BUTTON1 = "Clic Izquierdo" - KEY_BUTTON2 = "Clic Derecho" - DISABLED = "Desactivado" - DEFAULT_CONFIRM_MESSAGE = "¿Estás seguro de querer realizar `%s'?" + CLOSE = "Cerrar" + CLOSE_DESC = "Cierra el menú." + VALIDATION_ERROR = "Error de validación." + USAGE_TOOLTIP = "Uso: %s." + RANGE_TOOLTIP = + "Puedes desplazarte verticalmente con la rueda del ratón sobre el desplazador." + RESET_KEYBINDING_DESC = "Pulsa Escape para borrar la asignación de tecla." + KEY_BUTTON1 = "Clic Izquierdo" + KEY_BUTTON2 = "Clic Derecho" + DISABLED = "Desactivado" + DEFAULT_CONFIRM_MESSAGE = "¿Estás seguro de querer realizar `%s'?" elseif GetLocale() == "zhTW" then - CLOSE = "關閉" - CLOSE_DESC = "關閉選單。" - VALIDATION_ERROR = "驗證錯誤。" - USAGE_TOOLTIP = "用法: %s。" - RANGE_TOOLTIP = "你可以在捲動條上使用滑鼠滾輪來捲動。" - RESET_KEYBINDING_DESC = "按Esc鍵清除快捷鍵。" - KEY_BUTTON1 = "滑鼠左鍵" - KEY_BUTTON2 = "滑鼠右鍵" - DISABLED = "停用" - DEFAULT_CONFIRM_MESSAGE = "是否執行「%s」?" + CLOSE = "關閉" + CLOSE_DESC = "關閉選單。" + VALIDATION_ERROR = "驗證錯誤。" + USAGE_TOOLTIP = "用法: %s。" + RANGE_TOOLTIP = "你可以在捲動條上使用滑鼠滾輪來捲動。" + RESET_KEYBINDING_DESC = "按Esc鍵清除快捷鍵。" + KEY_BUTTON1 = "滑鼠左鍵" + KEY_BUTTON2 = "滑鼠右鍵" + DISABLED = "停用" + DEFAULT_CONFIRM_MESSAGE = "是否執行「%s」?" elseif GetLocale() == "zhCN" then - CLOSE = "关闭" - CLOSE_DESC = "关闭菜单" - VALIDATION_ERROR = "验证错误." - USAGE_TOOLTIP = "用法: %s." - RANGE_TOOLTIP = "你可以在滚动条上使用鼠标滚轮来翻页." - RESET_KEYBINDING_DESC = "按ESC键清除按键绑定" - KEY_BUTTON1 = "鼠标左键" - KEY_BUTTON2 = "鼠标右键" - DISABLED = "禁用" - DEFAULT_CONFIRM_MESSAGE = "是否执行'%s'?" + CLOSE = "关闭" + CLOSE_DESC = "关闭菜单" + VALIDATION_ERROR = "验证错误." + USAGE_TOOLTIP = "用法: %s." + RANGE_TOOLTIP = "你可以在滚动条上使用鼠标滚轮来翻页." + RESET_KEYBINDING_DESC = "按ESC键清除按键绑定" + KEY_BUTTON1 = "鼠标左键" + KEY_BUTTON2 = "鼠标右键" + DISABLED = "禁用" + DEFAULT_CONFIRM_MESSAGE = "是否执行'%s'?" elseif GetLocale() == "ruRU" then - CLOSE = "Закрыть" - CLOSE_DESC = "Закрыть меню." - VALIDATION_ERROR = "Ошибка проверки данных." - USAGE_TOOLTIP = "Используйте: %s." - RANGE_TOOLTIP = "Используйте колесо мыши для прокрутки ползунка." - RESET_KEYBINDING_DESC = "Нажмите клавишу Escape для очистки клавиши." - KEY_BUTTON1 = "ЛКМ" - KEY_BUTTON2 = "ПКМ" - DISABLED = "Отключено" - DEFAULT_CONFIRM_MESSAGE = "Вы уверены что вы хотите выполнять `%s'?" + CLOSE = "Закрыть" + CLOSE_DESC = "Закрыть меню." + VALIDATION_ERROR = "Ошибка проверки данных." + USAGE_TOOLTIP = "Используйте: %s." + RANGE_TOOLTIP = + "Используйте колесо мыши для прокрутки ползунка." + RESET_KEYBINDING_DESC = + "Нажмите клавишу Escape для очистки клавиши." + KEY_BUTTON1 = "ЛКМ" + KEY_BUTTON2 = "ПКМ" + DISABLED = "Отключено" + DEFAULT_CONFIRM_MESSAGE = + "Вы уверены что вы хотите выполнять `%s'?" end Dewdrop.KEY_BUTTON1 = KEY_BUTTON1 @@ -180,271 +186,238 @@ local options -- master secureframe that we pop onto menu items on mouseover. This requires -- some dark magic with OnLeave etc, but it's not too bad. -local secureFrame = CreateFrame("Button", nil, nil, "SecureActionButtonTemplate") +local secureFrame = + CreateFrame("Button", nil, nil, "SecureActionButtonTemplate") secureFrame:Hide() local function secureFrame_Show(self) - local owner = self.owner - if self.secure then -- Leftovers from previos owner, clean up! ("Shouldn't" happen but does..) - for k,v in pairs(self.secure) do - self:SetAttribute(k, nil) - end - end - self.secure = owner.secure; -- Grab hold of new secure data - - local scale = owner:GetEffectiveScale() - - self:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", owner:GetLeft() * scale, owner:GetTop() * scale) - self:SetPoint("BOTTOMRIGHT", nil, "BOTTOMLEFT", owner:GetRight() * scale, owner:GetBottom() * scale) - self:EnableMouse(true) - for k,v in pairs(self.secure) do - self:SetAttribute(k, v) - end - state = C_CVar.GetCVarBool("ActionButtonUseKeyDown") - if state then - self:RegisterForClicks("LeftButtonDown") - else - self:RegisterForClicks("LeftButtonUp") - end - - secureFrame:SetFrameStrata(owner:GetFrameStrata()) - secureFrame:SetFrameLevel(owner:GetFrameLevel()+2) - self:Show() + local owner = self.owner + if self.secure then -- Leftovers from previos owner, clean up! ("Shouldn't" happen but does..) + for k, v in pairs(self.secure) do self:SetAttribute(k, nil) end + end + self.secure = owner.secure; -- Grab hold of new secure data + + local scale = owner:GetEffectiveScale() + + self:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", owner:GetLeft() * scale, + owner:GetTop() * scale) + self:SetPoint("BOTTOMRIGHT", nil, "BOTTOMLEFT", owner:GetRight() * scale, + owner:GetBottom() * scale) + self:EnableMouse(true) + for k, v in pairs(self.secure) do self:SetAttribute(k, v) end + state = C_CVar.GetCVarBool("ActionButtonUseKeyDown") + if state then + self:RegisterForClicks("LeftButtonDown") + else + self:RegisterForClicks("LeftButtonUp") + end + + secureFrame:SetFrameStrata(owner:GetFrameStrata()) + secureFrame:SetFrameLevel(owner:GetFrameLevel() + 2) + self:Show() end local function secureFrame_Hide(self) - self:Hide() - if self.secure then - for k,v in pairs(self.secure) do - self:SetAttribute(k, nil) - end - end - self.secure = nil + self:Hide() + if self.secure then + for k, v in pairs(self.secure) do self:SetAttribute(k, nil) end + end + self.secure = nil end -secureFrame:SetScript("OnLeave", - function(self) - local owner=self.owner - self:Deactivate() - callBack = owner:GetScript("OnLeave") - return callBack(owner) - end -) - -secureFrame:HookScript("OnClick", - function(self,...) - if not self.owner then return end - self.owner:GetScript("OnClick")(self.owner,...) - end -) - -function secureFrame:IsOwnedBy(frame) - return self.owner == frame -end +secureFrame:SetScript("OnLeave", function(self) + local owner = self.owner + self:Deactivate() + callBack = owner:GetScript("OnLeave") + return callBack(owner) +end) + +secureFrame:HookScript("OnClick", function(self, ...) + if not self.owner then return end + self.owner:GetScript("OnClick")(self.owner, ...) +end) + +function secureFrame:IsOwnedBy(frame) return self.owner == frame end function secureFrame:Activate(owner) - if self.owner then -- "Shouldn't" happen but apparently it does and I cba to troubleshoot... - if not InCombatLockdown( ) then - secureFrame_Hide(self) - end - end - self.owner = owner - if not InCombatLockdown( ) then - secureFrame_Show(self) - end + if self.owner then -- "Shouldn't" happen but apparently it does and I cba to troubleshoot... + if not InCombatLockdown() then secureFrame_Hide(self) end + end + self.owner = owner + if not InCombatLockdown() then secureFrame_Show(self) end end function secureFrame:Deactivate() - if not InCombatLockdown( ) then - secureFrame_Hide(self) - end - self.owner = nil + if not InCombatLockdown() then secureFrame_Hide(self) end + self.owner = nil end -- END secure frame utilities - -- Underline on mouseover - use a single global underline that we move around, no point in creating lots of copies -local underlineFrame = CreateFrame( "Frame" ) -underlineFrame.tx = underlineFrame:CreateTexture( ) -underlineFrame.tx:SetTexture( 1, 1, 0.5, 0.75 ) -underlineFrame:SetScript( "OnHide", - function( self ) - self:Hide( ) - end -) -underlineFrame:SetScript( "OnShow", - function( self ) -- change sizing on the fly to catch runtime uiscale changes - self.tx:SetPoint( "TOPLEFT", -1, -2 / self:GetEffectiveScale( ) ) - self.tx:SetPoint( "RIGHT", 1, 0 ) - self.tx:SetHeight( 0.6 / self:GetEffectiveScale( ) ) - end -) -underlineFrame:SetHeight( 1 ) +local underlineFrame = CreateFrame("Frame") +underlineFrame.tx = underlineFrame:CreateTexture() +underlineFrame.tx:SetTexture(1, 1, 0.5, 0.75) +underlineFrame:SetScript("OnHide", function(self) self:Hide() end) +underlineFrame:SetScript("OnShow", + function(self) -- change sizing on the fly to catch runtime uiscale changes + self.tx:SetPoint("TOPLEFT", -1, -2 / self:GetEffectiveScale()) + self.tx:SetPoint("RIGHT", 1, 0) + self.tx:SetHeight(0.6 / self:GetEffectiveScale()) +end) +underlineFrame:SetHeight(1) -- END underline on mouseover - local function GetScaledCursorPosition() - local x, y = GetCursorPosition() - local scale = UIParent:GetEffectiveScale() - return x / scale, y / scale + local x, y = GetCursorPosition() + local scale = UIParent:GetEffectiveScale() + return x / scale, y / scale end local function StartCounting(level) - for i = level, 1, -1 do - if levels[i] then - levels[i].count = 3 - end - end + for i = level, 1, -1 do if levels[i] then levels[i].count = 3 end end end local function StopCounting(level) - for i = level, 1, -1 do - if levels[i] then - levels[i].count = nil - end - end + for i = level, 1, -1 do if levels[i] then levels[i].count = nil end end end local function OnUpdate(self, elapsed) - for _,level in ipairs(levels) do - local count = level.count - if count then - count = count - elapsed - if count < 0 then - level.count = nil - Dewdrop:Close(level.num) - else - level.count = count - end - end - end + for _, level in ipairs(levels) do + local count = level.count + if count then + count = count - elapsed + if count < 0 then + level.count = nil + Dewdrop:Close(level.num) + else + level.count = count + end + end + end end local function CheckDualMonitor(frame) - local ratio = GetScreenWidth() / GetScreenHeight() - if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then - local offsetx - if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then - offsetx = GetScreenWidth() / 2 - frame:GetRight() - else - offsetx = GetScreenWidth() / 2 - frame:GetLeft() - end - local point, parent, relativePoint, x, y = frame:GetPoint(1) - frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0) - end + local ratio = GetScreenWidth() / GetScreenHeight() + if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and + frame:GetLeft() < GetScreenWidth() / 2 then + local offsetx + if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then + offsetx = GetScreenWidth() / 2 - frame:GetRight() + else + offsetx = GetScreenWidth() / 2 - frame:GetLeft() + end + local point, parent, relativePoint, x, y = frame:GetPoint(1) + frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0) + end end local function CheckSize(level) - if not level.scrollFrame.child.buttons then - return - end - if #level.scrollFrame.child.buttons < Dewdrop.scrollListSize then - level.scrollFrame.ScrollBar:Hide() - else - level.scrollFrame.ScrollBar:Show() - end - local height = 20 - for _, button in ipairs(level.scrollFrame.child.buttons) do - height = height + button:GetHeight() - end - local levelMaxHeight = 16 * Dewdrop.scrollListSize - local levelHeight = height - if height > levelMaxHeight then levelHeight = levelMaxHeight end - level:SetHeight(levelHeight) - level.scrollFrame.child:SetHeight(height) - local width = 50 - for _, button in ipairs(level.scrollFrame.child.buttons) do - local extra = 1 - if button.hasArrow or button.hasColorSwatch then - extra = extra + 16 - end - if not button.notCheckable then - extra = extra + 24 - end - --button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) - if button.text:GetStringWidth() + extra > width then - width = button.text:GetStringWidth() + extra - end - end - level:SetWidth(width + 20) - level.scrollFrame.child:SetWidth(width + 20) - if level:GetLeft() and level:GetRight() and level:GetTop() and level:GetBottom() and (level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0) then - level:ClearAllPoints() - local parent = level.parent or level:GetParent() - if type(parent) ~= "table" then - parent = UIParent - end - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) - else - level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) - else - level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) - end - end - end - local dirty = false - if not level:GetRight() then - Dewdrop:Close() - return - end - if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then - level.lastDirection = "LEFT" - dirty = true - elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then - level.lastDirection = "RIGHT" - dirty = true - end - if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then - level.lastVDirection = "DOWN" - dirty = true - elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then - level.lastVDirection = "UP" - dirty = true - end - if dirty then - level:ClearAllPoints() - local parent = level.parent or level:GetParent() - if type(parent) ~= "table" then - parent = UIParent - end - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) - else - level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) - else - level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) - end - end - end - if level:GetTop() > GetScreenHeight() then - local top = level:GetTop() - local point, parent, relativePoint, x, y = level:GetPoint(1) - level:ClearAllPoints() - level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top) - elseif level:GetBottom() < 0 then - local bottom = level:GetBottom() - local point, parent, relativePoint, x, y = level:GetPoint(1) - level:ClearAllPoints() - level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) - end - CheckDualMonitor(level) - if mod(level.num, 5) == 0 then - local left, bottom = level:GetLeft(), level:GetBottom() - level:ClearAllPoints() - level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) - end + if not level.scrollFrame.child.buttons then return end + if #level.scrollFrame.child.buttons < Dewdrop.scrollListSize then + level.scrollFrame.ScrollBar:Hide() + else + level.scrollFrame.ScrollBar:Show() + end + local height = 20 + for _, button in ipairs(level.scrollFrame.child.buttons) do + height = height + button:GetHeight() + end + local levelMaxHeight = 16 * Dewdrop.scrollListSize + local levelHeight = height + if height > levelMaxHeight then levelHeight = levelMaxHeight end + level:SetHeight(levelHeight) + level.scrollFrame.child:SetHeight(height) + local width = 50 + for _, button in ipairs(level.scrollFrame.child.buttons) do + local extra = 1 + if button.hasArrow or button.hasColorSwatch then + extra = extra + 16 + end + if not button.notCheckable then extra = extra + 24 end + -- button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) + if button.text:GetStringWidth() + extra > width then + width = button.text:GetStringWidth() + extra + end + end + level:SetWidth(width + 20) + level.scrollFrame.child:SetWidth(width + 20) + if level:GetLeft() and level:GetRight() and level:GetTop() and + level:GetBottom() and + (level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or + level:GetTop() > GetScreenHeight() or level:GetBottom() < 0) then + level:ClearAllPoints() + local parent = level.parent or level:GetParent() + if type(parent) ~= "table" then parent = UIParent end + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) + else + level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) + end + else + if level.lastVDirection == "DOWN" then + level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) + else + level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) + end + end + end + local dirty = false + if not level:GetRight() then + Dewdrop:Close() + return + end + if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then + level.lastDirection = "LEFT" + dirty = true + elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then + level.lastDirection = "RIGHT" + dirty = true + end + if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then + level.lastVDirection = "DOWN" + dirty = true + elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then + level.lastVDirection = "UP" + dirty = true + end + if dirty then + level:ClearAllPoints() + local parent = level.parent or level:GetParent() + if type(parent) ~= "table" then parent = UIParent end + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) + else + level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) + end + else + if level.lastVDirection == "DOWN" then + level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) + else + level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) + end + end + end + if level:GetTop() > GetScreenHeight() then + local top = level:GetTop() + local point, parent, relativePoint, x, y = level:GetPoint(1) + level:ClearAllPoints() + level:SetPoint(point, parent, relativePoint, x or 0, + (y or 0) + GetScreenHeight() - top) + elseif level:GetBottom() < 0 then + local bottom = level:GetBottom() + local point, parent, relativePoint, x, y = level:GetPoint(1) + level:ClearAllPoints() + level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) + end + CheckDualMonitor(level) + if mod(level.num, 5) == 0 then + local left, bottom = level:GetLeft(), level:GetBottom() + level:ClearAllPoints() + level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) + end end local Open @@ -453,37 +426,32 @@ local OpenEditBox local Refresh local Clear local function ReleaseButton(level, index) - if not level.scrollFrame.child.buttons then - return - end - if not level.scrollFrame.child.buttons[index] then - return - end - local button = level.scrollFrame.child.buttons[index] - button:Hide() - if button.highlight then - button.highlight:Hide() - end --- button.arrow:SetVertexColor(1, 1, 1) --- button.arrow:SetHeight(16) --- button.arrow:SetWidth(16) - table.remove(level.scrollFrame.child.buttons, index) - table.insert(buttons, button) - for k in pairs(button) do - if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then - button[k] = nil - end - end - return true + if not level.scrollFrame.child.buttons then return end + if not level.scrollFrame.child.buttons[index] then return end + local button = level.scrollFrame.child.buttons[index] + button:Hide() + if button.highlight then button.highlight:Hide() end + -- button.arrow:SetVertexColor(1, 1, 1) + -- button.arrow:SetHeight(16) + -- button.arrow:SetWidth(16) + table.remove(level.scrollFrame.child.buttons, index) + table.insert(buttons, button) + for k in pairs(button) do + if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= + "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then + button[k] = nil + end + end + return true end local function getArgs(t, str, num, ...) - local x = t[str .. num] - if x == nil then - return ... - else - return x, getArgs(t, str, num + 1, ...) - end + local x = t[str .. num] + if x == nil then + return ... + else + return x, getArgs(t, str, num + 1, ...) + end end local sliderFrame @@ -494,655 +462,704 @@ local lastSetFont local justSetFont = false local regionTmp = {} local function fillRegionTmp(...) - for i = 1, select('#', ...) do - regionTmp[i] = select(i, ...) - end + for i = 1, select('#', ...) do regionTmp[i] = select(i, ...) end end local function showGameTooltip(self) - if self.tooltipTitle or self.tooltipText then - GameTooltip_SetDefaultAnchor(GameTooltip, self) - local disabled = not self.isTitle and self.disabled - if self.tooltipTitle then - if disabled then - GameTooltip:SetText(self.tooltipTitle, 0.5, 0.5, 0.5, 1) - else - GameTooltip:SetText(self.tooltipTitle, 1, 1, 1, 1) - end - if self.tooltipText then - if disabled then - GameTooltip:AddLine(self.tooltipText, (NORMAL_FONT_COLOR.r + 0.5) / 2, (NORMAL_FONT_COLOR.g + 0.5) / 2, (NORMAL_FONT_COLOR.b + 0.5) / 2, 1) - else - GameTooltip:AddLine(self.tooltipText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - end - else - if disabled then - GameTooltip:SetText(self.tooltipText, 0.5, 0.5, 0.5, 1) - else - GameTooltip:SetText(self.tooltipText, 1, 1, 1, 1) - end - end - GameTooltip:Show() - end - if self.tooltipFunc then - GameTooltip:SetOwner(self, "ANCHOR_NONE") - GameTooltip:SetPoint("TOPLEFT", self, "TOPRIGHT", 5, 0) - self.tooltipFunc(getArgs(self, 'tooltipArg', 1)) - GameTooltip:Show() - end + if self.tooltipTitle or self.tooltipText then + GameTooltip_SetDefaultAnchor(GameTooltip, self) + local disabled = not self.isTitle and self.disabled + if self.tooltipTitle then + if disabled then + GameTooltip:SetText(self.tooltipTitle, 0.5, 0.5, 0.5, 1) + else + GameTooltip:SetText(self.tooltipTitle, 1, 1, 1, 1) + end + if self.tooltipText then + if disabled then + GameTooltip:AddLine(self.tooltipText, + (NORMAL_FONT_COLOR.r + 0.5) / 2, + (NORMAL_FONT_COLOR.g + 0.5) / 2, + (NORMAL_FONT_COLOR.b + 0.5) / 2, 1) + else + GameTooltip:AddLine(self.tooltipText, NORMAL_FONT_COLOR.r, + NORMAL_FONT_COLOR.g, + NORMAL_FONT_COLOR.b, 1) + end + end + else + if disabled then + GameTooltip:SetText(self.tooltipText, 0.5, 0.5, 0.5, 1) + else + GameTooltip:SetText(self.tooltipText, 1, 1, 1, 1) + end + end + GameTooltip:Show() + end + if self.tooltipFunc then + GameTooltip:SetOwner(self, "ANCHOR_NONE") + GameTooltip:SetPoint("TOPLEFT", self, "TOPRIGHT", 5, 0) + self.tooltipFunc(getArgs(self, 'tooltipArg', 1)) + GameTooltip:Show() + end end -local tmpt = setmetatable({}, {mode='v'}) +local tmpt = setmetatable({}, {mode = 'v'}) local numButtons = 0 -local function AcquireButton( level ) - if not levels[level] then - return - end - level = levels[level] - if not level.scrollFrame.child.buttons then - level.scrollFrame.child.buttons = {} - end - - local button - if #buttons == 0 then - numButtons = numButtons + 1 - button = CreateFrame("Button", "LibDewdrop30Button" .. numButtons, nil) - button:SetFrameStrata("FULLSCREEN_DIALOG") - button:SetHeight(16) - local highlight = button:CreateTexture(nil, "BACKGROUND") - highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") - button.highlight = highlight - highlight:SetBlendMode("ADD") - highlight:SetAllPoints(button) - highlight:Hide() - local check = button:CreateTexture(nil, "ARTWORK") - button.check = check - check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") - check:SetPoint("CENTER", button, "LEFT", 12, 0) - check:SetWidth(24) - check:SetHeight(24) - local radioHighlight = button:CreateTexture(nil, "ARTWORK") - button.radioHighlight = radioHighlight - radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") - radioHighlight:SetAllPoints(check) - radioHighlight:SetBlendMode("ADD") - radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) - radioHighlight:Hide() - button:SetScript("OnEnter", function(self) - if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == self.level.num + 1) or (editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == self.level.num + 1) then - for i = 1, self.level.num do - Refresh(levels[i]) - end - return - end - Dewdrop:Close(self.level.num + 1) - if not self.disabled then - if self.secure then - secureFrame:Activate(self) - elseif self.hasSlider then - OpenSlider(self) - elseif self.hasEditBox then - OpenEditBox(self) - elseif self.hasArrow then - Open(self, nil, self.level.num + 1, self.value) - end - end - if not self.level then -- button reclaimed - return - end - StopCounting(self.level.num + 1) - if not self.disabled then - highlight:Show() - if self.isRadio then - button.radioHighlight:Show() - end - if self.mouseoverUnderline then - underlineFrame:SetParent(self) - underlineFrame:SetPoint("BOTTOMLEFT",self.text,0,0) - underlineFrame:SetWidth(self.text:GetStringWidth()) - underlineFrame:Show() - end - end - showGameTooltip(self) - end) - button:SetScript("OnHide", function(self) - if self.secure and secureFrame:IsOwnedBy(self) then - secureFrame:Deactivate() - end - end) - button:SetScript("OnLeave", function(self) - if self.secure and secureFrame:IsShown() then - return; -- it's ok, we didn't actually mouse out of the button, only onto the secure frame on top of it - end - underlineFrame:Hide() - if not self.selected then - highlight:Hide() - end - button.radioHighlight:Hide() - if self.level then - StartCounting(self.level.num) - end - GameTooltip:Hide() - end) - local first = true - button:SetScript("OnClick", function(self) - if not self.disabled then - if self.hasColorSwatch then - local func = button.colorFunc - local hasOpacity = self.hasOpacity - local self = self - for k in pairs(tmpt) do - tmpt[k] = nil - end - for i = 1, 1000 do - local x = self['colorArg'..i] - if x == nil then - break - else - tmpt[i] = x - end - end - ColorPickerFrame.func = function() - if func then - local r,g,b = ColorPickerFrame:GetColorRGB() - local a = hasOpacity and 1 - OpacitySliderFrame:GetValue() or nil - local n = #tmpt - tmpt[n+1] = r - tmpt[n+2] = g - tmpt[n+3] = b - tmpt[n+4] = a - func(unpack(tmpt)) - tmpt[n+1] = nil - tmpt[n+2] = nil - tmpt[n+3] = nil - tmpt[n+4] = nil - end - end - ColorPickerFrame.hasOpacity = self.hasOpacity - ColorPickerFrame.opacityFunc = ColorPickerFrame.func - ColorPickerFrame.opacity = 1 - self.opacity - ColorPickerFrame:SetColorRGB(self.r, self.g, self.b) - local r, g, b, a = self.r, self.g, self.b, self.opacity - ColorPickerFrame.cancelFunc = function() - if func then - local n = #tmpt - tmpt[n+1] = r - tmpt[n+2] = g - tmpt[n+3] = b - tmpt[n+4] = a - func(unpack(tmpt)) - for i = 1, n+4 do - tmpt[i] = nil - end - end - end - Dewdrop:Close(1) - ShowUIPanel(ColorPickerFrame) - elseif self.func then - local level = self.level - if type(self.func) == "string" then - if type(self.arg1[self.func]) ~= "function" then - self:error("Cannot call method %q", self.func) - end - self.arg1[self.func](self.arg1, getArgs(self, 'arg', 2)) - else - self.func(getArgs(self, 'arg', 1)) - end - if self.closeWhenClicked then - Dewdrop:Close() - elseif level:IsShown() then - for i = 1, level.num do - Refresh(levels[i]) - end - local value = levels[level.num].value - for i = level.num-1, 1, -1 do - local level = levels[i] - local good = false - for _,button in ipairs(level.scrollFrame.child.buttons) do - if button.value == value then - good = true - break - end - end - if not good then - Dewdrop:Close(i+1) - end - value = levels[i].value - end - end - elseif self.closeWhenClicked then - Dewdrop:Close() - end - end - end) - - local text = button:CreateFontString(nil, "ARTWORK") - button.text = text - button:SetScript("OnMouseDown", function(self) - if not self.disabled and (self.func or self.colorFunc or self.closeWhenClicked) then - text:SetPoint("LEFT", button, "LEFT", self.notCheckable and 1 or 25, -1) - end - end) - button:SetScript("OnMouseUp", function(self) - if not self.disabled and (self.func or self.colorFunc or self.closeWhenClicked) then - text:SetPoint("LEFT", button, "LEFT", self.notCheckable and 0 or 24, 0) - end - end) - local arrow = button:CreateTexture(nil, "ARTWORK") - button.arrow = arrow - arrow:SetPoint("LEFT", button, "RIGHT", -16, 0) - arrow:SetWidth(16) - arrow:SetHeight(16) - arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") - local colorSwatch = button:CreateTexture(nil, "ARTWORK") - button.colorSwatch = colorSwatch - colorSwatch:SetWidth(20) - colorSwatch:SetHeight(20) - colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") - local texture = button:CreateTexture(nil, "OVERLAY") - colorSwatch.texture = texture - texture:SetTexture("Interface\\Buttons\\WHITE8X8") - texture:SetWidth(11.5) - texture:SetHeight(11.5) - texture:Show() - texture:SetPoint("CENTER", colorSwatch, "CENTER") - colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) - else - button = table.remove(buttons) - end - button:ClearAllPoints() - button:SetFrameStrata(level:GetFrameStrata()) - button:SetFrameLevel(level:GetFrameLevel() + 5) - button:SetPoint("LEFT", level.scrollFrame.child, "LEFT", 10, 0) - button:SetPoint("RIGHT", level.scrollFrame.child, "RIGHT", -10, 0) - if #level.scrollFrame.child.buttons == 0 then - button:SetPoint("TOP", level.scrollFrame.child, "TOP", 0, -10) - else - button:SetPoint("TOP", level.scrollFrame.child.buttons[#level.scrollFrame.child.buttons], "BOTTOM", 0, 0) - end - button:SetParent(level.scrollFrame.child) - button.text:SetPoint("LEFT", button, "LEFT", 24, 0) - button:Show() - button.level = level - table.insert(level.scrollFrame.child.buttons, button) - if not level.parented then - level.parented = true - level:ClearAllPoints() - if level.num == 1 then - if level.parent ~= UIParent and type(level.parent) == "table" then - level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") - else - level:SetPoint("CENTER", UIParent, "CENTER") - end - else - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) - else - level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) - else - level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10) - end - end - end - level:SetFrameStrata("FULLSCREEN_DIALOG") - end - button:SetAlpha(1) - return button +local function AcquireButton(level) + if not levels[level] then return end + level = levels[level] + if not level.scrollFrame.child.buttons then + level.scrollFrame.child.buttons = {} + end + + local button + if #buttons == 0 then + numButtons = numButtons + 1 + button = CreateFrame("Button", "LibDewdrop30Button" .. numButtons, nil) + button:SetFrameStrata("FULLSCREEN_DIALOG") + button:SetHeight(16) + local highlight = button:CreateTexture(nil, "BACKGROUND") + highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") + button.highlight = highlight + highlight:SetBlendMode("ADD") + highlight:SetAllPoints(button) + highlight:Hide() + local check = button:CreateTexture(nil, "ARTWORK") + button.check = check + check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") + check:SetPoint("CENTER", button, "LEFT", 12, 0) + check:SetWidth(24) + check:SetHeight(24) + local radioHighlight = button:CreateTexture(nil, "ARTWORK") + button.radioHighlight = radioHighlight + radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") + radioHighlight:SetAllPoints(check) + radioHighlight:SetBlendMode("ADD") + radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) + radioHighlight:Hide() + button:SetScript("OnEnter", function(self) + if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and + sliderFrame.level == self.level.num + 1) or + (editBoxFrame and editBoxFrame:IsShown() and + editBoxFrame.mouseDown and editBoxFrame.level == + self.level.num + 1) then + for i = 1, self.level.num do Refresh(levels[i]) end + return + end + Dewdrop:Close(self.level.num + 1) + if not self.disabled then + if self.secure then + secureFrame:Activate(self) + elseif self.hasSlider then + OpenSlider(self) + elseif self.hasEditBox then + OpenEditBox(self) + elseif self.hasArrow then + Open(self, nil, self.level.num + 1, self.value) + end + end + if not self.level then -- button reclaimed + return + end + StopCounting(self.level.num + 1) + if not self.disabled then + highlight:Show() + if self.isRadio then button.radioHighlight:Show() end + if self.mouseoverUnderline then + underlineFrame:SetParent(self) + underlineFrame:SetPoint("BOTTOMLEFT", self.text, 0, 0) + underlineFrame:SetWidth(self.text:GetStringWidth()) + underlineFrame:Show() + end + end + showGameTooltip(self) + end) + button:SetScript("OnHide", function(self) + if self.secure and secureFrame:IsOwnedBy(self) then + secureFrame:Deactivate() + end + end) + button:SetScript("OnLeave", function(self) + if self.secure and secureFrame:IsShown() then + return; -- it's ok, we didn't actually mouse out of the button, only onto the secure frame on top of it + end + underlineFrame:Hide() + if not self.selected then highlight:Hide() end + button.radioHighlight:Hide() + if self.level then StartCounting(self.level.num) end + GameTooltip:Hide() + end) + local first = true + button:SetScript("OnClick", function(self) + if not self.disabled then + if self.hasColorSwatch then + local func = button.colorFunc + local hasOpacity = self.hasOpacity + local self = self + for k in pairs(tmpt) do tmpt[k] = nil end + for i = 1, 1000 do + local x = self['colorArg' .. i] + if x == nil then + break + else + tmpt[i] = x + end + end + ColorPickerFrame.func = function() + if func then + local r, g, b = ColorPickerFrame:GetColorRGB() + local a = hasOpacity and 1 - + OpacitySliderFrame:GetValue() or nil + local n = #tmpt + tmpt[n + 1] = r + tmpt[n + 2] = g + tmpt[n + 3] = b + tmpt[n + 4] = a + func(unpack(tmpt)) + tmpt[n + 1] = nil + tmpt[n + 2] = nil + tmpt[n + 3] = nil + tmpt[n + 4] = nil + end + end + ColorPickerFrame.hasOpacity = self.hasOpacity + ColorPickerFrame.opacityFunc = ColorPickerFrame.func + ColorPickerFrame.opacity = 1 - self.opacity + ColorPickerFrame:SetColorRGB(self.r, self.g, self.b) + local r, g, b, a = self.r, self.g, self.b, self.opacity + ColorPickerFrame.cancelFunc = function() + if func then + local n = #tmpt + tmpt[n + 1] = r + tmpt[n + 2] = g + tmpt[n + 3] = b + tmpt[n + 4] = a + func(unpack(tmpt)) + for i = 1, n + 4 do + tmpt[i] = nil + end + end + end + Dewdrop:Close(1) + ShowUIPanel(ColorPickerFrame) + elseif self.func then + local level = self.level + if type(self.func) == "string" then + if type(self.arg1[self.func]) ~= "function" then + self:error("Cannot call method %q", self.func) + end + self.arg1[self.func](self.arg1, getArgs(self, 'arg', 2)) + else + self.func(getArgs(self, 'arg', 1)) + end + if self.closeWhenClicked then + Dewdrop:Close() + elseif level:IsShown() then + for i = 1, level.num do + Refresh(levels[i]) + end + local value = levels[level.num].value + for i = level.num - 1, 1, -1 do + local level = levels[i] + local good = false + for _, button in ipairs( + level.scrollFrame.child.buttons) do + if button.value == value then + good = true + break + end + end + if not good then + Dewdrop:Close(i + 1) + end + value = levels[i].value + end + end + elseif self.closeWhenClicked then + Dewdrop:Close() + end + end + end) + + local text = button:CreateFontString(nil, "ARTWORK") + button.text = text + button:SetScript("OnMouseDown", function(self) + if not self.disabled and + (self.func or self.colorFunc or self.closeWhenClicked) then + text:SetPoint("LEFT", button, "LEFT", + self.notCheckable and 1 or 25, -1) + end + end) + button:SetScript("OnMouseUp", function(self) + if not self.disabled and + (self.func or self.colorFunc or self.closeWhenClicked) then + text:SetPoint("LEFT", button, "LEFT", + self.notCheckable and 0 or 24, 0) + end + end) + local arrow = button:CreateTexture(nil, "ARTWORK") + button.arrow = arrow + arrow:SetPoint("LEFT", button, "RIGHT", -16, 0) + arrow:SetWidth(16) + arrow:SetHeight(16) + arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") + local colorSwatch = button:CreateTexture(nil, "ARTWORK") + button.colorSwatch = colorSwatch + colorSwatch:SetWidth(20) + colorSwatch:SetHeight(20) + colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") + local texture = button:CreateTexture(nil, "OVERLAY") + colorSwatch.texture = texture + texture:SetTexture("Interface\\Buttons\\WHITE8X8") + texture:SetWidth(11.5) + texture:SetHeight(11.5) + texture:Show() + texture:SetPoint("CENTER", colorSwatch, "CENTER") + colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) + else + button = table.remove(buttons) + end + button:ClearAllPoints() + button:SetFrameStrata(level:GetFrameStrata()) + button:SetFrameLevel(level:GetFrameLevel() + 5) + button:SetPoint("LEFT", level.scrollFrame.child, "LEFT", 10, 0) + button:SetPoint("RIGHT", level.scrollFrame.child, "RIGHT", -10, 0) + if #level.scrollFrame.child.buttons == 0 then + button:SetPoint("TOP", level.scrollFrame.child, "TOP", 0, -10) + else + button:SetPoint("TOP", + level.scrollFrame.child.buttons[#level.scrollFrame.child + .buttons], "BOTTOM", 0, 0) + end + button:SetParent(level.scrollFrame.child) + button.text:SetPoint("LEFT", button, "LEFT", 24, 0) + button:Show() + button.level = level + table.insert(level.scrollFrame.child.buttons, button) + if not level.parented then + level.parented = true + level:ClearAllPoints() + if level.num == 1 then + if level.parent ~= UIParent and type(level.parent) == "table" then + level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") + else + level:SetPoint("CENTER", UIParent, "CENTER") + end + else + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) + else + level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, + -10) + end + else + if level.lastVDirection == "DOWN" then + level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) + else + level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", + -5, -10) + end + end + end + level:SetFrameStrata("FULLSCREEN_DIALOG") + end + button:SetAlpha(1) + return button end local numLevels = 0 local function AcquireLevel(level) - if not levels[level] then - for i = #levels + 1, level, -1 do - local i = i - numLevels = numLevels + 1 - local frame = CreateFrame("Button", "LibDewdrop30Level" .. numLevels, UIParent, BackdropTemplateMixin and "BackdropTemplate") - if i == 1 then - local old_CloseSpecialWindows = CloseSpecialWindows - function CloseSpecialWindows() - local found = old_CloseSpecialWindows() - if levels[1]:IsShown() then - Dewdrop:Close() - return 1 - end - return found - end - end - frame.scrollFrame = CreateFrame("ScrollFrame", "LibDewdrop30ScrollFrame" .. numLevels, frame, "ScrollFrameTemplate") - frame.scrollFrame.child = CreateFrame("Button", "LibDewdrop30ScrollFrameChild" .. numLevels, frame.scrollFrame) - frame.scrollFrame.child:SetHeight(16 * Dewdrop.scrollListSize) - frame.scrollFrame.child:SetWidth(frame:GetWidth()) - frame.scrollFrame:SetScrollChild(frame.scrollFrame.child) - frame.scrollFrame.child:SetAllPoints(frame.scrollFrame) - frame.scrollFrame:SetAllPoints(frame) - frame.scrollFrame:SetPoint("TOPLEFT", 1, -5) - frame.scrollFrame:SetPoint("TOPRIGHT", 1, -5) - frame.scrollFrame:SetPoint("BOTTOMLEFT", 1, 5) - frame.scrollFrame:SetPoint("BOTTOMRIGHT", 1, 5) - levels[i] = frame - frame.num = i - frame:SetFrameStrata("FULLSCREEN_DIALOG") - frame.scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG") - frame.scrollFrame.child:SetFrameStrata("FULLSCREEN_DIALOG") - frame:SetParent(UIParent) - frame:Hide() - frame:SetWidth(180) - frame:SetHeight(10) - frame:SetFrameLevel(i * 3) - frame:SetScript("OnHide", function() - Dewdrop:Close(level + 1) - end) - if frame.SetTopLevel then - frame:SetTopLevel(true) - end - frame:EnableMouse(true) - frame:EnableMouseWheel(true) - local backdrop = CreateFrame("Frame", nil, frame, BackdropTemplateMixin and "BackdropTemplate" ) - backdrop:SetAllPoints(frame) - backdrop:SetBackdrop(tmp( - 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", - 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", - 'tile', true, - 'insets', tmp2( - 'left', 0, - 'right', 0, - 'top', 0, - 'bottom', 0 - ), - 'tileSize', 16, - 'edgeSize', 16 - )) - backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) - backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) - frame:SetScript("OnClick", function(self) - Dewdrop:Close(i) - end) - frame:SetScript("OnEnter", function(self) - StopCounting(i) - end) - frame:SetScript("OnLeave", function(self) - StartCounting(i) - end) - if i == 1 then - frame:SetScript("OnUpdate", function(self, elapsed) - OnUpdate(self, elapsed) - end) - levels[1].lastDirection = "RIGHT" - levels[1].lastVDirection = "DOWN" - else - levels[i].lastDirection = levels[i - 1].lastDirection - levels[i].lastVDirection = levels[i - 1].lastVDirection - end - end - end - local fullscreenFrame = GetUIPanel("fullscreen") - local l = levels[level] - local strata, framelevel = l:GetFrameStrata(), l:GetFrameLevel() - if fullscreenFrame then - l:SetParent(fullscreenFrame) - else - l:SetParent(UIParent) - end - l:SetFrameStrata(strata) - l:SetFrameLevel(framelevel) - l:SetAlpha(1) - return l + if not levels[level] then + for i = #levels + 1, level, -1 do + local i = i + numLevels = numLevels + 1 + local frame = CreateFrame("Button", + "LibDewdrop30Level" .. numLevels, + UIParent, BackdropTemplateMixin and + "BackdropTemplate") + if i == 1 then + local old_CloseSpecialWindows = CloseSpecialWindows + function CloseSpecialWindows() + local found = old_CloseSpecialWindows() + if levels[1]:IsShown() then + Dewdrop:Close() + return 1 + end + return found + end + end + frame.scrollFrame = CreateFrame("ScrollFrame", + "LibDewdrop30ScrollFrame" .. + numLevels, frame, + "ScrollFrameTemplate") + frame.scrollFrame.child = CreateFrame("Button", + "LibDewdrop30ScrollFrameChild" .. + numLevels, + frame.scrollFrame) + frame.scrollFrame.child:SetHeight(16 * Dewdrop.scrollListSize) + frame.scrollFrame.child:SetWidth(frame:GetWidth()) + frame.scrollFrame:SetScrollChild(frame.scrollFrame.child) + frame.scrollFrame.child:SetAllPoints(frame.scrollFrame) + frame.scrollFrame:SetAllPoints(frame) + frame.scrollFrame:SetPoint("TOPLEFT", 1, -5) + frame.scrollFrame:SetPoint("TOPRIGHT", 1, -5) + frame.scrollFrame:SetPoint("BOTTOMLEFT", 1, 5) + frame.scrollFrame:SetPoint("BOTTOMRIGHT", 1, 5) + levels[i] = frame + frame.num = i + frame:SetFrameStrata("FULLSCREEN_DIALOG") + frame.scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG") + frame.scrollFrame.child:SetFrameStrata("FULLSCREEN_DIALOG") + frame:SetParent(UIParent) + frame:Hide() + frame:SetWidth(180) + frame:SetHeight(10) + frame:SetFrameLevel(i * 3) + frame:SetScript("OnHide", function() + Dewdrop:Close(level + 1) + end) + if frame.SetTopLevel then frame:SetTopLevel(true) end + frame:EnableMouse(true) + frame:EnableMouseWheel(true) + local backdrop = CreateFrame("Frame", nil, frame, + BackdropTemplateMixin and + "BackdropTemplate") + backdrop:SetAllPoints(frame) + backdrop:SetBackdrop(tmp('bgFile', + "Interface\\Tooltips\\UI-Tooltip-Background", + 'edgeFile', + "Interface\\Tooltips\\UI-Tooltip-Border", + 'tile', true, 'insets', tmp2('left', 0, + 'right', 0, + 'top', 0, + 'bottom', 0), + 'tileSize', 16, 'edgeSize', 16)) + backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, + TOOLTIP_DEFAULT_COLOR.g, + TOOLTIP_DEFAULT_COLOR.b) + backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, + TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, + TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) + frame:SetScript("OnClick", function(self) + Dewdrop:Close(i) + end) + frame:SetScript("OnEnter", function(self) StopCounting(i) end) + frame:SetScript("OnLeave", function(self) + StartCounting(i) + end) + if i == 1 then + frame:SetScript("OnUpdate", function(self, elapsed) + OnUpdate(self, elapsed) + end) + levels[1].lastDirection = "RIGHT" + levels[1].lastVDirection = "DOWN" + else + levels[i].lastDirection = levels[i - 1].lastDirection + levels[i].lastVDirection = levels[i - 1].lastVDirection + end + end + end + local fullscreenFrame = GetUIPanel("fullscreen") + local l = levels[level] + local strata, framelevel = l:GetFrameStrata(), l:GetFrameLevel() + if fullscreenFrame then + l:SetParent(fullscreenFrame) + else + l:SetParent(UIParent) + end + l:SetFrameStrata(strata) + l:SetFrameLevel(framelevel) + l:SetAlpha(1) + return l end local function validateOptions(options, position, baseOptions, fromPass) - if not baseOptions then - baseOptions = options - end - if type(options) ~= "table" then - return "Options must be a table.", position - end - local kind = options.type - if type(kind) ~= "string" then - return '"type" must be a string.', position - elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "dragLink" and kind ~= "header" then - return '"type" must either be "range", "text", "group", "toggle", "execute", "color", "dragLink", or "header".', position - end - if options.aliases then - if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then - return '"alias" must be a table or string', position - end - end - if not fromPass then - if kind == "execute" then - if type(options.func) ~= "string" and type(options.func) ~= "function" then - return '"func" must be a string or function', position - end - elseif kind == "range" or kind == "text" or kind == "toggle" then - if type(options.set) ~= "string" and type(options.set) ~= "function" then - return '"set" must be a string or function', position - end - if kind == "text" and options.get == false then - elseif type(options.get) ~= "string" and type(options.get) ~= "function" then - return '"get" must be a string or function', position - end - elseif kind == "group" and options.pass then - if options.pass ~= true then - return '"pass" must be either nil, true, or false', position - end - if not options.func then - if type(options.set) ~= "string" and type(options.set) ~= "function" then - return '"set" must be a string or function', position - end - if type(options.get) ~= "string" and type(options.get) ~= "function" then - return '"get" must be a string or function', position - end - elseif type(options.func) ~= "string" and type(options.func) ~= "function" then - return '"func" must be a string or function', position - end - end - end - if options ~= baseOptions then - if kind == "header" then - elseif type(options.desc) ~= "string" then - return '"desc" must be a string', position - elseif options.desc:len() == 0 then - return '"desc" cannot be a 0-length string', position - end - end - if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then - if options.type == "header" and not options.cmdName and not options.name then - elseif options.cmdName then - if type(options.cmdName) ~= "string" then - return '"cmdName" must be a string or nil', position - elseif options.cmdName:len() == 0 then - return '"cmdName" cannot be a 0-length string', position - end - if type(options.guiName) ~= "string" then - if not options.guiNameIsMap then - return '"guiName" must be a string or nil', position - end - elseif options.guiName:len() == 0 then - return '"guiName" cannot be a 0-length string', position - end - else - if type(options.name) ~= "string" then - return '"name" must be a string', position - elseif options.name:len() == 0 then - return '"name" cannot be a 0-length string', position - end - end - end - if options.guiNameIsMap then - if type(options.guiNameIsMap) ~= "boolean" then - return '"guiNameIsMap" must be a boolean or nil', position - elseif options.type ~= "toggle" then - return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position - elseif type(options.map) ~= "table" then - return '"map" must be a table', position - end - end - if options.message and type(options.message) ~= "string" then - return '"message" must be a string or nil', position - end - if options.error and type(options.error) ~= "string" then - return '"error" must be a string or nil', position - end - if options.current and type(options.current) ~= "string" then - return '"current" must be a string or nil', position - end - if options.order then - if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then - return '"order" must be a non-zero number or nil', position - end - end - if options.disabled then - if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then - return '"disabled" must be a function, string, or boolean', position - end - end - if options.cmdHidden then - if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then - return '"cmdHidden" must be a function, string, or boolean', position - end - end - if options.guiHidden then - if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then - return '"guiHidden" must be a function, string, or boolean', position - end - end - if options.hidden then - if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then - return '"hidden" must be a function, string, or boolean', position - end - end - if kind == "text" then - if type(options.validate) == "table" then - local t = options.validate - local iTable = nil - for k,v in pairs(t) do - if type(k) == "number" then - if iTable == nil then - iTable = true - elseif not iTable then - return '"validate" must either have all keys be indexed numbers or strings', position - elseif k < 1 or k > #t then - return '"validate" numeric keys must be indexed properly. >= 1 and <= #t', position - end - else - if iTable == nil then - iTable = false - elseif iTable then - return '"validate" must either have all keys be indexed numbers or strings', position - end - end - if type(v) ~= "string" then - return '"validate" values must all be strings', position - end - end - if options.multiToggle and options.multiToggle ~= true then - return '"multiToggle" must be a boolean or nil if "validate" is a table', position - end - elseif options.validate == "keybinding" then - -- no other checks - else - if type(options.usage) ~= "string" then - return '"usage" must be a string', position - elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then - return '"validate" must be a string, function, or table', position - end - end - if options.multiToggle and type(options.validate) ~= "table" then - return '"validate" must be a table if "multiToggle" is true', position - end - elseif kind == "range" then - if options.min or options.max then - if type(options.min) ~= "number" then - return '"min" must be a number', position - elseif type(options.max) ~= "number" then - return '"max" must be a number', position - elseif options.min >= options.max then - return '"min" must be less than "max"', position - end - end - if options.step then - if type(options.step) ~= "number" then - return '"step" must be a number', position - elseif options.step < 0 then - return '"step" must be nonnegative', position - end - end - if options.bigStep then - if type(options.bigStep) ~= "number" then - return '"bigStep" must be a number', position - elseif options.bigStep < 0 then - return '"bigStep" must be nonnegative', position - end - end - if options.isPercent and options.isPercent ~= true then - return '"isPercent" must either be nil, true, or false', position - end - elseif kind == "toggle" then - if options.map then - if type(options.map) ~= "table" then - return '"map" must be a table', position - elseif type(options.map[true]) ~= "string" then - return '"map[true]" must be a string', position - elseif type(options.map[false]) ~= "string" then - return '"map[false]" must be a string', position - end - end - elseif kind == "color" then - if options.hasAlpha and options.hasAlpha ~= true then - return '"hasAlpha" must be nil, true, or false', position - end - elseif kind == "group" then - if options.pass and options.pass ~= true then - return '"pass" must be nil, true, or false', position - end - if type(options.args) ~= "table" then - return '"args" must be a table', position - end - for k,v in pairs(options.args) do - if type(k) ~= "number" then - if type(k) ~= "string" then - return '"args" keys must be strings or numbers', position - elseif k:len() == 0 then - return '"args" keys must not be 0-length strings.', position - end - end - if type(v) ~= "table" then - return '"args" values must be tables', position and position .. "." .. k or k - end - local newposition - if position then - newposition = position .. ".args." .. k - else - newposition = "args." .. k - end - local err, pos = validateOptions(v, newposition, baseOptions, options.pass) - if err then - return err, pos - end - end - elseif kind == "execute" then - if type(options.confirm) ~= "string" and type(options.confirm) ~= "boolean" and type(options.confirm) ~= "nil" then - return '"confirm" must be a string, boolean, or nil', position - end - end - if options.icon and type(options.icon) ~= "string" then - return'"icon" must be a string', position - end - if options.iconWidth or options.iconHeight then - if type(options.iconWidth) ~= "number" or type(options.iconHeight) ~= "number" then - return '"iconHeight" and "iconWidth" must be numbers', position - end - end - if options.iconCoordLeft or options.iconCoordRight or options.iconCoordTop or options.iconCoordBottom then - if type(options.iconCoordLeft) ~= "number" or type(options.iconCoordRight) ~= "number" or type(options.iconCoordTop) ~= "number" or type(options.iconCoordBottom) ~= "number" then - return '"iconCoordLeft", "iconCoordRight", "iconCoordTop", and "iconCoordBottom" must be numbers', position - end - end + if not baseOptions then baseOptions = options end + if type(options) ~= "table" then + return "Options must be a table.", position + end + local kind = options.type + if type(kind) ~= "string" then + return '"type" must be a string.', position + elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= + "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= + "dragLink" and kind ~= "header" then + return + '"type" must either be "range", "text", "group", "toggle", "execute", "color", "dragLink", or "header".', + position + end + if options.aliases then + if type(options.aliases) ~= "table" and type(options.aliases) ~= + "string" then + return '"alias" must be a table or string', position + end + end + if not fromPass then + if kind == "execute" then + if type(options.func) ~= "string" and type(options.func) ~= + "function" then + return '"func" must be a string or function', position + end + elseif kind == "range" or kind == "text" or kind == "toggle" then + if type(options.set) ~= "string" and type(options.set) ~= "function" then + return '"set" must be a string or function', position + end + if kind == "text" and options.get == false then + elseif type(options.get) ~= "string" and type(options.get) ~= + "function" then + return '"get" must be a string or function', position + end + elseif kind == "group" and options.pass then + if options.pass ~= true then + return '"pass" must be either nil, true, or false', position + end + if not options.func then + if type(options.set) ~= "string" and type(options.set) ~= + "function" then + return '"set" must be a string or function', position + end + if type(options.get) ~= "string" and type(options.get) ~= + "function" then + return '"get" must be a string or function', position + end + elseif type(options.func) ~= "string" and type(options.func) ~= + "function" then + return '"func" must be a string or function', position + end + end + end + if options ~= baseOptions then + if kind == "header" then + elseif type(options.desc) ~= "string" then + return '"desc" must be a string', position + elseif options.desc:len() == 0 then + return '"desc" cannot be a 0-length string', position + end + end + if options ~= baseOptions or kind == "range" or kind == "text" or kind == + "toggle" or kind == "color" then + if options.type == "header" and not options.cmdName and not options.name then + elseif options.cmdName then + if type(options.cmdName) ~= "string" then + return '"cmdName" must be a string or nil', position + elseif options.cmdName:len() == 0 then + return '"cmdName" cannot be a 0-length string', position + end + if type(options.guiName) ~= "string" then + if not options.guiNameIsMap then + return '"guiName" must be a string or nil', position + end + elseif options.guiName:len() == 0 then + return '"guiName" cannot be a 0-length string', position + end + else + if type(options.name) ~= "string" then + return '"name" must be a string', position + elseif options.name:len() == 0 then + return '"name" cannot be a 0-length string', position + end + end + end + if options.guiNameIsMap then + if type(options.guiNameIsMap) ~= "boolean" then + return '"guiNameIsMap" must be a boolean or nil', position + elseif options.type ~= "toggle" then + return + 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', + position + elseif type(options.map) ~= "table" then + return '"map" must be a table', position + end + end + if options.message and type(options.message) ~= "string" then + return '"message" must be a string or nil', position + end + if options.error and type(options.error) ~= "string" then + return '"error" must be a string or nil', position + end + if options.current and type(options.current) ~= "string" then + return '"current" must be a string or nil', position + end + if options.order then + if type(options.order) ~= "number" or + (-1 < options.order and options.order < 0.999) then + return '"order" must be a non-zero number or nil', position + end + end + if options.disabled then + if type(options.disabled) ~= "function" and type(options.disabled) ~= + "string" and options.disabled ~= true then + return '"disabled" must be a function, string, or boolean', position + end + end + if options.cmdHidden then + if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= + "string" and options.cmdHidden ~= true then + return '"cmdHidden" must be a function, string, or boolean', + position + end + end + if options.guiHidden then + if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= + "string" and options.guiHidden ~= true then + return '"guiHidden" must be a function, string, or boolean', + position + end + end + if options.hidden then + if type(options.hidden) ~= "function" and type(options.hidden) ~= + "string" and options.hidden ~= true then + return '"hidden" must be a function, string, or boolean', position + end + end + if kind == "text" then + if type(options.validate) == "table" then + local t = options.validate + local iTable = nil + for k, v in pairs(t) do + if type(k) == "number" then + if iTable == nil then + iTable = true + elseif not iTable then + return + '"validate" must either have all keys be indexed numbers or strings', + position + elseif k < 1 or k > #t then + return + '"validate" numeric keys must be indexed properly. >= 1 and <= #t', + position + end + else + if iTable == nil then + iTable = false + elseif iTable then + return + '"validate" must either have all keys be indexed numbers or strings', + position + end + end + if type(v) ~= "string" then + return '"validate" values must all be strings', position + end + end + if options.multiToggle and options.multiToggle ~= true then + return + '"multiToggle" must be a boolean or nil if "validate" is a table', + position + end + elseif options.validate == "keybinding" then + -- no other checks + else + if type(options.usage) ~= "string" then + return '"usage" must be a string', position + elseif options.validate and type(options.validate) ~= "string" and + type(options.validate) ~= "function" then + return '"validate" must be a string, function, or table', + position + end + end + if options.multiToggle and type(options.validate) ~= "table" then + return '"validate" must be a table if "multiToggle" is true', + position + end + elseif kind == "range" then + if options.min or options.max then + if type(options.min) ~= "number" then + return '"min" must be a number', position + elseif type(options.max) ~= "number" then + return '"max" must be a number', position + elseif options.min >= options.max then + return '"min" must be less than "max"', position + end + end + if options.step then + if type(options.step) ~= "number" then + return '"step" must be a number', position + elseif options.step < 0 then + return '"step" must be nonnegative', position + end + end + if options.bigStep then + if type(options.bigStep) ~= "number" then + return '"bigStep" must be a number', position + elseif options.bigStep < 0 then + return '"bigStep" must be nonnegative', position + end + end + if options.isPercent and options.isPercent ~= true then + return '"isPercent" must either be nil, true, or false', position + end + elseif kind == "toggle" then + if options.map then + if type(options.map) ~= "table" then + return '"map" must be a table', position + elseif type(options.map[true]) ~= "string" then + return '"map[true]" must be a string', position + elseif type(options.map[false]) ~= "string" then + return '"map[false]" must be a string', position + end + end + elseif kind == "color" then + if options.hasAlpha and options.hasAlpha ~= true then + return '"hasAlpha" must be nil, true, or false', position + end + elseif kind == "group" then + if options.pass and options.pass ~= true then + return '"pass" must be nil, true, or false', position + end + if type(options.args) ~= "table" then + return '"args" must be a table', position + end + for k, v in pairs(options.args) do + if type(k) ~= "number" then + if type(k) ~= "string" then + return '"args" keys must be strings or numbers', position + elseif k:len() == 0 then + return '"args" keys must not be 0-length strings.', position + end + end + if type(v) ~= "table" then + return '"args" values must be tables', + position and position .. "." .. k or k + end + local newposition + if position then + newposition = position .. ".args." .. k + else + newposition = "args." .. k + end + local err, pos = validateOptions(v, newposition, baseOptions, + options.pass) + if err then return err, pos end + end + elseif kind == "execute" then + if type(options.confirm) ~= "string" and type(options.confirm) ~= + "boolean" and type(options.confirm) ~= "nil" then + return '"confirm" must be a string, boolean, or nil', position + end + end + if options.icon and type(options.icon) ~= "string" then + return '"icon" must be a string', position + end + if options.iconWidth or options.iconHeight then + if type(options.iconWidth) ~= "number" or type(options.iconHeight) ~= + "number" then + return '"iconHeight" and "iconWidth" must be numbers', position + end + end + if options.iconCoordLeft or options.iconCoordRight or options.iconCoordTop or + options.iconCoordBottom then + if type(options.iconCoordLeft) ~= "number" or + type(options.iconCoordRight) ~= "number" or + type(options.iconCoordTop) ~= "number" or + type(options.iconCoordBottom) ~= "number" then + return + '"iconCoordLeft", "iconCoordRight", "iconCoordTop", and "iconCoordBottom" must be numbers', + position + end + end end local validatedOptions @@ -1156,2161 +1173,2042 @@ local othersort_validate local baseFunc, currentLevel local function confirmPopup(message, func, ...) - if not StaticPopupDialogs["LIBDEWDROP30_CONFIRM_DIALOG"] then - StaticPopupDialogs["LIBDEWDROP30_CONFIRM_DIALOG"] = {} - end - local t = StaticPopupDialogs["LIBDEWDROP30_CONFIRM_DIALOG"] - for k in pairs(t) do - t[k] = nil - end - t.text = message - t.button1 = ACCEPT or "Accept" - t.button2 = CANCEL or "Cancel" - t.OnAccept = function() - func(unpack(t)) - end - for i = 1, select('#', ...) do - t[i] = select(i, ...) - end - t.timeout = 0 - t.whileDead = 1 - t.hideOnEscape = 1 - - Dewdrop:Close() - StaticPopup_Show("LIBDEWDROP30_CONFIRM_DIALOG") + if not StaticPopupDialogs["LIBDEWDROP30_CONFIRM_DIALOG"] then + StaticPopupDialogs["LIBDEWDROP30_CONFIRM_DIALOG"] = {} + end + local t = StaticPopupDialogs["LIBDEWDROP30_CONFIRM_DIALOG"] + for k in pairs(t) do t[k] = nil end + t.text = message + t.button1 = ACCEPT or "Accept" + t.button2 = CANCEL or "Cancel" + t.OnAccept = function() func(unpack(t)) end + for i = 1, select('#', ...) do t[i] = select(i, ...) end + t.timeout = 0 + t.whileDead = 1 + t.hideOnEscape = 1 + + Dewdrop:Close() + StaticPopup_Show("LIBDEWDROP30_CONFIRM_DIALOG") end - -local function getMethod(settingname, handler, v, methodName, ...) -- "..." is simply returned straight out cause you can't do "a,b,c = 111,f(),222" - assert(v and type(v)=="table") - assert(methodName and type(methodName)=="string") - - local method = v[methodName] - if type(method)=="function" then - return method, ... - elseif type(method)=="string" then - if not handler then - Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) - elseif not handler[method] then - Dewdrop:error("[%s] 'handler' method %q not defined", tostring(settingname), method) - end - return handler[method], handler, ... - end - - Dewdrop:error("[%s] Missing %q directive", tostring(settingname), methodName) +local function getMethod(settingname, handler, v, methodName, ...) -- "..." is simply returned straight out cause you can't do "a,b,c = 111,f(),222" + assert(v and type(v) == "table") + assert(methodName and type(methodName) == "string") + + local method = v[methodName] + if type(method) == "function" then + return method, ... + elseif type(method) == "string" then + if not handler then + Dewdrop:error( + "[%s] 'handler' is required if providing a method name: %q", + tostring(settingname), method) + elseif not handler[method] then + Dewdrop:error("[%s] 'handler' method %q not defined", + tostring(settingname), method) + end + return handler[method], handler, ... + end + + Dewdrop:error("[%s] Missing %q directive", tostring(settingname), methodName) end local function callMethod(settingname, handler, v, methodName, ...) - assert(v and type(v)=="table") - assert(methodName and type(methodName)=="string") - - local method = v[methodName] - if type(method)=="function" then - local success, ret,ret2,ret3,ret4 = pcall(v[methodName], ...) - if not success then - geterrorhandler()(ret) - return nil - end - return ret,ret2,ret3,ret4 - - elseif type(method)=="string" then - - local neg = method:match("^~(.-)$") - if neg then - method = neg - end - if not handler then - Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) - elseif not handler[method] then - Dewdrop:error("[%s] 'handler' (%q) method %q not defined", tostring(settingname), handler.name or "(unnamed)", method) - end - local success, ret,ret2,ret3,ret4 = pcall(handler[method], handler, ...) - if not success then - geterrorhandler()(ret) - return nil - end - if neg then - return not ret - end - return ret,ret2,ret3,ret4 - elseif method == false then - return nil - end - - Dewdrop:error("[%s] Missing %q directive in %q", tostring(settingname), methodName, v.name or "(unnamed)") + assert(v and type(v) == "table") + assert(methodName and type(methodName) == "string") + + local method = v[methodName] + if type(method) == "function" then + local success, ret, ret2, ret3, ret4 = pcall(v[methodName], ...) + if not success then + geterrorhandler()(ret) + return nil + end + return ret, ret2, ret3, ret4 + + elseif type(method) == "string" then + + local neg = method:match("^~(.-)$") + if neg then method = neg end + if not handler then + Dewdrop:error( + "[%s] 'handler' is required if providing a method name: %q", + tostring(settingname), method) + elseif not handler[method] then + Dewdrop:error("[%s] 'handler' (%q) method %q not defined", + tostring(settingname), handler.name or "(unnamed)", + method) + end + local success, ret, ret2, ret3, ret4 = + pcall(handler[method], handler, ...) + if not success then + geterrorhandler()(ret) + return nil + end + if neg then return not ret end + return ret, ret2, ret3, ret4 + elseif method == false then + return nil + end + + Dewdrop:error("[%s] Missing %q directive in %q", tostring(settingname), + methodName, v.name or "(unnamed)") end local function skip1Nil(...) - if select(1,...)==nil then - return select(2,...) - end - return ... + if select(1, ...) == nil then return select(2, ...) end + return ... end Dewdrop.fontsize = 14 -function Dewdrop:SetFontSize(fontSize) - Dewdrop.fontsize = tonumber(fontSize) -end +function Dewdrop:SetFontSize(fontSize) Dewdrop.fontsize = tonumber(fontSize) end function Dewdrop:SetScrollListSize(scrollListSize) - Dewdrop.scrollListSize = scrollListSize + Dewdrop.scrollListSize = scrollListSize end function Dewdrop:FeedAceOptionsTable(options, difference) - self:argCheck(options, 2, "table") - self:argCheck(difference, 3, "nil", "number") - if not currentLevel then - self:error("Cannot call `FeedAceOptionsTable' outside of a Dewdrop declaration") - end - if not difference then - difference = 0 - end - if not validatedOptions then - validatedOptions = {} - end - if not validatedOptions[options] then - local err, position = validateOptions(options) - - if err then - if position then - self:error(position .. ": " .. err) - else - self:error(err) - end - end - - validatedOptions[options] = true - end - local level = levels[currentLevel] - if not level then - self:error("Improper level given") - end - if not values then - values = {} - else - for k,v in pairs(values) do - values[k] = nil - end - end - - local current = level - while current do -- this traverses from higher level numbers to lower, building "values" with leaf nodes first and trunk nodes later - if current.num == difference + 1 then - break - end - table.insert(values, current.value) - current = levels[current.num - 1] - end - - local realOptions = options - local handler = options.handler - local passTable - local passValue - while #values > 0 do -- This loop traverses values from the END (trunk nodes first, then onto leaf nodes) - if options.pass then - if options.get and options.set then - passTable = options - elseif not passTable then - passTable = options - end - else - passTable = nil - end - local value = table.remove(values) - options = options.args and options.args[value] - if not options then - return - end - handler = options.handler or handler - passValue = passTable and value or nil - end - - if options.type == "group" then - local hidden = options.hidden - if type(hidden) == "function" or type(hidden) == "string" then - hidden = callMethod(options.name or "(options root)", handler, options, "hidden", options.passValue) or false - end - if hidden then - return - end - local disabled = options.disabled - if type(disabled) == "function" or type(disabled) == "string" then - disabled = callMethod(options.name or "(options root)", handler, options, "disabled", options.passValue) or false - end - if disabled then - self:AddLine( - 'text', DISABLED, - 'disabled', true - ) - return - end - for k in pairs(options.args) do - table.insert(values, k) - end - if options.pass then - if options.get and options.set then - passTable = options - elseif not passTable then - passTable = options - end - else - passTable = nil - end - if not mysort then - mysort = function(a, b) - local alpha, bravo = mysort_args[a], mysort_args[b] - local alpha_order = alpha.order or 100 - local bravo_order = bravo.order or 100 - local alpha_name = alpha.guiName or alpha.name - local bravo_name = bravo.guiName or bravo.name - if alpha_order == bravo_order then - if not alpha_name then - return bravo_name - elseif not bravo_name then - return false - else - return alpha_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < bravo_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() - end - else - if alpha_order < 0 then - if bravo_order > 0 then - return false - end - else - if bravo_order < 0 then - return true - end - end - return alpha_order < bravo_order - end - end - end - mysort_args = options.args - table.sort(values, mysort) - mysort_args = nil - local hasBoth = #values >= 1 and (options.args[values[1]].order or 100) > 0 and (options.args[values[#values]].order or 100) < 0 - local last_order = 1 - for _,k in ipairs(values) do - local v = options.args[k] - local handler = v.handler or handler - if hasBoth and last_order > 0 and (v.order or 100) < 0 then - hasBoth = false - self:AddLine() - end - local hidden, disabled = v.guiHidden or v.hidden, v.disabled - - if type(hidden) == "function" or type(hidden) == "string" then - hidden = callMethod(k, handler, v, "hidden", v.passValue) or false - end - if not hidden then - if type(disabled) == "function" or type(disabled) == "string" then - disabled = callMethod(k, handler, v, "disabled", v.passValue) or false - end - local name = (v.guiIconOnly and v.icon) and "" or (v.guiName or v.name) - local desc = v.guiDesc or v.desc - local iconHeight = v.iconHeight or 16 - local iconWidth = v.iconWidth or 16 - local iconCoordLeft = v.iconCoordLeft - local iconCoordRight = v.iconCoordRight - local iconCoordBottom = v.iconCoordBottom - local iconCoordTop = v.iconCoordTop - local tooltipTitle, tooltipText - tooltipTitle = name - if name ~= desc then - tooltipText = desc - end - if type(v.usage) == "string" and v.usage:trim():len() > 0 then - if tooltipText then - tooltipText = tooltipText .. "\n\n" .. USAGE_TOOLTIP:format(v.usage) - else - tooltipText = USAGE_TOOLTIP:format(v.usage) - end - end - local v_p = passTable - if not v_p or (v.type ~= "execute" and v.get and v.set) or (v.type == "execute" and v.func) then - v_p = v - end - local passValue = v.passValue or (v_p~=v and k) or nil - if v.type == "toggle" then - local checked = callMethod(name, handler, v_p, "get", passValue) or false - local checked_arg = checked - if type(v_p.get)=="string" and v_p.get:match("^~") then - checked_arg = not checked - end - local func, arg1, arg2, arg3 = getMethod(name, handler, v_p, "set", skip1Nil(passValue, not checked_arg)) - if v.guiNameIsMap then - checked = checked and true or false - name = tostring(v.map and v.map[checked]):gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") - tooltipTitle = name - checked = true--nil - end - self:AddLine( - 'text', name, - 'checked', checked, - 'isRadio', v.isRadio, - 'func', func, - 'arg1', arg1, - 'arg2', arg2, - 'arg3', arg3, - 'disabled', disabled, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText - ) - elseif v.type == "execute" then - local func, arg1, arg2, arg3, arg4 - local confirm = v.confirm - if confirm == true then - confirm = DEFAULT_CONFIRM_MESSAGE:format(tooltipText or tooltipTitle) - func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) - elseif type(confirm) == "string" then - func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) - else - func,arg1,arg2 = getMethod(name, handler, v_p, "func", passValue) - end - self:AddLine( - 'text', name, - 'checked', checked, - 'func', func, - 'arg1', arg1, - 'arg2', arg2, - 'arg3', arg3, - 'arg4', arg4, - 'disabled', disabled, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom - ) - elseif v.type == "range" then - local sliderValue - sliderValue = callMethod(name, handler, v_p, "get", passValue) or 0 - local sliderFunc, sliderArg1, sliderArg2 = getMethod(name, handler, v_p, "set", passValue) - if tooltipText then - tooltipText = format("%s\n\n%s", tooltipText, RANGE_TOOLTIP) - else - tooltipText = RANGE_TOOLTIP - end - self:AddLine( - 'text', name, - 'hasArrow', true, - 'hasSlider', true, - 'sliderMin', v.min or 0, - 'sliderMax', v.max or 1, - 'sliderStep', v.step or 0, - 'sliderBigStep', v.bigStep or nil, - 'sliderIsPercent', v.isPercent or false, - 'sliderValue', sliderValue, - 'sliderFunc', sliderFunc, - 'sliderArg1', sliderArg1, - 'sliderArg2', sliderArg2, - 'fromAceOptions', true, - 'disabled', disabled, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom - ) - elseif v.type == "color" then - local r,g,b,a = callMethod(name, handler, v_p, "get", passValue) - if not r then - r,g,b,a = 0,0,0,0 - end - local colorFunc, colorArg1, colorArg2 = getMethod(name, handler, v_p, "set", passValue) - self:AddLine( - 'text', name, - 'hasArrow', true, - 'hasColorSwatch', true, - 'r', r, - 'g', g, - 'b', b, - 'opacity', v.hasAlpha and a or nil, - 'hasOpacity', v.hasAlpha, - 'colorFunc', colorFunc, - 'colorArg1', colorArg1, - 'colorArg2', colorArg2, - 'disabled', disabled, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText - ) - elseif v.type == "text" then - if type(v.validate) == "table" then - local func,arg1,arg2 - if v.onClick then - func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) - end - local checked - if v.isChecked then - checked = callMethod(name, handler, v, "isChecked", passValue) or false - end - self:AddLine( - 'text', name, - 'hasArrow', true, - 'value', k, - 'func', func, - 'arg1', arg1, - 'arg2', arg2, - 'mouseoverUnderline', func and true or nil, - 'disabled', disabled, - 'checked', checked, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom - ) - else - local editBoxText - editBoxText = callMethod(name, handler, v_p, "get", passValue) or "" - local editBoxFunc, editBoxArg1, editBoxArg2 = getMethod(name, handler, v_p, "set", passValue) - - local editBoxValidateFunc, editBoxValidateArg1 - - if v.validate and v.validate ~= "keybinding" then - if v.validate == "keybinding" then - if tooltipText then - tooltipText = format("%s\n\n%s", tooltipText, RESET_KEYBINDING_DESC) - else - tooltipText = RESET_KEYBINDING_DESC - end - else - editBoxValidateFunc, editBoxValidateArg1 = getMethod(name, handler, v, "validate") -- no passvalue! - end - end - - self:AddLine( - 'text', name, - 'hasArrow', true, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom, - 'hasEditBox', true, - 'editBoxText', editBoxText, - 'editBoxFunc', editBoxFunc, - 'editBoxArg1', editBoxArg1, - 'editBoxArg2', editBoxArg2, - 'editBoxValidateFunc', editBoxValidateFunc, - 'editBoxValidateArg1', editBoxValidateArg1, - 'editBoxIsKeybinding', v.validate == "keybinding", - 'editBoxKeybindingOnly', v.keybindingOnly, - 'editBoxKeybindingExcept', v.keybindingExcept, - 'disabled', disabled, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText - ) - end - elseif v.type == "group" then - local func,arg1,arg2 - if v.onClick then - func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) - end - local checked - if v.isChecked then - checked = callMethod(name, handler, v, "isChecked", passValue) or false - end - self:AddLine( - 'text', name, - 'hasArrow', true, - 'value', k, - 'func', func, - 'arg1', arg1, - 'arg2', arg2, - 'mouseoverUnderline', func and true or nil, - 'disabled', disabled, - 'checked', checked, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom - ) - elseif v.type == "header" then - if name == "" or not name then - self:AddLine( - 'isTitle', true, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom - ) - else - self:AddLine( - 'text', name, - 'isTitle', true, - 'icon', v.icon, - 'iconHeight', iconHeight, - 'iconWidth', iconWidth, - 'iconCoordLeft', iconCoordLeft, - 'iconCoordRight', iconCoordRight, - 'iconCoordTop', iconCoordTop, - 'iconCoordBottom', iconCoordBottom - ) - end - end - end - last_order = v.order or 100 - end - elseif options.type == "text" and type(options.validate) == "table" then - local current - local options_p = passTable - if not options_p or (options.get and options.set) then - options_p = options - passTable = nil - passValue = nil - end - local multiToggle = options.multiToggle - local passValue = options.passValue or passValue - if not multiToggle then - current = callMethod(k, handler, options_p, "get", passValue) - end - local indexed = true - for k,v in pairs(options.validate) do - if type(k) ~= "number" then - indexed = false - end - table.insert(values, k) - end - if not indexed then - if not othersort then - othersort = function(alpha, bravo) - return othersort_validate[alpha]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < othersort_validate[bravo]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() - end - end - othersort_validate = options.validate - table.sort(values, othersort) - othersort_validate = nil - end - for _,k in ipairs(values) do - local v = options.validate[k] - if type(k) == "number" then - k = v - end - local func, arg1, arg2, arg3, arg4 = getMethod(k, handler, options_p, "set", skip1Nil(passValue, k)) - local checked - if multiToggle then - checked = callMethod(k, handler, options_p, "get", skip1Nil(passValue, k)) or false - if arg2 == nil then - arg2 = not checked - elseif arg3 == nil then - arg3 = not checked - else - arg4 = not checked - end - else - checked = (k == current or (type(k) == "string" and type(current) == "string" and k:lower() == current:lower())) - if checked then - func, arg1, arg2, arg3, arg4 = nil, nil, nil, nil, nil - end - end - local tooltipTitle - local tooltipText - if options.validateDesc then - tooltipTitle = v - tooltipText = options.validateDesc[k] - else - tooltipTitle = options.guiName or options.name - tooltipText = v - end - self:AddLine( - 'text', v, - 'func', func, - 'arg1', arg1, - 'arg2', arg2, - 'arg3', arg3, - 'arg4', arg4, - 'isRadio', not multiToggle, - 'checked', checked, - 'tooltipTitle', tooltipTitle, - 'tooltipText', tooltipText - ) - end - for k in pairs(values) do - values[k] = nil - end - else - return false - end - return true + self:argCheck(options, 2, "table") + self:argCheck(difference, 3, "nil", "number") + if not currentLevel then + self:error( + "Cannot call `FeedAceOptionsTable' outside of a Dewdrop declaration") + end + if not difference then difference = 0 end + if not validatedOptions then validatedOptions = {} end + if not validatedOptions[options] then + local err, position = validateOptions(options) + + if err then + if position then + self:error(position .. ": " .. err) + else + self:error(err) + end + end + + validatedOptions[options] = true + end + local level = levels[currentLevel] + if not level then self:error("Improper level given") end + if not values then + values = {} + else + for k, v in pairs(values) do values[k] = nil end + end + + local current = level + while current do -- this traverses from higher level numbers to lower, building "values" with leaf nodes first and trunk nodes later + if current.num == difference + 1 then break end + table.insert(values, current.value) + current = levels[current.num - 1] + end + + local realOptions = options + local handler = options.handler + local passTable + local passValue + while #values > 0 do -- This loop traverses values from the END (trunk nodes first, then onto leaf nodes) + if options.pass then + if options.get and options.set then + passTable = options + elseif not passTable then + passTable = options + end + else + passTable = nil + end + local value = table.remove(values) + options = options.args and options.args[value] + if not options then return end + handler = options.handler or handler + passValue = passTable and value or nil + end + + if options.type == "group" then + local hidden = options.hidden + if type(hidden) == "function" or type(hidden) == "string" then + hidden = callMethod(options.name or "(options root)", handler, + options, "hidden", options.passValue) or false + end + if hidden then return end + local disabled = options.disabled + if type(disabled) == "function" or type(disabled) == "string" then + disabled = callMethod(options.name or "(options root)", handler, + options, "disabled", options.passValue) or + false + end + if disabled then + self:AddLine('text', DISABLED, 'disabled', true) + return + end + for k in pairs(options.args) do table.insert(values, k) end + if options.pass then + if options.get and options.set then + passTable = options + elseif not passTable then + passTable = options + end + else + passTable = nil + end + if not mysort then + mysort = function(a, b) + local alpha, bravo = mysort_args[a], mysort_args[b] + local alpha_order = alpha.order or 100 + local bravo_order = bravo.order or 100 + local alpha_name = alpha.guiName or alpha.name + local bravo_name = bravo.guiName or bravo.name + if alpha_order == bravo_order then + if not alpha_name then + return bravo_name + elseif not bravo_name then + return false + else + return alpha_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub( + "|r", ""):upper() < + bravo_name:gsub("|c%x%x%x%x%x%x%x%x", "") + :gsub("|r", ""):upper() + end + else + if alpha_order < 0 then + if bravo_order > 0 then + return false + end + else + if bravo_order < 0 then + return true + end + end + return alpha_order < bravo_order + end + end + end + mysort_args = options.args + table.sort(values, mysort) + mysort_args = nil + local hasBoth = + #values >= 1 and (options.args[values[1]].order or 100) > 0 and + (options.args[values[#values]].order or 100) < 0 + local last_order = 1 + for _, k in ipairs(values) do + local v = options.args[k] + local handler = v.handler or handler + if hasBoth and last_order > 0 and (v.order or 100) < 0 then + hasBoth = false + self:AddLine() + end + local hidden, disabled = v.guiHidden or v.hidden, v.disabled + + if type(hidden) == "function" or type(hidden) == "string" then + hidden = callMethod(k, handler, v, "hidden", v.passValue) or + false + end + if not hidden then + if type(disabled) == "function" or type(disabled) == "string" then + disabled = + callMethod(k, handler, v, "disabled", v.passValue) or + false + end + local name = (v.guiIconOnly and v.icon) and "" or + (v.guiName or v.name) + local desc = v.guiDesc or v.desc + local iconHeight = v.iconHeight or 16 + local iconWidth = v.iconWidth or 16 + local iconCoordLeft = v.iconCoordLeft + local iconCoordRight = v.iconCoordRight + local iconCoordBottom = v.iconCoordBottom + local iconCoordTop = v.iconCoordTop + local tooltipTitle, tooltipText + tooltipTitle = name + if name ~= desc then tooltipText = desc end + if type(v.usage) == "string" and v.usage:trim():len() > 0 then + if tooltipText then + tooltipText = tooltipText .. "\n\n" .. + USAGE_TOOLTIP:format(v.usage) + else + tooltipText = USAGE_TOOLTIP:format(v.usage) + end + end + local v_p = passTable + if not v_p or (v.type ~= "execute" and v.get and v.set) or + (v.type == "execute" and v.func) then v_p = v end + local passValue = v.passValue or (v_p ~= v and k) or nil + if v.type == "toggle" then + local checked = callMethod(name, handler, v_p, "get", + passValue) or false + local checked_arg = checked + if type(v_p.get) == "string" and v_p.get:match("^~") then + checked_arg = not checked + end + local func, arg1, arg2, arg3 = + getMethod(name, handler, v_p, "set", + skip1Nil(passValue, not checked_arg)) + if v.guiNameIsMap then + checked = checked and true or false + name = tostring(v.map and v.map[checked]):gsub( + "|c%x%x%x%x%x%x%x%x(.-)|r", "%1") + tooltipTitle = name + checked = true -- nil + end + self:AddLine('text', name, 'checked', checked, 'isRadio', + v.isRadio, 'func', func, 'arg1', arg1, 'arg2', + arg2, 'arg3', arg3, 'disabled', disabled, + 'tooltipTitle', tooltipTitle, 'tooltipText', + tooltipText) + elseif v.type == "execute" then + local func, arg1, arg2, arg3, arg4 + local confirm = v.confirm + if confirm == true then + confirm = DEFAULT_CONFIRM_MESSAGE:format(tooltipText or + tooltipTitle) + func, arg1, arg2, arg3, arg4 = confirmPopup, confirm, + getMethod(name, handler, + v_p, "func", + passValue) + elseif type(confirm) == "string" then + func, arg1, arg2, arg3, arg4 = confirmPopup, confirm, + getMethod(name, handler, + v_p, "func", + passValue) + else + func, arg1, arg2 = + getMethod(name, handler, v_p, "func", passValue) + end + self:AddLine('text', name, 'checked', checked, 'func', func, + 'arg1', arg1, 'arg2', arg2, 'arg3', arg3, + 'arg4', arg4, 'disabled', disabled, + 'tooltipTitle', tooltipTitle, 'tooltipText', + tooltipText, 'icon', v.icon, 'iconHeight', + iconHeight, 'iconWidth', iconWidth, + 'iconCoordLeft', iconCoordLeft, + 'iconCoordRight', iconCoordRight, + 'iconCoordTop', iconCoordTop, + 'iconCoordBottom', iconCoordBottom) + elseif v.type == "range" then + local sliderValue + sliderValue = callMethod(name, handler, v_p, "get", + passValue) or 0 + local sliderFunc, sliderArg1, sliderArg2 = getMethod(name, + handler, + v_p, + "set", + passValue) + if tooltipText then + tooltipText = format("%s\n\n%s", tooltipText, + RANGE_TOOLTIP) + else + tooltipText = RANGE_TOOLTIP + end + self:AddLine('text', name, 'hasArrow', true, 'hasSlider', + true, 'sliderMin', v.min or 0, 'sliderMax', + v.max or 1, 'sliderStep', v.step or 0, + 'sliderBigStep', v.bigStep or nil, + 'sliderIsPercent', v.isPercent or false, + 'sliderValue', sliderValue, 'sliderFunc', + sliderFunc, 'sliderArg1', sliderArg1, + 'sliderArg2', sliderArg2, 'fromAceOptions', + true, 'disabled', disabled, 'tooltipTitle', + tooltipTitle, 'tooltipText', tooltipText, + 'icon', v.icon, 'iconHeight', iconHeight, + 'iconWidth', iconWidth, 'iconCoordLeft', + iconCoordLeft, 'iconCoordRight', + iconCoordRight, 'iconCoordTop', iconCoordTop, + 'iconCoordBottom', iconCoordBottom) + elseif v.type == "color" then + local r, g, b, a = callMethod(name, handler, v_p, "get", + passValue) + if not r then r, g, b, a = 0, 0, 0, 0 end + local colorFunc, colorArg1, colorArg2 = getMethod(name, + handler, + v_p, + "set", + passValue) + self:AddLine('text', name, 'hasArrow', true, + 'hasColorSwatch', true, 'r', r, 'g', g, 'b', b, + 'opacity', v.hasAlpha and a or nil, + 'hasOpacity', v.hasAlpha, 'colorFunc', + colorFunc, 'colorArg1', colorArg1, 'colorArg2', + colorArg2, 'disabled', disabled, + 'tooltipTitle', tooltipTitle, 'tooltipText', + tooltipText) + elseif v.type == "text" then + if type(v.validate) == "table" then + local func, arg1, arg2 + if v.onClick then + func, arg1, arg2 = + getMethod(name, handler, v, "onClick", passValue) + end + local checked + if v.isChecked then + checked = callMethod(name, handler, v, "isChecked", + passValue) or false + end + self:AddLine('text', name, 'hasArrow', true, 'value', k, + 'func', func, 'arg1', arg1, 'arg2', arg2, + 'mouseoverUnderline', func and true or nil, + 'disabled', disabled, 'checked', checked, + 'tooltipTitle', tooltipTitle, + 'tooltipText', tooltipText, 'icon', v.icon, + 'iconHeight', iconHeight, 'iconWidth', + iconWidth, 'iconCoordLeft', iconCoordLeft, + 'iconCoordRight', iconCoordRight, + 'iconCoordTop', iconCoordTop, + 'iconCoordBottom', iconCoordBottom) + else + local editBoxText + editBoxText = callMethod(name, handler, v_p, "get", + passValue) or "" + local editBoxFunc, editBoxArg1, editBoxArg2 = getMethod( + name, + handler, + v_p, + "set", + passValue) + + local editBoxValidateFunc, editBoxValidateArg1 + + if v.validate and v.validate ~= "keybinding" then + if v.validate == "keybinding" then + if tooltipText then + tooltipText = format("%s\n\n%s", + tooltipText, + RESET_KEYBINDING_DESC) + else + tooltipText = RESET_KEYBINDING_DESC + end + else + editBoxValidateFunc, editBoxValidateArg1 = + getMethod(name, handler, v, "validate") -- no passvalue! + end + end + + self:AddLine('text', name, 'hasArrow', true, 'icon', + v.icon, 'iconHeight', iconHeight, + 'iconWidth', iconWidth, 'iconCoordLeft', + iconCoordLeft, 'iconCoordRight', + iconCoordRight, 'iconCoordTop', + iconCoordTop, 'iconCoordBottom', + iconCoordBottom, 'hasEditBox', true, + 'editBoxText', editBoxText, 'editBoxFunc', + editBoxFunc, 'editBoxArg1', editBoxArg1, + 'editBoxArg2', editBoxArg2, + 'editBoxValidateFunc', editBoxValidateFunc, + 'editBoxValidateArg1', editBoxValidateArg1, + 'editBoxIsKeybinding', + v.validate == "keybinding", + 'editBoxKeybindingOnly', v.keybindingOnly, + 'editBoxKeybindingExcept', + v.keybindingExcept, 'disabled', disabled, + 'tooltipTitle', tooltipTitle, + 'tooltipText', tooltipText) + end + elseif v.type == "group" then + local func, arg1, arg2 + if v.onClick then + func, arg1, arg2 = + getMethod(name, handler, v, "onClick", passValue) + end + local checked + if v.isChecked then + checked = callMethod(name, handler, v, "isChecked", + passValue) or false + end + self:AddLine('text', name, 'hasArrow', true, 'value', k, + 'func', func, 'arg1', arg1, 'arg2', arg2, + 'mouseoverUnderline', func and true or nil, + 'disabled', disabled, 'checked', checked, + 'tooltipTitle', tooltipTitle, 'tooltipText', + tooltipText, 'icon', v.icon, 'iconHeight', + iconHeight, 'iconWidth', iconWidth, + 'iconCoordLeft', iconCoordLeft, + 'iconCoordRight', iconCoordRight, + 'iconCoordTop', iconCoordTop, + 'iconCoordBottom', iconCoordBottom) + elseif v.type == "header" then + if name == "" or not name then + self:AddLine('isTitle', true, 'icon', v.icon, + 'iconHeight', iconHeight, 'iconWidth', + iconWidth, 'iconCoordLeft', iconCoordLeft, + 'iconCoordRight', iconCoordRight, + 'iconCoordTop', iconCoordTop, + 'iconCoordBottom', iconCoordBottom) + else + self:AddLine('text', name, 'isTitle', true, 'icon', + v.icon, 'iconHeight', iconHeight, + 'iconWidth', iconWidth, 'iconCoordLeft', + iconCoordLeft, 'iconCoordRight', + iconCoordRight, 'iconCoordTop', + iconCoordTop, 'iconCoordBottom', + iconCoordBottom) + end + end + end + last_order = v.order or 100 + end + elseif options.type == "text" and type(options.validate) == "table" then + local current + local options_p = passTable + if not options_p or (options.get and options.set) then + options_p = options + passTable = nil + passValue = nil + end + local multiToggle = options.multiToggle + local passValue = options.passValue or passValue + if not multiToggle then + current = callMethod(k, handler, options_p, "get", passValue) + end + local indexed = true + for k, v in pairs(options.validate) do + if type(k) ~= "number" then indexed = false end + table.insert(values, k) + end + if not indexed then + if not othersort then + othersort = function(alpha, bravo) + return othersort_validate[alpha]:gsub("|c%x%x%x%x%x%x%x%x", + ""):gsub("|r", "") + :upper() < + othersort_validate[bravo]:gsub( + "|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") + :upper() + end + end + othersort_validate = options.validate + table.sort(values, othersort) + othersort_validate = nil + end + for _, k in ipairs(values) do + local v = options.validate[k] + if type(k) == "number" then k = v end + local func, arg1, arg2, arg3, arg4 = + getMethod(k, handler, options_p, "set", skip1Nil(passValue, k)) + local checked + if multiToggle then + checked = callMethod(k, handler, options_p, "get", + skip1Nil(passValue, k)) or false + if arg2 == nil then + arg2 = not checked + elseif arg3 == nil then + arg3 = not checked + else + arg4 = not checked + end + else + checked = (k == current or + (type(k) == "string" and type(current) == "string" and + k:lower() == current:lower())) + if checked then + func, arg1, arg2, arg3, arg4 = nil, nil, nil, nil, nil + end + end + local tooltipTitle + local tooltipText + if options.validateDesc then + tooltipTitle = v + tooltipText = options.validateDesc[k] + else + tooltipTitle = options.guiName or options.name + tooltipText = v + end + self:AddLine('text', v, 'func', func, 'arg1', arg1, 'arg2', arg2, + 'arg3', arg3, 'arg4', arg4, 'isRadio', not multiToggle, + 'checked', checked, 'tooltipTitle', tooltipTitle, + 'tooltipText', tooltipText) + end + for k in pairs(values) do values[k] = nil end + else + return false + end + return true end function Dewdrop:FeedTable(s, difference) - self:argCheck(s, 2, "table") - self:argCheck(difference, 3, "nil", "number") - if not currentLevel then - self:error("Cannot call `FeedTable' outside of a Dewdrop declaration") - end - if not difference then - difference = 0 - end - local level = levels[currentLevel] - if not level then - self:error("Improper level given") - end - if not values then - values = {} - else - for k,v in pairs(values) do - values[k] = nil - end - end - local t = s.subMenu and s or {subMenu = s} - local current = level - while current do - if current.num == difference + 1 then - break - end - table.insert(values, current.value) - current = levels[current.num - 1] - end - - while #values > 0 do - local value = table.remove(values) - t = t.subMenu and t.subMenu[value] - if not t then - return - end - end - - if t.subMenu or current.num == 1 then - for k in pairs(t.subMenu) do - table.insert(values, k) - end - table.sort(values) - for _,k in ipairs(values) do - local argTable = {"value", k} - for key, val in pairs(t.subMenu[k]) do - table.insert(argTable, key) - table.insert(argTable, val) - end - self:AddLine(unpack(argTable)) - end - for k in pairs(values) do - values[k] = nil - end - return false - end - return true + self:argCheck(s, 2, "table") + self:argCheck(difference, 3, "nil", "number") + if not currentLevel then + self:error("Cannot call `FeedTable' outside of a Dewdrop declaration") + end + if not difference then difference = 0 end + local level = levels[currentLevel] + if not level then self:error("Improper level given") end + if not values then + values = {} + else + for k, v in pairs(values) do values[k] = nil end + end + local t = s.subMenu and s or {subMenu = s} + local current = level + while current do + if current.num == difference + 1 then break end + table.insert(values, current.value) + current = levels[current.num - 1] + end + + while #values > 0 do + local value = table.remove(values) + t = t.subMenu and t.subMenu[value] + if not t then return end + end + + if t.subMenu or current.num == 1 then + for k in pairs(t.subMenu) do table.insert(values, k) end + table.sort(values) + for _, k in ipairs(values) do + local argTable = {"value", k} + for key, val in pairs(t.subMenu[k]) do + table.insert(argTable, key) + table.insert(argTable, val) + end + self:AddLine(unpack(argTable)) + end + for k in pairs(values) do values[k] = nil end + return false + end + return true end function Refresh(level) - if type(level) == "number" then - level = levels[level] - end - if not level then - return - end - if baseFunc then - Clear(level) - currentLevel = level.num - if type(baseFunc) == "table" then - if currentLevel == 1 then - local handler = baseFunc.handler - if handler then - local name = tostring(handler) - if not name:find('^table:') and not handler.hideMenuTitle then - name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") - Dewdrop:AddLine( - 'text', name, - 'isTitle', true - ) - end - end - end - Dewdrop:FeedAceOptionsTable(baseFunc) - if currentLevel == 1 then - Dewdrop:AddLine( - 'text', CLOSE, - 'tooltipTitle', CLOSE, - 'tooltipText', CLOSE_DESC, - 'closeWhenClicked', true - ) - end - else - baseFunc(currentLevel, level.value, levels[level.num - 1] and levels[level.num - 1].value, levels[level.num - 2] and levels[level.num - 2].value, levels[level.num - 3] and levels[level.num - 3].value, levels[level.num - 4] and levels[level.num - 4].value) - end - currentLevel = nil - CheckSize(level) - end + if type(level) == "number" then level = levels[level] end + if not level then return end + if baseFunc then + Clear(level) + currentLevel = level.num + if type(baseFunc) == "table" then + if currentLevel == 1 then + local handler = baseFunc.handler + if handler then + local name = tostring(handler) + if not name:find('^table:') and not handler.hideMenuTitle then + name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") + Dewdrop:AddLine('text', name, 'isTitle', true) + end + end + end + Dewdrop:FeedAceOptionsTable(baseFunc) + if currentLevel == 1 then + Dewdrop:AddLine('text', CLOSE, 'tooltipTitle', CLOSE, + 'tooltipText', CLOSE_DESC, 'closeWhenClicked', + true) + end + else + baseFunc(currentLevel, level.value, + levels[level.num - 1] and levels[level.num - 1].value, + levels[level.num - 2] and levels[level.num - 2].value, + levels[level.num - 3] and levels[level.num - 3].value, + levels[level.num - 4] and levels[level.num - 4].value) + end + currentLevel = nil + CheckSize(level) + end end function Dewdrop:Refresh(level) - Dewdrop:argCheck(level, 2, "number", "nil") - if not level then - for k,v in pairs(levels) do - Refresh(v) - end - else - Refresh(levels[level]) - end + Dewdrop:argCheck(level, 2, "number", "nil") + if not level then + for k, v in pairs(levels) do Refresh(v) end + else + Refresh(levels[level]) + end end function OpenSlider(parent) - if not sliderFrame then - - sliderFrame = CreateFrame("Frame") - sliderFrame:SetWidth(100) - sliderFrame:SetHeight(170) - sliderFrame:SetScale(UIParent:GetScale()) - sliderFrame:SetBackdrop(tmp( - 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", - 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", - 'tile', true, - 'insets', tmp2( - 'left', 5, - 'right', 5, - 'top', 5, - 'bottom', 5 - ), - 'tileSize', 16, - 'edgeSize', 16 - )) - sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG") - if sliderFrame.SetTopLevel then - sliderFrame:SetTopLevel(true) - end - sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) - sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) - sliderFrame:EnableMouse(true) - sliderFrame:EnableMouseWheel(true) - sliderFrame:Hide() - sliderFrame:SetPoint("CENTER", UIParent, "CENTER") - - local slider = CreateFrame("Slider", nil, sliderFrame) - sliderFrame.slider = slider - slider:SetOrientation("VERTICAL") - slider:SetMinMaxValues(0, 1) - slider:SetValueStep(0.000000001) - slider:SetValue(0.5) - slider:SetWidth(16) - slider:SetHeight(128) - slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) - slider:SetBackdrop(tmp( - 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", - 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", - 'tile', true, - 'edgeSize', 8, - 'tileSize', 8, - 'insets', tmp2( - 'left', 3, - 'right', 3, - 'top', 3, - 'bottom', 3 - ) - )) - local texture = slider:CreateTexture() - slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") - local text = slider:CreateFontString(nil, "ARTWORK") - sliderFrame.topText = text - text:SetFontObject(GameFontGreenSmall) - text:SetText("100%") - text:SetPoint("BOTTOM", slider, "TOP") - local text = slider:CreateFontString(nil, "ARTWORK") - sliderFrame.bottomText = text - text:SetFontObject(GameFontGreenSmall) - text:SetText("0%") - text:SetPoint("TOP", slider, "BOTTOM") - - local editBox = CreateFrame("EditBox", nil, sliderFrame) - sliderFrame.currentText = editBox - editBox:SetFontObject(ChatFontNormal) - editBox:SetHeight(13) - editBox:SetPoint("RIGHT", sliderFrame, "RIGHT", -16, 0) - editBox:SetPoint("LEFT", slider, "RIGHT", 12, 0) - editBox:SetText("50%") - editBox:SetJustifyH("CENTER") - - local width = editBox:GetWidth()/2 + 10 - local left = editBox:CreateTexture(nil, "BACKGROUND") - left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") - left:SetTexCoord(0, width / 256, 0, 1) - left:SetWidth(width) - left:SetHeight(32) - left:SetPoint("LEFT", editBox, "LEFT", -10, 0) - local right = editBox:CreateTexture(nil, "BACKGROUND") - right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") - right:SetTexCoord(1 - width / 256, 1, 0, 1) - right:SetWidth(width) - right:SetHeight(32) - right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) - - local changed = false - local inside = false - slider:SetScript("OnValueChanged", function() - if sliderFrame.changing then - return - end - changed = true - local done = false - if sliderFrame.parent and sliderFrame.parent.sliderFunc then - local min = sliderFrame.parent.sliderMin or 0 - local max = sliderFrame.parent.sliderMax or 1 - local step - if sliderFrame.fineStep then - step = sliderFrame.parent.sliderStep or (max - min) / 100 - else - step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 - end - local value = (1 - slider:GetValue()) * (max - min) + min - if step > 0 then - value = math.floor((value - min) / step + 0.5) * step + min - if value > max then - value = max - elseif value < min then - value = min - end - end - if value == sliderFrame.lastValue then - return - end - sliderFrame.lastValue = value - local text = sliderFrame.parent.sliderFunc(getArgs(sliderFrame.parent, 'sliderArg', 1, value)) - if sliderFrame.parent.fromAceOptions then - text = nil - elseif type(text) == "string" or type(text) == "number" then - sliderFrame.currentText:SetText(text) - done = true - end - end - if not done then - local min = sliderFrame.parent.sliderMin or 0 - local max = sliderFrame.parent.sliderMax or 1 - local step - if sliderFrame.fineStep then - step = sliderFrame.parent.sliderStep or (max - min) / 100 - else - step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 - end - local value = (1 - slider:GetValue()) * (max - min) + min - if step > 0 then - value = math.floor((value - min) / step + 0.5) * step + min - if value > max then - value = max - elseif value < min then - value = min - end - end - if sliderFrame.parent.sliderIsPercent then - sliderFrame.currentText:SetText(string.format("%.0f%%", value * 100)) - else - if step < 0.1 then - sliderFrame.currentText:SetText(string.format("%.2f", value)) - elseif step < 1 then - sliderFrame.currentText:SetText(string.format("%.1f", value)) - else - sliderFrame.currentText:SetText(string.format("%.0f", value)) - end - end - end - end) - local function onEnter() - StopCounting(sliderFrame.level) - showGameTooltip(sliderFrame.parent) - end - local function onLeave() - GameTooltip:Hide() - end - sliderFrame:SetScript("OnEnter", onEnter) - sliderFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - if changed then - local parent = sliderFrame.parent - local sliderFunc = parent.sliderFunc - for i = 1, sliderFrame.level - 1 do - Refresh(levels[i]) - end - local newParent - for _,button in ipairs(levels[sliderFrame.level-1].scrollFrame.child.buttons) do - if button.sliderFunc == sliderFunc then - newParent = button - break - end - end - if newParent then - OpenSlider(newParent) - else - sliderFrame:Hide() - end - end - end) - editBox:SetScript("OnEnter", onEnter) - editBox:SetScript("OnLeave", onLeave) - slider:SetScript("OnMouseDown", function() - sliderFrame.mouseDown = true - GameTooltip:Hide() - end) - slider:SetScript("OnMouseUp", function() - sliderFrame.mouseDown = false - if changed--[[ and not inside]] then - local parent = sliderFrame.parent - local sliderFunc = parent.sliderFunc - for i = 1, sliderFrame.level - 1 do - Refresh(levels[i]) - end - local newParent - for _,button in ipairs(levels[sliderFrame.level-1].scrollFrame.child.buttons) do - if button.sliderFunc == sliderFunc then - newParent = button - break - end - end - if newParent then - OpenSlider(newParent) - else - sliderFrame:Hide() - end - end - if inside then - showGameTooltip(sliderFrame.parent) - end - end) - slider:SetScript("OnEnter", function() - inside = true - StopCounting(sliderFrame.level) - showGameTooltip(sliderFrame.parent) - end) - slider:SetScript("OnLeave", function() - inside = false - GameTooltip:Hide() - if changed and not sliderFrame.mouseDown then - local parent = sliderFrame.parent - local sliderFunc = parent.sliderFunc - for i = 1, sliderFrame.level - 1 do - Refresh(levels[i]) - end - local newParent - for _,button in ipairs(levels[sliderFrame.level-1].scrollFrame.child.buttons) do - if button.sliderFunc == sliderFunc then - newParent = button - break - end - end - if newParent then - OpenSlider(newParent) - else - sliderFrame:Hide() - end - - changed = false - end - end) - sliderFrame:SetScript("OnMouseWheel", function(self, arg1) - local up = arg1 > 0 - - local min = sliderFrame.parent.sliderMin or 0 - local max = sliderFrame.parent.sliderMax or 1 - local step = sliderFrame.parent.sliderStep or (max - min) / 100 - if step <= 0 then - step = (max - min) / 100 - end - - local value = (1 - slider:GetValue()) * (max - min) + min - if up then - value = value + step - else - value = value - step - end - if value > max then - value = max - elseif value < min then - value = min - end - sliderFrame.fineStep = true - if max<=min then - slider:SetValue(0) - else - slider:SetValue(1 - (value - min) / (max - min)) - end - sliderFrame.fineStep = nil - end) - slider:SetScript("OnMouseWheel", sliderFrame:GetScript("OnMouseWheel")) - editBox:SetScript("OnEnterPressed", function() - local value = editBox:GetNumber() - - if sliderFrame.parent.sliderIsPercent then - value = value / 100 - end - - local min = sliderFrame.parent.sliderMin or 0 - local max = sliderFrame.parent.sliderMax or 1 - - if value > max then - value = max - elseif value < min then - value = min - end - sliderFrame.fineStep = true - if max <= min then - slider:SetValue(0) - else - slider:SetValue(1 - (value - min) / (max - min)) - end - sliderFrame.fineStep = nil - - StartCounting(sliderFrame.level) - end) - editBox:SetScript("OnEscapePressed", function() - Dewdrop:Close(sliderFrame.level) - StartCounting(sliderFrame.level) - end) - editBox:SetAutoFocus(false) - end - sliderFrame.parent = parent - sliderFrame.level = parent.level.num + 1 - sliderFrame.parentValue = parent.level.value - sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) - sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) - sliderFrame.currentText:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) - sliderFrame.currentText:ClearFocus() - sliderFrame.changing = true - if not parent.sliderMin or not parent.sliderMax then - return - end - - if parent.arrow then --- parent.arrow:SetVertexColor(0.2, 0.6, 0) --- parent.arrow:SetHeight(24) --- parent.arrow:SetWidth(24) - parent.selected = true - parent.highlight:Show() - end - - sliderFrame:SetClampedToScreen(false) - if not parent.sliderValue then - parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2 - end - if parent.sliderMax <= parent.sliderMin then - sliderFrame.slider:SetValue(0) - else - sliderFrame.slider:SetValue(1 - (parent.sliderValue - parent.sliderMin) / (parent.sliderMax - parent.sliderMin)) - end - sliderFrame.changing = false - sliderFrame.bottomText:SetText(parent.sliderMinText or "0") - sliderFrame.topText:SetText(parent.sliderMaxText or "1") - local text - if parent.sliderFunc and not parent.fromAceOptions then - text = parent.sliderFunc(getArgs(parent, 'sliderArg', 1, parent.sliderValue)) - end - if type(text) == "number" or type(text) == "string" then - sliderFrame.currentText:SetText(text) - elseif parent.sliderIsPercent then - sliderFrame.currentText:SetText(string.format("%.0f%%", parent.sliderValue * 100)) - else - if parent.sliderStep < 0.1 then - sliderFrame.currentText:SetText(string.format("%.2f", parent.sliderValue)) - elseif parent.sliderStep < 1 then - sliderFrame.currentText:SetText(string.format("%.1f", parent.sliderValue)) - else - sliderFrame.currentText:SetText(string.format("%.0f", parent.sliderValue)) - end - end - - - sliderFrame.lastValue = parent.sliderValue - - local level = parent.level - sliderFrame:Show() - sliderFrame:ClearAllPoints() - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) - else - sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) - else - sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) - end - end - local dirty - if level.lastDirection == "RIGHT" then - if sliderFrame:GetRight() > GetScreenWidth() then - level.lastDirection = "LEFT" - dirty = true - end - elseif sliderFrame:GetLeft() < 0 then - level.lastDirection = "RIGHT" - dirty = true - end - if level.lastVDirection == "DOWN" then - if sliderFrame:GetBottom() < 0 then - level.lastVDirection = "UP" - dirty = true - end - elseif sliderFrame:GetTop() > GetScreenWidth() then - level.lastVDirection = "DOWN" - dirty = true - end - if dirty then - sliderFrame:ClearAllPoints() - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) - else - sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) - else - sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) - end - end - end - local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() - sliderFrame:ClearAllPoints() - sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) - if mod(level.num, 5) == 0 then - local left, bottom = level:GetLeft(), level:GetBottom() - level:ClearAllPoints() - level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) - end - sliderFrame:SetClampedToScreen(true) + if not sliderFrame then + + sliderFrame = CreateFrame("Frame") + sliderFrame:SetWidth(100) + sliderFrame:SetHeight(170) + sliderFrame:SetScale(UIParent:GetScale()) + sliderFrame:SetBackdrop(tmp('bgFile', + "Interface\\Tooltips\\UI-Tooltip-Background", + 'edgeFile', + "Interface\\Tooltips\\UI-Tooltip-Border", + 'tile', true, 'insets', tmp2('left', 5, + 'right', 5, + 'top', 5, + 'bottom', 5), + 'tileSize', 16, 'edgeSize', 16)) + sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG") + if sliderFrame.SetTopLevel then sliderFrame:SetTopLevel(true) end + sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, + TOOLTIP_DEFAULT_COLOR.g, + TOOLTIP_DEFAULT_COLOR.b) + sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, + TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, + TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) + sliderFrame:EnableMouse(true) + sliderFrame:EnableMouseWheel(true) + sliderFrame:Hide() + sliderFrame:SetPoint("CENTER", UIParent, "CENTER") + + local slider = CreateFrame("Slider", nil, sliderFrame) + sliderFrame.slider = slider + slider:SetOrientation("VERTICAL") + slider:SetMinMaxValues(0, 1) + slider:SetValueStep(0.000000001) + slider:SetValue(0.5) + slider:SetWidth(16) + slider:SetHeight(128) + slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) + slider:SetBackdrop(tmp('bgFile', + "Interface\\Buttons\\UI-SliderBar-Background", + 'edgeFile', + "Interface\\Buttons\\UI-SliderBar-Border", + 'tile', true, 'edgeSize', 8, 'tileSize', 8, + 'insets', tmp2('left', 3, 'right', 3, 'top', 3, + 'bottom', 3))) + local texture = slider:CreateTexture() + slider:SetThumbTexture( + "Interface\\Buttons\\UI-SliderBar-Button-Vertical") + local text = slider:CreateFontString(nil, "ARTWORK") + sliderFrame.topText = text + text:SetFontObject(GameFontGreenSmall) + text:SetText("100%") + text:SetPoint("BOTTOM", slider, "TOP") + local text = slider:CreateFontString(nil, "ARTWORK") + sliderFrame.bottomText = text + text:SetFontObject(GameFontGreenSmall) + text:SetText("0%") + text:SetPoint("TOP", slider, "BOTTOM") + + local editBox = CreateFrame("EditBox", nil, sliderFrame) + sliderFrame.currentText = editBox + editBox:SetFontObject(ChatFontNormal) + editBox:SetHeight(13) + editBox:SetPoint("RIGHT", sliderFrame, "RIGHT", -16, 0) + editBox:SetPoint("LEFT", slider, "RIGHT", 12, 0) + editBox:SetText("50%") + editBox:SetJustifyH("CENTER") + + local width = editBox:GetWidth() / 2 + 10 + local left = editBox:CreateTexture(nil, "BACKGROUND") + left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") + left:SetTexCoord(0, width / 256, 0, 1) + left:SetWidth(width) + left:SetHeight(32) + left:SetPoint("LEFT", editBox, "LEFT", -10, 0) + local right = editBox:CreateTexture(nil, "BACKGROUND") + right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") + right:SetTexCoord(1 - width / 256, 1, 0, 1) + right:SetWidth(width) + right:SetHeight(32) + right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) + + local changed = false + local inside = false + slider:SetScript("OnValueChanged", function() + if sliderFrame.changing then return end + changed = true + local done = false + if sliderFrame.parent and sliderFrame.parent.sliderFunc then + local min = sliderFrame.parent.sliderMin or 0 + local max = sliderFrame.parent.sliderMax or 1 + local step + if sliderFrame.fineStep then + step = sliderFrame.parent.sliderStep or (max - min) / 100 + else + step = sliderFrame.parent.sliderBigStep or + sliderFrame.parent.sliderStep or (max - min) / + 100 + end + local value = (1 - slider:GetValue()) * (max - min) + min + if step > 0 then + value = math.floor((value - min) / step + 0.5) * step + min + if value > max then + value = max + elseif value < min then + value = min + end + end + if value == sliderFrame.lastValue then return end + sliderFrame.lastValue = value + local text = sliderFrame.parent.sliderFunc(getArgs( + sliderFrame.parent, + 'sliderArg', 1, + value)) + if sliderFrame.parent.fromAceOptions then + text = nil + elseif type(text) == "string" or type(text) == "number" then + sliderFrame.currentText:SetText(text) + done = true + end + end + if not done then + local min = sliderFrame.parent.sliderMin or 0 + local max = sliderFrame.parent.sliderMax or 1 + local step + if sliderFrame.fineStep then + step = sliderFrame.parent.sliderStep or (max - min) / 100 + else + step = sliderFrame.parent.sliderBigStep or + sliderFrame.parent.sliderStep or (max - min) / + 100 + end + local value = (1 - slider:GetValue()) * (max - min) + min + if step > 0 then + value = math.floor((value - min) / step + 0.5) * step + min + if value > max then + value = max + elseif value < min then + value = min + end + end + if sliderFrame.parent.sliderIsPercent then + sliderFrame.currentText:SetText( + string.format("%.0f%%", value * 100)) + else + if step < 0.1 then + sliderFrame.currentText:SetText( + string.format("%.2f", value)) + elseif step < 1 then + sliderFrame.currentText:SetText( + string.format("%.1f", value)) + else + sliderFrame.currentText:SetText( + string.format("%.0f", value)) + end + end + end + end) + local function onEnter() + StopCounting(sliderFrame.level) + showGameTooltip(sliderFrame.parent) + end + local function onLeave() GameTooltip:Hide() end + sliderFrame:SetScript("OnEnter", onEnter) + sliderFrame:SetScript("OnLeave", function() + GameTooltip:Hide() + if changed then + local parent = sliderFrame.parent + local sliderFunc = parent.sliderFunc + for i = 1, sliderFrame.level - 1 do + Refresh(levels[i]) + end + local newParent + for _, button in ipairs(levels[sliderFrame.level - 1] + .scrollFrame.child.buttons) do + if button.sliderFunc == sliderFunc then + newParent = button + break + end + end + if newParent then + OpenSlider(newParent) + else + sliderFrame:Hide() + end + end + end) + editBox:SetScript("OnEnter", onEnter) + editBox:SetScript("OnLeave", onLeave) + slider:SetScript("OnMouseDown", function() + sliderFrame.mouseDown = true + GameTooltip:Hide() + end) + slider:SetScript("OnMouseUp", function() + sliderFrame.mouseDown = false + if changed --[[ and not inside]] then + local parent = sliderFrame.parent + local sliderFunc = parent.sliderFunc + for i = 1, sliderFrame.level - 1 do + Refresh(levels[i]) + end + local newParent + for _, button in ipairs(levels[sliderFrame.level - 1] + .scrollFrame.child.buttons) do + if button.sliderFunc == sliderFunc then + newParent = button + break + end + end + if newParent then + OpenSlider(newParent) + else + sliderFrame:Hide() + end + end + if inside then showGameTooltip(sliderFrame.parent) end + end) + slider:SetScript("OnEnter", function() + inside = true + StopCounting(sliderFrame.level) + showGameTooltip(sliderFrame.parent) + end) + slider:SetScript("OnLeave", function() + inside = false + GameTooltip:Hide() + if changed and not sliderFrame.mouseDown then + local parent = sliderFrame.parent + local sliderFunc = parent.sliderFunc + for i = 1, sliderFrame.level - 1 do + Refresh(levels[i]) + end + local newParent + for _, button in ipairs(levels[sliderFrame.level - 1] + .scrollFrame.child.buttons) do + if button.sliderFunc == sliderFunc then + newParent = button + break + end + end + if newParent then + OpenSlider(newParent) + else + sliderFrame:Hide() + end + + changed = false + end + end) + sliderFrame:SetScript("OnMouseWheel", function(self, arg1) + local up = arg1 > 0 + + local min = sliderFrame.parent.sliderMin or 0 + local max = sliderFrame.parent.sliderMax or 1 + local step = sliderFrame.parent.sliderStep or (max - min) / 100 + if step <= 0 then step = (max - min) / 100 end + + local value = (1 - slider:GetValue()) * (max - min) + min + if up then + value = value + step + else + value = value - step + end + if value > max then + value = max + elseif value < min then + value = min + end + sliderFrame.fineStep = true + if max <= min then + slider:SetValue(0) + else + slider:SetValue(1 - (value - min) / (max - min)) + end + sliderFrame.fineStep = nil + end) + slider:SetScript("OnMouseWheel", sliderFrame:GetScript("OnMouseWheel")) + editBox:SetScript("OnEnterPressed", function() + local value = editBox:GetNumber() + + if sliderFrame.parent.sliderIsPercent then + value = value / 100 + end + + local min = sliderFrame.parent.sliderMin or 0 + local max = sliderFrame.parent.sliderMax or 1 + + if value > max then + value = max + elseif value < min then + value = min + end + sliderFrame.fineStep = true + if max <= min then + slider:SetValue(0) + else + slider:SetValue(1 - (value - min) / (max - min)) + end + sliderFrame.fineStep = nil + + StartCounting(sliderFrame.level) + end) + editBox:SetScript("OnEscapePressed", function() + Dewdrop:Close(sliderFrame.level) + StartCounting(sliderFrame.level) + end) + editBox:SetAutoFocus(false) + end + sliderFrame.parent = parent + sliderFrame.level = parent.level.num + 1 + sliderFrame.parentValue = parent.level.value + sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) + sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) + sliderFrame.currentText:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) + sliderFrame.currentText:ClearFocus() + sliderFrame.changing = true + if not parent.sliderMin or not parent.sliderMax then return end + + if parent.arrow then + -- parent.arrow:SetVertexColor(0.2, 0.6, 0) + -- parent.arrow:SetHeight(24) + -- parent.arrow:SetWidth(24) + parent.selected = true + parent.highlight:Show() + end + + sliderFrame:SetClampedToScreen(false) + if not parent.sliderValue then + parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2 + end + if parent.sliderMax <= parent.sliderMin then + sliderFrame.slider:SetValue(0) + else + sliderFrame.slider:SetValue( + 1 - (parent.sliderValue - parent.sliderMin) / + (parent.sliderMax - parent.sliderMin)) + end + sliderFrame.changing = false + sliderFrame.bottomText:SetText(parent.sliderMinText or "0") + sliderFrame.topText:SetText(parent.sliderMaxText or "1") + local text + if parent.sliderFunc and not parent.fromAceOptions then + text = parent.sliderFunc(getArgs(parent, 'sliderArg', 1, + parent.sliderValue)) + end + if type(text) == "number" or type(text) == "string" then + sliderFrame.currentText:SetText(text) + elseif parent.sliderIsPercent then + sliderFrame.currentText:SetText(string.format("%.0f%%", + parent.sliderValue * 100)) + else + if parent.sliderStep < 0.1 then + sliderFrame.currentText:SetText( + string.format("%.2f", parent.sliderValue)) + elseif parent.sliderStep < 1 then + sliderFrame.currentText:SetText( + string.format("%.1f", parent.sliderValue)) + else + sliderFrame.currentText:SetText( + string.format("%.0f", parent.sliderValue)) + end + end + + sliderFrame.lastValue = parent.sliderValue + + local level = parent.level + sliderFrame:Show() + sliderFrame:ClearAllPoints() + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) + else + sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) + end + else + if level.lastVDirection == "DOWN" then + sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) + else + sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) + end + end + local dirty + if level.lastDirection == "RIGHT" then + if sliderFrame:GetRight() > GetScreenWidth() then + level.lastDirection = "LEFT" + dirty = true + end + elseif sliderFrame:GetLeft() < 0 then + level.lastDirection = "RIGHT" + dirty = true + end + if level.lastVDirection == "DOWN" then + if sliderFrame:GetBottom() < 0 then + level.lastVDirection = "UP" + dirty = true + end + elseif sliderFrame:GetTop() > GetScreenWidth() then + level.lastVDirection = "DOWN" + dirty = true + end + if dirty then + sliderFrame:ClearAllPoints() + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) + else + sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) + end + else + if level.lastVDirection == "DOWN" then + sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) + else + sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, + -10) + end + end + end + local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() + sliderFrame:ClearAllPoints() + sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) + if mod(level.num, 5) == 0 then + local left, bottom = level:GetLeft(), level:GetBottom() + level:ClearAllPoints() + level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) + end + sliderFrame:SetClampedToScreen(true) end function OpenEditBox(parent) - if not editBoxFrame then - editBoxFrame = CreateFrame("Frame", nil, nil, BackdropTemplateMixin and "BackdropTemplate") - editBoxFrame:SetWidth(200) - editBoxFrame:SetHeight(40) - editBoxFrame:SetScale(UIParent:GetScale()) - editBoxFrame:SetBackdrop(tmp( - 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", - 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", - 'tile', true, - 'insets', tmp2( - 'left', 5, - 'right', 5, - 'top', 5, - 'bottom', 5 - ), - 'tileSize', 16, - 'edgeSize', 16 - )) - editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG") - if editBoxFrame.SetTopLevel then - editBoxFrame:SetTopLevel(true) - end - editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) - editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) - editBoxFrame:EnableMouse(true) - editBoxFrame:EnableMouseWheel(true) - editBoxFrame:Hide() - editBoxFrame:SetPoint("CENTER", UIParent, "CENTER") - - local editBox = CreateFrame("EditBox", nil, editBoxFrame) - editBoxFrame.editBox = editBox - editBox:SetFontObject(ChatFontNormal) - editBox:SetWidth(160) - editBox:SetHeight(13) - editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0) - - local left = editBox:CreateTexture(nil, "BACKGROUND") - left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") - left:SetTexCoord(0, 100 / 256, 0, 1) - left:SetWidth(100) - left:SetHeight(32) - left:SetPoint("LEFT", editBox, "LEFT", -10, 0) - local right = editBox:CreateTexture(nil, "BACKGROUND") - right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") - right:SetTexCoord(156/256, 1, 0, 1) - right:SetWidth(100) - right:SetHeight(32) - right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) - - editBox:SetScript("OnEnterPressed", function() - if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then - local t = editBox.realText or editBox:GetText() or "" - local result = editBoxFrame.parent.editBoxValidateFunc(getArgs(editBoxFrame.parent, 'editBoxValidateArg', 1, t)) - if not result then - UIErrorsFrame:AddMessage(VALIDATION_ERROR, 1, 0, 0) - return - end - end - if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then - local t - if editBox.realText ~= "NONE" then - t = editBox.realText or editBox:GetText() or "" - end - editBoxFrame.parent.editBoxFunc(getArgs(editBoxFrame.parent, 'editBoxArg', 1, t)) - end - Dewdrop:Close(editBoxFrame.level) - for i = 1, editBoxFrame.level - 1 do - Refresh(levels[i]) - end - StartCounting(editBoxFrame.level-1) - end) - editBox:SetScript("OnEscapePressed", function() - Dewdrop:Close(editBoxFrame.level) - StartCounting(editBoxFrame.level-1) - end) - editBox:SetScript("OnReceiveDrag", function() - if GetCursorInfo then - local type, alpha, bravo = GetCursorInfo() - local text - if type == "spell" then - text = GetSpellName(alpha, bravo) - elseif type == "item" then - text = bravo - end - if not text then - return - end - ClearCursor() - editBox:SetText(text) - end - end) - local changing = false - local skipNext = false - - function editBox:SpecialSetText(text) - local oldText = editBox:GetText() or "" - if not text then - text = "" - end - if text ~= oldText then - changing = true - self:SetText(tostring(text)) - changing = false - skipNext = true - end - end - - editBox:SetScript("OnTextChanged", function() - if skipNext then - skipNext = false - elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then - local t - if editBox.realText ~= "NONE" then - t = editBox.realText or editBox:GetText() or "" - end - local text = editBoxFrame.parent.editBoxChangeFunc(getArgs(editBoxFrame.parent, 'editBoxChangeArg', 1, t)) - if text then - editBox:SpecialSetText(text) - end - end - end) - editBoxFrame:SetScript("OnEnter", function() - StopCounting(editBoxFrame.level) - showGameTooltip(editBoxFrame.parent) - end) - editBoxFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - editBox:SetScript("OnEnter", function() - StopCounting(editBoxFrame.level) - showGameTooltip(editBoxFrame.parent) - end) - editBox:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - editBoxFrame:SetScript("OnKeyDown", function(self, arg1) - if not editBox.keybinding then - return - end - local screenshotKey = GetBindingKey("SCREENSHOT") - if screenshotKey and arg1 == screenshotKey then - Screenshot() - return - end - - if arg1 == "LeftButton" then - arg1 = "BUTTON1" - elseif arg1 == "RightButton" then - arg1 = "BUTTON2" - elseif arg1 == "MiddleButton" then - arg1 = "BUTTON3" - elseif arg1 == "Button4" then - arg1 = "BUTTON4" - elseif arg1 == "Button5" then - arg1 = "BUTTON5" - end - if arg1 == "UNKNOWN" then - return - elseif arg1 == "SHIFT" or arg1 == "CTRL" or arg1 == "ALT" then - return - elseif arg1 == "ENTER" then - if editBox.keybindingOnly and not editBox.keybindingOnly[editBox.realText] then - return editBox:GetScript("OnEscapePressed")() - elseif editBox.keybindingExcept and editBox.keybindingExcept[editBox.realText] then - return editBox:GetScript("OnEscapePressed")() - else - return editBox:GetScript("OnEnterPressed")() - end - elseif arg1 == "ESCAPE" then - if editBox.realText == "NONE" then - return editBox:GetScript("OnEscapePressed")() - else - editBox:SpecialSetText(NONE or "NONE") - editBox.realText = "NONE" - return - end - elseif editBox.keybindingOnly and not editBox.keybindingOnly[arg1] then - return - elseif editBox.keybindingExcept and editBox.keybindingExcept[arg1] then - return - end - local s = GetBindingText(arg1, "KEY_") - if s == "BUTTON1" then - s = KEY_BUTTON1 - elseif s == "BUTTON2" then - s = KEY_BUTTON2 - end - local real = arg1 - if IsShiftKeyDown() then - s = "Shift-" .. s - real = "SHIFT-" .. real - end - if IsControlKeyDown() then - s = "Ctrl-" .. s - real = "CTRL-" .. real - end - if IsAltKeyDown() then - s = "Alt-" .. s - real = "ALT-" .. real - end - if editBox:GetText() ~= s then - editBox:SpecialSetText("-") - editBox:SpecialSetText(s) - editBox.realText = real - return editBox:GetScript("OnTextChanged")() - end - end) - editBoxFrame:SetScript("OnMouseDown", editBoxFrame:GetScript("OnKeyDown")) - editBox:SetScript("OnMouseDown", function(self, ...) - if GetCursorInfo and (CursorHasItem() or CursorHasSpell()) then - return editBox:GetScript("OnReceiveDrag")(self, ...) - end - return editBoxFrame:GetScript("OnKeyDown")(self, ...) - end) - editBoxFrame:SetScript("OnMouseWheel", function(self, arg1) - local up = ( arg1 > 0 ) and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" - return editBoxFrame:GetScript("OnKeyDown")(self, up) - end) - editBox:SetScript("OnMouseWheel", editBoxFrame:GetScript("OnMouseWheel")) - end - editBoxFrame.parent = parent - editBoxFrame.level = parent.level.num + 1 - editBoxFrame.parentValue = parent.level.value - editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) - editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1) - editBoxFrame.editBox.realText = nil - editBoxFrame:SetClampedToScreen(false) - - editBoxFrame.editBox:SpecialSetText("") - if parent.editBoxIsKeybinding then - local s = parent.editBoxText - if s == "" then - s = "NONE" - end - editBoxFrame.editBox.realText = s - if s and s ~= "NONE" then - local alpha,bravo = s:match("^(.+)%-(.+)$") - if not bravo then - alpha = nil - bravo = s - end - bravo = GetBindingText(bravo, "KEY_") - if alpha then - editBoxFrame.editBox:SpecialSetText(alpha:upper() .. "-" .. bravo) - else - editBoxFrame.editBox:SpecialSetText(bravo) - end - else - editBoxFrame.editBox:SpecialSetText(NONE or "NONE") - end - else - editBoxFrame.editBox:SpecialSetText(parent.editBoxText) - end - - editBoxFrame.editBox.keybinding = parent.editBoxIsKeybinding - editBoxFrame.editBox.keybindingOnly = parent.editBoxKeybindingOnly - editBoxFrame.editBox.keybindingExcept = parent.editBoxKeybindingExcept - editBoxFrame.editBox:EnableKeyboard(not parent.editBoxIsKeybinding) - editBoxFrame:EnableKeyboard(parent.editBoxIsKeybinding) - - if parent.arrow then --- parent.arrow:SetVertexColor(0.2, 0.6, 0) --- parent.arrow:SetHeight(24) --- parent.arrow:SetWidth(24) - parent.selected = true - parent.highlight:Show() - end - - local level = parent.level - editBoxFrame:Show() - editBoxFrame:ClearAllPoints() - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) - else - editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) - else - editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) - end - end - local dirty - if level.lastDirection == "RIGHT" then - if editBoxFrame:GetRight() > GetScreenWidth() then - level.lastDirection = "LEFT" - dirty = true - end - elseif editBoxFrame:GetLeft() < 0 then - level.lastDirection = "RIGHT" - dirty = true - end - if level.lastVDirection == "DOWN" then - if editBoxFrame:GetBottom() < 0 then - level.lastVDirection = "UP" - dirty = true - end - elseif editBoxFrame:GetTop() > GetScreenWidth() then - level.lastVDirection = "DOWN" - dirty = true - end - if dirty then - editBoxFrame:ClearAllPoints() - if level.lastDirection == "RIGHT" then - if level.lastVDirection == "DOWN" then - editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) - else - editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) - end - else - if level.lastVDirection == "DOWN" then - editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) - else - editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) - end - end - end - local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom() - editBoxFrame:ClearAllPoints() - editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) - if mod(level.num, 5) == 0 then - local left, bottom = level:GetLeft(), level:GetBottom() - level:ClearAllPoints() - level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) - end - editBoxFrame:SetClampedToScreen(true) + if not editBoxFrame then + editBoxFrame = CreateFrame("Frame", nil, nil, + BackdropTemplateMixin and "BackdropTemplate") + editBoxFrame:SetWidth(200) + editBoxFrame:SetHeight(40) + editBoxFrame:SetScale(UIParent:GetScale()) + editBoxFrame:SetBackdrop(tmp('bgFile', + "Interface\\Tooltips\\UI-Tooltip-Background", + 'edgeFile', + "Interface\\Tooltips\\UI-Tooltip-Border", + 'tile', true, 'insets', tmp2('left', 5, + 'right', 5, + 'top', 5, + 'bottom', 5), + 'tileSize', 16, 'edgeSize', 16)) + editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG") + if editBoxFrame.SetTopLevel then editBoxFrame:SetTopLevel(true) end + editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, + TOOLTIP_DEFAULT_COLOR.g, + TOOLTIP_DEFAULT_COLOR.b) + editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, + TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, + TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) + editBoxFrame:EnableMouse(true) + editBoxFrame:EnableMouseWheel(true) + editBoxFrame:Hide() + editBoxFrame:SetPoint("CENTER", UIParent, "CENTER") + + local editBox = CreateFrame("EditBox", nil, editBoxFrame) + editBoxFrame.editBox = editBox + editBox:SetFontObject(ChatFontNormal) + editBox:SetWidth(160) + editBox:SetHeight(13) + editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0) + + local left = editBox:CreateTexture(nil, "BACKGROUND") + left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") + left:SetTexCoord(0, 100 / 256, 0, 1) + left:SetWidth(100) + left:SetHeight(32) + left:SetPoint("LEFT", editBox, "LEFT", -10, 0) + local right = editBox:CreateTexture(nil, "BACKGROUND") + right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") + right:SetTexCoord(156 / 256, 1, 0, 1) + right:SetWidth(100) + right:SetHeight(32) + right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) + + editBox:SetScript("OnEnterPressed", function() + if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then + local t = editBox.realText or editBox:GetText() or "" + local result = editBoxFrame.parent.editBoxValidateFunc(getArgs( + editBoxFrame.parent, + 'editBoxValidateArg', + 1, t)) + if not result then + UIErrorsFrame:AddMessage(VALIDATION_ERROR, 1, 0, 0) + return + end + end + if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then + local t + if editBox.realText ~= "NONE" then + t = editBox.realText or editBox:GetText() or "" + end + editBoxFrame.parent.editBoxFunc( + getArgs(editBoxFrame.parent, 'editBoxArg', 1, t)) + end + Dewdrop:Close(editBoxFrame.level) + for i = 1, editBoxFrame.level - 1 do Refresh(levels[i]) end + StartCounting(editBoxFrame.level - 1) + end) + editBox:SetScript("OnEscapePressed", function() + Dewdrop:Close(editBoxFrame.level) + StartCounting(editBoxFrame.level - 1) + end) + editBox:SetScript("OnReceiveDrag", function() + if GetCursorInfo then + local type, alpha, bravo = GetCursorInfo() + local text + if type == "spell" then + text = GetSpellName(alpha, bravo) + elseif type == "item" then + text = bravo + end + if not text then return end + ClearCursor() + editBox:SetText(text) + end + end) + local changing = false + local skipNext = false + + function editBox:SpecialSetText(text) + local oldText = editBox:GetText() or "" + if not text then text = "" end + if text ~= oldText then + changing = true + self:SetText(tostring(text)) + changing = false + skipNext = true + end + end + + editBox:SetScript("OnTextChanged", function() + if skipNext then + skipNext = false + elseif not changing and editBoxFrame.parent and + editBoxFrame.parent.editBoxChangeFunc then + local t + if editBox.realText ~= "NONE" then + t = editBox.realText or editBox:GetText() or "" + end + local text = editBoxFrame.parent.editBoxChangeFunc(getArgs( + editBoxFrame.parent, + 'editBoxChangeArg', + 1, t)) + if text then editBox:SpecialSetText(text) end + end + end) + editBoxFrame:SetScript("OnEnter", function() + StopCounting(editBoxFrame.level) + showGameTooltip(editBoxFrame.parent) + end) + editBoxFrame:SetScript("OnLeave", function() GameTooltip:Hide() end) + editBox:SetScript("OnEnter", function() + StopCounting(editBoxFrame.level) + showGameTooltip(editBoxFrame.parent) + end) + editBox:SetScript("OnLeave", function() GameTooltip:Hide() end) + editBoxFrame:SetScript("OnKeyDown", function(self, arg1) + if not editBox.keybinding then return end + local screenshotKey = GetBindingKey("SCREENSHOT") + if screenshotKey and arg1 == screenshotKey then + Screenshot() + return + end + + if arg1 == "LeftButton" then + arg1 = "BUTTON1" + elseif arg1 == "RightButton" then + arg1 = "BUTTON2" + elseif arg1 == "MiddleButton" then + arg1 = "BUTTON3" + elseif arg1 == "Button4" then + arg1 = "BUTTON4" + elseif arg1 == "Button5" then + arg1 = "BUTTON5" + end + if arg1 == "UNKNOWN" then + return + elseif arg1 == "SHIFT" or arg1 == "CTRL" or arg1 == "ALT" then + return + elseif arg1 == "ENTER" then + if editBox.keybindingOnly and + not editBox.keybindingOnly[editBox.realText] then + return editBox:GetScript("OnEscapePressed")() + elseif editBox.keybindingExcept and + editBox.keybindingExcept[editBox.realText] then + return editBox:GetScript("OnEscapePressed")() + else + return editBox:GetScript("OnEnterPressed")() + end + elseif arg1 == "ESCAPE" then + if editBox.realText == "NONE" then + return editBox:GetScript("OnEscapePressed")() + else + editBox:SpecialSetText(NONE or "NONE") + editBox.realText = "NONE" + return + end + elseif editBox.keybindingOnly and not editBox.keybindingOnly[arg1] then + return + elseif editBox.keybindingExcept and editBox.keybindingExcept[arg1] then + return + end + local s = GetBindingText(arg1, "KEY_") + if s == "BUTTON1" then + s = KEY_BUTTON1 + elseif s == "BUTTON2" then + s = KEY_BUTTON2 + end + local real = arg1 + if IsShiftKeyDown() then + s = "Shift-" .. s + real = "SHIFT-" .. real + end + if IsControlKeyDown() then + s = "Ctrl-" .. s + real = "CTRL-" .. real + end + if IsAltKeyDown() then + s = "Alt-" .. s + real = "ALT-" .. real + end + if editBox:GetText() ~= s then + editBox:SpecialSetText("-") + editBox:SpecialSetText(s) + editBox.realText = real + return editBox:GetScript("OnTextChanged")() + end + end) + editBoxFrame:SetScript("OnMouseDown", + editBoxFrame:GetScript("OnKeyDown")) + editBox:SetScript("OnMouseDown", function(self, ...) + if GetCursorInfo and (CursorHasItem() or CursorHasSpell()) then + return editBox:GetScript("OnReceiveDrag")(self, ...) + end + return editBoxFrame:GetScript("OnKeyDown")(self, ...) + end) + editBoxFrame:SetScript("OnMouseWheel", function(self, arg1) + local up = (arg1 > 0) and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" + return editBoxFrame:GetScript("OnKeyDown")(self, up) + end) + editBox:SetScript("OnMouseWheel", editBoxFrame:GetScript("OnMouseWheel")) + end + editBoxFrame.parent = parent + editBoxFrame.level = parent.level.num + 1 + editBoxFrame.parentValue = parent.level.value + editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) + editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1) + editBoxFrame.editBox.realText = nil + editBoxFrame:SetClampedToScreen(false) + + editBoxFrame.editBox:SpecialSetText("") + if parent.editBoxIsKeybinding then + local s = parent.editBoxText + if s == "" then s = "NONE" end + editBoxFrame.editBox.realText = s + if s and s ~= "NONE" then + local alpha, bravo = s:match("^(.+)%-(.+)$") + if not bravo then + alpha = nil + bravo = s + end + bravo = GetBindingText(bravo, "KEY_") + if alpha then + editBoxFrame.editBox:SpecialSetText( + alpha:upper() .. "-" .. bravo) + else + editBoxFrame.editBox:SpecialSetText(bravo) + end + else + editBoxFrame.editBox:SpecialSetText(NONE or "NONE") + end + else + editBoxFrame.editBox:SpecialSetText(parent.editBoxText) + end + + editBoxFrame.editBox.keybinding = parent.editBoxIsKeybinding + editBoxFrame.editBox.keybindingOnly = parent.editBoxKeybindingOnly + editBoxFrame.editBox.keybindingExcept = parent.editBoxKeybindingExcept + editBoxFrame.editBox:EnableKeyboard(not parent.editBoxIsKeybinding) + editBoxFrame:EnableKeyboard(parent.editBoxIsKeybinding) + + if parent.arrow then + -- parent.arrow:SetVertexColor(0.2, 0.6, 0) + -- parent.arrow:SetHeight(24) + -- parent.arrow:SetWidth(24) + parent.selected = true + parent.highlight:Show() + end + + local level = parent.level + editBoxFrame:Show() + editBoxFrame:ClearAllPoints() + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) + else + editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) + end + else + if level.lastVDirection == "DOWN" then + editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) + else + editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) + end + end + local dirty + if level.lastDirection == "RIGHT" then + if editBoxFrame:GetRight() > GetScreenWidth() then + level.lastDirection = "LEFT" + dirty = true + end + elseif editBoxFrame:GetLeft() < 0 then + level.lastDirection = "RIGHT" + dirty = true + end + if level.lastVDirection == "DOWN" then + if editBoxFrame:GetBottom() < 0 then + level.lastVDirection = "UP" + dirty = true + end + elseif editBoxFrame:GetTop() > GetScreenWidth() then + level.lastVDirection = "DOWN" + dirty = true + end + if dirty then + editBoxFrame:ClearAllPoints() + if level.lastDirection == "RIGHT" then + if level.lastVDirection == "DOWN" then + editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) + else + editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, + -10) + end + else + if level.lastVDirection == "DOWN" then + editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) + else + editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, + -10) + end + end + end + local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom() + editBoxFrame:ClearAllPoints() + editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) + if mod(level.num, 5) == 0 then + local left, bottom = level:GetLeft(), level:GetBottom() + level:ClearAllPoints() + level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) + end + editBoxFrame:SetClampedToScreen(true) end function Dewdrop:EncodeKeybinding(text) - if text == nil or text == "NONE" then - return nil - end - text = tostring(text):upper() - local shift, ctrl, alt - local modifier - while true do - if text == "-" then - break - end - modifier, text = strsplit('-', text, 2) - if text then - if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then - return false - end - if modifier == "SHIFT" then - if shift then - return false - end - shift = true - end - if modifier == "CTRL" then - if ctrl then - return false - end - ctrl = true - end - if modifier == "ALT" then - if alt then - return false - end - alt = true - end - else - text = modifier - break - end - end - if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:len() == 0 or text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] and text ~= "BUTTON1" and text ~= "BUTTON2" then - return false - end - local s = GetBindingText(text, "KEY_") - if s == "BUTTON1" then - s = KEY_BUTTON1 - elseif s == "BUTTON2" then - s = KEY_BUTTON2 - end - if shift then - s = "Shift-" .. s - end - if ctrl then - s = "Ctrl-" .. s - end - if alt then - s = "Alt-" .. s - end - return s + if text == nil or text == "NONE" then return nil end + text = tostring(text):upper() + local shift, ctrl, alt + local modifier + while true do + if text == "-" then break end + modifier, text = strsplit('-', text, 2) + if text then + if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then + return false + end + if modifier == "SHIFT" then + if shift then return false end + shift = true + end + if modifier == "CTRL" then + if ctrl then return false end + ctrl = true + end + if modifier == "ALT" then + if alt then return false end + alt = true + end + else + text = modifier + break + end + end + if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and + (text:len() == 0 or text:byte() < 128 or text:len() > 4) and + not _G["KEY_" .. text] and text ~= "BUTTON1" and text ~= "BUTTON2" then + return false + end + local s = GetBindingText(text, "KEY_") + if s == "BUTTON1" then + s = KEY_BUTTON1 + elseif s == "BUTTON2" then + s = KEY_BUTTON2 + end + if shift then s = "Shift-" .. s end + if ctrl then s = "Ctrl-" .. s end + if alt then s = "Alt-" .. s end + return s end local function GetTipAnchor(frame) - local x, y = frame:GetCenter() - if not x or not y then return "TOPLEFT", "BOTTOMLEFT" 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 + local x, y = frame:GetCenter() + if not x or not y then return "TOPLEFT", "BOTTOMLEFT" 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 function Dewdrop:SmartAnchorTo(frame) - if not frame then - error("Invalid frame provided.", 2) - end - if (levels[1] and levels[1]:IsShown()) then - levels[1]:ClearAllPoints() - levels[1]:SetClampedToScreen(true) - levels[1]:SetPoint(GetTipAnchor(frame)) - end + if not frame then error("Invalid frame provided.", 2) end + if (levels[1] and levels[1]:IsShown()) then + levels[1]:ClearAllPoints() + levels[1]:SetClampedToScreen(true) + levels[1]:SetPoint(GetTipAnchor(frame)) + end end function Dewdrop:IsOpen(parent) - self:argCheck(parent, 2, "table", "string", "nil") - return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent()) + self:argCheck(parent, 2, "table", "string", "nil") + return levels[1] and levels[1]:IsShown() and + (not parent or parent == levels[1].parent or parent == + levels[1]:GetParent()) end function Dewdrop:GetOpenedParent() - return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent()) + return (levels[1] and levels[1]:IsShown()) and + (levels[1].parent or levels[1]:GetParent()) end function Open(parent, func, level, value, point, relativePoint, cursorX, cursorY) - Dewdrop:Close(level) - if type(parent) == "table" then - parent:GetCenter() - end - local frame = AcquireLevel(level) - if level == 1 then - frame.lastDirection = "RIGHT" - frame.lastVDirection = "DOWN" - else - frame.lastDirection = levels[level - 1].lastDirection - frame.lastVDirection = levels[level - 1].lastVDirection - end - frame:SetFrameStrata("FULLSCREEN_DIALOG") - frame:ClearAllPoints() - frame.parent = parent - frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) - frame:Show() - - if level == 1 then - baseFunc = func - end - levels[level].value = value --- levels[level].parentText = parent.text and parent.text:GetText() or nil --- levels[level].parentTooltipTitle = parent.tooltipTitle --- levels[level].parentTooltipText = parent.tooltipText --- levels[level].parentTooltipFunc = parent.tooltipFunc - if type(parent) == "table" and parent.arrow then --- parent.arrow:SetVertexColor(0.2, 0.6, 0) --- parent.arrow:SetHeight(24) --- parent.arrow:SetWidth(24) - parent.selected = true - parent.highlight:Show() - end - relativePoint = relativePoint or point - Refresh(levels[level]) - if point or (cursorX and cursorY) then - frame:ClearAllPoints() - if cursorX and cursorY then - local curX, curY = GetScaledCursorPosition() - if curY < GetScreenHeight() / 2 then - point, relativePoint = "BOTTOM", "BOTTOM" - else - point, relativePoint = "TOP", "TOP" - end - if curX < GetScreenWidth() / 2 then - point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT" - else - point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT" - end - end - frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint) - if cursorX and cursorY then - local left = frame:GetLeft() - local width = frame:GetWidth() - local bottom = frame:GetBottom() - local height = frame:GetHeight() - local curX, curY = GetScaledCursorPosition() - frame:ClearAllPoints() - relativePoint = relativePoint or point - if point == "BOTTOM" or point == "TOP" then - if curX < GetScreenWidth() / 2 then - point = point .. "LEFT" - else - point = point .. "RIGHT" - end - elseif point == "CENTER" then - if curX < GetScreenWidth() / 2 then - point = "LEFT" - else - point = "RIGHT" - end - end - local xOffset, yOffset = 0, 0 - if curY > GetScreenHeight() / 2 then - yOffset = -height - end - if curX > GetScreenWidth() / 2 then - xOffset = -width - end - frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left + xOffset, curY - bottom + yOffset) - if level == 1 then - frame.lastDirection = "RIGHT" - end - elseif cursorX then - local left = frame:GetLeft() - local width = frame:GetWidth() - local curX, curY = GetScaledCursorPosition() - frame:ClearAllPoints() - relativePoint = relativePoint or point - if point == "BOTTOM" or point == "TOP" then - if curX < GetScreenWidth() / 2 then - point = point .. "LEFT" - else - point = point .. "RIGHT" - end - elseif point == "CENTER" then - if curX < GetScreenWidth() / 2 then - point = "LEFT" - else - point = "RIGHT" - end - end - frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left - width / 2, 0) - if level == 1 then - frame.lastDirection = "RIGHT" - end - elseif cursorY then - local bottom = frame:GetBottom() - local height = frame:GetHeight() - local curX, curY = GetScaledCursorPosition() - frame:ClearAllPoints() - relativePoint = relativePoint or point - if point == "LEFT" or point == "RIGHT" then - if curX < GetScreenHeight() / 2 then - point = point .. "BOTTOM" - else - point = point .. "TOP" - end - elseif point == "CENTER" then - if curX < GetScreenHeight() / 2 then - point = "BOTTOM" - else - point = "TOP" - end - end - frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, 0, curY - bottom - height / 2) - if level == 1 then - frame.lastDirection = "DOWN" - end - end - if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then - if frame:GetBottom() < 0 then - local point, parent, relativePoint, x, y = frame:GetPoint(1) - local change = GetScreenHeight() - frame:GetTop() - local otherChange = -frame:GetBottom() - if otherChange < change then - change = otherChange - end - frame:SetPoint(point, parent, relativePoint, x, y + change) - elseif frame:GetTop() > GetScreenHeight() then - local point, parent, relativePoint, x, y = frame:GetPoint(1) - local change = GetScreenHeight() - frame:GetTop() - local otherChange = -frame:GetBottom() - if otherChange < change then - change = otherChange - end - frame:SetPoint(point, parent, relativePoint, x, y + change) - end - end - end - CheckDualMonitor(frame) - frame:SetClampedToScreen(true) - frame:SetClampedToScreen(false) - StartCounting(level) + Dewdrop:Close(level) + if type(parent) == "table" then parent:GetCenter() end + local frame = AcquireLevel(level) + if level == 1 then + frame.lastDirection = "RIGHT" + frame.lastVDirection = "DOWN" + else + frame.lastDirection = levels[level - 1].lastDirection + frame.lastVDirection = levels[level - 1].lastVDirection + end + frame:SetFrameStrata("FULLSCREEN_DIALOG") + frame:ClearAllPoints() + frame.parent = parent + frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) + frame:Show() + + if level == 1 then baseFunc = func end + levels[level].value = value + -- levels[level].parentText = parent.text and parent.text:GetText() or nil + -- levels[level].parentTooltipTitle = parent.tooltipTitle + -- levels[level].parentTooltipText = parent.tooltipText + -- levels[level].parentTooltipFunc = parent.tooltipFunc + if type(parent) == "table" and parent.arrow then + -- parent.arrow:SetVertexColor(0.2, 0.6, 0) + -- parent.arrow:SetHeight(24) + -- parent.arrow:SetWidth(24) + parent.selected = true + parent.highlight:Show() + end + relativePoint = relativePoint or point + Refresh(levels[level]) + if point or (cursorX and cursorY) then + frame:ClearAllPoints() + if cursorX and cursorY then + local curX, curY = GetScaledCursorPosition() + if curY < GetScreenHeight() / 2 then + point, relativePoint = "BOTTOM", "BOTTOM" + else + point, relativePoint = "TOP", "TOP" + end + if curX < GetScreenWidth() / 2 then + point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT" + else + point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT" + end + end + frame:SetPoint(point, type(parent) == "table" and parent or UIParent, + relativePoint) + if cursorX and cursorY then + local left = frame:GetLeft() + local width = frame:GetWidth() + local bottom = frame:GetBottom() + local height = frame:GetHeight() + local curX, curY = GetScaledCursorPosition() + frame:ClearAllPoints() + relativePoint = relativePoint or point + if point == "BOTTOM" or point == "TOP" then + if curX < GetScreenWidth() / 2 then + point = point .. "LEFT" + else + point = point .. "RIGHT" + end + elseif point == "CENTER" then + if curX < GetScreenWidth() / 2 then + point = "LEFT" + else + point = "RIGHT" + end + end + local xOffset, yOffset = 0, 0 + if curY > GetScreenHeight() / 2 then yOffset = -height end + if curX > GetScreenWidth() / 2 then xOffset = -width end + frame:SetPoint(point, + type(parent) == "table" and parent or UIParent, + relativePoint, curX - left + xOffset, + curY - bottom + yOffset) + if level == 1 then frame.lastDirection = "RIGHT" end + elseif cursorX then + local left = frame:GetLeft() + local width = frame:GetWidth() + local curX, curY = GetScaledCursorPosition() + frame:ClearAllPoints() + relativePoint = relativePoint or point + if point == "BOTTOM" or point == "TOP" then + if curX < GetScreenWidth() / 2 then + point = point .. "LEFT" + else + point = point .. "RIGHT" + end + elseif point == "CENTER" then + if curX < GetScreenWidth() / 2 then + point = "LEFT" + else + point = "RIGHT" + end + end + frame:SetPoint(point, + type(parent) == "table" and parent or UIParent, + relativePoint, curX - left - width / 2, 0) + if level == 1 then frame.lastDirection = "RIGHT" end + elseif cursorY then + local bottom = frame:GetBottom() + local height = frame:GetHeight() + local curX, curY = GetScaledCursorPosition() + frame:ClearAllPoints() + relativePoint = relativePoint or point + if point == "LEFT" or point == "RIGHT" then + if curX < GetScreenHeight() / 2 then + point = point .. "BOTTOM" + else + point = point .. "TOP" + end + elseif point == "CENTER" then + if curX < GetScreenHeight() / 2 then + point = "BOTTOM" + else + point = "TOP" + end + end + frame:SetPoint(point, + type(parent) == "table" and parent or UIParent, + relativePoint, 0, curY - bottom - height / 2) + if level == 1 then frame.lastDirection = "DOWN" end + end + if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then + if frame:GetBottom() < 0 then + local point, parent, relativePoint, x, y = frame:GetPoint(1) + local change = GetScreenHeight() - frame:GetTop() + local otherChange = -frame:GetBottom() + if otherChange < change then change = otherChange end + frame:SetPoint(point, parent, relativePoint, x, y + change) + elseif frame:GetTop() > GetScreenHeight() then + local point, parent, relativePoint, x, y = frame:GetPoint(1) + local change = GetScreenHeight() - frame:GetTop() + local otherChange = -frame:GetBottom() + if otherChange < change then change = otherChange end + frame:SetPoint(point, parent, relativePoint, x, y + change) + end + end + end + CheckDualMonitor(frame) + frame:SetClampedToScreen(true) + frame:SetClampedToScreen(false) + StartCounting(level) end function Dewdrop:IsRegistered(parent) - self:argCheck(parent, 2, "table", "string") - return not not self.registry[parent] + self:argCheck(parent, 2, "table", "string") + return not not self.registry[parent] end function Dewdrop:Open(parent, ...) - self:argCheck(parent, 2, "table", "string") - local info - local k1 = ... - if type(k1) == "table" and k1[0] and k1.IsObjectType and self.registry[k1] then - info = tmp(select(2, ...)) - for k,v in pairs(self.registry[k1]) do - if info[k] == nil then - info[k] = v - end - end - else - info = tmp(...) - if self.registry[parent] then - for k,v in pairs(self.registry[parent]) do - if info[k] == nil then - info[k] = v - end - end - end - end - local point = info.point - local relativePoint = info.relativePoint - local cursorX = info.cursorX - local cursorY = info.cursorY - if type(point) == "function" then - local b - point, b = point(parent) - if b then - relativePoint = b - end - end - if type(relativePoint) == "function" then - relativePoint = relativePoint(parent) - end - Open(parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) - self:SmartAnchorTo(parent) + self:argCheck(parent, 2, "table", "string") + local info + local k1 = ... + if type(k1) == "table" and k1[0] and k1.IsObjectType and self.registry[k1] then + info = tmp(select(2, ...)) + for k, v in pairs(self.registry[k1]) do + if info[k] == nil then info[k] = v end + end + else + info = tmp(...) + if self.registry[parent] then + for k, v in pairs(self.registry[parent]) do + if info[k] == nil then info[k] = v end + end + end + end + local point = info.point + local relativePoint = info.relativePoint + local cursorX = info.cursorX + local cursorY = info.cursorY + if type(point) == "function" then + local b + point, b = point(parent) + if b then relativePoint = b end + end + if type(relativePoint) == "function" then + relativePoint = relativePoint(parent) + end + Open(parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) + self:SmartAnchorTo(parent) end function Clear(level) - if level then - if level.scrollFrame.child.buttons then - for i = #level.scrollFrame.child.buttons, 1, -1 do - ReleaseButton(level, i) - end - end - end + if level then + if level.scrollFrame.child.buttons then + for i = #level.scrollFrame.child.buttons, 1, -1 do + ReleaseButton(level, i) + end + end + end end function Dewdrop:Close(level) - if DropDownList1:IsShown() then - DropDownList1:Hide() - end - self:argCheck(level, 2, "number", "nil") - if not level then - level = 1 - end - if level == 1 and levels[level] then - levels[level].parented = false - end - if level > 1 and levels[level-1].scrollFrame.child.buttons then - local buttons = levels[level-1].scrollFrame.child.buttons - for _,button in ipairs(buttons) do --- button.arrow:SetWidth(16) --- button.arrow:SetHeight(16) - button.selected = nil - button.highlight:Hide() --- button.arrow:SetVertexColor(1, 1, 1) - end - end - if sliderFrame and sliderFrame.level >= level then - sliderFrame:Hide() - end - if editBoxFrame and editBoxFrame.level >= level then - editBoxFrame:Hide() - end - for i = level, #levels do - Clear(levels[level]) - levels[i]:Hide() - levels[i]:ClearAllPoints() - levels[i]:SetPoint("CENTER", UIParent, "CENTER") - levels[i].value = nil - end + if DropDownList1:IsShown() then DropDownList1:Hide() end + self:argCheck(level, 2, "number", "nil") + if not level then level = 1 end + if level == 1 and levels[level] then levels[level].parented = false end + if level > 1 and levels[level - 1].scrollFrame.child.buttons then + local buttons = levels[level - 1].scrollFrame.child.buttons + for _, button in ipairs(buttons) do + -- button.arrow:SetWidth(16) + -- button.arrow:SetHeight(16) + button.selected = nil + button.highlight:Hide() + -- button.arrow:SetVertexColor(1, 1, 1) + end + end + if sliderFrame and sliderFrame.level >= level then sliderFrame:Hide() end + if editBoxFrame and editBoxFrame.level >= level then editBoxFrame:Hide() end + for i = level, #levels do + Clear(levels[level]) + levels[i]:Hide() + levels[i]:ClearAllPoints() + levels[i]:SetPoint("CENTER", UIParent, "CENTER") + levels[i].value = nil + end end function Dewdrop:AddSeparator(level) - level = levels[level or currentLevel] - if not level or not level.scrollFrame.child.buttons then return; end + level = levels[level or currentLevel] + if not level or not level.scrollFrame.child.buttons then return; end - local prevbutton = level.scrollFrame.child.buttons[#level.scrollFrame.child.buttons] - if not prevbutton then return; end + local prevbutton = level.scrollFrame.child.buttons[#level.scrollFrame.child + .buttons] + if not prevbutton then return; end - if prevbutton.disabled and prevbutton.text:GetText() == "" then - return - end - self:AddLine("text", "", "disabled", true) + if prevbutton.disabled and prevbutton.text:GetText() == "" then return end + self:AddLine("text", "", "disabled", true) end function Dewdrop:AddLine(...) - local info = tmp(...) - local level = info.level or currentLevel - if (info.icon and type(info.icon) == "number") then info.icon = tostring(info.icon) end - info.level = nil - local button = AcquireButton( level) - if not next(info) then - info.disabled = true - end - button.disabled = info.isTitle or info.notClickable or info.disabled or (InCombatLockdown( ) and info.secure) - button.isTitle = info.isTitle - button.notClickable = info.notClickable - if info.disabled then - button.arrow:SetDesaturated(true) - button.check:SetDesaturated(true) - else - button.arrow:SetDesaturated(false) - button.check:SetDesaturated(false) - end - button.notCheckable = info.notCheckable - button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0) - button.checked = not info.notCheckable and info.checked - button.mouseoverUnderline = info.mouseoverUnderline - button.isRadio = not info.notCheckable and info.isRadio - if info.isRadio then - button.check:Show() - button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") - if button.checked then - button.check:SetTexCoord(0.25, 0.5, 0, 1) - button.check:SetVertexColor(1, 1, 1, 1) - else - button.check:SetTexCoord(0, 0.25, 0, 1) - button.check:SetVertexColor(1, 1, 1, 0.5) - end - button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") - button.check:SetWidth(16) - button.check:SetHeight(16) - elseif info.icon then - button.check:Show() - button.check:SetTexture(info.icon) - if info.iconWidth and info.iconHeight then - button.check:SetWidth(info.iconWidth) - button.check:SetHeight(info.iconHeight) - else - button.check:SetWidth(16) - button.check:SetHeight(16) - end - if info.iconCoordLeft and info.iconCoordRight and info.iconCoordTop and info.iconCoordBottom then - button.check:SetTexCoord(info.iconCoordLeft, info.iconCoordRight, info.iconCoordTop, info.iconCoordBottom) - elseif info.icon:find("^Interface\\Icons\\") then - button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) - else - button.check:SetTexCoord(0, 1, 0, 1) - end - button.check:SetVertexColor(1, 1, 1, 1) - else - if button.checked then - if info.checkIcon then - button.check:SetWidth(16) - button.check:SetHeight(16) - button.check:SetTexture(info.checkIcon) - if info.checkIcon:find("^Interface\\Icons\\") then - button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) - else - button.check:SetTexCoord(0, 1, 0, 1) - end - else - button.check:SetWidth(24) - button.check:SetHeight(24) - button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") - button.check:SetTexCoord(0, 1, 0, 1) - end - button.check:SetVertexColor(1, 1, 1, 1) - else - button.check:SetVertexColor(1, 1, 1, 0) - end - end - if not button.disabled then - button.func = info.func - button.secure = info.secure - end - button.hasColorSwatch = info.hasColorSwatch - if button.hasColorSwatch then - button.colorSwatch:Show() - button.colorSwatch.texture:Show() - button.r = info.r or 1 - button.g = info.g or 1 - button.b = info.b or 1 - button.colorSwatch.texture:SetVertexColor(button.r, button.g, button.b) - button.checked = false - button.func = nil - button.colorFunc = info.colorFunc - local i = 1 - while true do - local k = "colorArg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - button.hasOpacity = info.hasOpacity - button.opacity = info.opacity or 1 - else - button.colorSwatch:Hide() - button.colorSwatch.texture:Hide() - end - button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow - if button.hasArrow then - button.arrow:SetAlpha(1) - if info.hasSlider then - button.hasSlider = true - button.sliderMin = info.sliderMin or 0 - button.sliderMax = info.sliderMax or 1 - button.sliderStep = info.sliderStep or 0 - button.sliderBigStep = info.sliderBigStep or button.sliderStep - if button.sliderBigStep < button.sliderStep then - button.sliderBigStep = button.sliderStep - end - button.sliderIsPercent = info.sliderIsPercent and true or false - button.sliderMinText = info.sliderMinText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMin * 100) or button.sliderMin - button.sliderMaxText = info.sliderMaxText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMax * 100) or button.sliderMax - button.sliderFunc = info.sliderFunc - button.sliderValue = info.sliderValue - button.fromAceOptions = info.fromAceOptions - local i = 1 - while true do - local k = "sliderArg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - elseif info.hasEditBox then - button.hasEditBox = true - button.editBoxText = info.editBoxText or "" - button.editBoxFunc = info.editBoxFunc - local i = 1 - while true do - local k = "editBoxArg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - button.editBoxChangeFunc = info.editBoxChangeFunc - local i = 1 - while true do - local k = "editBoxChangeArg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - button.editBoxValidateFunc = info.editBoxValidateFunc - local i = 1 - while true do - local k = "editBoxValidateArg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - button.editBoxIsKeybinding = info.editBoxIsKeybinding - button.editBoxKeybindingOnly = info.editBoxKeybindingOnly - button.editBoxKeybindingExcept = info.editBoxKeybindingExcept - else - button.value = info.value - local l = levels[level+1] - if l and info.value == l.value then --- button.arrow:SetWidth(24) --- button.arrow:SetHeight(24) - button.selected = true - button.highlight:Show() - end - end - else - button.arrow:SetAlpha(0) - end - local i = 1 - while true do - local k = "arg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - button.closeWhenClicked = info.closeWhenClicked --- button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10 - - local fontsize = self.fontsize - local fontcolor - - button.textHeight = fontsize - --button.text:SetFont("Fonts\\MORPHEUS.TTF",button.textHeight) --- local font,_ = button.text:GetFont() --- print("FONT "..font) - --button.text:SetFont("Fonts\\FRIZQT__.TTF", 4, "OUTLINE") - --button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) - - if button.isTitle then - button.text:SetFont(options.fonts.title.ttf,fontsize) - fontcolor = options.fonts.title.color - elseif button.notClickable then - button.text:SetFont(options.fonts.notClickable.ttf,fontsize) - fontcolor = options.fonts.notClickable.color - elseif button.disabled then - button.text:SetFont(options.fonts.disabled.ttf,fontsize) - fontcolor = options.fonts.disabled.color - else - button.text:SetFont(options.fonts.standard.ttf,fontsize) - fontcolor = options.fonts.standard.color - end - - button.text:SetTextColor(unpack(fontcolor)) --- button.text:SetTextColor(fontcolor) - - -- if info.textR and info.textG and info.textB then - -- button.textR = info.textR - -- button.textG = info.textG - -- button.textB = info.textB - -- button.text:SetTextColor(button.textR, button.textG, button.textB) - -- else - -- button.text:SetTextColor(fontcolor) - -- end - - button:SetHeight(button.textHeight + 6) - --button:SetHeight( 6) - - button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT") - button.text:SetJustifyH(info.justifyH or "LEFT") - button.text:SetText(info.text) - button.tooltipTitle = info.tooltipTitle - button.tooltipText = info.tooltipText - button.tooltipFunc = info.tooltipFunc - local i = 1 - while true do - local k = "tooltipArg" .. i - local x = info[k] - if x == nil then - break - end - button[k] = x - i = i + 1 - end - if not button.tooltipTitle and not button.tooltipText and not button.tooltipFunc and not info.isTitle then - button.tooltipTitle = info.text - end - if type(button.func) == "string" then - if type(button.arg1) ~= "table" then - self:error("Cannot call method %q on a non-table", button.func) - end - if type(button.arg1[button.func]) ~= "function" then - self:error("Method %q nonexistant.", button.func) - end - end + local info = tmp(...) + local level = info.level or currentLevel + if (info.icon and type(info.icon) == "number") then + info.icon = tostring(info.icon) + end + info.level = nil + local button = AcquireButton(level) + if not next(info) then info.disabled = true end + button.disabled = info.isTitle or info.notClickable or info.disabled or + (InCombatLockdown() and info.secure) + button.isTitle = info.isTitle + button.notClickable = info.notClickable + if info.disabled then + button.arrow:SetDesaturated(true) + button.check:SetDesaturated(true) + else + button.arrow:SetDesaturated(false) + button.check:SetDesaturated(false) + end + button.notCheckable = info.notCheckable + button.text:SetPoint("LEFT", button, "LEFT", + button.notCheckable and 0 or 24, 0) + button.checked = not info.notCheckable and info.checked + button.mouseoverUnderline = info.mouseoverUnderline + button.isRadio = not info.notCheckable and info.isRadio + if info.isRadio then + button.check:Show() + button.check:SetTexture(info.checkIcon or + "Interface\\Buttons\\UI-RadioButton") + if button.checked then + button.check:SetTexCoord(0.25, 0.5, 0, 1) + button.check:SetVertexColor(1, 1, 1, 1) + else + button.check:SetTexCoord(0, 0.25, 0, 1) + button.check:SetVertexColor(1, 1, 1, 0.5) + end + button.radioHighlight:SetTexture(info.checkIcon or + "Interface\\Buttons\\UI-RadioButton") + button.check:SetWidth(16) + button.check:SetHeight(16) + elseif info.icon then + button.check:Show() + button.check:SetTexture(info.icon) + if info.iconWidth and info.iconHeight then + button.check:SetWidth(info.iconWidth) + button.check:SetHeight(info.iconHeight) + else + button.check:SetWidth(16) + button.check:SetHeight(16) + end + if info.iconCoordLeft and info.iconCoordRight and info.iconCoordTop and + info.iconCoordBottom then + button.check:SetTexCoord(info.iconCoordLeft, info.iconCoordRight, + info.iconCoordTop, info.iconCoordBottom) + elseif info.icon:find("^Interface\\Icons\\") then + button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) + else + button.check:SetTexCoord(0, 1, 0, 1) + end + button.check:SetVertexColor(1, 1, 1, 1) + else + if button.checked then + if info.checkIcon then + button.check:SetWidth(16) + button.check:SetHeight(16) + button.check:SetTexture(info.checkIcon) + if info.checkIcon:find("^Interface\\Icons\\") then + button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) + else + button.check:SetTexCoord(0, 1, 0, 1) + end + else + button.check:SetWidth(24) + button.check:SetHeight(24) + button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") + button.check:SetTexCoord(0, 1, 0, 1) + end + button.check:SetVertexColor(1, 1, 1, 1) + else + button.check:SetVertexColor(1, 1, 1, 0) + end + end + if not button.disabled then + button.func = info.func + button.secure = info.secure + end + button.hasColorSwatch = info.hasColorSwatch + if button.hasColorSwatch then + button.colorSwatch:Show() + button.colorSwatch.texture:Show() + button.r = info.r or 1 + button.g = info.g or 1 + button.b = info.b or 1 + button.colorSwatch.texture:SetVertexColor(button.r, button.g, button.b) + button.checked = false + button.func = nil + button.colorFunc = info.colorFunc + local i = 1 + while true do + local k = "colorArg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + button.hasOpacity = info.hasOpacity + button.opacity = info.opacity or 1 + else + button.colorSwatch:Hide() + button.colorSwatch.texture:Hide() + end + button.hasArrow = not button.hasColorSwatch and + (info.value or info.hasSlider or info.hasEditBox) and + info.hasArrow + if button.hasArrow then + button.arrow:SetAlpha(1) + if info.hasSlider then + button.hasSlider = true + button.sliderMin = info.sliderMin or 0 + button.sliderMax = info.sliderMax or 1 + button.sliderStep = info.sliderStep or 0 + button.sliderBigStep = info.sliderBigStep or button.sliderStep + if button.sliderBigStep < button.sliderStep then + button.sliderBigStep = button.sliderStep + end + button.sliderIsPercent = info.sliderIsPercent and true or false + button.sliderMinText = + info.sliderMinText or button.sliderIsPercent and + string.format("%.0f%%", button.sliderMin * 100) or + button.sliderMin + button.sliderMaxText = + info.sliderMaxText or button.sliderIsPercent and + string.format("%.0f%%", button.sliderMax * 100) or + button.sliderMax + button.sliderFunc = info.sliderFunc + button.sliderValue = info.sliderValue + button.fromAceOptions = info.fromAceOptions + local i = 1 + while true do + local k = "sliderArg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + elseif info.hasEditBox then + button.hasEditBox = true + button.editBoxText = info.editBoxText or "" + button.editBoxFunc = info.editBoxFunc + local i = 1 + while true do + local k = "editBoxArg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + button.editBoxChangeFunc = info.editBoxChangeFunc + local i = 1 + while true do + local k = "editBoxChangeArg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + button.editBoxValidateFunc = info.editBoxValidateFunc + local i = 1 + while true do + local k = "editBoxValidateArg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + button.editBoxIsKeybinding = info.editBoxIsKeybinding + button.editBoxKeybindingOnly = info.editBoxKeybindingOnly + button.editBoxKeybindingExcept = info.editBoxKeybindingExcept + else + button.value = info.value + local l = levels[level + 1] + if l and info.value == l.value then + -- button.arrow:SetWidth(24) + -- button.arrow:SetHeight(24) + button.selected = true + button.highlight:Show() + end + end + else + button.arrow:SetAlpha(0) + end + local i = 1 + while true do + local k = "arg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + button.closeWhenClicked = info.closeWhenClicked + -- button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10 + + local fontsize = self.fontsize + local fontcolor + + button.textHeight = fontsize + -- button.text:SetFont("Fonts\\MORPHEUS.TTF",button.textHeight) + -- local font,_ = button.text:GetFont() + -- print("FONT "..font) + -- button.text:SetFont("Fonts\\FRIZQT__.TTF", 4, "OUTLINE") + -- button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) + + if button.isTitle then + button.text:SetFont(options.fonts.title.ttf, fontsize) + fontcolor = options.fonts.title.color + elseif button.notClickable then + button.text:SetFont(options.fonts.notClickable.ttf, fontsize) + fontcolor = options.fonts.notClickable.color + elseif button.disabled then + button.text:SetFont(options.fonts.disabled.ttf, fontsize) + fontcolor = options.fonts.disabled.color + else + button.text:SetFont(options.fonts.standard.ttf, fontsize) + fontcolor = options.fonts.standard.color + end + + button.text:SetTextColor(unpack(fontcolor)) + -- button.text:SetTextColor(fontcolor) + + -- if info.textR and info.textG and info.textB then + -- button.textR = info.textR + -- button.textG = info.textG + -- button.textB = info.textB + -- button.text:SetTextColor(button.textR, button.textG, button.textB) + -- else + -- button.text:SetTextColor(fontcolor) + -- end + + button:SetHeight(button.textHeight + 6) + -- button:SetHeight( 6) + + button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or + button.hasArrow) and "LEFT" or "RIGHT") + button.text:SetJustifyH(info.justifyH or "LEFT") + button.text:SetText(info.text) + button.tooltipTitle = info.tooltipTitle + button.tooltipText = info.tooltipText + button.tooltipFunc = info.tooltipFunc + local i = 1 + while true do + local k = "tooltipArg" .. i + local x = info[k] + if x == nil then break end + button[k] = x + i = i + 1 + end + if not button.tooltipTitle and not button.tooltipText and + not button.tooltipFunc and not info.isTitle then + button.tooltipTitle = info.text + end + if type(button.func) == "string" then + if type(button.arg1) ~= "table" then + self:error("Cannot call method %q on a non-table", button.func) + end + if type(button.arg1[button.func]) ~= "function" then + self:error("Method %q nonexistant.", button.func) + end + end end function Dewdrop:OnTooltipHide() - if lastSetFont then - if lastSetFont == normalFont then - lastSetFont = nil - return - end - fillRegionTmp(GameTooltip:GetRegions()) - for i,v in ipairs(regionTmp) do - if v.GetFont then - local font,size,outline = v:GetFont() - if font == lastSetFont then - v:SetFont(normalFont, size, outline) - end - end - regionTmp[i] = nil - end - lastSetFont = nil - end + if lastSetFont then + if lastSetFont == normalFont then + lastSetFont = nil + return + end + fillRegionTmp(GameTooltip:GetRegions()) + for i, v in ipairs(regionTmp) do + if v.GetFont then + local font, size, outline = v:GetFont() + if font == lastSetFont then + v:SetFont(normalFont, size, outline) + end + end + regionTmp[i] = nil + end + lastSetFont = nil + end end local function activate() - - local self = Dewdrop - - self.registry = {} - self.onceRegistered = {} - - local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") - local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") - local oldX, oldY, clickTime - - WorldFrame:SetScript("OnMouseDown", function(self, ...) - oldX,oldY = GetCursorPosition() - clickTime = GetTime() - if WorldFrame_OnMouseDown then - WorldFrame_OnMouseDown(self, ...) - end - end) - - WorldFrame:SetScript("OnMouseUp", function(self, ...) - local x,y = GetCursorPosition() - if not oldX or not oldY or not x or not y or not clickTime then - Dewdrop:Close() - if WorldFrame_OnMouseUp then - WorldFrame_OnMouseUp(self, ...) - end - return - end - local d = math.abs(x - oldX) + math.abs(y - oldY) - if d <= 5 and GetTime() - clickTime < 0.5 then - Dewdrop:Close() - end - if WorldFrame_OnMouseUp then - WorldFrame_OnMouseUp(self, ...) - end - end) - - hooksecurefunc(DropDownList1, "Show", function() - if levels[1] and levels[1]:IsVisible() then - Dewdrop:Close() - end - end) - hooksecurefunc("HideDropDownMenu", function() - if levels[1] and levels[1]:IsVisible() then - Dewdrop:Close() - end - end) ---[[ + local self = Dewdrop + + self.registry = {} + self.onceRegistered = {} + + local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") + local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") + local oldX, oldY, clickTime + + WorldFrame:SetScript("OnMouseDown", function(self, ...) + oldX, oldY = GetCursorPosition() + clickTime = GetTime() + if WorldFrame_OnMouseDown then WorldFrame_OnMouseDown(self, ...) end + end) + + WorldFrame:SetScript("OnMouseUp", function(self, ...) + local x, y = GetCursorPosition() + if not oldX or not oldY or not x or not y or not clickTime then + Dewdrop:Close() + if WorldFrame_OnMouseUp then + WorldFrame_OnMouseUp(self, ...) + end + return + end + local d = math.abs(x - oldX) + math.abs(y - oldY) + if d <= 5 and GetTime() - clickTime < 0.5 then Dewdrop:Close() end + if WorldFrame_OnMouseUp then WorldFrame_OnMouseUp(self, ...) end + end) + + hooksecurefunc(DropDownList1, "Show", function() + if levels[1] and levels[1]:IsVisible() then Dewdrop:Close() end + end) + + hooksecurefunc("HideDropDownMenu", function() + if levels[1] and levels[1]:IsVisible() then Dewdrop:Close() end + end) + --[[ hooksecurefunc("CloseDropDownMenus", function() if levels[1] and levels[1]:IsVisible() then local stack = debugstack() @@ -3320,147 +3218,154 @@ local function activate() end end) --]] - - self.frame = CreateFrame("Frame") - self.frame:UnregisterAllEvents() - self.frame:RegisterEvent("PLAYER_REGEN_ENABLED") - self.frame:RegisterEvent("PLAYER_REGEN_DISABLED") - self.frame:SetScript("OnEvent", function(self, event) - if event=="PLAYER_REGEN_ENABLED" then -- track combat state for secure frame operations - self.combat = false - elseif event=="PLAYER_REGEN_DISABLED" then - self.combat = true - end - end) - self.frame:SetScript("OnUpdate", function(self,elapsed) - self:Hide() - Refresh(1) - end) - self.frame:Show() - self.hookedTooltip = true - - local OnTooltipHide = GameTooltip:GetScript("OnHide") - GameTooltip:SetScript("OnHide", function(self, ...) - if OnTooltipHide then - OnTooltipHide(self, ...) - end - if type(self.OnTooltipHide) == "function" then - self:OnTooltipHide() - end - end) - - levels = {} - buttons = {} - options = - { - fonts = - { - standard = - { - ttf = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", - size = 14, - color = {GameFontHighlightSmall:GetTextColor()}, - }, - title = - { - ttf = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", - size = 11, - color = {0.2,1,1,1}, --GameFontNormal:GetTextColor()}, - }, - notClickable = - { - ttf = "Fonts\\ARIALN.ttf", --MORPHEUS.TTF", - size = 6, - color = {GameFontNormalMed3:GetTextColor()}, - }, - disabled = - { - ttf = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", - size = 8, - color = {GameFontDisableSmall:GetTextColor()}, - }, - } - } + + self.frame = CreateFrame("Frame") + self.frame:UnregisterAllEvents() + self.frame:RegisterEvent("PLAYER_REGEN_ENABLED") + self.frame:RegisterEvent("PLAYER_REGEN_DISABLED") + self.frame:SetScript("OnEvent", function(self, event) + if event == "PLAYER_REGEN_ENABLED" then -- track combat state for secure frame operations + self.combat = false + elseif event == "PLAYER_REGEN_DISABLED" then + self.combat = true + end + end) + self.frame:SetScript("OnUpdate", function(self, elapsed) + self:Hide() + Refresh(1) + end) + self.frame:Show() + self.hookedTooltip = true + + local OnTooltipHide = GameTooltip:GetScript("OnHide") + GameTooltip:SetScript("OnHide", function(self, ...) + if OnTooltipHide then OnTooltipHide(self, ...) end + if type(self.OnTooltipHide) == "function" then + self:OnTooltipHide() + end + end) + + levels = {} + buttons = {} + options = { + fonts = { + standard = { + ttf = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", + size = 14, + color = {GameFontHighlightSmall:GetTextColor()} + }, + title = { + ttf = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", + size = 11, + color = {0.2, 1, 1, 1} -- GameFontNormal:GetTextColor()}, + }, + notClickable = { + ttf = "Fonts\\ARIALN.ttf", -- MORPHEUS.TTF", + size = 6, + color = {GameFontNormalMed3:GetTextColor()} + }, + disabled = { + ttf = STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", + size = 8, + color = {GameFontDisableSmall:GetTextColor()} + } + } + } end -activate( ) +activate() function Dewdrop:argCheck(arg, num, kind, kind2, kind3, kind4, kind5) - if type(num) ~= "number" then - return error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num)) - elseif type(kind) ~= "string" then - return error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind)) - end - arg = type(arg) - if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then - local stack = debugstack() - local func = stack:match("`argCheck'.-([`<].-['>])") - if not func then - func = stack:match("([`<].-['>])") - end - if kind5 then - return error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg) - elseif kind4 then - return error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg) - elseif kind3 then - return error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg) - elseif kind2 then - return error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg) - else - return error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg) - end - end + if type(num) ~= "number" then + return error(self, + "Bad argument #3 to `argCheck' (number expected, got %s)", + type(num)) + elseif type(kind) ~= "string" then + return error(self, + "Bad argument #4 to `argCheck' (string expected, got %s)", + type(kind)) + end + arg = type(arg) + if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= + kind5 then + local stack = debugstack() + local func = stack:match("`argCheck'.-([`<].-['>])") + if not func then func = stack:match("([`<].-['>])") end + if kind5 then + return error(self, + "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", + tonumber(num) or 0 / 0, func, kind, kind2, kind3, + kind4, kind5, arg) + elseif kind4 then + return error(self, + "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", + tonumber(num) or 0 / 0, func, kind, kind2, kind3, + kind4, arg) + elseif kind3 then + return error(self, + "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", + tonumber(num) or 0 / 0, func, kind, kind2, kind3, arg) + elseif kind2 then + return error(self, + "Bad argument #%s to %s (%s or %s expected, got %s)", + tonumber(num) or 0 / 0, func, kind, kind2, arg) + else + return error(self, "Bad argument #%s to %s (%s expected, got %s)", + tonumber(num) or 0 / 0, func, kind, arg) + end + end end function Dewdrop:error(message, ...) - if type(self) ~= "table" then - return _G.error(("Bad argument #1 to `error' (table expected, got %s)"):format(type(self)), 2) - end - - local stack = debugstack() - if not message then - local second = stack:match("\n(.-)\n") - message = "error raised! " .. second - else - local arg = { ... } -- not worried about table creation, as errors don't happen often - - for i = 1, #arg do - arg[i] = tostring(arg[i]) - end - for i = 1, 10 do - table.insert(arg, "nil") - end - message = message:format(unpack(arg)) - end - - if getmetatable(self) and getmetatable(self).__tostring then - message = ("%s: %s"):format(tostring(self), message) - elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then - message = ("%s: %s"):format(self:GetLibraryVersion(), message) - elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then - message = ("%s: %s"):format(self.class:GetLibraryVersion(), message) - end - - local first = stack:gsub("\n.*", "") - local file = first:gsub(".*\\(.*).lua:%d+: .*", "%1") - file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") - - - local i = 0 - for s in stack:gmatch("\n([^\n]*)") do - i = i + 1 - if not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then - file = s:gsub("^.*\\(.*).lua:%d+: .*", "%1") - file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") - break - end - end - local j = 0 - for s in stack:gmatch("\n([^\n]*)") do - j = j + 1 - if j > i and not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then - return _G.error(message, j+1) - end - end - return _G.error(message, 2) + if type(self) ~= "table" then + return _G.error( + ("Bad argument #1 to `error' (table expected, got %s)"):format( + type(self)), 2) + end + + local stack = debugstack() + if not message then + local second = stack:match("\n(.-)\n") + message = "error raised! " .. second + else + local arg = {...} -- not worried about table creation, as errors don't happen often + + for i = 1, #arg do arg[i] = tostring(arg[i]) end + for i = 1, 10 do table.insert(arg, "nil") end + message = message:format(unpack(arg)) + end + + if getmetatable(self) and getmetatable(self).__tostring then + message = ("%s: %s"):format(tostring(self), message) + elseif type(rawget(self, 'GetLibraryVersion')) == "function" and + AceLibrary:HasInstance(self:GetLibraryVersion()) then + message = ("%s: %s"):format(self:GetLibraryVersion(), message) + elseif type(rawget(self, 'class')) == "table" and + type(rawget(self.class, 'GetLibraryVersion')) == "function" and + AceLibrary:HasInstance(self.class:GetLibraryVersion()) then + message = ("%s: %s"):format(self.class:GetLibraryVersion(), message) + end + + local first = stack:gsub("\n.*", "") + local file = first:gsub(".*\\(.*).lua:%d+: .*", "%1") + file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + + local i = 0 + for s in stack:gmatch("\n([^\n]*)") do + i = i + 1 + if not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then + file = s:gsub("^.*\\(.*).lua:%d+: .*", "%1") + file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + break + end + end + local j = 0 + for s in stack:gmatch("\n([^\n]*)") do + j = j + 1 + if j > i and not s:find(file .. "%.lua:%d+:") and + not s:find("%(tail call%)") then + return _G.error(message, j + 1) + end + end + return _G.error(message, 2) end diff --git a/libs/LibStub/LibStub.lua b/libs/LibStub/LibStub.lua index ae1900e..cbfef90 100644 --- a/libs/LibStub/LibStub.lua +++ b/libs/LibStub/LibStub.lua @@ -2,50 +2,52 @@ -- 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_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 }) + 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 diff --git a/portals.lua b/portals.lua index c99a1c0..a60ba90 100644 --- a/portals.lua +++ b/portals.lua @@ -8,15 +8,16 @@ local _ local CreateFrame = CreateFrame local C_ToyBox = C_ToyBox local GetBindLocation = GetBindLocation -local GetContainerItemCooldown = C_Container.GetContainerItemCooldown -local GetContainerItemInfo = C_Container.GetContainerItemInfo -local GetContainerItemLink = C_Container.GetContainerItemLink -local GetContainerNumSlots = C_Container.GetContainerNumSlots +local GetContainerItemCooldown = C_Container.GetContainerItemCooldown +local GetContainerItemInfo = C_Container.GetContainerItemInfo +local GetContainerItemLink = C_Container.GetContainerItemLink +local GetContainerNumSlots = C_Container.GetContainerNumSlots local GetItemCooldown = C_Container.GetItemCooldown local GetInventoryItemCooldown = GetInventoryItemCooldown local GetInventoryItemLink = GetInventoryItemLink local GetNumGroupMembers = GetNumGroupMembers -local GetSpellBookItemName = GetSpellBookItemName or C_SpellBook.GetSpellBookItemName +local GetSpellBookItemName = GetSpellBookItemName or + C_SpellBook.GetSpellBookItemName local GetSpellCooldown = GetSpellCooldown or C_Spell.GetSpellCooldown local GetSpellInfo = GetSpellInfo or C_Spell.GetSpellInfo local GetTime = GetTime @@ -30,14 +31,14 @@ local UnitRace = UnitRace local UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT local isCataclysmClassic = (WOW_PROJECT_ID == WOW_PROJECT_CATACLYSM_CLASSIC) -local engineeringName = C_TradeSkillUI.GetTradeSkillDisplayName(202) -local engineeringIcon = C_TradeSkillUI.GetTradeSkillTexture(202) -local heartstonesIcon = 134414 -- icon of Heartstone -local teleportsIcon = 237509 -- Teleport to Dalaran icon used -local variousItemsIcon = 134248 -- Key icon used +local engineeringName = C_TradeSkillUI.GetTradeSkillDisplayName(202) +local engineeringIcon = C_TradeSkillUI.GetTradeSkillTexture(202) +local heartstonesIcon = 134414 -- icon of Heartstone +local teleportsIcon = 237509 -- Teleport to Dalaran icon used +local variousItemsIcon = 134248 -- Key icon used local engineringItemsCount = 0 -local challengeSpellCount = 0 +local challengeSpellCount = 0 local heartstoneItemsCount = 0 local databaseLoaded = false @@ -51,63 +52,63 @@ local L = addonTable.L -- IDs of items usable for transportation local items = { -- Dalaran rings - 40585, -- Signet of the Kirin Tor - 40586, -- Band of the Kirin Tor - 44934, -- Loop of the Kirin Tor - 44935, -- Ring of the Kirin Tor - 45688, -- Inscribed Band of the Kirin Tor - 45689, -- Inscribed Loop of the Kirin Tor - 45690, -- Inscribed Ring of the Kirin Tor - 45691, -- Inscribed Signet of the Kirin Tor - 48954, -- Etched Band of the Kirin Tor - 48955, -- Etched Loop of the Kirin Tor - 48956, -- Etched Ring of the Kirin Tor - 48957, -- Etched Signet of the Kirin Tor - 51557, -- Runed Signet of the Kirin Tor - 51558, -- Runed Loop of the Kirin Tor - 51559, -- Runed Ring of the Kirin Tor - 51560, -- Runed Band of the Kirin Tor + 40585, -- Signet of the Kirin Tor + 40586, -- Band of the Kirin Tor + 44934, -- Loop of the Kirin Tor + 44935, -- Ring of the Kirin Tor + 45688, -- Inscribed Band of the Kirin Tor + 45689, -- Inscribed Loop of the Kirin Tor + 45690, -- Inscribed Ring of the Kirin Tor + 45691, -- Inscribed Signet of the Kirin Tor + 48954, -- Etched Band of the Kirin Tor + 48955, -- Etched Loop of the Kirin Tor + 48956, -- Etched Ring of the Kirin Tor + 48957, -- Etched Signet of the Kirin Tor + 51557, -- Runed Signet of the Kirin Tor + 51558, -- Runed Loop of the Kirin Tor + 51559, -- Runed Ring of the Kirin Tor + 51560, -- Runed Band of the Kirin Tor 139599, -- Empowered Ring of the Kirin Tor -- Seasonal items - 21711, -- Lunar Festival Invitation - 37863, -- Direbrew's Remote + 21711, -- Lunar Festival Invitation + 37863, -- Direbrew's Remote -- Miscellaneous - 17690, -- Frostwolf Insignia Rank 1 (Horde) - 17691, -- Stormpike Insignia Rank 1 (Alliance) - 17900, -- Stormpike Insignia Rank 2 (Alliance) - 17901, -- Stormpike Insignia Rank 3 (Alliance) - 17902, -- Stormpike Insignia Rank 4 (Alliance) - 17903, -- Stormpike Insignia Rank 5 (Alliance) - 17904, -- Stormpike Insignia Rank 6 (Alliance) - 17905, -- Frostwolf Insignia Rank 2 (Horde) - 17906, -- Frostwolf Insignia Rank 3 (Horde) - 17907, -- Frostwolf Insignia Rank 4 (Horde) - 17908, -- Frostwolf Insignia Rank 5 (Horde) - 17909, -- Frostwolf Insignia Rank 6 (Horde) - 22631, -- Atiesh, Greatstaff of the Guardian - 32757, -- Blessed Medallion of Karabor - 35230, -- Darnarian's Scroll of Teleportation - 43824, -- The Schools of Arcane Magic - Mastery - 46874, -- Argent Crusader's Tabard - 50287, -- Boots of the Bay - 52251, -- Jaina's Locket - 58487, -- Potion of Deepholm - 61379, -- Gidwin's Hearthstone - 63206, -- Wrap of Unity (Alliance) - 63207, -- Wrap of Unity (Horde) - 63352, -- Shroud of Cooperation (Alliance) - 63353, -- Shroud of Cooperation (Horde) - 63378, -- Hellscream's Reach Tabard - 63379, -- Baradin's Wardens Tabard - 64457, -- The Last Relic of Argus - 65274, -- Cloak of Coordination (Horde) - 65360, -- Cloak of Coordination (Alliance) - 95050, -- The Brassiest Knuckle (Horde) - 95051, -- The Brassiest Knuckle (Alliance) - 95567, -- Kirin Tor Beacon - 95568, -- Sunreaver Beacon - 87548, -- Lorewalker's Lodestone - 93672, -- Dark Portal + 17690, -- Frostwolf Insignia Rank 1 (Horde) + 17691, -- Stormpike Insignia Rank 1 (Alliance) + 17900, -- Stormpike Insignia Rank 2 (Alliance) + 17901, -- Stormpike Insignia Rank 3 (Alliance) + 17902, -- Stormpike Insignia Rank 4 (Alliance) + 17903, -- Stormpike Insignia Rank 5 (Alliance) + 17904, -- Stormpike Insignia Rank 6 (Alliance) + 17905, -- Frostwolf Insignia Rank 2 (Horde) + 17906, -- Frostwolf Insignia Rank 3 (Horde) + 17907, -- Frostwolf Insignia Rank 4 (Horde) + 17908, -- Frostwolf Insignia Rank 5 (Horde) + 17909, -- Frostwolf Insignia Rank 6 (Horde) + 22631, -- Atiesh, Greatstaff of the Guardian + 32757, -- Blessed Medallion of Karabor + 35230, -- Darnarian's Scroll of Teleportation + 43824, -- The Schools of Arcane Magic - Mastery + 46874, -- Argent Crusader's Tabard + 50287, -- Boots of the Bay + 52251, -- Jaina's Locket + 58487, -- Potion of Deepholm + 61379, -- Gidwin's Hearthstone + 63206, -- Wrap of Unity (Alliance) + 63207, -- Wrap of Unity (Horde) + 63352, -- Shroud of Cooperation (Alliance) + 63353, -- Shroud of Cooperation (Horde) + 63378, -- Hellscream's Reach Tabard + 63379, -- Baradin's Wardens Tabard + 64457, -- The Last Relic of Argus + 65274, -- Cloak of Coordination (Horde) + 65360, -- Cloak of Coordination (Alliance) + 95050, -- The Brassiest Knuckle (Horde) + 95051, -- The Brassiest Knuckle (Alliance) + 95567, -- Kirin Tor Beacon + 95568, -- Sunreaver Beacon + 87548, -- Lorewalker's Lodestone + 93672, -- Dark Portal 103678, -- Time-Lost Artifact 110560, -- Garrison Hearthstone 118662, -- Bladespire Relic @@ -124,20 +125,20 @@ local items = { 144391, -- Pugilist's Powerful Punching Ring (Alliance) 144392, -- Pugilist's Powerful Punching Ring (Horde) 151016, -- Fractured Necrolyte Skull - 166559 -- Commander's Signet of Battle + 166559 -- Commander's Signet of Battle } local heartstones = { -- items usable instead of hearthstone - 28585, -- Ruby Slippers - 37118, -- Scroll of Recall - 44314, -- Scroll of Recall II - 44315, -- Scroll of Recall III - 37118, -- Scroll of Recall - 44314, -- Scroll of Recall II - 44315, -- Scroll of Recall III - 54452, -- Ethereal Portal - 64488, -- The Innkeeper's Daughter + 28585, -- Ruby Slippers + 37118, -- Scroll of Recall + 44314, -- Scroll of Recall II + 44315, -- Scroll of Recall III + 37118, -- Scroll of Recall + 44314, -- Scroll of Recall II + 44315, -- Scroll of Recall III + 54452, -- Ethereal Portal + 64488, -- The Innkeeper's Daughter 142298, -- Astonishingly Scarlet Slippers 142542, -- Tome of Town Portal 162973, -- Greatfather Winter's Hearthstone @@ -162,17 +163,17 @@ local heartstones = { 200630, -- Ohn'ir Windsage's Hearthstone 208704, -- Deepdweller's Earthen Hearthstone 209035, -- Hearthstone of the Flame - 212337 -- Stone of the Hearth + 212337 -- Stone of the Hearth } local engineeringItems = { -- Engineering Gadgets - 18984, -- Dimensional Ripper - Everlook - 18986, -- Ultrasafe Transporter: Gadgetzan - 30542, -- Dimensional Ripper - Area 52 - 30544, -- Ultrasafe Transporter: Toshley's Station - 48933, -- Wormhole Generator: Northrend - 87215, -- Wormhole Generator: Pandaria + 18984, -- Dimensional Ripper - Everlook + 18986, -- Ultrasafe Transporter: Gadgetzan + 30542, -- Dimensional Ripper - Area 52 + 30544, -- Ultrasafe Transporter: Toshley's Station + 48933, -- Wormhole Generator: Northrend + 87215, -- Wormhole Generator: Pandaria 112059, -- Wormhole Centrifuge 151652, -- Wormhole Generator: Argus 168807, -- Wormhole Generator: Kul Tiras @@ -181,121 +182,125 @@ local engineeringItems = { 198156, -- Wormhole Generator: Dragon Isles 221966, -- Wormhole GeneratorL Khaz Algar 132523, -- Reaves Battery, unfortunately we can't check for Wormhole Generator module - 144341 -- Rechargeable Reaves Battery, same as with Reaves Battery + 144341 -- Rechargeable Reaves Battery, same as with Reaves Battery } local scrolls = { - 6948 -- Hearthstone + 6948 -- Hearthstone } -- Gold Challenge portals local challengeSpells = { - --DH Classic - { 159902, 'TRUE' }, -- Path of the Burning Mountain - { 373262, 'TRUE' }, -- Path of the Fallen Guardian - { 131232, 'TRUE' }, -- Path of the Necromancer - { 131231, 'TRUE' }, -- Path of the Scarlet Blade - { 131229, 'TRUE' }, -- Path of the Scarlet Mitre - { 393222, 'TRUE' }, -- Path of the Watcher's Legacy - --DH BC - --DH Cata - { 445424, 'TRUE' }, -- Path of the Grim Batol - { 424142, 'TRUE' }, -- Path of the Tidehunter - { 410080, 'TRUE' }, -- Path of the Wind's Domain - --DH MOP - { 131228, 'TRUE' }, -- Path of the Black Ox - { 131204, 'TRUE' }, -- Path of the Jade Serpent - { 131222, 'TRUE' }, -- Path of the Mogu King - { 131225, 'TRUE' }, -- Path of the Setting Sun - { 131206, 'TRUE' }, -- Path of the Shado-Pan - { 131205, 'TRUE' }, -- Path of the Stout Brew - --DH WOD - { 159895, 'TRUE' }, -- Path of the Bloodmaul - { 159899, 'TRUE' }, -- Path of the Crescent Moon - { 159900, 'TRUE' }, -- Path of the Dark Rail - { 159896, 'TRUE' }, -- Path of the Iron Prow - { 159898, 'TRUE' }, -- Path of the Skies - { 159901, 'TRUE' }, -- Path of the Verdant - { 159897, 'TRUE' }, -- Path of the Vigilant - --DH Legion - { 424153, 'TRUE' }, -- Path of the Ancient Horrors - { 410078, 'TRUE' }, -- Path of the Earth-Warder - { 393766, 'TRUE' }, -- Path of the Grand Magistrix - { 424163, 'TRUE' }, -- Path of the Nightmare Lord - { 393764, 'TRUE' }, -- Path of the Proven Worth - --DH BFA - { 410074, 'TRUE' }, -- Path of the Festering Rot - { 410071, 'TRUE' }, -- Path of the Freebooter - { 424187, 'TRUE' }, -- Path of the Golden Tomb - { 424167, 'TRUE' }, -- Path of the Heart's Bane - { 373274, 'TRUE' }, -- Path of the Scrappy Prince - { 445418, 'TRUE' }, -- Path of the Siege of Boralus - --DH SL - { 354466, 'TRUE' }, -- Path of the Ascendant - { 354462, 'TRUE' }, -- Path of the Courageous - { 373192, 'TRUE' }, -- Path of the First Ones - { 354464, 'TRUE' }, -- Path of the Misty Forest - { 354463, 'TRUE' }, -- Path of the Plagued - { 354468, 'TRUE' }, -- Path of the Scheming Loa - { 354465, 'TRUE' }, -- Path of the Sinful Soul - { 373190, 'TRUE' }, -- Path of the Sire - { 354469, 'TRUE' }, -- Path of the Stone Warden - { 367416, 'TRUE' }, -- Path of the Streetwise Merchant - { 373191, 'TRUE' }, -- Path of the Tormented Soul - { 354467, 'TRUE' }, -- Path of the Undefeated - --DH DF - { 393279, 'TRUE' }, -- Path of the Arcane Secrets - { 432257, 'TRUE' }, -- Path of the Bitter Lagacy - { 393256, 'TRUE' }, -- Path of the Clutch Defender - { 393273, 'TRUE' }, -- Path of the Draconic Diploma - { 393276, 'TRUE' }, -- Path of the Obsidian Hoard - { 432254, 'TRUE' }, -- Path of the Primal Prison - { 393267, 'TRUE' }, -- Path of the Rotting Woods - { 432258, 'TRUE' }, -- Path of the Scorching Dream - { 393283, 'TRUE' }, -- Path of the Titanic Reservoir - { 424197, 'TRUE' }, -- Path of the Twisted Time - { 393262, 'TRUE' }, -- Path of the Windswept Plains - --DH TWW - { 445417, 'TRUE' }, -- Path of the Ara-Kara, City of Echoes - { 445440, 'TRUE' }, -- Path of the Brewery - { 445416, 'TRUE' }, -- Path of the City of Threads - { 445441, 'TRUE' }, -- Path of the Darkflame Cleft - { 445414, 'TRUE' }, -- Path of the Dawnbreaker - { 445444, 'TRUE' }, -- Path of the Priory of the Sacred Flame - { 445443, 'TRUE' }, -- Path of the Rookery - { 445269, 'TRUE' } -- Path of the Stonevault + -- DH Classic + {159902, 'TRUE'}, -- Path of the Burning Mountain + {373262, 'TRUE'}, -- Path of the Fallen Guardian + {131232, 'TRUE'}, -- Path of the Necromancer + {131231, 'TRUE'}, -- Path of the Scarlet Blade + {131229, 'TRUE'}, -- Path of the Scarlet Mitre + {393222, 'TRUE'}, -- Path of the Watcher's Legacy + -- DH BC + -- DH Cata + {445424, 'TRUE'}, -- Path of the Grim Batol + {424142, 'TRUE'}, -- Path of the Tidehunter + {410080, 'TRUE'}, -- Path of the Wind's Domain + -- DH MOP + {131228, 'TRUE'}, -- Path of the Black Ox + {131204, 'TRUE'}, -- Path of the Jade Serpent + {131222, 'TRUE'}, -- Path of the Mogu King + {131225, 'TRUE'}, -- Path of the Setting Sun + {131206, 'TRUE'}, -- Path of the Shado-Pan + {131205, 'TRUE'}, -- Path of the Stout Brew + -- DH WOD + {159895, 'TRUE'}, -- Path of the Bloodmaul + {159899, 'TRUE'}, -- Path of the Crescent Moon + {159900, 'TRUE'}, -- Path of the Dark Rail + {159896, 'TRUE'}, -- Path of the Iron Prow + {159898, 'TRUE'}, -- Path of the Skies + {159901, 'TRUE'}, -- Path of the Verdant + {159897, 'TRUE'}, -- Path of the Vigilant + -- DH Legion + {424153, 'TRUE'}, -- Path of the Ancient Horrors + {410078, 'TRUE'}, -- Path of the Earth-Warder + {393766, 'TRUE'}, -- Path of the Grand Magistrix + {424163, 'TRUE'}, -- Path of the Nightmare Lord + {393764, 'TRUE'}, -- Path of the Proven Worth + -- DH BFA + {410074, 'TRUE'}, -- Path of the Festering Rot + {410071, 'TRUE'}, -- Path of the Freebooter + {424187, 'TRUE'}, -- Path of the Golden Tomb + {424167, 'TRUE'}, -- Path of the Heart's Bane + {373274, 'TRUE'}, -- Path of the Scrappy Prince + {445418, 'TRUE'}, -- Path of the Siege of Boralus + -- DH SL + {354466, 'TRUE'}, -- Path of the Ascendant + {354462, 'TRUE'}, -- Path of the Courageous + {373192, 'TRUE'}, -- Path of the First Ones + {354464, 'TRUE'}, -- Path of the Misty Forest + {354463, 'TRUE'}, -- Path of the Plagued + {354468, 'TRUE'}, -- Path of the Scheming Loa + {354465, 'TRUE'}, -- Path of the Sinful Soul + {373190, 'TRUE'}, -- Path of the Sire + {354469, 'TRUE'}, -- Path of the Stone Warden + {367416, 'TRUE'}, -- Path of the Streetwise Merchant + {373191, 'TRUE'}, -- Path of the Tormented Soul + {354467, 'TRUE'}, -- Path of the Undefeated + -- DH DF + {393279, 'TRUE'}, -- Path of the Arcane Secrets + {432257, 'TRUE'}, -- Path of the Bitter Lagacy + {393256, 'TRUE'}, -- Path of the Clutch Defender + {393273, 'TRUE'}, -- Path of the Draconic Diploma + {393276, 'TRUE'}, -- Path of the Obsidian Hoard + {432254, 'TRUE'}, -- Path of the Primal Prison + {393267, 'TRUE'}, -- Path of the Rotting Woods + {432258, 'TRUE'}, -- Path of the Scorching Dream + {393283, 'TRUE'}, -- Path of the Titanic Reservoir + {424197, 'TRUE'}, -- Path of the Twisted Time + {393262, 'TRUE'}, -- Path of the Windswept Plains + -- DH TWW + {445417, 'TRUE'}, -- Path of the Ara-Kara, City of Echoes + {445440, 'TRUE'}, -- Path of the Brewery + {445416, 'TRUE'}, -- Path of the City of Threads + {445441, 'TRUE'}, -- Path of the Darkflame Cleft + {445414, 'TRUE'}, -- Path of the Dawnbreaker + {445444, 'TRUE'}, -- Path of the Priory of the Sacred Flame + {445443, 'TRUE'}, -- Path of the Rookery + {445269, 'TRUE'} -- Path of the Stonevault } -local whistle = { +local whistle = { 141605, -- Flight Master's Whistle - 168862 -- G.E.A.R. Tracking Beacon + 168862 -- G.E.A.R. Tracking Beacon } local obj = LibStub:GetLibrary('LibDataBroker-1.1'):NewDataObject(addonName, { type = 'data source', text = L['P'], - icon = 'Interface\\Icons\\INV_Misc_Rune_06', + icon = 'Interface\\Icons\\INV_Misc_Rune_06' }) local portals local frame = CreateFrame('frame') local function CreateCheckbox(checkboxText, key, checkboxTooltip) - local checkbox = CreateFrame("CheckButton", "BPCheckboxID" .. checkboxes, settingsFrame, "UICheckButtonTemplate") + local checkbox = CreateFrame("CheckButton", "BPCheckboxID" .. checkboxes, + settingsFrame, "UICheckButtonTemplate") checkbox.Text:SetText(checkboxText) - checkbox:SetPoint("TOPLEFT", settingsFrame, "TOPLEFT", 10, -30 + (checkboxes * -30)) + checkbox:SetPoint("TOPLEFT", settingsFrame, "TOPLEFT", 10, + -30 + (checkboxes * -30)) end - -frame:SetScript('OnEvent', function(self, event, ...) if self[event] then return self[event](self, event, ...) end end) +frame:SetScript('OnEvent', function(self, event, ...) + if self[event] then return self[event](self, event, ...) end +end) frame:RegisterEvent('PLAYER_LOGIN') - local function CreateSettingsPanel() if Settings then OptionsFrame = CreateFrame("Frame", "OptionsFrame", UIParent) OptionsFrame.name = "Broker Portals" - local showItemsCheckBox = CreateFrame("CheckButton", "ShowItemsCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showItemsCheckBox = CreateFrame("CheckButton", + "ShowItemsCheckBox", OptionsFrame, + "InterfaceOptionsCheckButtonTemplate") showItemsCheckBox:SetPoint("TOPLEFT", 16, -16) showItemsCheckBox.Text:SetText(L["SHOW_ITEMS"]) showItemsCheckBox.tooltipText = L["SHOW_ITEMS_TOOLTIP"] @@ -305,15 +310,18 @@ local function CreateSettingsPanel() PortalsDB.showItems = not PortalsDB.showItems parentFrame = self:GetParent() children = {parentFrame:GetChildren()} - for _,child in ipairs(children) do - if child:GetDebugName() == "showItemsSubCatCheckBox" or child:GetDebugName() == "showEngineeringSubCatCheckBox" then + for _, child in ipairs(children) do + if child:GetDebugName() == "showItemsSubCatCheckBox" or + child:GetDebugName() == "showEngineeringSubCatCheckBox" then child:SetEnabled(PortalsDB.showItems) end end end) - - local showItemsSubCatCheckBox = CreateFrame("CheckButton", "showItemsSubCatCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showItemsSubCatCheckBox = CreateFrame("CheckButton", + "showItemsSubCatCheckBox", + OptionsFrame, + "InterfaceOptionsCheckButtonTemplate") showItemsSubCatCheckBox:SetPoint("TOPLEFT", 320, -16) showItemsSubCatCheckBox.Text:SetText(L["SHOW_ITEMS_SUBCAT"]) showItemsSubCatCheckBox.tooltipText = L["SHOW_ITEMS_SUBCAT_TOOLTIP"] @@ -323,8 +331,10 @@ local function CreateSettingsPanel() PortalsDB.showItemsSubCat = not PortalsDB.showItemsSubCat end) - - local showHSItemsCheckBox = CreateFrame("CheckButton", "showHSItemsCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showHSItemsCheckBox = CreateFrame("CheckButton", + "showHSItemsCheckBox", + OptionsFrame, + "InterfaceOptionsCheckButtonTemplate") showHSItemsCheckBox:SetPoint("TOPLEFT", 16, -64) showHSItemsCheckBox.Text:SetText(L["SHOW_HS_ITEMS"]) showHSItemsCheckBox.tooltipText = L["SHOW_HS_ITEMS_TOOLTIP"] @@ -334,45 +344,57 @@ local function CreateSettingsPanel() PortalsDB.showHSItems = not PortalsDB.showHSItems parentFrame = self:GetParent() children = {parentFrame:GetChildren()} - for _,child in ipairs(children) do + for _, child in ipairs(children) do if child:GetDebugName() == "showHSItemsSubCatCheckBox" then child:SetEnabled(PortalsDB.showHSItems) end end end) - local showHSItemsSubCatCheckBox = CreateFrame("CheckButton", "showHSItemsSubCatCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showHSItemsSubCatCheckBox = + CreateFrame("CheckButton", "showHSItemsSubCatCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") showHSItemsSubCatCheckBox:SetPoint("TOPLEFT", 320, -64) showHSItemsSubCatCheckBox.Text:SetText(L["SHOW_HS_ITEMS_SUBCAT"]) - showHSItemsSubCatCheckBox.tooltipText = L["SHOW_HS_ITEMS_SUBCAT_TOOLTIP"] + showHSItemsSubCatCheckBox.tooltipText = + L["SHOW_HS_ITEMS_SUBCAT_TOOLTIP"] showHSItemsSubCatCheckBox:SetChecked(PortalsDB.showHSItemsSubCat) showHSItemsSubCatCheckBox:SetScript("OnClick", function(self) PortalsDB.showHSItemsSubCat = not PortalsDB.showHSItemsSubCat end) - local showEngineeringSubCatCheckBox = CreateFrame("CheckButton", "showEngineeringSubCatCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showEngineeringSubCatCheckBox = + CreateFrame("CheckButton", "showEngineeringSubCatCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") showEngineeringSubCatCheckBox:SetPoint("TOPLEFT", 16, -110) showEngineeringSubCatCheckBox.Text:SetText(L["SHOW_ENGINEERING_SUBCAT"]) - showEngineeringSubCatCheckBox.tooltipText = L["SHOW_ENGINEERING_SUBCAT_TOOLTIP"] + showEngineeringSubCatCheckBox.tooltipText = + L["SHOW_ENGINEERING_SUBCAT_TOOLTIP"] showEngineeringSubCatCheckBox:SetChecked(PortalsDB.showEngineeringSubCat) showEngineeringSubCatCheckBox:SetScript("OnClick", function(self) - PortalsDB.showEngineeringSubCat = not PortalsDB.showEngineeringSubCat + PortalsDB.showEngineeringSubCat = + not PortalsDB.showEngineeringSubCat end) - - local showTeleportsSubCatCheckBox = CreateFrame("CheckButton", "showTeleportsSubCatCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showTeleportsSubCatCheckBox = + CreateFrame("CheckButton", "showTeleportsSubCatCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") showTeleportsSubCatCheckBox:SetPoint("TOPLEFT", 320, -110) showTeleportsSubCatCheckBox.Text:SetText(L["SHOW_TELEPORTS_SUBCAT"]) - showTeleportsSubCatCheckBox.tooltipText = L["SHOW_TELEPORTS_SUBCAT_TOOLTIP"] + showTeleportsSubCatCheckBox.tooltipText = + L["SHOW_TELEPORTS_SUBCAT_TOOLTIP"] showTeleportsSubCatCheckBox:SetChecked(PortalsDB.showTeleportsSubCat) showTeleportsSubCatCheckBox:SetScript("OnClick", function(self) PortalsDB.showTeleportsSubCat = not PortalsDB.showTeleportsSubCat end) - local minimapButtonBox = CreateFrame("CheckButton", "showMinimapButtonCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local minimapButtonBox = CreateFrame("CheckButton", + "showMinimapButtonCheckBox", + OptionsFrame, + "InterfaceOptionsCheckButtonTemplate") minimapButtonBox:SetPoint("TOPLEFT", 16, -158) minimapButtonBox.Text:SetText(L['ATT_MINIMAP']) minimapButtonBox.tooltipText = L['ATT_MINIMAP'] @@ -382,7 +404,9 @@ local function CreateSettingsPanel() ToggleMinimap() end) - local announceCheckBox = CreateFrame("CheckButton", "announceCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local announceCheckBox = CreateFrame("CheckButton", "announceCheckBox", + OptionsFrame, + "InterfaceOptionsCheckButtonTemplate") announceCheckBox:SetPoint("TOPLEFT", 320, -158) announceCheckBox.Text:SetText(L["ANNOUNCE"]) announceCheckBox.tooltipText = L["ANNOUNCE_TOOLTIP"] @@ -392,35 +416,46 @@ local function CreateSettingsPanel() PortalsDB.announce = not PortalsDB.announce end) - local fontSizeSlider = CreateFrame("Slider", "fontSizeSlider", OptionsFrame, "OptionsSliderTemplate") + local fontSizeSlider = CreateFrame("Slider", "fontSizeSlider", + OptionsFrame, "OptionsSliderTemplate") fontSizeSlider:SetPoint("TOPLEFT", 16, -206) - fontSizeSlider.Text:SetText(L['DROPDOWN_FONT_SIZE'] .. PortalsDB.fontSize) + fontSizeSlider.Text:SetText(L['DROPDOWN_FONT_SIZE'] .. + PortalsDB.fontSize) fontSizeSlider.tooltipText = L['DROPDOWN_FONT_SIZE'] fontSizeSlider:SetMinMaxValues(8, 32) fontSizeSlider.Low:SetText(8) fontSizeSlider.High:SetText(32) fontSizeSlider:SetValueStep(1) - fontSizeSlider:SetScript('OnShow', function(self) self:SetValue(PortalsDB.fontSize) end) - fontSizeSlider:SetScript('OnValueChanged', function(self,value) + fontSizeSlider:SetScript('OnShow', function(self) + self:SetValue(PortalsDB.fontSize) + end) + fontSizeSlider:SetScript('OnValueChanged', function(self, value) PortalsDB.fontSize = floor(tonumber(value)) self.Text:SetText(L['DROPDOWN_FONT_SIZE'] .. PortalsDB.fontSize) end) - local scrollSizeSlider = CreateFrame("Slider", "scrollSizeSlider", OptionsFrame, "OptionsSliderTemplate") + local scrollSizeSlider = CreateFrame("Slider", "scrollSizeSlider", + OptionsFrame, + "OptionsSliderTemplate") scrollSizeSlider:SetPoint("TOPLEFT", 320, -206) - scrollSizeSlider.Text:SetText(L['SCROLL_LIST_SIZE'] .. PortalsDB.scrollListSize) + scrollSizeSlider.Text:SetText(L['SCROLL_LIST_SIZE'] .. + PortalsDB.scrollListSize) scrollSizeSlider.tooltipText = L['SCROLL_LIST_SIZE'] scrollSizeSlider:SetMinMaxValues(30, 60) scrollSizeSlider.Low:SetText(30) scrollSizeSlider.High:SetText(60) scrollSizeSlider:SetValueStep(1) - scrollSizeSlider:SetScript('OnShow', function(self) self:SetValue(PortalsDB.scrollListSize) end) - scrollSizeSlider:SetScript('OnValueChanged', function(self,value) + scrollSizeSlider:SetScript('OnShow', function(self) + self:SetValue(PortalsDB.scrollListSize) + end) + scrollSizeSlider:SetScript('OnValueChanged', function(self, value) PortalsDB.scrollListSize = floor(tonumber(value)) self.Text:SetText(L['SCROLL_LIST_SIZE'] .. PortalsDB.scrollListSize) end) - local showItemsCooldownCheckBox = CreateFrame("CheckButton", "showItemsCooldownCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local showItemsCooldownCheckBox = + CreateFrame("CheckButton", "showItemsCooldownCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") showItemsCooldownCheckBox:SetPoint("TOPLEFT", 16, -254) showItemsCooldownCheckBox.Text:SetText(L["SHOW_ITEM_COOLDOWNS"]) showItemsCooldownCheckBox.tooltipText = L["SHOW_ITEM_COOLDOWNS_TOOLTIP"] @@ -430,7 +465,9 @@ local function CreateSettingsPanel() PortalsDB.showItemCooldowns = not PortalsDB.showItemCooldowns end) - local sortItemsAlphabeticalyCheckBox = CreateFrame("CheckButton", "sortItemsAlphabeticalyCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + local sortItemsAlphabeticalyCheckBox = + CreateFrame("CheckButton", "sortItemsAlphabeticalyCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") sortItemsAlphabeticalyCheckBox:SetPoint("TOPLEFT", 320, -254) sortItemsAlphabeticalyCheckBox.Text:SetText(L["SORT_ITEMS"]) sortItemsAlphabeticalyCheckBox.tooltipText = L["SORT_ITEMS_TOOLTIP"] @@ -440,47 +477,54 @@ local function CreateSettingsPanel() PortalsDB.sortItems = not PortalsDB.sortItems end) - if not isCataclysmClassic then - local showChallengeTeleportsCheckBox = CreateFrame("CheckButton", "showChallengeTeleportsCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") - showChallengeTeleportsCheckBox:SetPoint("TOPLEFT", 16, -302) - showChallengeTeleportsCheckBox.Text:SetText(L["SHOW_CHALLENGE_TELEPORTS"]) - showChallengeTeleportsCheckBox.tooltipText = L["SHOW_CHALLENGE_TELEPORTS_TOOLTIP"] - showChallengeTeleportsCheckBox:SetChecked(PortalsDB.showChallengeTeleports) - - showChallengeTeleportsCheckBox:SetScript("OnClick", function(self) - PortalsDB.showChallengeTeleports = not PortalsDB.showChallengeTeleports - for _,child in ipairs(children) do - if child:GetDebugName() == "showChallengeSubCatCheckBox" then - child:SetEnabled(PortalsDB.showChallengeTeleports) - end + local showChallengeTeleportsCheckBox = + CreateFrame("CheckButton", "showChallengeTeleportsCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + showChallengeTeleportsCheckBox:SetPoint("TOPLEFT", 16, -302) + showChallengeTeleportsCheckBox.Text:SetText( + L["SHOW_CHALLENGE_TELEPORTS"]) + showChallengeTeleportsCheckBox.tooltipText = + L["SHOW_CHALLENGE_TELEPORTS_TOOLTIP"] + showChallengeTeleportsCheckBox:SetChecked( + PortalsDB.showChallengeTeleports) + + showChallengeTeleportsCheckBox:SetScript("OnClick", function(self) + PortalsDB.showChallengeTeleports = + not PortalsDB.showChallengeTeleports + for _, child in ipairs(children) do + if child:GetDebugName() == "showChallengeSubCatCheckBox" then + child:SetEnabled(PortalsDB.showChallengeTeleports) end - end) - - local showChallengeSubCatCheckBox = CreateFrame("CheckButton", "showChallengeSubCatCheckBox", OptionsFrame, "InterfaceOptionsCheckButtonTemplate") - showChallengeSubCatCheckBox:SetPoint("TOPLEFT", 320, -302) - showChallengeSubCatCheckBox.Text:SetText(L["SHOW_CHALLENGE_TELEPORTS_SUBCAT"]) - showChallengeSubCatCheckBox.tooltipText = L["SHOW_CHALLENGE_TELEPORTS_SUBCAT_TOOLTIP"] - showChallengeSubCatCheckBox:SetChecked(PortalsDB.showChallengeSubCat) - - showChallengeSubCatCheckBox:SetScript("OnClick", function(self) - PortalsDB.showChallengeSubCat = not PortalsDB.showChallengeSubCat - end) + end + end) + + local showChallengeSubCatCheckBox = + CreateFrame("CheckButton", "showChallengeSubCatCheckBox", + OptionsFrame, "InterfaceOptionsCheckButtonTemplate") + showChallengeSubCatCheckBox:SetPoint("TOPLEFT", 320, -302) + showChallengeSubCatCheckBox.Text:SetText( + L["SHOW_CHALLENGE_TELEPORTS_SUBCAT"]) + showChallengeSubCatCheckBox.tooltipText = + L["SHOW_CHALLENGE_TELEPORTS_SUBCAT_TOOLTIP"] + showChallengeSubCatCheckBox:SetChecked(PortalsDB.showChallengeSubCat) + + showChallengeSubCatCheckBox:SetScript("OnClick", function(self) + PortalsDB.showChallengeSubCat = + not PortalsDB.showChallengeSubCat + end) end - category = Settings.RegisterCanvasLayoutCategory(OptionsFrame, OptionsFrame.name) - Settings.RegisterAddOnCategory(category) + category = Settings.RegisterCanvasLayoutCategory(OptionsFrame, + OptionsFrame.name) + Settings.RegisterAddOnCategory(category) end end local function pairsByKeys(t, sortTable) local a = {} - for n in pairs(t) do - table.insert(a, n) - end - if sortTable then - table.sort(a) - end + for n in pairs(t) do table.insert(a, n) end + if sortTable then table.sort(a) end local i = 0 local iter = function() @@ -495,9 +539,7 @@ local function pairsByKeys(t, sortTable) end local function tconcat(t1, t2) - for i = 1, #t2 do - t1[#t1 + 1] = t2[i] - end + for i = 1, #t2 do t1[#t1 + 1] = t2[i] end return t1 end @@ -571,74 +613,74 @@ end local function SetupSpells() local spells = { Alliance = { - { 3561, 'TP_RUNE' }, -- TP:Stormwind - { 3562, 'TP_RUNE' }, -- TP:Ironforge - { 3565, 'TP_RUNE' }, -- TP:Darnassus - { 32271, 'TP_RUNE' }, -- TP:Exodar - { 49359, 'TP_RUNE' }, -- TP:Theramore - { 33690, 'TP_RUNE' }, -- TP:Shattrath - { 53140, 'TP_RUNE' }, -- TP:Dalaran - { 88342, 'TP_RUNE' }, -- TP:Tol Barad - { 132621, 'TP_RUNE' }, -- TP:Vale of Eternal Blossoms - { 120145, 'TP_RUNE' }, -- TP:Ancient Dalaran - { 176248, 'TP_RUNE' }, -- TP:StormShield - { 224869, 'TP_RUNE' }, -- TP:Dalaran - Broken Isles - { 193759, 'TP_RUNE' }, -- TP:Hall of the Guardian - { 281403, 'TP_RUNE' }, -- TP:Boralus - { 344587, 'TP_RUNE' }, -- TP:Oribos - { 395277, 'TP_RUNE' }, -- TP:Valdrakken - { 446540, 'TP_RUNE' }, -- TP:Dornogal - { 10059, 'P_RUNE' }, -- P:Stormwind - { 11416, 'P_RUNE' }, -- P:Ironforge - { 11419, 'P_RUNE' }, -- P:Darnassus - { 32266, 'P_RUNE' }, -- P:Exodar - { 49360, 'P_RUNE' }, -- P:Theramore - { 33691, 'P_RUNE' }, -- P:Shattrath - { 53142, 'P_RUNE' }, -- P:Dalaran - { 88345, 'P_RUNE' }, -- P:Tol Barad - { 120146, 'P_RUNE' }, -- P:Ancient Dalaran - { 132620, 'P_RUNE' }, -- P:Vale of Eternal Blossoms - { 176246, 'P_RUNE' }, -- P:StormShield - { 224871, 'P_RUNE' }, -- P:Dalaran - Broken Isles - { 281400, 'P_RUNE' }, -- P:Boralus - { 344597, 'P_RUNE' }, -- P:Oribos - { 395289, 'P_RUNE' }, -- P:Valdrakken - { 446534, 'P_RUNE' } -- P:Dornogal + {3561, 'TP_RUNE'}, -- TP:Stormwind + {3562, 'TP_RUNE'}, -- TP:Ironforge + {3565, 'TP_RUNE'}, -- TP:Darnassus + {32271, 'TP_RUNE'}, -- TP:Exodar + {49359, 'TP_RUNE'}, -- TP:Theramore + {33690, 'TP_RUNE'}, -- TP:Shattrath + {53140, 'TP_RUNE'}, -- TP:Dalaran + {88342, 'TP_RUNE'}, -- TP:Tol Barad + {132621, 'TP_RUNE'}, -- TP:Vale of Eternal Blossoms + {120145, 'TP_RUNE'}, -- TP:Ancient Dalaran + {176248, 'TP_RUNE'}, -- TP:StormShield + {224869, 'TP_RUNE'}, -- TP:Dalaran - Broken Isles + {193759, 'TP_RUNE'}, -- TP:Hall of the Guardian + {281403, 'TP_RUNE'}, -- TP:Boralus + {344587, 'TP_RUNE'}, -- TP:Oribos + {395277, 'TP_RUNE'}, -- TP:Valdrakken + {446540, 'TP_RUNE'}, -- TP:Dornogal + {10059, 'P_RUNE'}, -- P:Stormwind + {11416, 'P_RUNE'}, -- P:Ironforge + {11419, 'P_RUNE'}, -- P:Darnassus + {32266, 'P_RUNE'}, -- P:Exodar + {49360, 'P_RUNE'}, -- P:Theramore + {33691, 'P_RUNE'}, -- P:Shattrath + {53142, 'P_RUNE'}, -- P:Dalaran + {88345, 'P_RUNE'}, -- P:Tol Barad + {120146, 'P_RUNE'}, -- P:Ancient Dalaran + {132620, 'P_RUNE'}, -- P:Vale of Eternal Blossoms + {176246, 'P_RUNE'}, -- P:StormShield + {224871, 'P_RUNE'}, -- P:Dalaran - Broken Isles + {281400, 'P_RUNE'}, -- P:Boralus + {344597, 'P_RUNE'}, -- P:Oribos + {395289, 'P_RUNE'}, -- P:Valdrakken + {446534, 'P_RUNE'} -- P:Dornogal }, Horde = { - { 3563, 'TP_RUNE' }, -- TP:Undercity - { 3566, 'TP_RUNE' }, -- TP:Thunder Bluff - { 3567, 'TP_RUNE' }, -- TP:Orgrimmar - { 32272, 'TP_RUNE' }, -- TP:Silvermoon - { 49358, 'TP_RUNE' }, -- TP:Stonard - { 35715, 'TP_RUNE' }, -- TP:Shattrath - { 53140, 'TP_RUNE' }, -- TP:Dalaran - { 88344, 'TP_RUNE' }, -- TP:Tol Barad - { 132627, 'TP_RUNE' }, -- TP:Vale of Eternal Blossoms - { 120145, 'TP_RUNE' }, -- TP:Ancient Dalaran - { 176242, 'TP_RUNE' }, -- TP:Warspear - { 224869, 'TP_RUNE' }, -- TP:Dalaran - Broken Isles - { 193759, 'TP_RUNE' }, -- TP:Hall of the Guardian - { 281404, 'TP_RUNE' }, -- TP:Dazar'alor - { 344587, 'TP_RUNE' }, -- TP:Oribos - { 395277, 'TP_RUNE' }, -- TP:Valdrakken - { 446540, 'TP_RUNE' }, -- TP:Dornogal - { 11418, 'P_RUNE' }, -- P:Undercity - { 11420, 'P_RUNE' }, -- P:Thunder Bluff - { 11417, 'P_RUNE' }, -- P:Orgrimmar - { 32267, 'P_RUNE' }, -- P:Silvermoon - { 49361, 'P_RUNE' }, -- P:Stonard - { 35717, 'P_RUNE' }, -- P:Shattrath - { 53142, 'P_RUNE' }, -- P:Dalaran - { 88346, 'P_RUNE' }, -- P:Tol Barad - { 120146, 'P_RUNE' }, -- P:Ancient Dalaran - { 132626, 'P_RUNE' }, -- P:Vale of Eternal Blossoms - { 176244, 'P_RUNE' }, -- P:Warspear - { 224871, 'P_RUNE' }, -- P:Dalaran - Broken Isles - { 281402, 'P_RUNE' }, -- P:Dazar'alor - { 344597, 'P_RUNE' }, -- P:Oribos - { 395289, 'P_RUNE' }, -- P:Valdrakken - { 446534, 'P_RUNE' } -- P:Dornogal + {3563, 'TP_RUNE'}, -- TP:Undercity + {3566, 'TP_RUNE'}, -- TP:Thunder Bluff + {3567, 'TP_RUNE'}, -- TP:Orgrimmar + {32272, 'TP_RUNE'}, -- TP:Silvermoon + {49358, 'TP_RUNE'}, -- TP:Stonard + {35715, 'TP_RUNE'}, -- TP:Shattrath + {53140, 'TP_RUNE'}, -- TP:Dalaran + {88344, 'TP_RUNE'}, -- TP:Tol Barad + {132627, 'TP_RUNE'}, -- TP:Vale of Eternal Blossoms + {120145, 'TP_RUNE'}, -- TP:Ancient Dalaran + {176242, 'TP_RUNE'}, -- TP:Warspear + {224869, 'TP_RUNE'}, -- TP:Dalaran - Broken Isles + {193759, 'TP_RUNE'}, -- TP:Hall of the Guardian + {281404, 'TP_RUNE'}, -- TP:Dazar'alor + {344587, 'TP_RUNE'}, -- TP:Oribos + {395277, 'TP_RUNE'}, -- TP:Valdrakken + {446540, 'TP_RUNE'}, -- TP:Dornogal + {11418, 'P_RUNE'}, -- P:Undercity + {11420, 'P_RUNE'}, -- P:Thunder Bluff + {11417, 'P_RUNE'}, -- P:Orgrimmar + {32267, 'P_RUNE'}, -- P:Silvermoon + {49361, 'P_RUNE'}, -- P:Stonard + {35717, 'P_RUNE'}, -- P:Shattrath + {53142, 'P_RUNE'}, -- P:Dalaran + {88346, 'P_RUNE'}, -- P:Tol Barad + {120146, 'P_RUNE'}, -- P:Ancient Dalaran + {132626, 'P_RUNE'}, -- P:Vale of Eternal Blossoms + {176244, 'P_RUNE'}, -- P:Warspear + {224871, 'P_RUNE'}, -- P:Dalaran - Broken Isles + {281402, 'P_RUNE'}, -- P:Dazar'alor + {344597, 'P_RUNE'}, -- P:Oribos + {395289, 'P_RUNE'}, -- P:Valdrakken + {446534, 'P_RUNE'} -- P:Dornogal } } @@ -647,22 +689,22 @@ local function SetupSpells() portals = spells[select(1, UnitFactionGroup('player'))] elseif class == 'DEATHKNIGHT' then portals = { - { 50977, 'TRUE' } -- Death Gate + {50977, 'TRUE'} -- Death Gate } elseif class == 'DRUID' then portals = { - { 18960, 'TRUE' }, -- TP:Moonglade - { 147420, 'TRUE' }, -- TP:One with Nature - { 193753, 'TRUE' } -- TP:Dreamwalk + {18960, 'TRUE'}, -- TP:Moonglade + {147420, 'TRUE'}, -- TP:One with Nature + {193753, 'TRUE'} -- TP:Dreamwalk } elseif class == 'SHAMAN' then portals = { - { 556, 'TRUE' } -- Astral Recall + {556, 'TRUE'} -- Astral Recall } elseif class == 'MONK' then portals = { - { 126892, 'TRUE' }, -- Zen Pilgrimage - { 126895, 'TRUE' } -- Zen Pilgrimage: Return + {126892, 'TRUE'}, -- Zen Pilgrimage + {126895, 'TRUE'} -- Zen Pilgrimage: Return } else portals = {} @@ -670,17 +712,16 @@ local function SetupSpells() local _, race = UnitRace('player') if race == 'DarkIronDwarf' then - table.insert(portals, { 265225, 'TRUE' }) -- Mole Machine + table.insert(portals, {265225, 'TRUE'}) -- Mole Machine end if race == 'Vulpera' then - table.insert(portals, { 312370, 'TRUE' }) -- Make Camp - table.insert(portals, { 312372, 'TRUE' }) -- Return To Camp + table.insert(portals, {312370, 'TRUE'}) -- Make Camp + table.insert(portals, {312372, 'TRUE'}) -- Return To Camp end wipe(spells) end - local function GenerateMenuEntries(itemType, itemList, menuCategory) local itemsGenerated = 0 @@ -688,9 +729,10 @@ local function GenerateMenuEntries(itemType, itemList, menuCategory) for _, unTransSpell in ipairs(itemList) do if IsPlayerSpell(unTransSpell[1]) then local spellName - local spell, _, spellIcon, _, _, _, spellId = GetSpellInfo(unTransSpell[1]) + local spell, _, spellIcon, _, _, _, spellId = GetSpellInfo( + unTransSpell[1]) if type(spell) == "table" then - spellId = spell.spellID + spellId = spell.spellID spellIcon = spell.iconID spellName = spell.name else @@ -702,16 +744,13 @@ local function GenerateMenuEntries(itemType, itemList, menuCategory) methods[menuCategory] = {} end methods[menuCategory][spellName] = { - itemID = spellId, + itemID = spellId, itemName = spellName, itemIcon = spellIcon, itemType = itemType, - itemRGB = nil, + itemRGB = nil, isPortal = unTransSpell[2] == 'P_RUNE', - secure = { - type = 'spell', - spell = spellName - } + secure = {type = 'spell', spell = spellName} } itemsGenerated = itemsGenerated + 1 end @@ -721,20 +760,18 @@ local function GenerateMenuEntries(itemType, itemList, menuCategory) local i = 0 for i = 1, #itemList do if hasItem(itemList[i]) then - local itemName, _, itemQuality, _, _, _, _, _, _, itemIcon = GetItemInfo(itemList[i]) + local itemName, _, itemQuality, _, _, _, _, _, _, itemIcon = + GetItemInfo(itemList[i]) if not methods[menuCategory] then methods[menuCategory] = {} end methods[menuCategory][itemName] = { - itemID = itemList[i], + itemID = itemList[i], itemName = itemName, itemIcon = itemIcon, itemType = itemType, - itemRGB = ITEM_QUALITY_COLORS[itemQuality], - secure = { - type = 'item', - item = itemName - } + itemRGB = ITEM_QUALITY_COLORS[itemQuality], + secure = {type = 'item', item = itemName} } itemsGenerated = itemsGenerated + 1 end @@ -748,59 +785,60 @@ local function PrepareMenuData() wipe(methods) - if not portals then - SetupSpells() - end + if not portals then SetupSpells() end - if portals then - GenerateMenuEntries("spell", portals, "mainspells") - end + if portals then GenerateMenuEntries("spell", portals, "mainspells") end if not isCataclysmClassic then - challengeSpellCount = GenerateMenuEntries("spell", challengeSpells, "challenges") + challengeSpellCount = GenerateMenuEntries("spell", challengeSpells, + "challenges") end GenerateMenuEntries("items", items, "mainitems") - engineringItemsCount = GenerateMenuEntries("items", engineeringItems, "engineering") - heartstoneItemsCount = GenerateMenuEntries("items", heartstones, "heartstones") + engineringItemsCount = GenerateMenuEntries("items", engineeringItems, + "engineering") + heartstoneItemsCount = GenerateMenuEntries("items", heartstones, + "heartstones") databaseLoaded = true end -local function UpdateIcon(icon) - obj.icon = icon -end +local function UpdateIcon(icon) obj.icon = icon end local function ShowMenuEntries(category, sortTable) if methods[category] then for _, menuEntry in pairsByKeys(methods[category], sortTable) do if menuEntry.itemType == "spell" then local spellCooldown - if isCataclysmClassic then spellCooldown = GetSpellCooldown(menuEntry.itemName) else spellCooldown = GetSpellCooldown(menuEntry.itemName).startTime end + if isCataclysmClassic then + spellCooldown = GetSpellCooldown(menuEntry.itemName) + else + spellCooldown = + GetSpellCooldown(menuEntry.itemName).startTime + end if menuEntry.secure and spellCooldown == 0 then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', menuEntry.itemName, - 'secure', menuEntry.secure, - 'icon', tostring(menuEntry.itemIcon), - 'func', function() - UpdateIcon(menuEntry.itemIcon) - if announce and menuyEntry.isPortal and chatType then - SendChatMessage(L['ANNOUNCEMENT'] .. ' ' .. menuEntry.itemName, chatType) - end - end, - 'closeWhenClicked', true) + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + menuEntry.itemName, 'secure', + menuEntry.secure, 'icon', + tostring(menuEntry.itemIcon), 'func', + function() + UpdateIcon(menuEntry.itemIcon) + if announce and menuyEntry.isPortal and chatType then + SendChatMessage( + L['ANNOUNCEMENT'] .. ' ' .. menuEntry.itemName, + chatType) + end + end, 'closeWhenClicked', true) end else - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', menuEntry.itemName, - 'textR', menuEntry.itemRGB.r, - 'textG', menuEntry.itemRGB.g, - 'textB', menuEntry.itemRGB.b, - 'secure', menuEntry.secure, - 'icon', tostring(menuEntry.itemIcon), - 'func', function() UpdateIcon(menuEntry.itemIcon) end, - 'closeWhenClicked', true) + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + menuEntry.itemName, 'textR', + menuEntry.itemRGB.r, 'textG', + menuEntry.itemRGB.g, 'textB', + menuEntry.itemRGB.b, 'secure', menuEntry.secure, + 'icon', tostring(menuEntry.itemIcon), 'func', + function() + UpdateIcon(menuEntry.itemIcon) + end, 'closeWhenClicked', true) end end dewdrop:AddLine() @@ -809,15 +847,15 @@ end local function GetItemCooldowns() local cooldown, cooldowns, hours, mins, secs - if cooldowns == nil then - cooldowns = {} - end + if cooldowns == nil then cooldowns = {} end for i = 1, #items do - if GetItemCount(items[i]) > 0 or (PlayerHasToy(items[i]) and C_ToyBox.IsToyUsable(items[i])) then + if GetItemCount(items[i]) > 0 or + (PlayerHasToy(items[i]) and C_ToyBox.IsToyUsable(items[i])) then startTime, duration = GetItemCooldown(items[i]) cooldown = duration - (GetTime() - startTime) - local name = GetItemInfo(items[i]) or select(2, C_ToyBox.GetToyInfo(items[i])) + local name = GetItemInfo(items[i]) or + select(2, C_ToyBox.GetToyInfo(items[i])) if name then if cooldown <= 0 then cooldown = L['READY'] @@ -830,11 +868,15 @@ local function GetItemCooldowns() end for i = 1, #engineeringItems do - if GetItemCount(engineeringItems[i]) > 0 or (PlayerHasToy(engineeringItems[i]) and C_ToyBox.IsToyUsable(engineeringItems[i])) then + if GetItemCount(engineeringItems[i]) > 0 or + (PlayerHasToy(engineeringItems[i]) and + C_ToyBox.IsToyUsable(engineeringItems[i])) then startTime, duration = GetItemCooldown(engineeringItems[i]) cooldown = duration - (GetTime() - startTime) if cooldown > 0 then - local name = GetItemInfo(engineeringItems[i]) or select(2, C_ToyBox.GetToyInfo(engineeringItems[i])) + local name = GetItemInfo(engineeringItems[i]) or + select(2, C_ToyBox.GetToyInfo( + engineeringItems[i])) if name then cooldown = SecondsToTime(cooldown) cooldowns[name] = cooldown @@ -850,7 +892,8 @@ local function GetScrollCooldown() local cooldown, startTime, duration for i = 1, #scrolls do - if GetItemCount(scrolls[i]) > 0 or (PlayerHasToy(scrolls[i]) and C_ToyBox.IsToyUsable(scrolls[i])) then + if GetItemCount(scrolls[i]) > 0 or + (PlayerHasToy(scrolls[i]) and C_ToyBox.IsToyUsable(scrolls[i])) then startTime, duration = GetItemCooldown(scrolls[i]) cooldown = duration - (GetTime() - startTime) if cooldown <= 0 then @@ -886,22 +929,16 @@ local function ShowHearthstone() if hasItem(scrolls[i]) then name, _, _, _, _, _, _, _, _, icon = GetItemInfo(scrolls[i]) text = L['INN'] .. ' ' .. bindLoc - secure = { - type = 'item', - item = name - } + secure = {type = 'item', item = name} break end end if secure ~= nil then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', text, - 'secure', secure, - 'icon', tostring(icon), - 'func', function() UpdateIcon(icon) end, - 'closeWhenClicked', true) + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', text, + 'secure', secure, 'icon', tostring(icon), 'func', + function() UpdateIcon(icon) end, 'closeWhenClicked', + true) end end @@ -909,19 +946,13 @@ local function ShowWhistle() local secure, icon, name if hasItem(whistle[1]) then name, _, _, _, _, _, _, _, _, icon = GetItemInfo(whistle[1]) - secure = { - type = 'item', - item = name - } + secure = {type = 'item', item = name} end if secure ~= nil then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', name, - 'secure', secure, - 'icon', tostring(icon), - 'func', function() UpdateIcon(icon) end, - 'closeWhenClicked', true) + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', name, + 'secure', secure, 'icon', tostring(icon), 'func', + function() UpdateIcon(icon) end, 'closeWhenClicked', + true) dewdrop:AddLine() end end @@ -944,12 +975,11 @@ local function UpdateMenu(level, value) dewdrop:AddLine('text', 'Broker_Portals', 'isTitle', true) PrepareMenuData() - local chatType = (UnitInRaid("player") and "RAID") or (GetNumGroupMembers() > 0 and "PARTY") or nil + local chatType = (UnitInRaid("player") and "RAID") or + (GetNumGroupMembers() > 0 and "PARTY") or nil local announce = PortalsDB.announce - if not portals then - SetupSpells() - end + if not portals then SetupSpells() end if portals then if not PortalsDB.showTeleportsSubCat then @@ -966,7 +996,8 @@ local function UpdateMenu(level, value) end end - if PortalsDB.showChallengeTeleports and not isCataclysmClassic and challengeSpellCount > 0 then + if PortalsDB.showChallengeTeleports and not isCataclysmClassic and + challengeSpellCount > 0 then if not PortalsDB.showChallengeSubCat then ShowMenuEntries("challenges", PortalsDB.sortItems) end @@ -980,75 +1011,60 @@ local function UpdateMenu(level, value) if portals then if PortalsDB.showTeleportsSubCat then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', L["TP_P"], - 'icon', tostring(teleportsIcon), - 'hasArrow', true, - 'value', 'mainspells') + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + L["TP_P"], 'icon', tostring(teleportsIcon), + 'hasArrow', true, 'value', 'mainspells') end end if PortalsDB.showItems then if PortalsDB.showItemsSubCat then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', L["MAIN_ITEMS"], - 'icon', tostring(variousItemsIcon), - 'hasArrow', true, - 'value', 'mainitems') + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + L["MAIN_ITEMS"], 'icon', + tostring(variousItemsIcon), 'hasArrow', true, + 'value', 'mainitems') end end if PortalsDB.showItems and engineringItemsCount > 0 then if PortalsDB.showEngineeringSubCat then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', engineeringName, - 'icon', tostring(engineeringIcon), - 'hasArrow', true, - 'value', 'engineering') + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + engineeringName, 'icon', + tostring(engineeringIcon), 'hasArrow', true, + 'value', 'engineering') end end - if PortalsDB.showChallengeTeleports and not isCataclysmClassic and challengeSpellCount > 0 then + if PortalsDB.showChallengeTeleports and not isCataclysmClassic and + challengeSpellCount > 0 then if PortalsDB.showChallengeSubCat then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', L['CHALLENGE_TELEPORTS'], - 'icon', tostring(teleportsIcon), - 'hasArrow', true, - 'value', 'challenges') + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + L['CHALLENGE_TELEPORTS'], 'icon', + tostring(teleportsIcon), 'hasArrow', true, + 'value', 'challenges') end end if PortalsDB.showHSItems and heartstoneItemsCount > 0 then if PortalsDB.showHSItemsSubCat then - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', L['HEARTHSTONE_ANALOGUES'], - 'icon', tostring(heartstonesIcon), - 'hasArrow', true, - 'value', 'heartstones') + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', + L['HEARTHSTONE_ANALOGUES'], 'icon', + tostring(heartstonesIcon), 'hasArrow', true, + 'value', 'heartstones') end end ShowHearthstone() ShowWhistle() - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', L['OPTIONS'], - 'hasArrow', false, - 'func', function() Settings.OpenToCategory(category:GetID()); end, - 'closeWhenClicked', true) + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', L['OPTIONS'], + 'hasArrow', false, 'func', function() + Settings.OpenToCategory(category:GetID()); + end, 'closeWhenClicked', true) - dewdrop:AddLine( - 'textHeight', PortalsDB.fontSize, - 'text', CLOSE, - 'tooltipTitle', CLOSE, - 'tooltipText', CLOSE_DESC, - 'closeWhenClicked', true) + dewdrop:AddLine('textHeight', PortalsDB.fontSize, 'text', CLOSE, + 'tooltipTitle', CLOSE, 'tooltipText', CLOSE_DESC, + 'closeWhenClicked', true) elseif level == 2 and value == 'mainspells' then ShowMenuEntries("mainspells", true) @@ -1078,7 +1094,7 @@ function frame:PLAYER_LOGIN() PortalsDB.showChallengeSubCat = false PortalsDB.showTeleportsSubCat = false PortalsDB.scrollListSize = 33 - PortalsDB.sortItems = false + PortalsDB.sortItems = false PortalsDB.announce = false PortalsDB.announce = false PortalsDB.fontSize = UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT @@ -1086,8 +1102,8 @@ function frame:PLAYER_LOGIN() end -- upgrade from versions if PortalsDB.version == 8 then - PortalsDB.sortItems = false - PortalsDB.version = 9 + PortalsDB.sortItems = false + PortalsDB.version = 9 elseif PortalsDB.version == 7 then PortalsDB.showEngineeringSubCat = true PortalsDB.showChallengeSubCat = false @@ -1117,9 +1133,7 @@ function frame:PLAYER_LOGIN() PortalsDB.version = 4 end - if icon then - icon:Register('Broker_Portals', obj, PortalsDB.minimap) - end + if icon then icon:Register('Broker_Portals', obj, PortalsDB.minimap) end CreateSettingsPanel() self:UnregisterEvent('PLAYER_LOGIN') end @@ -1128,21 +1142,22 @@ end local function GetTipAnchor(frame) local x, y = frame:GetCenter() if not x or not y then return 'TOPLEFT', 'BOTTOMLEFT' end - local hhalf = (x > UIParent:GetWidth() * 2 / 3) and 'RIGHT' or (x < UIParent:GetWidth() / 3) and 'LEFT' or '' + 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 + return vhalf .. hhalf, frame, + (vhalf == 'TOP' and 'BOTTOM' or 'TOP') .. hhalf end function obj.OnClick(self, button) GameTooltip:Hide() if button == 'RightButton' then - dewdrop:Open(self, 'children', function(level, value) UpdateMenu(level, value) end) + dewdrop:Open(self, 'children', + function(level, value) UpdateMenu(level, value) end) end end -function obj.OnLeave() - GameTooltip:Hide() -end +function obj.OnLeave() GameTooltip:Hide() end function obj.OnEnter(self) GameTooltip:SetOwner(self, 'ANCHOR_NONE') @@ -1150,19 +1165,24 @@ function obj.OnEnter(self) GameTooltip:ClearLines() GameTooltip:AddLine('Broker Portals') - GameTooltip:AddDoubleLine(L['RCLICK'], L['SEE_SPELLS'], 0.9, 0.6, 0.2, 0.2, 1, 0.2) + GameTooltip:AddDoubleLine(L['RCLICK'], L['SEE_SPELLS'], 0.9, 0.6, 0.2, 0.2, + 1, 0.2) GameTooltip:AddLine(' ') local scrollCooldown = GetScrollCooldown() if scrollCooldown == L['READY'] then - GameTooltip:AddDoubleLine(L['HEARTHSTONE'] .. ': ' .. GetBindLocation(), scrollCooldown, 0.9, 0.6, 0.2, 0.2, 1, 0.2) + GameTooltip:AddDoubleLine(L['HEARTHSTONE'] .. ': ' .. GetBindLocation(), + scrollCooldown, 0.9, 0.6, 0.2, 0.2, 1, 0.2) else - GameTooltip:AddDoubleLine(L['HEARTHSTONE'] .. ': ' .. GetBindLocation(), scrollCooldown, 0.9, 0.6, 0.2, 1, 1, 0.2) + GameTooltip:AddDoubleLine(L['HEARTHSTONE'] .. ': ' .. GetBindLocation(), + scrollCooldown, 0.9, 0.6, 0.2, 1, 1, 0.2) end if isCataclysmClassic then GameTooltip:AddLine(" ") - GameTooltip:AddDoubleLine(L["TP_P"], getReagentCount(L["TP_RUNE"]).."/"..getReagentCount(L["P_RUNE"]), 0.9, 0.6, 0.2, 0.2, 1, 0.2) + GameTooltip:AddDoubleLine(L["TP_P"], getReagentCount(L["TP_RUNE"]) .. + "/" .. getReagentCount(L["P_RUNE"]), 0.9, + 0.6, 0.2, 0.2, 1, 0.2) end if PortalsDB.showItemCooldowns then @@ -1171,9 +1191,11 @@ function obj.OnEnter(self) GameTooltip:AddLine(' ') for name, cooldown in pairs(cooldowns) do if cooldown == L['READY'] then - GameTooltip:AddDoubleLine(name, cooldown, 0.9, 0.6, 0.2, 0.2, 1, 0.2) + GameTooltip:AddDoubleLine(name, cooldown, 0.9, 0.6, 0.2, + 0.2, 1, 0.2) else - GameTooltip:AddDoubleLine(name, cooldown, 0.9, 0.6, 0.2, 1, 1, 0.2) + GameTooltip:AddDoubleLine(name, cooldown, 0.9, 0.6, 0.2, 1, + 1, 0.2) end end end @@ -1182,9 +1204,11 @@ function obj.OnEnter(self) if not isCataclysmClassic then local whistleCooldown = GetWhistleCooldown() if whistleCooldown == L['READY'] then - GameTooltip:AddDoubleLine(GetItemInfo(whistle[1]), whistleCooldown, 0.9, 0.6, 0.2, 0.2, 1, 0.2) + GameTooltip:AddDoubleLine(GetItemInfo(whistle[1]), whistleCooldown, + 0.9, 0.6, 0.2, 0.2, 1, 0.2) else - GameTooltip:AddDoubleLine(GetItemInfo(whistle[1]), whistleCooldown, 0.9, 0.6, 0.2, 1, 1, 0.2) + GameTooltip:AddDoubleLine(GetItemInfo(whistle[1]), whistleCooldown, + 0.9, 0.6, 0.2, 1, 1, 0.2) end end GameTooltip:Show()