Mercurial > wow > reaction
changeset 32:821b2b7edff1
Removed FuBar_ReActionFu
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Thu, 03 Apr 2008 16:59:16 +0000 |
parents | 27dde2743f43 |
children | c54c481ad0ed |
files | modules/FuBar_ReActionFu/FuBar_ReActionFu.lua modules/FuBar_ReActionFu/FuBar_ReActionFu.toc modules/FuBar_ReActionFu/FuBar_ReActionFu.xml modules/FuBar_ReActionFu/lib/AceLibrary/AceLibrary.lua modules/FuBar_ReActionFu/lib/AceLibrary/AceLibrary.toc modules/FuBar_ReActionFu/lib/Dewdrop-2.0/Dewdrop-2.0.lua modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/Changelog-LibFuBarPlugin-3.0-r63707.txt modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.lua modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.toc modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/lib.xml modules/FuBar_ReActionFu/lib/LibRock-1.0/Changelog-LibRock-1.0-r63317.txt modules/FuBar_ReActionFu/lib/LibRock-1.0/LibRock-1.0.lua modules/FuBar_ReActionFu/lib/LibRock-1.0/LibRock-1.0.toc modules/FuBar_ReActionFu/lib/LibRock-1.0/LibStub/LibStub.lua modules/FuBar_ReActionFu/lib/LibRock-1.0/lib.xml modules/FuBar_ReActionFu/lib/embeds.xml modules/modules.xml |
diffstat | 17 files changed, 0 insertions(+), 9634 deletions(-) [+] |
line wrap: on
line diff
--- a/modules/FuBar_ReActionFu/FuBar_ReActionFu.lua Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ ---[[ - FuBar plugin module for ReAction - ---]] - --- local imports -local ReAction = ReAction - --- module declaration -local moduleID = "ReActionFu" -local module = ReAction:NewModule( moduleID, - "FuBarPlugin-3.0" -) - -local fubarOptions = { - iconPath = "Interface\\Icons\\INV_Qiraj_JewelEncased", - hasNoColor = true, - tooltipType = "Tablet-2.0", - configType = "Dewdrop-2.0", - hasNoText = true, - defaultPosition = "LEFT", - defaultMinimapPosition = 240, -- degrees - clickableTooltip = false, - independentProfile = true - cannotDetachTooltip = true - hideMenuTitle = true -} - -function module:OnInitialize() - self.db = ReAction.db:RegisterNamespace(moduleID, - { - profile = { - requireFuBar = false - } - } - ) - self.db.RegisterCallback(self,"OnProfileChanged") - - if self.db.profile.requireFuBar == true then - self:Hide() - end - - self.OnMenuRequest = { - type = "group", - handler = ReAction, - args = { - -- include profile management by default - profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ReAction.db) - } - } - - -- insert each module's registered global opts into the table top level - local opts = self.OnMenuRequest - for m, tbl in pairs(ReAction:GetOptions("global")) do - if tbl.args then - for k, v in pairs(tbl.args) do - opts.args[k] = v - end - end - end - - -- listen for new module adds - ReAction.RegisterCallback(self, "OnOptionsRegistered") - - -- configure FuBarPlugin - for k, v in pairs(fubarOptions) do - self:SetFuBarOption(k,v) - end -end - -function module:OnProfileChanged() - if self.db.profile.requireFuBar == true then - module:Hide() - else - self:Show() - end -end - -function module:OnOptionsRegistered( evtName, context, module, opts ) - if context == "global" then - if opts.args then - for k, v in pairs(tbl.args) do - opts.args[k] = v - end - end - end -end - -function module:OnFuBarClick(button) - -- TODO: - -- alt, shift, ctrl clicks -end - -function module:OnUpdateFuBarTooltip() - -- TODO: - -- display status of config mode, keybind mode, etc -end -
--- a/modules/FuBar_ReActionFu/FuBar_ReActionFu.toc Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -## Interface: 20300 -## Title: FuBar - |cffffffffReAction|r|cff00ff00Fu|r -## Notes: FuBar plugin for ReAction -## DefaultState: enabled -## LoadOnDemand: 1 -## Author: Flick -## Version: 1.0 -## X-Category: Action Bars -## X-Embeds: FuBarPlugin-2.0, Tablet-2.0 -## Dependencies: ReAction - -FuBar_ReActionFu.xml
--- a/modules/FuBar_ReActionFu/FuBar_ReActionFu.xml Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd"> - - <Include file="lib\embeds.xml"/> - <Script file="FuBar_ReActionFu.lua"/> - -</Ui> \ No newline at end of file
--- a/modules/FuBar_ReActionFu/lib/AceLibrary/AceLibrary.lua Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,856 +0,0 @@ ---[[ -Name: AceLibrary -Revision: $Rev: 49421 $ -Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) -Inspired By: Iriel (iriel@vigilance-committee.org) - Tekkub (tekkub@gmail.com) - Revision: $Rev: 49421 $ -Website: http://www.wowace.com/ -Documentation: http://www.wowace.com/index.php/AceLibrary -SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary -Description: Versioning library to handle other library instances, upgrading, - and proper access. - It also provides a base for libraries to work off of, providing - proper error tools. It is handy because all the errors occur in the - file that called it, not in the library file itself. -Dependencies: None -License: LGPL v2.1 -]] - -local ACELIBRARY_MAJOR = "AceLibrary" -local ACELIBRARY_MINOR = "$Revision: 49421 $" - -local _G = getfenv(0) -local previous = _G[ACELIBRARY_MAJOR] -if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end - -do - -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info - -- LibStub is hereby placed in the Public Domain -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke - local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! - local LibStub = _G[LIBSTUB_MAJOR] - - if not LibStub or LibStub.minor < LIBSTUB_MINOR then - LibStub = LibStub or {libs = {}, minors = {} } - _G[LIBSTUB_MAJOR] = LibStub - LibStub.minor = LIBSTUB_MINOR - - 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 - - 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 - - function LibStub:IterateLibraries() return pairs(self.libs) end - setmetatable(LibStub, { __call = LibStub.GetLibrary }) - end -end -local LibStub = _G.LibStub - --- If you don't want AceLibrary to enable libraries that are LoadOnDemand but --- disabled in the addon screen, set this to true. -local DONT_ENABLE_LIBRARIES = nil - -local function safecall(func,...) - local success, err = pcall(func,...) - if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end -end - -local WoW22 = false -if type(GetBuildInfo) == "function" then - local success, buildinfo = pcall(GetBuildInfo) - if success and type(buildinfo) == "string" then - local num = tonumber(buildinfo:match("^(%d+%.%d+)")) - if num and num >= 2.2 then - WoW22 = true - end - end -end - --- @table AceLibrary --- @brief System to handle all versioning of libraries. -local AceLibrary = {} -local AceLibrary_mt = {} -setmetatable(AceLibrary, AceLibrary_mt) - -local function error(self, 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) -end - -local assert -if not WoW22 then - function assert(self, condition, message, ...) - if not condition then - if not message then - local stack = debugstack() - local second = stack:match("\n(.-)\n") - message = "assertion failed! " .. second - end - return error(self, message, ...) - end - return condition - end -end - -local type = type -local function argCheck(self, 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 -end - -local pcall -do - local function check(self, ret, ...) - if not ret then - local s = ... - return error(self, (s:gsub(".-%.lua:%d-: ", ""))) - else - return ... - end - end - - function pcall(self, func, ...) - return check(self, _G.pcall(func, ...)) - end -end - -local recurse = {} -local function addToPositions(t, major) - if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then - rawset(t, recurse, true) - AceLibrary.positions[t] = major - for k,v in pairs(t) do - if type(v) == "table" and not rawget(v, recurse) then - addToPositions(v, major) - end - if type(k) == "table" and not rawget(k, recurse) then - addToPositions(k, major) - end - end - local mt = getmetatable(t) - if mt and not rawget(mt, recurse) then - addToPositions(mt, major) - end - rawset(t, recurse, nil) - end -end - -local function svnRevisionToNumber(text) - local kind = type(text) - if kind == "number" or tonumber(text) then - return tonumber(text) - elseif kind == "string" then - if text:find("^%$Revision: (%d+) %$$") then - return tonumber((text:match("^%$Revision: (%d+) %$$"))) - elseif text:find("^%$Rev: (%d+) %$$") then - return tonumber((text:match("^%$Rev: (%d+) %$$"))) - elseif text:find("^%$LastChangedRevision: (%d+) %$$") then - return tonumber((text:match("^%$LastChangedRevision: (%d+) %$$"))) - end - end - return nil -end - -local crawlReplace -do - local recurse = {} - local function func(t, to, from) - if recurse[t] then - return - end - recurse[t] = true - local mt = getmetatable(t) - setmetatable(t, nil) - rawset(t, to, rawget(t, from)) - rawset(t, from, nil) - for k,v in pairs(t) do - if v == from then - t[k] = to - elseif type(v) == "table" then - if not recurse[v] then - func(v, to, from) - end - end - - if type(k) == "table" then - if not recurse[k] then - func(k, to, from) - end - end - end - setmetatable(t, mt) - if mt then - if mt == from then - setmetatable(t, to) - elseif not recurse[mt] then - func(mt, to, from) - end - end - end - function crawlReplace(t, to, from) - func(t, to, from) - for k in pairs(recurse) do - recurse[k] = nil - end - end -end - --- @function destroyTable --- @brief remove all the contents of a table --- @param t table to destroy -local function destroyTable(t) - setmetatable(t, nil) - for k,v in pairs(t) do - t[k] = nil - end -end - -local function isFrame(frame) - return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function" -end - --- @function copyTable --- @brief Create a shallow copy of a table and return it. --- @param from The table to copy from --- @return A shallow copy of the table -local function copyTable(from, to) - if not to then - to = {} - end - for k,v in pairs(from) do - to[k] = v - end - setmetatable(to, getmetatable(from)) - return to -end - --- @function deepTransfer --- @brief Fully transfer all data, keeping proper previous table --- backreferences stable. --- @param to The table with which data is to be injected into --- @param from The table whose data will be injected into the first --- @param saveFields If available, a shallow copy of the basic data is saved --- in here. --- @param list The account of table references --- @param list2 The current status on which tables have been traversed. -local deepTransfer -do - -- @function examine - -- @brief Take account of all the table references to be shared - -- between the to and from tables. - -- @param to The table with which data is to be injected into - -- @param from The table whose data will be injected into the first - -- @param list An account of the table references - local function examine(to, from, list, major) - list[from] = to - for k,v in pairs(from) do - if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then - if from[k] == to[k] then - list[from[k]] = to[k] - elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then - list[from[k]] = from[k] - elseif not list[from[k]] then - examine(to[k], from[k], list, major) - end - end - end - return list - end - - function deepTransfer(to, from, saveFields, major, list, list2) - setmetatable(to, nil) - if not list then - list = {} - list2 = {} - examine(to, from, list, major) - end - list2[to] = to - for k,v in pairs(to) do - if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then - if saveFields then - saveFields[k] = v - end - to[k] = nil - elseif v ~= _G then - if saveFields then - saveFields[k] = copyTable(v) - end - end - end - for k in pairs(from) do - if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then - if not list2[to[k]] then - deepTransfer(to[k], from[k], nil, major, list, list2) - end - to[k] = list[to[k]] or list2[to[k]] - else - rawset(to, k, from[k]) - end - end - setmetatable(to, getmetatable(from)) - local mt = getmetatable(to) - if mt then - if list[mt] then - setmetatable(to, list[mt]) - elseif mt.__index and list[mt.__index] then - mt.__index = list[mt.__index] - end - end - destroyTable(from) - end -end - -local function TryToEnable(addon) - if DONT_ENABLE_LIBRARIES then return end - local isondemand = IsAddOnLoadOnDemand(addon) - if isondemand then - local _, _, _, enabled = GetAddOnInfo(addon) - EnableAddOn(addon) - local _, _, _, _, loadable = GetAddOnInfo(addon) - if not loadable and not enabled then - DisableAddOn(addon) - end - - return loadable - end -end - --- @method TryToLoadStandalone --- @brief Attempt to find and load a standalone version of the requested library --- @param major A string representing the major version --- @return If library is found and loaded, true is return. If not loadable, false is returned. --- If the library has been requested previously, nil is returned. -local function TryToLoadStandalone(major) - if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end - if AceLibrary.scannedlibs[major] then return end - - AceLibrary.scannedlibs[major] = true - - local name, _, _, enabled, loadable = GetAddOnInfo(major) - - loadable = (enabled and loadable) or TryToEnable(name) - - local loaded = false - if loadable then - loaded = true - LoadAddOn(name) - end - - local field = "X-AceLibrary-" .. major - for i = 1, GetNumAddOns() do - if GetAddOnMetadata(i, field) then - name, _, _, enabled, loadable = GetAddOnInfo(i) - - loadable = (enabled and loadable) or TryToEnable(name) - if loadable then - loaded = true - LoadAddOn(name) - end - end - end - return loaded -end - --- @method IsNewVersion --- @brief Obtain whether the supplied version would be an upgrade to the --- current version. This allows for bypass code in library --- declaration. --- @param major A string representing the major version --- @param minor An integer or an svn revision string representing the minor version --- @return whether the supplied version would be newer than what is --- currently available. -function AceLibrary:IsNewVersion(major, minor) - argCheck(self, major, 2, "string") - TryToLoadStandalone(major) - - if type(minor) == "string" then - local m = svnRevisionToNumber(minor) - if m then - minor = m - else - _G.error(("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) - end - end - argCheck(self, minor, 3, "number") - local lib, oldMinor = LibStub:GetLibrary(major, true) - if lib then - return oldMinor < minor - end - local data = self.libs[major] - if not data then - return true - end - return data.minor < minor -end - --- @method HasInstance --- @brief Returns whether an instance exists. This allows for optional support of a library. --- @param major A string representing the major version. --- @param minor (optional) An integer or an svn revision string representing the minor version. --- @return Whether an instance exists. -function AceLibrary:HasInstance(major, minor) - argCheck(self, major, 2, "string") - if minor ~= false then - TryToLoadStandalone(major) - end - - local lib, ver = LibStub:GetLibrary(major, true) - if not lib and self.libs[major] then - lib, ver = self.libs[major].instance, self.libs[major].minor - end - if minor then - if type(minor) == "string" then - local m = svnRevisionToNumber(minor) - if m then - minor = m - else - _G.error(("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) - end - end - argCheck(self, minor, 3, "number") - if not lib then - return false - end - return ver == minor - end - return not not lib -end - --- @method GetInstance --- @brief Returns the library with the given major/minor version. --- @param major A string representing the major version. --- @param minor (optional) An integer or an svn revision string representing the minor version. --- @return The library with the given major/minor version. -function AceLibrary:GetInstance(major, minor) - argCheck(self, major, 2, "string") - if minor ~= false then - TryToLoadStandalone(major) - end - - local data, ver = LibStub:GetLibrary(major, true) - if not data then - if self.libs[major] then - data, ver = self.libs[major].instance, self.libs[major].minor - else - _G.error(("Cannot find a library instance of %s."):format(major), 2) - return - end - end - if minor then - if type(minor) == "string" then - local m = svnRevisionToNumber(minor) - if m then - minor = m - else - _G.error(("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) - end - end - argCheck(self, minor, 2, "number") - if ver ~= minor then - _G.error(("Cannot find a library instance of %s, minor version %d."):format(major, minor), 2) - end - end - return data -end - --- Syntax sugar. AceLibrary("FooBar-1.0") -AceLibrary_mt.__call = AceLibrary.GetInstance - -local donothing = function() end - -local AceEvent - -local tmp = {} - --- @method Register --- @brief Registers a new version of a given library. --- @param newInstance the library to register --- @param major the major version of the library --- @param minor the minor version of the library --- @param activateFunc (optional) A function to be called when the library is --- fully activated. Takes the arguments --- (newInstance [, oldInstance, oldDeactivateFunc]). If --- oldInstance is given, you should probably call --- oldDeactivateFunc(oldInstance). --- @param deactivateFunc (optional) A function to be called by a newer library's --- activateFunc. --- @param externalFunc (optional) A function to be called whenever a new --- library is registered. -function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc) - argCheck(self, newInstance, 2, "table") - argCheck(self, major, 3, "string") - if major ~= ACELIBRARY_MAJOR then - for k,v in pairs(_G) do - if v == newInstance then - geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) - end - end - end - if major ~= ACELIBRARY_MAJOR and not major:find("^[%a%-][%a%d%-]*%-%d+%.%d+$") then - _G.error(string.format("Bad argument #3 to `Register'. Must be in the form of \"Name-1.0\". %q is not appropriate", major), 2) - end - if type(minor) == "string" then - local m = svnRevisionToNumber(minor) - if m then - minor = m - else - _G.error(("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) - end - end - argCheck(self, minor, 4, "number") - if math.floor(minor) ~= minor or minor < 0 then - error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor) - end - argCheck(self, activateFunc, 5, "function", "nil") - argCheck(self, deactivateFunc, 6, "function", "nil") - argCheck(self, externalFunc, 7, "function", "nil") - if not deactivateFunc then - deactivateFunc = donothing - end - local data = self.libs[major] - if not data then - -- This is new - if LibStub:GetLibrary(major, true) then - error(self, "Cannot register library %q. It is already registered with LibStub.", major) - end - local instance = LibStub:NewLibrary(major, minor) - copyTable(newInstance, instance) - crawlReplace(instance, instance, newInstance) - destroyTable(newInstance) - if AceLibrary == newInstance then - self = instance - AceLibrary = instance - end - self.libs[major] = { - instance = instance, - minor = minor, - deactivateFunc = deactivateFunc, - externalFunc = externalFunc, - } - rawset(instance, 'GetLibraryVersion', function(self) - return major, minor - end) - if not rawget(instance, 'error') then - rawset(instance, 'error', error) - end - if not WoW22 and not rawget(instance, 'assert') then - rawset(instance, 'assert', assert) - end - if not rawget(instance, 'argCheck') then - rawset(instance, 'argCheck', argCheck) - end - if not rawget(instance, 'pcall') then - rawset(instance, 'pcall', pcall) - end - addToPositions(instance, major) - if activateFunc then - safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil - ---[[ if major ~= ACELIBRARY_MAJOR then - for k,v in pairs(_G) do - if v == instance then - geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) - end - end - end]] - end - - if externalFunc then - for k, data_instance in LibStub:IterateLibraries() do -- all libraries - tmp[k] = data_instance - end - for k, data in pairs(self.libs) do -- Ace libraries which may not have been registered with LibStub - tmp[k] = data.instance - end - for k, data_instance in pairs(tmp) do - if k ~= major then - safecall(externalFunc, instance, k, data_instance) - end - tmp[k] = nil - end - end - - for k,data in pairs(self.libs) do -- only Ace libraries - if k ~= major and data.externalFunc then - safecall(data.externalFunc, data.instance, major, instance) - end - end - if major == "AceEvent-2.0" then - AceEvent = instance - end - if AceEvent then - AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance) - end - - return instance - end - if minor <= data.minor then - -- This one is already obsolete, raise an error. - _G.error(("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end"):format(major, data.minor, minor, major, minor), 2) - return - end - local instance = data.instance - -- This is an update - local oldInstance = {} - - local libStubInstance = LibStub:GetLibrary(major, true) - if not libStubInstance then -- non-LibStub AceLibrary registered the library - -- pass - elseif libStubInstance ~= instance then - error(self, "Cannot register library %q. It is already registered with LibStub.", major) - else - LibStub:NewLibrary(major, minor) -- upgrade the minor version - end - - addToPositions(newInstance, major) - local isAceLibrary = (AceLibrary == newInstance) - local old_error, old_assert, old_argCheck, old_pcall - if isAceLibrary then - self = instance - AceLibrary = instance - - old_error = instance.error - if not WoW22 then - old_assert = instance.assert - end - old_argCheck = instance.argCheck - old_pcall = instance.pcall - - self.error = error - if not WoW22 then - self.assert = assert - end - self.argCheck = argCheck - self.pcall = pcall - end - deepTransfer(instance, newInstance, oldInstance, major) - crawlReplace(instance, instance, newInstance) - local oldDeactivateFunc = data.deactivateFunc - data.minor = minor - data.deactivateFunc = deactivateFunc - data.externalFunc = externalFunc - rawset(instance, 'GetLibraryVersion', function() - return major, minor - end) - if not rawget(instance, 'error') then - rawset(instance, 'error', error) - end - if not WoW22 and not rawget(instance, 'assert') then - rawset(instance, 'assert', assert) - end - if not rawget(instance, 'argCheck') then - rawset(instance, 'argCheck', argCheck) - end - if not rawget(instance, 'pcall') then - rawset(instance, 'pcall', pcall) - end - if isAceLibrary then - for _,v in pairs(self.libs) do - local i = type(v) == "table" and v.instance - if type(i) == "table" then - if not rawget(i, 'error') or i.error == old_error then - rawset(i, 'error', error) - end - if not WoW22 and (not rawget(i, 'assert') or i.assert == old_assert) then - rawset(i, 'assert', assert) - end - if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then - rawset(i, 'argCheck', argCheck) - end - if not rawget(i, 'pcall') or i.pcall == old_pcall then - rawset(i, 'pcall', pcall) - end - end - end - end - if activateFunc then - safecall(activateFunc, instance, oldInstance, oldDeactivateFunc) - ---[[ if major ~= ACELIBRARY_MAJOR then - for k,v in pairs(_G) do - if v == instance then - geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) - end - end - end]] - else - safecall(oldDeactivateFunc, oldInstance) - end - oldInstance = nil - - if externalFunc then - for k, data_instance in LibStub:IterateLibraries() do -- all libraries - tmp[k] = data_instance - end - for k, data in pairs(self.libs) do -- Ace libraries which may not have been registered with LibStub - tmp[k] = data.instance - end - for k, data_instance in pairs(tmp) do - if k ~= major then - safecall(externalFunc, instance, k, data_instance) - end - tmp[k] = nil - end - end - - return instance -end - -function AceLibrary:IterateLibraries() - local t = {} - for major, instance in LibStub:IterateLibraries() do - t[major] = instance - end - for major, data in pairs(self.libs) do - t[major] = data.instance - end - return pairs(t) -end - -local function manuallyFinalize(major, instance) - if AceLibrary.libs[major] then - -- don't work on Ace libraries - return - end - local finalizedExternalLibs = AceLibrary.finalizedExternalLibs - if finalizedExternalLibs[major] then - return - end - finalizedExternalLibs[major] = true - - for k,data in pairs(AceLibrary.libs) do -- only Ace libraries - if k ~= major and data.externalFunc then - safecall(data.externalFunc, data.instance, major, instance) - end - end -end - --- @function Activate --- @brief The activateFunc for AceLibrary itself. Called when --- AceLibrary properly registers. --- @param self Reference to AceLibrary --- @param oldLib (optional) Reference to an old version of AceLibrary --- @param oldDeactivate (optional) Function to deactivate the old lib -local function activate(self, oldLib, oldDeactivate) - AceLibrary = self - if not self.libs then - self.libs = oldLib and oldLib.libs or {} - self.scannedlibs = oldLib and oldLib.scannedlibs or {} - end - if not self.positions then - self.positions = oldLib and oldLib.positions or setmetatable({}, { __mode = "k" }) - end - self.finalizedExternalLibs = oldLib and oldLib.finalizedExternalLibs or {} - self.frame = oldLib and oldLib.frame or CreateFrame("Frame") - self.frame:UnregisterAllEvents() - self.frame:RegisterEvent("ADDON_LOADED") - self.frame:SetScript("OnEvent", function() - for major, instance in LibStub:IterateLibraries() do - manuallyFinalize(major, instance) - end - end) - for major, instance in LibStub:IterateLibraries() do - manuallyFinalize(major, instance) - end - - -- Expose the library in the global environment - _G[ACELIBRARY_MAJOR] = self - - if oldDeactivate then - oldDeactivate(oldLib) - end -end - -if not previous then - previous = AceLibrary -end -if not previous.libs then - previous.libs = {} -end -AceLibrary.libs = previous.libs -if not previous.positions then - previous.positions = setmetatable({}, { __mode = "k" }) -end -AceLibrary.positions = previous.positions -AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate, nil)
--- a/modules/FuBar_ReActionFu/lib/AceLibrary/AceLibrary.toc Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -## Interface: 20200 - -## Title: Lib: AceLibrary -## Notes: AddOn development framework -## Author: Ace Development Team -## X-Website: http://www.wowace.com -## X-Category: Library -## X-License: LGPL v2.1 + MIT for AceOO-2.0 - -AceLibrary.lua
--- a/modules/FuBar_ReActionFu/lib/Dewdrop-2.0/Dewdrop-2.0.lua Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3487 +0,0 @@ ---[[ -Name: Dewdrop-2.0 -Revision: $Rev: 56529 $ -Author(s): ckknight (ckknight@gmail.com) -Website: http://ckknight.wowinterface.com/ -Documentation: http://wiki.wowace.com/index.php/Dewdrop-2.0 -SVN: http://svn.wowace.com/root/trunk/DewdropLib/Dewdrop-2.0 -Description: A library to provide a clean dropdown menu interface. -Dependencies: AceLibrary -License: LGPL v2.1 -]] - -local MAJOR_VERSION = "Dewdrop-2.0" -local MINOR_VERSION = "$Revision: 56529 $" - -if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end -if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end - -local Dewdrop = {} - -local SharedMedia - -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 RESET_KEYBINDING_DESC = "Hit escape to clear the keybinding." -local KEY_BUTTON1 = "Left Mouse" -local KEY_BUTTON2 = "Right Mouse" -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?" -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' 실행을 하시겠습니까 ?" -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' ?" -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'?" -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」?" -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'?" -end - -Dewdrop.KEY_BUTTON1 = KEY_BUTTON1 -Dewdrop.KEY_BUTTON2 = KEY_BUTTON2 - -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 -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 -end -local levels -local buttons - - --- Secure frame handling: --- Rather than using secure buttons in the menu (has problems), we have one --- 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") -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 - - secureFrame:SetFrameStrata(owner:GetFrameStrata()) - secureFrame:SetFrameLevel(owner:GetFrameLevel()+1) - - 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 -end - -secureFrame:SetScript("OnEvent", - function() - if event=="PLAYER_REGEN_ENABLED" then - this.combat = false - if not this:IsShown() and this.owner then - secureFrame_Show(this) - end - elseif event=="PLAYER_REGEN_DISABLED" then - this.combat = true - if this:IsShown() then - secureFrame_Hide(this) - end - end - end -) -secureFrame:RegisterEvent("PLAYER_REGEN_ENABLED") -secureFrame:RegisterEvent("PLAYER_REGEN_DISABLED") - -secureFrame:SetScript("OnLeave", - function() - local owner=this.owner - this:Deactivate() - owner:GetScript("OnLeave")() - end -) - -secureFrame:HookScript("OnClick", - function() - local realthis = this - this = this.owner - this:GetScript("OnClick")() - 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 self.combat then - secureFrame_Hide(self) - end - end - self.owner = owner - if not self.combat then - secureFrame_Show(self) - end -end - -function secureFrame:Deactivate() - if not self.combat 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", nil) -underlineFrame.tx = underlineFrame:CreateTexture() -underlineFrame.tx:SetTexture(1,1,0.5,0.75) -underlineFrame:SetScript("OnHide", function(this) this:Hide(); end) -underlineFrame:SetScript("OnShow", function(this) -- change sizing on the fly to catch runtime uiscale changes - underlineFrame.tx:SetPoint("TOPLEFT", -1, -2/this:GetEffectiveScale()) - underlineFrame.tx:SetPoint("RIGHT", 1,0) - underlineFrame.tx:SetHeight(0.6 / this: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 -end - -local function StartCounting(self, level) - for i = level, 1, -1 do - if levels[i] then - levels[i].count = 3 - end - end -end - -local function StopCounting(self, level) - 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 - self:Close(level.num) - else - level.count = count - end - end - end -end - -local function CheckDualMonitor(self, 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 -end - -local function CheckSize(self, level) - if not level.buttons then - return - end - local height = 20 - for _, button in ipairs(level.buttons) do - height = height + button:GetHeight() - end - level:SetHeight(height) - local width = 160 - for _, button in ipairs(level.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:GetWidth() + extra > width then - width = button.text:GetWidth() + extra - end - end - level: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 - self: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(self, 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 -local OpenSlider -local OpenEditBox -local Refresh -local Clear -local function ReleaseButton(self, level, index) - if not level.buttons then - return - end - if not level.buttons[index] then - return - end - local button = level.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.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 Scroll(self, level, down) - if down then - if level:GetBottom() < 0 then - local point, parent, relativePoint, x, y = level:GetPoint(1) - level:SetPoint(point, parent, relativePoint, x, y + 50) - if level:GetBottom() > 0 then - level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom()) - end - end - else - if level:GetTop() > GetScreenHeight() then - local point, parent, relativePoint, x, y = level:GetPoint(1) - level:SetPoint(point, parent, relativePoint, x, y - 50) - if level:GetTop() < GetScreenHeight() then - level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop()) - end - end - end -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 -end - -local sliderFrame -local editBoxFrame - -local normalFont -local lastSetFont -local justSetFont = false -local regionTmp = {} -local function fillRegionTmp(...) - for i = 1, select('#', ...) do - regionTmp[i] = select(i, ...) - end -end - -local function showGameTooltip(this) - if this.tooltipTitle or this.tooltipText then - GameTooltip_SetDefaultAnchor(GameTooltip, this) - local disabled = not this.isTitle and this.disabled - local font - if this.tooltipTitle then - if SharedMedia and SharedMedia:IsValid("font", this.tooltipTitle) then - font = SharedMedia:Fetch("font", this.tooltipTitle) - end - if disabled then - GameTooltip:SetText(this.tooltipTitle, 0.5, 0.5, 0.5, 1) - else - GameTooltip:SetText(this.tooltipTitle, 1, 1, 1, 1) - end - if this.tooltipText then - if not font and SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then - font = SharedMedia:Fetch("font", this.tooltipText) - end - if disabled then - GameTooltip:AddLine(this.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(this.tooltipText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - end - else - if SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then - font = SharedMedia:Fetch("font", this.tooltipText) - end - if disabled then - GameTooltip:SetText(this.tooltipText, 0.5, 0.5, 0.5, 1) - else - GameTooltip:SetText(this.tooltipText, 1, 1, 1, 1) - end - end - if font then - fillRegionTmp(GameTooltip:GetRegions()) - lastSetFont = font - justSetFont = true - for i,v in ipairs(regionTmp) do - if v.SetFont then - local norm,size,outline = v:GetFont() - v:SetFont(font, size, outline) - if not normalFont then - normalFont = norm - end - end - regionTmp[i] = nil - end - elseif not normalFont then - fillRegionTmp(GameTooltip:GetRegions()) - for i,v in ipairs(regionTmp) do - if v.GetFont and not normalFont then - normalFont = v:GetFont() - end - regionTmp[i] = nil - end - end - GameTooltip:Show() - end - if this.tooltipFunc then - GameTooltip:SetOwner(this, "ANCHOR_NONE") - GameTooltip:SetPoint("TOPLEFT", this, "TOPRIGHT", 5, 0) - this.tooltipFunc(getArgs(this, 'tooltipArg', 1)) - GameTooltip:Show() - end -end - -local tmpt = setmetatable({}, {mode='v'}) -local numButtons = 0 -local function AcquireButton(self, level) - if not levels[level] then - return - end - level = levels[level] - if not level.buttons then - level.buttons = {} - end - local button - if #buttons == 0 then - numButtons = numButtons + 1 - button = CreateFrame("Button", "Dewdrop20Button" .. 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() - if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1) or (editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == this.level.num + 1) then - for i = 1, this.level.num do - Refresh(self, levels[i]) - end - return - end - self:Close(this.level.num + 1) - if not this.disabled then - if this.secure then - secureFrame:Activate(this) - elseif this.hasSlider then - OpenSlider(self, this) - elseif this.hasEditBox then - OpenEditBox(self, this) - elseif this.hasArrow then - Open(self, this, nil, this.level.num + 1, this.value) - end - end - if not this.level then -- button reclaimed - return - end - StopCounting(self, this.level.num + 1) - if not this.disabled then - highlight:Show() - if this.isRadio then - button.radioHighlight:Show() - end - if this.mouseoverUnderline then - underlineFrame:SetParent(this) - underlineFrame:SetPoint("BOTTOMLEFT",this.text,0,0) - underlineFrame:SetWidth(this.text:GetWidth()) - underlineFrame:Show() - end - end - showGameTooltip(this) - end) - button:SetScript("OnHide", function() - if this.secure and secureFrame:IsOwnedBy(this) then - secureFrame:Deactivate() - end - end) - button:SetScript("OnLeave", function() - if this.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 this.selected then - highlight:Hide() - end - button.radioHighlight:Hide() - if this.level then - StartCounting(self, this.level.num) - end - GameTooltip:Hide() - end) - local first = true - button:SetScript("OnClick", function() - if not this.disabled then - if this.hasColorSwatch then - local func = button.colorFunc - local hasOpacity = this.hasOpacity - local this = this - for k in pairs(tmpt) do - tmpt[k] = nil - end - for i = 1, 1000 do - local x = this['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 = this.hasOpacity - ColorPickerFrame.opacityFunc = ColorPickerFrame.func - ColorPickerFrame.opacity = 1 - this.opacity - ColorPickerFrame:SetColorRGB(this.r, this.g, this.b) - local r, g, b, a = this.r, this.g, this.b, this.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 - self:Close(1) - ShowUIPanel(ColorPickerFrame) - elseif this.func then - local level = this.level - if type(this.func) == "string" then - if type(this.arg1[this.func]) ~= "function" then - self:error("Cannot call method %q", this.func) - end - this.arg1[this.func](this.arg1, getArgs(this, 'arg', 2)) - else - this.func(getArgs(this, 'arg', 1)) - end - if this.closeWhenClicked then - self:Close() - elseif level:IsShown() then - for i = 1, level.num do - Refresh(self, 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.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 this.closeWhenClicked then - self:Close() - end - end - end) - local text = button:CreateFontString(nil, "ARTWORK") - button.text = text - text:SetFontObject(GameFontHighlightSmall) - button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT) - button:SetScript("OnMouseDown", function() - if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then - text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1) - end - end) - button:SetScript("OnMouseUp", function() - if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then - text:SetPoint("LEFT", button, "LEFT", this.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:SetParent(level) - button:SetFrameStrata(level:GetFrameStrata()) - button:SetFrameLevel(level:GetFrameLevel() + 1) - button:SetPoint("LEFT", level, "LEFT", 10, 0) - button:SetPoint("RIGHT", level, "RIGHT", -10, 0) - if #level.buttons == 0 then - button:SetPoint("TOP", level, "TOP", 0, -10) - else - button:SetPoint("TOP", level.buttons[#level.buttons], "BOTTOM", 0, 0) - end - button.text:SetPoint("LEFT", button, "LEFT", 24, 0) - button:Show() - button.level = level - table.insert(level.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(self, level) - if not levels[level] then - for i = #levels + 1, level, -1 do - local i = i - numLevels = numLevels + 1 - local frame = CreateFrame("Button", "Dewdrop20Level" .. numLevels, nil) - if i == 1 then - local old_CloseSpecialWindows = CloseSpecialWindows - function CloseSpecialWindows() - local found = old_CloseSpecialWindows() - if levels[1]:IsShown() then - self:Close() - return 1 - end - return found - end - end - levels[i] = frame - frame.num = i - frame:SetParent(UIParent) - frame:SetFrameStrata("FULLSCREEN_DIALOG") - frame:Hide() - frame:SetWidth(180) - frame:SetHeight(10) - frame:SetFrameLevel(i * 3) - frame:SetScript("OnHide", function() - self:Close(level + 1) - end) - if frame.SetTopLevel then - frame:SetTopLevel(true) - end - frame:EnableMouse(true) - frame:EnableMouseWheel(true) - local backdrop = CreateFrame("Frame", nil, frame) - backdrop:SetAllPoints(frame) - backdrop: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 - )) - 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:Close(i) - end) - frame:SetScript("OnEnter", function() - StopCounting(self, i) - end) - frame:SetScript("OnLeave", function() - StartCounting(self, i) - end) - frame:SetScript("OnMouseWheel", function() - Scroll(self, frame, arg1 < 0) - end) - if i == 1 then - frame:SetScript("OnUpdate", function(this, arg1) - OnUpdate(self, arg1) - 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 -end - -local validatedOptions - -local values -local mysort_args -local mysort -local othersort -local othersort_validate - -local baseFunc, currentLevel - -local function confirmPopup(message, func, ...) - if not StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] then - StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] = {} - end - local t = StaticPopupDialogs["DEWDROP20_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("DEWDROP20_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) -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)") -end - -local function skip1Nil(...) - if select(1,...)==nil then - return select(2,...) - end - return ... -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 - Dewdrop:error(position .. ": " .. err) - else - Dewdrop: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 -end - -function Refresh(self, level) - if type(level) == "number" then - level = levels[level] - end - if not level then - return - end - if baseFunc then - Clear(self, 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") - self:AddLine( - 'text', name, - 'isTitle', true - ) - end - end --- elseif level.parentText then --- self:AddLine( --- 'text', level.parentText, --- 'tooltipTitle', level.parentTooltipTitle, --- 'tooltipText', level.parentTooltipText, --- 'tooltipFunc', level.parentTooltipFunc, --- 'isTitle', true --- ) - end - self:FeedAceOptionsTable(baseFunc) - if currentLevel == 1 then - self:AddLine( - 'text', CLOSE, - 'tooltipTitle', CLOSE, - 'tooltipText', CLOSE_DESC, - 'closeWhenClicked', true - ) - end - else --- if level.parentText then --- self:AddLine( --- 'text', level.parentText, --- 'tooltipTitle', level.parentTooltipTitle, --- 'tooltipText', level.parentTooltipText, --- 'tooltipFunc', level.parentTooltipFunc, --- 'isTitle', true --- ) --- end - 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(self, level) - end -end - -function Dewdrop:Refresh(level) - self:argCheck(level, 2, "number", "nil") - if not level then - for k,v in pairs(levels) do - Refresh(self, v) - end - else - Refresh(self, levels[level]) - end -end - -function OpenSlider(self, parent) - if not sliderFrame then - sliderFrame = CreateFrame("Frame", nil, nil) - 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(self, 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(self, levels[i]) - end - local newParent - for _,button in ipairs(levels[sliderFrame.level-1].buttons) do - if button.sliderFunc == sliderFunc then - newParent = button - break - end - end - if newParent then - OpenSlider(self, 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(self, levels[i]) - end - local newParent - for _,button in ipairs(levels[sliderFrame.level-1].buttons) do - if button.sliderFunc == sliderFunc then - newParent = button - break - end - end - if newParent then - OpenSlider(self, newParent) - else - sliderFrame:Hide() - end - end - if inside then - showGameTooltip(sliderFrame.parent) - end - end) - slider:SetScript("OnEnter", function() - inside = true - StopCounting(self, 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(self, levels[i]) - end - local newParent - for _,button in ipairs(levels[sliderFrame.level-1].buttons) do - if button.sliderFunc == sliderFunc then - newParent = button - break - end - end - if newParent then - OpenSlider(self, newParent) - else - sliderFrame:Hide() - end - - changed = false - end - end) - sliderFrame:SetScript("OnMouseWheel", function(t, a1) - local arg1 = a1 or 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(t, a1) - 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(self, sliderFrame.level) - end) - editBox:SetScript("OnEscapePressed", function() - self:Close(sliderFrame.level) - StartCounting(self, 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(self, parent) - if not editBoxFrame then - editBoxFrame = CreateFrame("Frame", nil, nil) - 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 - self:Close(editBoxFrame.level) - for i = 1, editBoxFrame.level - 1 do - Refresh(self, levels[i]) - end - StartCounting(self, editBoxFrame.level-1) - end) - editBox:SetScript("OnEscapePressed", function() - self:Close(editBoxFrame.level) - StartCounting(self, editBoxFrame.level-1) - end) - editBox:SetScript("OnReceiveDrag", function(this) - 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(self, editBoxFrame.level) - showGameTooltip(editBoxFrame.parent) - end) - editBoxFrame:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - editBox:SetScript("OnEnter", function() - StopCounting(self, editBoxFrame.level) - showGameTooltip(editBoxFrame.parent) - end) - editBox:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - editBoxFrame:SetScript("OnKeyDown", function(this, a1) - if not editBox.keybinding then - return - end - local arg1 = a1 or arg1 - 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(this, ...) - if GetCursorInfo and (CursorHasItem() or CursorHasSpell()) then - return editBox:GetScript("OnReceiveDrag")(this, ...) - end - return editBoxFrame:GetScript("OnKeyDown")(this, ...) - end) - editBoxFrame:SetScript("OnMouseWheel", function(t, a1) - local arg1 = a1 or arg1 - local up = arg1 > 0 - arg1 = up and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" - return editBoxFrame:GetScript("OnKeyDown")(t or this, arg1) - 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 -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()) -end - -function Dewdrop:GetOpenedParent() - return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent()) -end - -function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY) - self:Close(level) - if DewdropLib then - local d = DewdropLib:GetInstance('1.0') - local ret, val = pcall(d, IsOpen, d) - if ret and val then - DewdropLib:GetInstance('1.0'):Close() - end - end - if type(parent) == "table" then - parent:GetCenter() - end - local frame = AcquireLevel(self, 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(self, 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(self, frame) - frame:SetClampedToScreen(true) - frame:SetClampedToScreen(false) - StartCounting(self, level) -end - -function Dewdrop:IsRegistered(parent) - self:argCheck(parent, 2, "table", "string") - return not not self.registry[parent] -end - -function Dewdrop:Register(parent, ...) - self:argCheck(parent, 2, "table", "string") - if self.registry[parent] then - self:Unregister(parent) - end - local info = new(...) - if type(info.children) == "table" then - local err, position = validateOptions(info.children) - - if err then - if position then - Dewdrop:error(position .. ": " .. err) - else - Dewdrop:error(err) - end - end - end - self.registry[parent] = info - if not info.dontHook and not self.onceRegistered[parent] and type(parent) == "table" then - if parent:HasScript("OnMouseUp") then - local script = parent:GetScript("OnMouseUp") - parent:SetScript("OnMouseUp", function(this, ...) - if script then - script(this, ...) - end - if arg1 == "RightButton" and self.registry[parent] then - if self:IsOpen(parent) then - self:Close() - else - self:Open(parent) - end - end - end) - end - if parent:HasScript("OnMouseDown") then - local script = parent:GetScript("OnMouseDown") - parent:SetScript("OnMouseDown", function(this, ...) - if script then - script(this, ...) - end - if self.registry[parent] then - self:Close() - end - end) - end - end - self.onceRegistered[parent] = true -end - -function Dewdrop:Unregister(parent) - self:argCheck(parent, 2, "table", "string") - self.registry[parent] = nil -end - -function Dewdrop:Open(parent, ...) - self:argCheck(parent, 2, "table", "string") - local info - local k1 = ... - if type(k1) == "table" and k1[0] and k1.IsFrameType 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(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) -end - -function Clear(self, level) - if level then - if level.buttons then - for i = #level.buttons, 1, -1 do - ReleaseButton(self, level, i) - end - end - end -end - -function Dewdrop:Close(level) - if DropDownList1:IsShown() then - DropDownList1:Hide() - end - if DewdropLib then - local d = DewdropLib:GetInstance('1.0') - local ret, val = pcall(d, IsOpen, d) - if ret and val then - DewdropLib:GetInstance('1.0'):Close() - end - 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].buttons then - local buttons = levels[level-1].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(self, 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.buttons then return; end - - local prevbutton = level.buttons[#level.buttons] - if not prevbutton then return; end - - 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 - info.level = nil - local button = AcquireButton(self, level) - if not next(info) then - info.disabled = true - end - button.disabled = info.isTitle or info.notClickable or info.disabled or (self.combat and info.secure) - button.isTitle = info.isTitle - button.notClickable = info.notClickable - if button.isTitle then - button.text:SetFontObject(GameFontNormalSmall) - elseif button.notClickable then - button.text:SetFontObject(GameFontHighlightSmall) - elseif button.disabled then - button.text:SetFontObject(GameFontDisableSmall) - else - button.text:SetFontObject(GameFontHighlightSmall) - end - if info.disabled then - button.arrow:SetDesaturated(true) - button.check:SetDesaturated(true) - else - button.arrow:SetDesaturated(false) - button.check:SetDesaturated(false) - end - 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(button.text:GetFontObject():GetTextColor()) - 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 font,_ = button.text:GetFont() - button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) - button:SetHeight(button.textHeight + 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:InjectAceOptionsTable(handler, options) - self:argCheck(handler, 2, "table") - self:argCheck(options, 3, "table") - if tostring(options.type):lower() ~= "group" then - self:error('Cannot inject into options table argument #3 if its type is not "group"') - end - if options.handler ~= nil and options.handler ~= handler then - self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") - end - options.handler = handler - local class = handler.class - if not AceLibrary:HasInstance("AceOO-2.0") or not class then - if Rock then - -- possible Rock object - for mixin in Rock:IterateObjectMixins(handler) do - if type(mixin.GetAceOptionsDataTable) == "function" then - local t = mixin:GetAceOptionsDataTable(handler) - for k,v in pairs(t) do - if type(options.args) ~= "table" then - options.args = {} - end - if options.args[k] == nil then - options.args[k] = v - end - end - end - end - end - else - -- Ace2 object - while class and class ~= AceLibrary("AceOO-2.0").Class do - if type(class.GetAceOptionsDataTable) == "function" then - local t = class:GetAceOptionsDataTable(handler) - for k,v in pairs(t) do - if type(options.args) ~= "table" then - options.args = {} - end - if options.args[k] == nil then - options.args[k] = v - end - end - end - local mixins = class.mixins - if mixins then - for mixin in pairs(mixins) do - if type(mixin.GetAceOptionsDataTable) == "function" then - local t = mixin:GetAceOptionsDataTable(handler) - for k,v in pairs(t) do - if type(options.args) ~= "table" then - options.args = {} - end - if options.args[k] == nil then - options.args[k] = v - end - end - end - end - end - class = class.super - end - end - return options -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 -end - -local function activate(self, oldLib, oldDeactivate) - Dewdrop = self - if oldLib and oldLib.registry then - self.registry = oldLib.registry - self.onceRegistered = oldLib.onceRegistered - else - self.registry = {} - self.onceRegistered = {} - - local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") - local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") - local oldX, oldY, clickTime - WorldFrame:SetScript("OnMouseDown", function(this, ...) - oldX,oldY = GetCursorPosition() - clickTime = GetTime() - if WorldFrame_OnMouseDown then - WorldFrame_OnMouseDown(this, ...) - end - end) - - WorldFrame:SetScript("OnMouseUp", function(this, ...) - local x,y = GetCursorPosition() - if not oldX or not oldY or not x or not y or not clickTime then - self:Close() - if WorldFrame_OnMouseUp then - WorldFrame_OnMouseUp(this, ...) - end - return - end - local d = math.abs(x - oldX) + math.abs(y - oldY) - if d <= 5 and GetTime() - clickTime < 0.5 then - self:Close() - end - if WorldFrame_OnMouseUp then - WorldFrame_OnMouseUp(this, ...) - end - end) - - hooksecurefunc(DropDownList1, "Show", function() - if levels[1] and levels[1]:IsVisible() then - self:Close() - end - end) - - hooksecurefunc("HideDropDownMenu", function() - if levels[1] and levels[1]:IsVisible() then - self:Close() - end - end) - - hooksecurefunc("CloseDropDownMenus", function() - if levels[1] and levels[1]:IsVisible() then - local stack = debugstack() - if not stack:find("`TargetFrame_OnHide'") then - self:Close() - end - end - end) - end - self.frame = oldLib and oldLib.frame or CreateFrame("Frame") - self.frame:UnregisterAllEvents() - self.frame:RegisterEvent("PLAYER_REGEN_ENABLED") - self.frame:RegisterEvent("PLAYER_REGEN_DISABLED") - self.frame:Hide() - self.frame:SetScript("OnEvent", function(this, event) - this:Show() - 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(this) - this:Hide() - self:Refresh(1) - end) - self.hookedTooltip = true - if not oldLib or not oldLib.hookedTooltip then - local OnTooltipHide = GameTooltip:GetScript("OnHide") - GameTooltip:SetScript("OnHide", function(this, ...) - if OnTooltipHide then - OnTooltipHide(this, ...) - end - if type(self.OnTooltipHide) == "function" then - self:OnTooltipHide() - end - end) - end - levels = {} - buttons = {} - - if oldDeactivate then - oldDeactivate(oldLib) - end -end - -local function external(lib, major, instance) - if major == "SharedMedia-1.0" then - SharedMedia = instance - end -end - -AceLibrary:Register(Dewdrop, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
--- a/modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/Changelog-LibFuBarPlugin-3.0-r63707.txt Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ ------------------------------------------------------------------------- -r63707 | arrowmaster | 2008-03-05 19:54:23 -0500 (Wed, 05 Mar 2008) | 1 line -Changed paths: - M /trunk/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.lua - -LibFuBarPlugin-3.0: fix MINOR_VERSION to stop going negative ------------------------------------------------------------------------- -r63318 | ckknight | 2008-03-01 12:59:56 -0500 (Sat, 01 Mar 2008) | 1 line -Changed paths: - M /trunk/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.lua - -LibFuBarPlugin-3.0 - remove a pointless :OnEmbedProfileEnable ------------------------------------------------------------------------- -r62709 | ckknight | 2008-02-23 21:15:11 -0500 (Sat, 23 Feb 2008) | 1 line -Changed paths: - M /trunk/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.lua - -LibFuBarPlugin-3.0 - move around tricorner minimaps properly. ------------------------------------------------------------------------- -r61479 | ckknight | 2008-02-15 12:18:37 -0500 (Fri, 15 Feb 2008) | 1 line -Changed paths: - M /trunk/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.lua - -LibFuBarPlugin-3.0 - properly move around SIDE-TOP and SIDE-BOTTOM minimaps -------------------------------------------------------------------------
--- a/modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.lua Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2145 +0,0 @@ ---[[ -Name: LibFuBarPlugin-3.0 -Revision: $Rev: 63707 $ -Developed by: ckknight (ckknight@gmail.com) -Website: http://www.wowace.com/ -Description: Plugin for FuBar. -Dependencies: LibRock-1.0 -License: LGPL v2.1 -]] - -local MAJOR_VERSION = "LibFuBarPlugin-3.0" -local MINOR_VERSION = tonumber(("$Revision: 63707 $"):match("(%d+)")) - 60000 - -if not Rock then error(MAJOR_VERSION .. " requires LibRock-1.0") end - -local FuBarPlugin, oldLib = Rock:NewLibrary(MAJOR_VERSION, MINOR_VERSION) -if not FuBarPlugin then - return -end - -local SHOW_FUBAR_ICON = "Show FuBar icon" -local SHOW_FUBAR_ICON_DESC = "Show the FuBar plugin's icon on the panel." -local SHOW_FUBAR_TEXT = "Show FuBar text" -local SHOW_FUBAR_TEXT_DESC = "Show the FuBar plugin's text on the panel." -local SHOW_COLORED_FUBAR_TEXT = "Show colored FuBar text" -local SHOW_COLORED_FUBAR_TEXT_DESC = "Allow the FuBar plugin to color its text on the panel." -local DETACH_FUBAR_TOOLTIP = "Detach FuBar tooltip" -local DETACH_FUBAR_TOOLTIP_DESC = "Detach the FuBar tooltip from the panel." -local LOCK_FUBAR_TOOLTIP = "Lock tooltip" -local LOCK_FUBAR_TOOLTIP_DESC = "Lock the tooltips position. When the tooltip is locked, you must use Alt to access it with your mouse." -local POSITION_ON_FUBAR = "Position on FuBar" -local POSITION_ON_FUBAR_DESC = "Position the FuBar plugin on the panel." -local POSITION_LEFT = "Left" -local POSITION_RIGHT = "Right" -local POSITION_CENTER = "Center" -local ATTACH_PLUGIN_TO_MINIMAP = "Attach FuBar plugin to minimap" -local ATTACH_PLUGIN_TO_MINIMAP_DESC = "Attach the FuBar plugin to the minimap instead of the panel." -local HIDE_FUBAR_PLUGIN = "Hide FuBar plugin" -local HIDE_MINIMAP_BUTTON = "Hide minimap button" -local HIDE_FUBAR_PLUGIN_DESC = "Hide the FuBar plugin from the panel or minimap, leaving the addon running." -local OTHER = "Other" -local CLOSE = "Close" -local CLOSE_DESC = "Close the menu." - -if GetLocale() == "zhCN" then - SHOW_FUBAR_ICON = "显示FuBar图标" - SHOW_FUBAR_ICON_DESC = "在面板上显示FuBar插件的图标." - SHOW_FUBAR_TEXT = "显示FuBar文字" - SHOW_FUBAR_TEXT_DESC = "在面板上显示Fubar插件文字标题" - SHOW_COLORED_FUBAR_TEXT = "显示彩色文字" - SHOW_COLORED_FUBAR_TEXT_DESC = "允许插件显示彩色文字." - DETACH_FUBAR_TOOLTIP = "独立提示信息" - DETACH_FUBAR_TOOLTIP_DESC = "从面板上独立显示信息" - LOCK_FUBAR_TOOLTIP = "锁定提示信息" - LOCK_FUBAR_TOOLTIP_DESC = "锁定提示信息位置.当提示信息被锁定时,你必须要按Alt-鼠标方可查看." - POSITION_ON_FUBAR = "位置" - POSITION_ON_FUBAR_DESC = "FuBar插件在面板上的位置." - POSITION_LEFT = "居左" - POSITION_RIGHT = "居右" - POSITION_CENTER = "居中" - ATTACH_PLUGIN_TO_MINIMAP = "依附在小地图" - ATTACH_PLUGIN_TO_MINIMAP_DESC = "插件图标依附在小地图而不显示在面板上." - HIDE_FUBAR_PLUGIN = "隐藏FuBar插件" - HIDE_MINIMAP_BUTTON = "隐藏小地图按钮" - HIDE_FUBAR_PLUGIN_DESC = "隐藏在面板或小地图上的FuBar插件,暂定插件工作." - OTHER = "其他" - CLOSE = "关闭" - LOSE_DESC = "关闭目录." -elseif GetLocale() == "zhTW" then - SHOW_FUBAR_ICON = "顯示圖示" - SHOW_FUBAR_ICON_DESC = "在面板上顯示插件圖示。" - SHOW_FUBAR_TEXT = "顯示文字" - SHOW_FUBAR_TEXT_DESC = "在面板上顯示插件文字。" - SHOW_COLORED_FUBAR_TEXT = "允許彩色文字" - SHOW_COLORED_FUBAR_TEXT_DESC = "允許插件在面板上使用彩色文字。" - DETACH_FUBAR_TOOLTIP = "獨立提示訊息" - DETACH_FUBAR_TOOLTIP_DESC = "從面板上獨立提示訊息。" - LOCK_FUBAR_TOOLTIP = "鎖定提示訊息" - LOCK_FUBAR_TOOLTIP_DESC = "鎖定提示訊息位置。當提示訊息鎖定時,需要用Alt鍵使用提示訊息的功能。" - POSITION_ON_FUBAR = "位置" - POSITION_ON_FUBAR_DESC = "插件在面板上的位置。" - POSITION_LEFT = "靠左" - POSITION_RIGHT = "靠右" - POSITION_CENTER = "置中" - ATTACH_PLUGIN_TO_MINIMAP = "依附在小地圖" - ATTACH_PLUGIN_TO_MINIMAP_DESC = "插件圖標依附在小地圖而不顯示在面板上。" - HIDE_FUBAR_PLUGIN = "隱藏插件" - HIDE_MINIMAP_BUTTON = "隱藏小地圖按鈕" - HIDE_FUBAR_PLUGIN_DESC = "在面板或小地圖上隱藏該插件,但保持執行狀態。" - OTHER = "其他" - CLOSE = "關閉" - CLOSE_DESC = "關閉選單。" -elseif GetLocale() == "koKR" then - SHOW_FUBAR_ICON = "FuBar 아이콘 표시" - SHOW_FUBAR_ICON_DESC = "FuBar 패널에 플러그인 아이콘을 표시합니다." - SHOW_FUBAR_TEXT = "FuBar 텍스트 표시" - SHOW_FUBAR_TEXT_DESC = "FuBar 페널에 플러그인 텍스트를 표시합니다." - SHOW_COLORED_FUBAR_TEXT = "색상화된 FuBar 텍스트 표시" - SHOW_COLORED_FUBAR_TEXT_DESC = "패널의 FuBar 플러그인의 텍스트 색상을 허용합니다." - DETACH_FUBAR_TOOLTIP = "FuBar 툴팁 분리" - DETACH_FUBAR_TOOLTIP_DESC = "패널에서 FuBar 툴팁을 분리합니다." - LOCK_FUBAR_TOOLTIP = "툴팁 고정" - LOCK_FUBAR_TOOLTIP_DESC = "툴팁 위치를 고정시킵니다. 툴팁이 고정되어 있을때, 마우스로 접근하기 위해 Alt키를 사용하여야 합니다." - POSITION_ON_FUBAR = "FuBar 위치" - POSITION_ON_FUBAR_DESC = "패널 위의 FuBar 플러그인의 위치를 설정합니다." - POSITION_LEFT = "좌측" - POSITION_RIGHT = "우측" - POSITION_CENTER = "중앙" - ATTACH_PLUGIN_TO_MINIMAP = "FuBar 플러그인 미니맵 표시" - ATTACH_PLUGIN_TO_MINIMAP_DESC = "FuBar 플러그인을 패널 대신 미니맵에 표시합니다." - HIDE_FUBAR_PLUGIN = "FuBar 플러그인 숨김" - HIDE_MINIMAP_BUTTON = "미니맵 버튼 숨김" - HIDE_FUBAR_PLUGIN_DESC = "FuBar 플러그인을 패널이나 미니맵으로 부터 숨김니다." - OTHER = "기타" - CLOSE = "닫기" - CLOSE_DESC = "메뉴를 닫습니다." -elseif GetLocale() == "frFR" then - SHOW_FUBAR_ICON = "Afficher l'icône FuBar" - SHOW_FUBAR_ICON_DESC = "Affiche l'icône du plugin FuBar sur le panneau." - SHOW_FUBAR_TEXT = "Afficher le texte FuBar" - SHOW_FUBAR_TEXT_DESC = "Affiche le texte du plugin FuBar sur le panneau." - SHOW_COLORED_FUBAR_TEXT = "Afficher le texte FuBar coloré" - SHOW_COLORED_FUBAR_TEXT_DESC = "Autorise le plugin FuBar à colorer son texte sur le panneau." - DETACH_FUBAR_TOOLTIP = "Détacher l'infobulle FuBar" - DETACH_FUBAR_TOOLTIP_DESC = "Détache l'infobulle FuBar du panneau." - LOCK_FUBAR_TOOLTIP = "Verrouiller l'infobulle" - LOCK_FUBAR_TOOLTIP_DESC = "Verrouille l'infobulle dans sa position actuelle. Quand l'infobulle est verrouillée, vous devez utiliser la touche Alt pour y interagir avec la souris." - POSITION_ON_FUBAR = "Position sur FuBar" - POSITION_ON_FUBAR_DESC = "Position du plugin FuBar sur le panneau." - POSITION_LEFT = "Gauche" - POSITION_RIGHT = "Droite" - POSITION_CENTER = "Centre" - ATTACH_PLUGIN_TO_MINIMAP = "Attacher le plugin FuBar sur la minicarte" - ATTACH_PLUGIN_TO_MINIMAP_DESC = "Attache le plugin FuBar sur la minicarte au lieu du panneau." - HIDE_FUBAR_PLUGIN = "Masquer le plugin FuBar" - HIDE_MINIMAP_BUTTON = "Masquer le bouton de la minicarte" - HIDE_FUBAR_PLUGIN_DESC = "Masque le plugin FuBar du panneau ou de la minicarte, laissant l'addon fonctionner." - OTHER = "Autre" - CLOSE = "Fermer" - CLOSE_DESC = "Ferme le menu." -end - --- #AUTODOC_NAMESPACE FuBarPlugin - -local precondition, argCheck = Rock:GetContractFunctions(MAJOR_VERSION, "precondition", "argCheck") -local newList, del = Rock:GetRecyclingFunctions(MAJOR_VERSION, "newList", "del") - -FuBarPlugin.pluginToFrame = oldLib and oldLib.pluginToFrame or {} -local pluginToFrame = FuBarPlugin.pluginToFrame -FuBarPlugin.pluginToMinimapFrame = oldLib and oldLib.pluginToMinimapFrame or {} -local pluginToMinimapFrame = FuBarPlugin.pluginToMinimapFrame -FuBarPlugin.pluginToPanel = oldLib and oldLib.pluginToPanel or {} -local pluginToPanel = FuBarPlugin.pluginToPanel -FuBarPlugin.pluginToOptions = oldLib and oldLib.pluginToOptions or {} -local pluginToOptions = FuBarPlugin.pluginToOptions -FuBarPlugin.folderNames = oldLib and oldLib.folderNames or {} -local folderNames = FuBarPlugin.folderNames - -local Tablet20 -local Dewdrop20 - -FuBarPlugin.MinimapContainer = oldLib and oldLib.MinimapContainer or {} -local MinimapContainer = FuBarPlugin.MinimapContainer - -local epsilon = 1e-5 - --- #AUTODOC_NAMESPACE FuBarPlugin - ---[[--------------------------------------------------------------------------- -Notes: - *Set metadata about a certain plugin. - ; tooltipType : string - - : "GameTooltip" - :: Use Blizzard's GameTooltip. (default if not given) - : "Tablet-2.0" - :: Use Tablet-2.0. - : "Custom" - :: LibFuBarPlugin-3.0 will not provide any extra mechanisms, all done manually. - ; configType : string - - : "LibRockConfig-1.0" - :: Use LibRockConfig-1.0 to show configuration. (default if not given) - : "Dewdrop-2.0" - :: Use Dewdrop-2.0. - ; hasNoText : boolean - If set to true, then it will be a text-less frame. - ; iconPath : string - the path of the icon to show. - ; hasNoColor : boolean - If set to true, then it is assumed that no color will be in the text (and thus not show the menu item) - ; cannotHideText : boolean - If set to true, then the menu item to hide text will not be shown. - ; overrideMenu : boolean - If set to true, then the menu will not show any of the standard menu items - ; hideMenuTitle : boolean - If set to true, the plugins name will not be added to the top of the menu as a header. - ; defaultPosition : string - - : "LEFT" - ::show on the left. (default if not given) - : "CENTER" - ::show in the center. - : "RIGHT" - ::show on the right. - : "MINIMAP" - ::show on the minimap. - ; defaultMinimapPosition : number - Angle on the minimap, in degrees. [0, 360) - ; clickableTooltip : boolean - Whether you can drag your mouse onto the tooltip and click a line - ; tooltipHiddenWhenEmpty : boolean - Whether the detached tooltip is hidden when it is empty. - ; cannotDetachTooltip : boolean - Whether the tooltip cannot be detached from the plugin text. - ::Normally, a tooltip can detach (if using Tablet-2.0). This should be set if there is no relevant data in the tooltip. - ; independentProfile : boolean - If set to true, then the profile setting will not be stripped from .OnMenuRequest, and FuBar will not set the plugin's profile when it changes. - ::non-FuBar-centric plugins should set this to true. -Arguments: - string - the key to set - value - the value to set said key to. -Example: - self:SetFuBarOption('tooltipType', "Tablet-2.0") ------------------------------------------------------------------------------]] -function FuBarPlugin:SetFuBarOption(key, value) - local pluginToOptions_self = pluginToOptions[self] - if not pluginToOptions_self then - pluginToOptions_self = {} - pluginToOptions[self] = pluginToOptions_self - end - - pluginToOptions_self[key] = value - - if key == 'tooltipType' then - if value == "Tablet-2.0" then - Tablet20 = Rock("Tablet-2.0", false, true) - if not Tablet20 then - error(("Cannot specify %q = %q if %q is not loaded."):format(key, value, value), 2) - end - end - end - if key == 'configType' then - if value == "Dewdrop-2.0" then - Dewdrop20 = Rock("Dewdrop-2.0", false, true) - if not Dewdrop20 then - error(("Cannot specify %q = %q if %q is not loaded."):format(key, value, value), 2) - end - end - end -end -precondition(FuBarPlugin, 'SetFuBarOption', function(self, key, value) - argCheck(self, 1, "table") - argCheck(key, 2, "string") - argCheck(value, 3, "string", "number", "boolean") - - if pluginToOptions[self] and pluginToOptions[self][key] ~= nil then - error(("Bad argument #2 to `SetFuBarOption'. Cannot specify %q more than once."):format(key), 3) - end -end) - -local function getPluginOption(object, key, default) - local pluginToOptions_object = pluginToOptions[object] - if pluginToOptions_object == nil then - return default - end - local value = pluginToOptions_object[key] - if value == nil then - return default - end - return value -end - -local good = nil -local function CheckFuBar() - if not good then - if FuBar then - local version = FuBar.version - if type(version) == "string" then - local num = version:match("^(%d+%.?%d*)") - if num then - num = tonumber(num) - good = num >= 3 - end - end - end - end - return good -end - ---[[--------------------------------------------------------------------------- -Returns: - string - the localized name of the plugin, not including the "FuBar - " part. -Example - local title = self:GetTitle() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetTitle() - local name = self.title or self.name - if type(name) ~= "string" then - error("You must provide self.title or self.name", 2) - end - local title = name:match("[Ff][Uu][Bb][Aa][Rr]%s*%-%s*(.-)%s*$") or name - return title:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") -end - ---[[--------------------------------------------------------------------------- -Returns: - string - name of the plugin. -Notes: - This is here for FuBar core to communicate properly. -Example: - local name = self:GetName() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetName() - return self.name -end - ---[[--------------------------------------------------------------------------- -Returns: - string - category of the plugin. -Notes: - This is here for FuBar core to communicate properly. -Example: - local category = self:GetCategory() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetCategory() - return self.category or OTHER -end - ---[[--------------------------------------------------------------------------- -Returns: - frame - frame for the plugin. -Notes: - This is here for FuBar core to communicate properly. -Example: - local frame = self:GetFrame() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetFrame() - return pluginToFrame[self] -end - ---[[--------------------------------------------------------------------------- -Returns: - object - panel for the plugin. -Notes: - This is here for FuBar core to communicate properly. -Example: - local panel = self:GetPanel() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetPanel() - return pluginToPanel[self] -end - -local function getLazyDatabaseValueDefault(object, value, ...) - local object_db = object.db - if type(object_db) ~= "table" then - return value - end - local current = object_db.profile - for i = 1, select('#', ...) do - -- traverse through, make sure tables exist. - if type(current) ~= "table" then - return value - end - current = current[(select(i, ...))] - end - if current == nil then - return value - else - return current - end -end - -local function getLazyDatabaseValue(object, ...) - return getLazyDatabaseValueDefault(object, nil, ...) -end - -local function setLazyDatabaseValue(object, value, ...) - local object_db = object.db - if type(object_db) ~= "table" then - return nil - end - local current = object_db.profile - if type(current) ~= "table" then - return nil - end - local n = select('#', ...) - for i = 1, n-1 do - -- traverse through, create tables if necessary. - local nextOne = current[(select(i, ...))] - if type(nextOne) ~= "table" then - if nextOne ~= nil then - return nil - end - nextOne = {} - current[(select(i, ...))] = nextOne - end - current = nextOne - end - current[select(n, ...)] = value - return true -end - ---[[--------------------------------------------------------------------------- -Returns: - boolean - whether the text has color applied. -Example: - local colored = self:IsFuBarTextColored() ------------------------------------------------------------------------------]] -function FuBarPlugin:IsFuBarTextColored() - return not getLazyDatabaseValue(self, 'uncolored') -end - ---[[--------------------------------------------------------------------------- -Notes: - Toggles whether the text has color applied -Example: - self:ToggleTextColored() ------------------------------------------------------------------------------]] -function FuBarPlugin:ToggleFuBarTextColored() - if not setLazyDatabaseValue(self, not getLazyDatabaseValue(self, 'uncolored') or nil, 'uncolored') then - error(("%s: Cannot change text color if self.db is not available."):format(self:GetTitle()), 2) - end - self:UpdateFuBarText() -end - ---[[--------------------------------------------------------------------------- -Returns: - boolean - whether the plugin is attached to the minimap. -Example: - local attached = self:IsMinimapAttached() ------------------------------------------------------------------------------]] -function FuBarPlugin:IsFuBarMinimapAttached() - if not CheckFuBar() then - return true - end - return pluginToPanel[self] == MinimapContainer -end - ---[[--------------------------------------------------------------------------- -Notes: - Toggles whether the plugin is attached to the minimap. -Example: - self:ToggleMinimapAttached() ------------------------------------------------------------------------------]] -function FuBarPlugin:ToggleFuBarMinimapAttached() - if CheckFuBar() and not getPluginOption(self, 'cannotAttachToMinimap', false) then - local panel = pluginToPanel[self] - local value = panel == MinimapContainer - if value then - panel:RemovePlugin(self) - local defaultPosition = getPluginOption(self, 'defaultPosition', "LEFT") - FuBar:GetPanel(1):AddPlugin(self, nil, defaultPosition == "MINIMAP" and "LEFT" or defaultPosition) - else - if panel then - panel:RemovePlugin(self) - end - MinimapContainer:AddPlugin(self) - end - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Calls :UpdateFuBarText() and :UpdateFuBarTooltip(), in that order. -Example: - self:UpdateFuBarPlugin() ------------------------------------------------------------------------------]] -function FuBarPlugin:UpdateFuBarPlugin() - self:UpdateFuBarText() - self:UpdateFuBarTooltip() -end - ---[[--------------------------------------------------------------------------- -Notes: - * Calls :OnUpdateFuBarText() if it is available and the plugin is not disabled. - * It is expected to update the icon in :OnUpdateFuBarText as well as text. -Example: - self:UpdateFuBarText() ------------------------------------------------------------------------------]] -function FuBarPlugin:UpdateFuBarText() - if type(self.OnUpdateFuBarText) == "function" then - if not self:IsDisabled() then - self:OnUpdateFuBarText() - end - elseif self:IsFuBarTextShown() then - self:SetFuBarText(self:GetTitle()) - end -end - -local function Tablet20_point(frame) - if frame:GetTop() > GetScreenHeight() / 2 then - local x = frame:GetCenter() - if x < GetScreenWidth() / 3 then - return "TOPLEFT", "BOTTOMLEFT" - elseif x < GetScreenWidth() * 2 / 3 then - return "TOP", "BOTTOM" - else - return "TOPRIGHT", "BOTTOMRIGHT" - end - else - local x = frame:GetCenter() - if x < GetScreenWidth() / 3 then - return "BOTTOMLEFT", "TOPLEFT" - elseif x < GetScreenWidth() * 2 / 3 then - return "BOTTOM", "TOP" - else - return "BOTTOMRIGHT", "TOPRIGHT" - end - end -end - -local function RegisterTablet20(self) - local frame = pluginToFrame[self] - if not Tablet20:IsRegistered(frame) then - local db = getLazyDatabaseValue(self) - if db and not db.detachedTooltip then - db.detachedTooltip = {} - end - Tablet20:Register(frame, - 'children', function() - Tablet20:SetTitle(self:GetTitle()) - if type(self.OnUpdateFuBarTooltip) == "function" then - if not self:IsDisabled() then - self:OnUpdateFuBarTooltip() - end - end - end, - 'clickable', getPluginOption(self, 'clickableTooltip', false), - 'data', CheckFuBar() and FuBar.db.profile.tooltip or db and db.detachedTooltip or {}, - 'detachedData', db and db.detachedTooltip or {}, - 'point', Tablet20_point, - 'menu', self.OnMenuRequest and function(level, value, valueN_1, valueN_2, valueN_3, valueN_4) - if level == 1 then - local name = tostring(self) - if not name:find('^table:') then - name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") - Rock("Dewdrop-2.0"):AddLine( - 'text', name, - 'isTitle', true - ) - end - end - if type(self.OnMenuRequest) == "function" then - self:OnMenuRequest(level, value, true, valueN_1, valueN_2, valueN_3, valueN_4) - elseif type(self.OnMenuRequest) == "table" then - Rock("Dewdrop-2.0"):FeedAceOptionsTable(self.OnMenuRequest) - end - end, - 'hideWhenEmpty', getPluginOption(self, 'tooltipHiddenWhenEmpty', false) - ) - local func = pluginToFrame[self]:GetScript("OnEnter") - frame:SetScript("OnEnter", function(this, ...) - -- HACK - func(this, ...) - - if FuBar and FuBar.IsHidingTooltipsInCombat and FuBar:IsHidingTooltipsInCombat() and InCombatLockdown() then - if Tablet20:IsAttached(this) then - Tablet20:Close(this) - end - end - end) - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Calls :OnUpdateFuBarTooltip() if it is available, the plugin is not disabled, and the tooltip is shown. -Example: - self:UpdateFuBarTooltip() ------------------------------------------------------------------------------]] -function FuBarPlugin:UpdateFuBarTooltip() - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - - if tooltipType == "GameTooltip" then - local frame = self:IsFuBarMinimapAttached() and pluginToMinimapFrame[self] or pluginToFrame[self] - if not GameTooltip:IsOwned(frame) then - return - end - GameTooltip:Hide() - - local anchor - if frame:GetTop() > GetScreenHeight() / 2 then - local x = frame:GetCenter() - if x < GetScreenWidth() / 2 then - anchor = "ANCHOR_BOTTOMRIGHT" - else - anchor = "ANCHOR_BOTTOMLEFT" - end - else - local x = frame:GetCenter() - if x < GetScreenWidth() / 2 then - anchor = "ANCHOR_TOPLEFT" - else - anchor = "ANCHOR_TOPRIGHT" - end - end - GameTooltip:SetOwner(frame, anchor) - if type(self.OnUpdateFuBarTooltip) == "function" and not self:IsDisabled() then - self:OnUpdateFuBarTooltip() - end - GameTooltip:Show() - return - elseif tooltipType == "Custom" then - if type(self.OnUpdateFuBarTooltip) == "function" and not self:IsDisabled() then - self:OnUpdateFuBarTooltip() - end - return - elseif tooltipType == "Tablet-2.0" then - RegisterTablet20(self) - if self:IsFuBarMinimapAttached() and not self:IsFuBarTooltipDetached() and pluginToMinimapFrame[self] then - Tablet20:Refresh(pluginToMinimapFrame[self]) - else - Tablet20:Refresh(pluginToFrame[self]) - end - elseif tooltipType == "None" then - return - else - error(("Unknown %s option for %q: %q"):format(MAJOR_VERSION, 'tooltipType', tostring(tooltipType)), 2) - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Shows the plugin, enables the plugin if previously disabled, and calls :UpdateFuBarPlugin(). -Example: - self:Show() ------------------------------------------------------------------------------]] -function FuBarPlugin:Show(panelId) - if pluginToFrame[self]:IsShown() or (pluginToMinimapFrame[self] and pluginToMinimapFrame[self]:IsShown()) then - return - end - if panelId ~= false then - setLazyDatabaseValue(self, nil, 'hidden') - end - if self.IsActive and not self:IsActive() then - self.panelIdTmp = panelId - self:ToggleActive() - self.panelIdTmp = nil - setLazyDatabaseValue(self, nil, 'disabled') - elseif not getLazyDatabaseValue(self, 'hidden') then - if panelId == 0 or not CheckFuBar() then - MinimapContainer:AddPlugin(self) - else - FuBar:ShowPlugin(self, panelId or self.panelIdTmp) - end - if not getPluginOption(self, 'userDefinedFrame', false) then - if not self:IsFuBarTextShown() then - local text = pluginToFrame[self].text - text:SetText("") - text:SetWidth(epsilon) - text:Hide() - end - if not self:IsFuBarIconShown() then - local icon = pluginToFrame[self].icon - icon:SetWidth(epsilon) - icon:Hide() - end - end - self:UpdateFuBarPlugin() - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Hides the plugin, disables the plugin if cannot hide without standby. -Arguments: - [optional] boolean - internal variable. Do not set this. -Example: - self:Hide() ------------------------------------------------------------------------------]] -function FuBarPlugin:Hide(check) - if not pluginToFrame[self]:IsShown() and (not pluginToMinimapFrame[self] or not pluginToMinimapFrame[self]:IsShown()) then - return - end - local hideWithoutStandby = getPluginOption(self, 'hideWithoutStandby', false) - if hideWithoutStandby and check ~= false then - setLazyDatabaseValue(self, true, 'hidden') - end - if not hideWithoutStandby then - if getPluginOption(self, 'tooltipType', "GameTooltip") == "Tablet-2.0" and not getPluginOption(self, 'cannotDetachTooltip', false) and self:IsFuBarTooltipDetached() and getLazyDatabaseValue(self, 'detachedTooltip', 'detached') then - self:ReattachTooltip() - setLazyDatabaseValue(self, true, 'detachedTooltip', 'detached') - end - if self.IsActive and self:IsActive() and self.ToggleActive and (not CheckFuBar() or not FuBar:IsChangingProfile()) then - self:ToggleActive() - end - end - if pluginToPanel[self] then - pluginToPanel[self]:RemovePlugin(self) - end - pluginToFrame[self]:Hide() - if pluginToMinimapFrame[self] then - pluginToMinimapFrame[self]:Hide() - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Sets the path to the icon for the plugin. -Arguments: - string or nil - The path to the icon. If nil, then no icon. -Example: - self:SetFuBarIcon("Interface\\AddOns\\MyAddon\\otherIcon") ------------------------------------------------------------------------------]] -function FuBarPlugin:SetFuBarIcon(path) - if not path then - return - end - if not pluginToFrame[self] or not pluginToFrame[self].icon then - return - end - if path:match([[^Interface\Icons\]]) then - pluginToFrame[self].icon:SetTexCoord(0.05, 0.95, 0.05, 0.95) - else - pluginToFrame[self].icon:SetTexCoord(0, 1, 0, 1) - end - pluginToFrame[self].icon:SetTexture(path) - if pluginToMinimapFrame[self] and pluginToMinimapFrame[self].icon then - if path:match([[^Interface\Icons\]]) then - pluginToMinimapFrame[self].icon:SetTexCoord(0.05, 0.95, 0.05, 0.95) - else - pluginToMinimapFrame[self].icon:SetTexCoord(0, 1, 0, 1) - end - pluginToMinimapFrame[self].icon:SetTexture(path) - end -end -precondition(FuBarPlugin, 'SetFuBarIcon', function(self, path) - if not path then - return - end - argCheck(path, 2, "string", "nil") - if not getPluginOption(self, 'iconPath', false) then - error(("%s: Cannot set icon unless 'iconPath' is set."):format(self:GetTitle()), 3) - end -end) - ---[[--------------------------------------------------------------------------- -Returns: - string or nil - The path to the icon for the plugin. If nil, then no icon. -Example: - local path = self:GetFuBarIcon() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetFuBarIcon() - if getPluginOption(self, 'iconPath', false) then - return pluginToFrame[self] and pluginToFrame[self].icon and pluginToFrame[self].icon:GetTexture() - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Checks the current width of the icon and text, then updates frame to expand/shrink to it if necessary. -Arguments: - [optional] boolean - if true, Shrink/expand no matter what, otherwise if the width is less than 8 pixels smaller, don't shrink. -Example: - self:CheckWidth(true) ------------------------------------------------------------------------------]] -function FuBarPlugin:CheckWidth(force) - local frame = pluginToFrame[self] - if not frame then - return - end - local icon = frame.icon - local text = frame.text - if (not icon or not icon:IsShown()) and (not text or not text:IsShown()) then - return - end - - local db = getLazyDatabaseValue(self) - - if (db and not self:IsFuBarIconShown()) or not getPluginOption(self, 'iconPath', false) then - icon:SetWidth(epsilon) - end - local width - if not getPluginOption(self, 'hasNoText', false) then - text:SetHeight(0) - text:SetWidth(500) - width = text:GetStringWidth() + 1 - text:SetWidth(width) - text:SetHeight(text:GetHeight()) - end - local panel = pluginToPanel[self] - if getPluginOption(self, 'hasNoText', false) or not text:IsShown() then - frame:SetWidth(icon:GetWidth()) - if panel and panel:GetPluginSide(self) == "CENTER" then - panel:UpdateCenteredPosition() - end - elseif force or not frame.textWidth or frame.textWidth < width or frame.textWidth - 8 > width then - frame.textWidth = width - text:SetWidth(width) - if icon and icon:IsShown() then - frame:SetWidth(width + icon:GetWidth()) - else - frame:SetWidth(width) - end - if panel and panel:GetPluginSide(self) == "CENTER" then - panel:UpdateCenteredPosition() - end - end -end -precondition(FuBarPlugin, 'CheckWidth', function(self, force) - argCheck(force, 2, "boolean", "nil") -end) - ---[[--------------------------------------------------------------------------- -Notes: - Sets the text of the plugin. Should only be called from within :OnFuBarUpdateText() -Arguments: - string - text to set the plugin to. If not given, set to title. -Example: - myAddon.OnFuBarUpdateText = function(self) - self:SetFuBarText("Hello") - fend ------------------------------------------------------------------------------]] -function FuBarPlugin:SetFuBarText(text) - local frame = pluginToFrame[self] - if not frame or not frame.text then - return - end - if text == "" then - if getPluginOption(self, 'iconPath', false) then - self:ShowFuBarIcon() - else - text = self:GetTitle() - end - end - if not self:IsFuBarTextColored() then - text = text:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") - end - frame.text:SetText(text) - self:CheckWidth() -end -precondition(FuBarPlugin, 'SetFuBarText', function(self, text) - local frame = pluginToFrame[self] - if not frame or not frame.text then - return - end - if getPluginOption(self, 'hasNoText', false) then - error(("%s: Cannot set text if 'hasNoText' has been set."):format(self:GetTitle()), 3) - end - argCheck(text, 2, "string", "number") -end) - ---[[--------------------------------------------------------------------------- -Returns: - string - The current text of the plugin. -Example: - local text = self:GetFuBarText() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetFuBarText() - local frame = pluginToFrame[self] - if not frame or not frame.text then - error(("%s: Cannot get text without a text frame."):format(self:GetTitle()), 2) - end - if not getPluginOption(self, 'hasNoText', false) then - return frame.text:GetText() or "" - end -end - ---[[--------------------------------------------------------------------------- -Returns: - boolean - whether the icon for the plugin is showing. -Example: - local isIconShowing = self:IsFuBarIconShown() ------------------------------------------------------------------------------]] -function FuBarPlugin:IsFuBarIconShown() - if not getPluginOption(self, 'iconPath', false) then - return false - elseif getPluginOption(self, 'hasNoText', false) then - return true - end - return not not getLazyDatabaseValueDefault(self, true, 'showIcon') -end - ---[[--------------------------------------------------------------------------- -Notes: - Toggles whether the icon for the plugin is showing. -Example: - self:ToggleFuBarIconShown() ------------------------------------------------------------------------------]] -function FuBarPlugin:ToggleFuBarIconShown() - local frame = pluginToFrame[self] - local icon = frame and frame.icon - local text = frame and frame.text - if not icon then - error(("%s: Cannot toggle icon without an icon frame."):format(self:GetTitle()), 2) - elseif not text then - error(("%s: Cannot toggle icon without a text frame."):format(self:GetTitle()), 2) - elseif not getPluginOption(self, 'iconPath', false) then - error(("%s: Cannot show icon unless 'iconPath' is set."):format(self:GetTitle()), 2) - elseif getPluginOption(self, 'hasNoText', false) then - error(("%s: Cannot show icon if 'hasNoText' is set."):format(self:GetTitle()), 2) - elseif not getLazyDatabaseValue(self) then - error(("%s: Cannot hide icon if self.db is not available."):format(self:GetTitle()), 2) - end - local value = not self:IsFuBarIconShown() - setLazyDatabaseValue(self, value, 'showIcon') - if value then - if not self:IsFuBarTextShown() and text:IsShown() and text:GetText() == self:GetTitle() then - text:Hide() - text:SetText("") - end - icon:Show() - icon:SetWidth(pluginToFrame[self].icon:GetHeight()) - self:UpdateFuBarText() - else - if not text:IsShown() or not text:GetText() or text:GetText() == "" then - text:Show() - text:SetText(self:GetTitle()) - end - icon:Hide() - icon:SetWidth(epsilon) - end - self:CheckWidth(true) - return value -end - ---[[--------------------------------------------------------------------------- -Notes: - Shows the icon of the plugin if hidden. -Example: - self:ShowFuBarIcon() ------------------------------------------------------------------------------]] -function FuBarPlugin:ShowFuBarIcon() - if not self:IsFuBarIconShown() then - self:ToggleFuBarIconShown() - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Hides the icon of the plugin if shown. -Example: - self:HideFuBarIcon() ------------------------------------------------------------------------------]] -function FuBarPlugin:HideFuBarIcon() - if self:IsFuBarIconShown() then - self:ToggleFuBarIconShown() - end -end - ---[[--------------------------------------------------------------------------- -Returns: - boolean - whether the text for the plugin is showing. -Example: - local isTextShowing = self:IsFuBarTextShown() ------------------------------------------------------------------------------]] -function FuBarPlugin:IsFuBarTextShown() - if getPluginOption(self, 'hasNoText', false) then - return false - elseif not getPluginOption(self, 'iconPath', false) then - return true - end - return not not getLazyDatabaseValueDefault(self, true, 'showText') -end - ---[[--------------------------------------------------------------------------- -Notes: - Toggles whether the text for the plugin is showing. -Example: - self:ToggleFuBarTextShown() ------------------------------------------------------------------------------]] -function FuBarPlugin:ToggleFuBarTextShown() - local frame = pluginToFrame[self] - local icon = frame and frame.icon - local text = frame and frame.text - if not icon then - error(("%s: Cannot toggle text without an icon frame."):format(self:GetTitle()), 2) - elseif not text then - error(("%s: Cannot toggle text without a text frame."):format(self:GetTitle()), 2) - elseif getPluginOption(self, 'cannotHideText', false) then - error(("%s: Cannot toggle text if 'cannotHideText' is set."):format(self:GetTitle()), 2) - elseif not getPluginOption(self, 'iconPath', false) then - error(("%s: Cannot toggle text unless 'iconPath' is set."):format(self:GetTitle()), 2) - elseif getPluginOption(self, 'hasNoText', false) then - error(("%s: Cannot toggle text if 'hasNoText' is set."):format(self:GetTitle()), 2) - elseif not getLazyDatabaseValue(self) then - error(("%s: Cannot toggle text if self.db is not available."):format(self:GetTitle()), 2) - end - local value = not self:IsFuBarTextShown() - setLazyDatabaseValue(self, value, 'showText') - if value then - text:Show() - self:UpdateFuBarText() - else - text:SetText("") - text:SetWidth(epsilon) - text:Hide() - self:ShowFuBarIcon() - end - self:CheckWidth(true) - return value -end - ---[[--------------------------------------------------------------------------- -Notes: - Shows the text of the plugin if hidden. -Example: - self:ShowFuBarText() ------------------------------------------------------------------------------]] -function FuBarPlugin:ShowFuBarText() - if not self:IsFuBarTextShown() then - self:ToggleFuBarTextShown() - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Hides the text of the plugin if shown. -Example: - self:HideFuBarText() ------------------------------------------------------------------------------]] -function FuBarPlugin:HideFuBarText() - if self:IsFuBarTextShown() then - self:ToggleFuBarTextShown() - end -end - ---[[--------------------------------------------------------------------------- -Returns: - string - default position of the plugin. -Notes: - This is here for FuBar core to communicate properly. -Example: - local pos = self:GetDefaultPosition() ------------------------------------------------------------------------------]] -function FuBarPlugin:GetDefaultPosition() - return getPluginOption(self, 'defaultPosition', "LEFT") -end - ---[[--------------------------------------------------------------------------- -Returns: - boolean - Whether the tooltip is detached. -Example: - local detached = self:IsFuBarTooltipDetached() ------------------------------------------------------------------------------]] -function FuBarPlugin:IsFuBarTooltipDetached() - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType ~= "Tablet-2.0" then - return - end - - RegisterTablet20(self) - return not Tablet20:IsAttached(pluginToFrame[self]) -end - ---[[--------------------------------------------------------------------------- -Notes: - Toggles whether the tooltip is detached. -Example: - self:ToggleFuBarTooltipDetached() ------------------------------------------------------------------------------]] -function FuBarPlugin:ToggleFuBarTooltipDetached() - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType ~= "Tablet-2.0" then - return - end - - RegisterTablet20(self) - if Tablet20:IsAttached(pluginToFrame[self]) then - Tablet20:Detach(pluginToFrame[self]) - else - Tablet20:Attach(pluginToFrame[self]) - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * Detaches the tooltip from the plugin. - * This does nothing if already detached. -Example: - self:DetachFuBarTooltip() ------------------------------------------------------------------------------]] -function FuBarPlugin:DetachFuBarTooltip() - if not self:IsFuBarTooltipDetached() then - self:ToggleFuBarTooltipDetached() - end -end - ---[[--------------------------------------------------------------------------- -Notes: - Reattaches the tooltip to the plugin. - This does nothing if already attached. -Example: - self:ReattachFuBarTooltip() ------------------------------------------------------------------------------]] -function FuBarPlugin:ReattachFuBarTooltip() - if self:IsFuBarTooltipDetached() then - self:ToggleFuBarTooltipDetached() - end -end - -local function IsCorrectPanel(panel) - if type(panel) ~= "table" then - return false - elseif type(panel.AddPlugin) ~= "function" then - return false - elseif type(panel.RemovePlugin) ~= "function" then - return false - elseif type(panel.GetNumPlugins) ~= "function" then - return false - elseif type(panel:GetNumPlugins()) ~= "number" then - return false - elseif type(panel.GetPlugin) ~= "function" then - return false - elseif type(panel.HasPlugin) ~= "function" then - return false - elseif type(panel.GetPluginSide) ~= "function" then - return false - end - return true -end - --- #NODOC --- this is used internally by FuBar -function FuBarPlugin:SetPanel(panel) - pluginToPanel[self] = panel -end -precondition(FuBarPlugin, 'SetPanel', function(self, panel) - argCheck(panel, 2, "table", "nil") - if panel and not IsCorrectPanel(panel) then - error("Bad argument #2 to `SetPanel'. Panel does not have the correct API.", 3) - end -end) - --- #NODOC --- this is used internally by FuBar -function FuBarPlugin:SetFontSize(size) - if getPluginOption(self, 'userDefinedFrame', false) then - error(("%sYou must provide a :SetFontSize(size) method if you have 'userDefinedFrame' set."):format(self.name and self.name .. ": " or ""), 2) - end - if getPluginOption(self, 'iconPath', false) then - local frame = pluginToFrame[self] - local icon = frame and frame.icon - if not icon then - error(("%sno icon frame found."):format(self.name and self.name .. ": " or ""), 2) - end - icon:SetWidth(size + 3) - icon:SetHeight(size + 3) - end - if not getPluginOption(self, 'hasNoText', false) then - local frame = pluginToFrame[self] - local text = frame and frame.text - if not text then - error(("%sno text frame found."):format(self.name and self.name .. ": " or ""), 2) - end - local font, _, flags = text:GetFont() - text:SetFont(font, size, flags) - end - self:CheckWidth() -end - -local function IsLoadOnDemand(plugin) - return IsAddOnLoadOnDemand(folderNames[plugin] or "") -end - --- #NODOC --- this is used internally by FuBar. -function FuBarPlugin:IsDisabled() - return type(self.IsActive) == "function" and not self:IsActive() or false -end - -function FuBarPlugin:OnEmbed(target) - local folder = Rock.addonToFolder[target] - if not folder then - for i = 6, 3, -1 do - folder = debugstack(i, 1, 0):match([[\AddOns\(.*)\]]) - if folder then - break - end - end - end - folderNames[target] = folder -end - -local frame_OnClick, frame_OnDoubleClick, frame_OnMouseDown, frame_OnMouseUp, frame_OnReceiveDrag, frame_OnEnter, frame_OnLeave ---[[--------------------------------------------------------------------------- -Arguments: - [optional] string - name of the frame -Returns: - frame - a frame with the basic scripts to be considered a plugin frame. -Example: - MyPlugin.frame = MyPlugin:CreateBasicPluginFrame("FuBar_MyPluginFrame") ------------------------------------------------------------------------------]] -function FuBarPlugin:CreateBasicPluginFrame(name) - local frame = CreateFrame("Button", name, UIParent) - frame:SetFrameStrata("HIGH") - frame:SetFrameLevel(7) - frame:EnableMouse(true) - frame:EnableMouseWheel(true) - frame:SetMovable(true) - frame:SetWidth(150) - frame:SetHeight(24) - frame:SetPoint("CENTER", UIParent, "CENTER") - frame.self = self - if not frame_OnEnter then - function frame_OnEnter(this) - local self = this.self - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType == "GameTooltip" then - GameTooltip:SetOwner(self:IsFuBarMinimapAttached() and pluginToMinimapFrame[self] or pluginToFrame[self], "ANCHOR_CURSOR") - self:UpdateFuBarTooltip() - end - if type(self.OnFuBarEnter) == "function" then - self:OnFuBarEnter() - end - end - end - frame:SetScript("OnEnter", frame_OnEnter) - if not frame_OnLeave then - function frame_OnLeave(this) - local self = this.self - if type(self.OnFuBarLeave) == "function" then - self:OnFuBarLeave() - end - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType == "GameTooltip" and GameTooltip:IsOwned(self:IsFuBarMinimapAttached() and pluginToMinimapFrame[self] or pluginToFrame[self]) then - GameTooltip:Hide() - end - end - end - frame:SetScript("OnLeave", frame_OnLeave) - if not frame_OnClick then - function frame_OnClick(this, button) - local self = this.self - if self:IsFuBarMinimapAttached() and this.dragged then return end - if type(self.OnFuBarClick) == "function" then - self:OnFuBarClick(button) - end - end - end - frame:SetScript("OnClick", frame_OnClick) - if not frame_OnDoubleClick then - function frame_OnDoubleClick(this, button) - local self = this.self - if type(self.OnFuBarDoubleClick) == "function" then - self:OnFuBarDoubleClick(button) - end - end - end - frame:SetScript("OnDoubleClick", frame_OnDoubleClick) - if not frame_OnMouseDown then - function frame_OnMouseDown(this, button) - local self = this.self - if button == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then - self:OpenMenu() - return - else - if type(self.OnFuBarMouseDown) == "function" then - self:OnFuBarMouseDown(button) - end - end - end - end - frame:SetScript("OnMouseDown", frame_OnMouseDown) - if not frame_OnMouseUp then - function frame_OnMouseUp(this, button) - local self = this.self - if type(self.OnFuBarMouseUp) == "function" then - self:OnFuBarMouseUp(button) - end - end - end - frame:SetScript("OnMouseUp", frame_OnMouseUp) - if not frame_OnReceiveDrag then - function frame_OnReceiveDrag(this) - local self = this.self - if (self:IsFuBarMinimapAttached() and not this.dragged) and type(self.OnReceiveDrag) == "function" then - self:OnFuBarReceiveDrag() - end - end - end - frame:SetScript("OnReceiveDrag", frame_OnReceiveDrag) - return frame -end - -local child_OnEnter, child_OnLeave, child_OnClick, child_OnDoubleClick, child_OnMouseDown, child_OnMouseUp, child_OnReceiveDrag ---[[--------------------------------------------------------------------------- -Arguments: - string - type of the frame, e.g. "Frame", "Button", etc. - [optional] string - name of the frame - [optional] frame - parent frame -Returns: - frame - a child frame that can be manipulated and used -Example: - local child = self:CreatePluginChildFrame("Frame", nil, self.frame) ------------------------------------------------------------------------------]] -function FuBarPlugin:CreatePluginChildFrame(frameType, name, parent) - local child = CreateFrame(frameType, name, parent) - if parent then - child:SetFrameLevel(parent:GetFrameLevel() + 2) - end - child.self = self - if not child_OnEnter then - function child_OnEnter(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:GetScript("OnEnter") then - frame:GetScript("OnEnter")(frame, ...) - end - end - end - child:SetScript("OnEnter", child_OnEnter) - if not child_OnLeave then - function child_OnLeave(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:GetScript("OnLeave") then - frame:GetScript("OnLeave")(frame, ...) - end - end - end - child:SetScript("OnLeave", child_OnLeave) - if child:HasScript("OnClick") then - if not child_OnClick then - function child_OnClick(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:HasScript("OnClick") and frame:GetScript("OnClick") then - frame:GetScript("OnClick")(frame, ...) - end - end - end - child:SetScript("OnClick", child_OnClick) - end - if child:HasScript("OnDoubleClick") then - if not child_OnDoubleClick then - function child_OnDoubleClick(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:HasScript("OnDoubleClick") and frame:GetScript("OnDoubleClick") then - frame:GetScript("OnDoubleClick")(frame, ...) - end - end - end - child:SetScript("OnDoubleClick", child_OnDoubleClick) - end - if not child_OnMouseDown then - function child_OnMouseDown(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:HasScript("OnMouseDown") and frame:GetScript("OnMouseDown") then - frame:GetScript("OnMouseDown")(frame, ...) - end - end - end - child:SetScript("OnMouseDown", child_OnMouseDown) - if not child_OnMouseUp then - function child_OnMouseUp(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:HasScript("OnMouseUp") and frame:GetScript("OnMouseUp") then - frame:GetScript("OnMouseUp")(frame, ...) - end - end - end - child:SetScript("OnMouseUp", child_OnMouseUp) - if not child_OnReceiveDrag then - function child_OnReceiveDrag(this, ...) - local self = this.self - local frame = pluginToFrame[self] - if frame:HasScript("OnReceiveDrag") and frame:GetScript("OnReceiveDrag") then - frame:GetScript("OnReceiveDrag")(frame, ...) - end - end - end - child:SetScript("OnReceiveDrag", child_OnReceiveDrag) - return child -end -precondition(FuBarPlugin, 'CreatePluginChildFrame', function(self, frameType, name, parent) - if not pluginToFrame[self] then - error(("%sYou must have self.frame declared in order to add child frames."):format(self.name and self.name .. ": " or ""), 3) - end - argCheck(frameType, 2, "string") -end) - ---[[--------------------------------------------------------------------------- -Notes: - Opens the configuration menu associated with this plugin. -Example: - self:OpenMenu() ------------------------------------------------------------------------------]] -function FuBarPlugin:OpenMenu(frame) - if not frame then - frame = self:IsFuBarMinimapAttached() and pluginToMinimapFrame[self] or pluginToFrame[self] - end - if not frame:IsVisible() then - frame = UIParent - end - local configType = getPluginOption(self, 'configType', "LibRockConfig-1.0") - if configType == "Dewdrop-2.0" then - if not frame or not self:GetFrame() or Dewdrop20:IsOpen(frame) then - Dewdrop20:Close() - return - end - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType == "GameTooltip" then - if GameTooltip:IsOwned(frame) then - GameTooltip:Hide() - end - elseif tooltipType == "Custom" and type(self.CloseTooltip) == "function" then - self:CloseTooltip() - elseif tooltipType == "Tablet-2.0" and Tablet20 then - Tablet20:Close() - end - - if not Dewdrop20:IsRegistered(self:GetFrame()) then - if type(self.OnMenuRequest) == "table" and (not self.OnMenuRequest.handler or self.OnMenuRequest.handler == self) and self.OnMenuRequest.type == "group" then - Dewdrop20:InjectAceOptionsTable(self, self.OnMenuRequest) - if self.OnMenuRequest.args and CheckFuBar() and not getPluginOption(self, 'independentProfile', false) then - self.OnMenuRequest.args.profile = nil - if self.OnMenuRequest.extraArgs then - self.OnMenuRequest.extraArgs.profile = nil - end - end - end - Dewdrop20:Register(self:GetFrame(), - 'children', type(self.OnMenuRequest) == "table" and self.OnMenuRequest or function(level, value, valueN_1, valueN_2, valueN_3, valueN_4) - if level == 1 then - if not getPluginOption(self, 'hideMenuTitle', false) then - Dewdrop20:AddLine( - 'text', self:GetTitle(), - 'isTitle', true - ) - end - - if self.OnMenuRequest then - self:OnMenuRequest(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4) - end - - if not getPluginOption(self, 'overrideMenu', false) then - if self.MenuSettings and not getPluginOption(self, 'hideMenuTitle', false) then - Dewdrop20:AddLine() - end - self:AddImpliedMenuOptions() - end - else - if not getPluginOption(self, 'overrideMenu', false) and self:AddImpliedMenuOptions() then - else - if self.OnMenuRequest then - self:OnMenuRequest(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4) - end - end - end - if level == 1 then - Dewdrop20:AddLine( - 'text', CLOSE, - 'tooltipTitle', CLOSE, - 'tooltipText', CLOSE_DESC, - 'func', Dewdrop.Close, - 'arg1', Dewdrop - ) - end - end, - 'point', function(frame) - local x, y = frame:GetCenter() - local leftRight - if x < GetScreenWidth() / 2 then - leftRight = "LEFT" - else - leftRight = "RIGHT" - end - if y < GetScreenHeight() / 2 then - return "BOTTOM" .. leftRight, "TOP" .. leftRight - else - return "TOP" .. leftRight, "BOTTOM" .. leftRight - end - end, - 'dontHook', true - ) - end - if frame == self:GetFrame() then - Dewdrop20:Open(self:GetFrame()) - elseif frame ~= UIParent then - Dewdrop20:Open(frame, self:GetFrame()) - else - Dewdrop20:Open(frame, self:GetFrame(), 'cursorX', true, 'cursorY', true) - end - elseif configType == "LibRockConfig-1.0" then - local RockConfig = Rock("LibRockConfig-1.0", false, true) - if RockConfig then - RockConfig.OpenConfigMenu(self) - end - else - -- TODO: add more possibilities - end -end - -function FuBarPlugin.OnEmbedInitialize(FuBarPlugin, self) - if not self.frame then - local name = MAJOR_VERSION .. "_" .. self:GetTitle() .. "_" .. "Frame" - local frame = _G[name] - if not frame or not _G[name .. "Text"] or not _G[name .. "Icon"] then - frame = FuBarPlugin.CreateBasicPluginFrame(self, name) - - local icon = frame:CreateTexture(name .. "Icon", "ARTWORK") - frame.icon = icon - icon:SetWidth(16) - icon:SetHeight(16) - icon:SetPoint("LEFT", frame, "LEFT") - - local text = frame:CreateFontString(name .. "Text", "ARTWORK") - frame.text = text - text:SetWidth(134) - text:SetHeight(24) - text:SetPoint("LEFT", icon, "RIGHT", 0, 1) - text:SetFontObject(GameFontNormal) - end - pluginToFrame[self] = frame - else - pluginToFrame[self] = self.frame - if not pluginToOptions[self] then - pluginToOptions[self] = {} - end - pluginToOptions[self].userDefinedFrame = true - end - - local frame = pluginToFrame[self] - frame.plugin = self - frame:SetParent(UIParent) - frame:SetPoint("RIGHT", UIParent, "LEFT", -5, 0) - frame:Hide() - - local iconPath = getPluginOption(self, 'iconPath', false) - if iconPath then - self:SetFuBarIcon(iconPath) - end - - if CheckFuBar() then - FuBar:RegisterPlugin(self) - end -end - - -local CheckShow = function(self, panelId) - if not pluginToFrame[self]:IsShown() and (not pluginToMinimapFrame[self] or not pluginToMinimapFrame[self]:IsShown()) then - self:Show(panelId) - end -end - -local schedules = {} -local f = CreateFrame("Frame") -f:SetScript("OnUpdate", function(this) - for i,v in ipairs(schedules) do - local success, ret = pcall(unpack(v)) - if not success then - geterrorhandler()(ret) - end - schedules[i] = del(v) - end - f:Hide() -end) - -local recheckPlugins -local AceConsole -function FuBarPlugin.OnEmbedEnable(FuBarPlugin, self, first) - if not getPluginOption(self, 'userDefinedFrame', false) then - local icon = pluginToFrame[self].icon - if self:IsFuBarIconShown() then - icon:Show() - else - icon:Hide() - end - end - self:CheckWidth(true) - - if not getPluginOption(self, 'hideWithoutStandby', false) or (getLazyDatabaseValue(self) and not getLazyDatabaseValue(self, 'hidden')) then - if not first then - CheckShow(self, self.panelIdTmp) - else - schedules[#schedules+1] = newList(CheckShow, self, self.panelIdTmp) - f:Show() - end - end - - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType == "Tablet-2.0" and not getPluginOption(self, 'cannotDetachTooltip', false) and getLazyDatabaseValue(self, 'detachedTooltip', 'detached') then - schedules[#schedules+1] = newList(self.DetachFuBarTooltip, self) - f:Show() - end - - if IsLoadOnDemand(self) and CheckFuBar() then - if not FuBar.db.profile.loadOnDemand then - FuBar.db.profile.loadOnDemand = {} - end - if not FuBar.db.profile.loadOnDemand[folderNames[self]] then - FuBar.db.profile.loadOnDemand[folderNames[self]] = {} - end - FuBar.db.profile.loadOnDemand[folderNames[self]].disabled = nil - end - --[[ - if CheckFuBar() and AceLibrary:HasInstance("AceConsole-2.0") then - if not recheckPlugins then - if not AceConsole then - AceConsole = AceLibrary("AceConsole-2.0") - end - recheckPlugins = function() - for k,v in pairs(AceConsole.registry) do - if type(v) == "table" and v.args and AceOO.inherits(v.handler, FuBarPlugin) and not v.handler.independentProfile then - v.args.profile = nil - end - end - end - end - FuBarPlugin:ScheduleEvent("FuBarPlugin-recheckPlugins", recheckPlugins, 0) - end - ]] -end - -function FuBarPlugin.OnEmbedDisable(FuBarPlugin, self) - self:Hide(false) - - if IsLoadOnDemand(self) and CheckFuBar() then - if not FuBar.db.profile.loadOnDemand then - FuBar.db.profile.loadOnDemand = {} - end - if not FuBar.db.profile.loadOnDemand[folderNames[self]] then - FuBar.db.profile.loadOnDemand[folderNames[self]] = {} - end - FuBar.db.profile.loadOnDemand[folderNames[self]].disabled = true - end -end - -function FuBarPlugin.OnEmbedProfileEnable(FuBarPlugin, self) - self:UpdateFuBarPlugin() - if getLazyDatabaseValue(self) then - if not getLazyDatabaseValue(self, 'detachedTooltip') then - setLazyDatabaseValue(self, {}, 'detachedTooltip') - end - local tooltipType = getPluginOption(self, 'tooltipType', "GameTooltip") - if tooltipType == "Tablet-2.0" and Tablet20 then - if Tablet20.registry[pluginToFrame[self]] then - Tablet20:UpdateDetachedData(pluginToFrame[self], getLazyDatabaseValue(self, 'detachedTooltip')) - else - RegisterTablet20(self) - end - end - if MinimapContainer:HasPlugin(self) then - MinimapContainer:ReadjustLocation(self) - end - end -end - --- #NODOC -function FuBarPlugin.GetEmbedRockConfigOptions(FuBarPlugin, self) - return 'icon', { - type = 'boolean', - name = SHOW_FUBAR_ICON, - desc = SHOW_FUBAR_ICON_DESC, - set = "ToggleFuBarIconShown", - get = "IsFuBarIconShown", - hidden = function() - return not getPluginOption(self, 'iconPath', false) or getPluginOption(self, 'hasNoText', false) or self:IsDisabled() or self:IsFuBarMinimapAttached() or not getLazyDatabaseValue(self) - end, - order = -13.7, - handler = self, - }, 'text', { - type = 'boolean', - name = SHOW_FUBAR_TEXT, - desc = SHOW_FUBAR_TEXT_DESC, - set = "ToggleFuBarTextShown", - get = "IsFuBarTextShown", - hidden = function() - return getPluginOption(self, 'cannotHideText', false) or not getPluginOption(self, 'iconPath', false) or getPluginOption(self, 'hasNoText') or self:IsDisabled() or self:IsFuBarMinimapAttached() or not getLazyDatabaseValue(self) - end, - order = -13.6, - handler = self, - }, 'colorText', { - type = 'boolean', - name = SHOW_COLORED_FUBAR_TEXT, - desc = SHOW_COLORED_FUBAR_TEXT_DESC, - set = "ToggleFuBarTextColored", - get = "IsFuBarTextColored", - hidden = function() - return getPluginOption(self, 'userDefinedFrame', false) or getPluginOption(self, 'hasNoText', false) or getPluginOption(self, 'hasNoColor', false) or self:IsDisabled() or self:IsFuBarMinimapAttached() or not getLazyDatabaseValue(self) - end, - order = -13.5, - handler = self, - }, 'detachTooltip', { - type = 'boolean', - name = DETACH_FUBAR_TOOLTIP, - desc = DETACH_FUBAR_TOOLTIP_DESC, - get = "IsFuBarTooltipDetached", - set = "ToggleFuBarTooltipDetached", - hidden = function() - return not Tablet20 or getPluginOption(self, 'tooltipType', "GameTooltip") ~= "Tablet-2.0" or self:IsDisabled() - end, - order = -13.4, - handler = self, - }, 'lockTooltip', { - type = 'boolean', - name = LOCK_FUBAR_TOOLTIP, - desc = LOCK_FUBAR_TOOLTIP_DESC, - get = function() - return Tablet20:IsLocked(pluginToFrame[self]) - end, - set = function() - return Tablet20:ToggleLocked(pluginToFrame[self]) - end, - disabled = function() - return not self:IsFuBarTooltipDetached() - end, - hidden = function() - return not Tablet20 or getPluginOption(self, 'tooltipType', "GameTooltip") ~= "Tablet-2.0" or getPluginOption(self, 'cannotDetachTooltip', false) or self:IsDisabled() - end, - order = -13.3, - handler = self, - }, 'position', { - type = 'choice', - name = POSITION_ON_FUBAR, - desc = POSITION_ON_FUBAR_DESC, - choices = { - LEFT = POSITION_LEFT, - CENTER = POSITION_CENTER, - RIGHT = POSITION_RIGHT - }, - choiceSort = { - "LEFT", - "CENTER", - "RIGHT", - }, - get = function() - return self:GetPanel() and self:GetPanel():GetPluginSide(self) - end, - set = function(value) - if self:GetPanel() then - self:GetPanel():SetPluginSide(self, value) - end - end, - hidden = function() - return self:IsFuBarMinimapAttached() or self:IsDisabled() or not pluginToPanel[self] - end, - order = -13.2, - handler = self, - }, 'minimapAttach', { - type = 'boolean', - name = ATTACH_PLUGIN_TO_MINIMAP, - desc = ATTACH_PLUGIN_TO_MINIMAP_DESC, - get = "IsFuBarMinimapAttached", - set = "ToggleFuBarMinimapAttached", - hidden = function() - return (getPluginOption(self, 'cannotAttachToMinimap', false) and not self:IsFuBarMinimapAttached()) or not CheckFuBar() or self:IsDisabled() - end, - order = -13.1, - handler = self, - }, 'hide', { - type = 'boolean', - name = function() - if self:IsFuBarMinimapAttached() then - return HIDE_MINIMAP_BUTTON - else - return HIDE_FUBAR_PLUGIN - end - end, - desc = HIDE_FUBAR_PLUGIN_DESC, - get = function() - return not pluginToFrame[self]:IsShown() and (not pluginToMinimapFrame[self] or not pluginToMinimapFrame[self]:IsShown()) - end, - set = function(value) - if not value then - self:Show() - else - self:Hide() - end - end, - hidden = function() - return not getPluginOption(self, 'hideWithoutStandby', false) or self:IsDisabled() - end, - order = -13, - handler = self, - } -end - -local plugins = MinimapContainer.plugins or {} -for k in pairs(MinimapContainer) do - MinimapContainer[k] = nil -end -MinimapContainer.plugins = plugins - -local minimap_OnMouseDown, minimap_OnMouseUp -function MinimapContainer:AddPlugin(plugin) - if CheckFuBar() and FuBar:IsChangingProfile() then - return - end - if pluginToPanel[plugin] then - pluginToPanel[plugin]:RemovePlugin(plugin) - end - pluginToPanel[plugin] = self - if not pluginToMinimapFrame[plugin] then - local frame = CreateFrame("Button", pluginToFrame[plugin]:GetName() .. "MinimapButton", Minimap) - pluginToMinimapFrame[plugin] = frame - plugin.minimapFrame = frame - frame.plugin = plugin - frame:SetWidth(31) - frame:SetHeight(31) - frame:SetFrameStrata("BACKGROUND") - frame:SetFrameLevel(4) - frame:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") - local icon = frame:CreateTexture(frame:GetName() .. "Icon", "BACKGROUND") - plugin.minimapIcon = icon - local path = plugin:GetFuBarIcon() or (pluginToFrame[plugin].icon and pluginToFrame[plugin].icon:GetTexture()) or "Interface\\Icons\\INV_Misc_QuestionMark" - icon:SetTexture(path) - if path:sub(1, 16) == "Interface\\Icons\\" then - icon:SetTexCoord(0.07, 0.93, 0.07, 0.93) - else - icon:SetTexCoord(0, 1, 0, 1) - end - icon:SetWidth(20) - icon:SetHeight(20) - icon:SetPoint("TOPLEFT", frame, "TOPLEFT", 7, -5) - local overlay = frame:CreateTexture(frame:GetName() .. "Overlay","OVERLAY") - overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder") - overlay:SetWidth(53) - overlay:SetHeight(53) - overlay:SetPoint("TOPLEFT",frame,"TOPLEFT") - frame:EnableMouse(true) - frame:RegisterForClicks("LeftButtonUp") - - frame.self = plugin - if not frame_OnEnter then - function frame_OnEnter(this) - if type(this.self.OnFuBarEnter) == "function" then - this.self:OnFuBarEnter() - end - end - end - frame:SetScript("OnEnter", frame_OnEnter) - if not frame_OnLeave then - function frame_OnLeave(this) - if type(this.self.OnFuBarLeave) == "function" then - this.self:OnFuBarLeave() - end - end - end - frame:SetScript("OnLeave", frame_OnLeave) - if not frame_OnClick then - function frame_OnClick(this, arg1) - if this.self:IsMinimapAttached() and this.dragged then return end - if type(this.self.OnFuBarClick) == "function" then - this.self:OnFuBarClick(arg1) - end - end - end - frame:SetScript("OnClick", frame_OnClick) - if not frame_OnDoubleClick then - function frame_OnDoubleClick(this, arg1) - if type(this.self.OnFuBarDoubleClick) == "function" then - this.self:OnFuBarDoubleClick(arg1) - end - end - end - frame:SetScript("OnDoubleClick", frame_OnDoubleClick) - if not frame_OnReceiveDrag then - function frame_OnReceiveDrag(this) - if this.self:IsMinimapAttached() and this.dragged then return end - if type(this.self.OnFuBarReceiveDrag) == "function" then - this.self:OnFuBarReceiveDrag() - end - end - end - frame:SetScript("OnReceiveDrag", frame_OnReceiveDrag) - if not minimap_OnMouseDown then - function minimap_OnMouseDown(this, arg1) - this.dragged = false - if arg1 == "LeftButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then - HideDropDownMenu(1) - if type(this.self.OnFuBarMouseDown) == "function" then - this.self:OnFuBarMouseDown(arg1) - end - elseif arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then - this.self:OpenMenu(this) - else - HideDropDownMenu(1) - if type(this.self.OnFuBarMouseDown) == "function" then - this.self:OnFuBarMouseDown(arg1) - end - end - if this.self.OnFuBarClick or this.self.OnFuBarMouseDown or this.self.OnFuBarMouseUp or this.self.OnFuBarDoubleClick then - if this.self.minimapIcon:GetTexture():sub(1, 16) == "Interface\\Icons\\" then - this.self.minimapIcon:SetTexCoord(0.14, 0.86, 0.14, 0.86) - else - this.self.minimapIcon:SetTexCoord(0.1, 0.9, 0.1, 0.9) - end - end - end - end - frame:SetScript("OnMouseDown", minimap_OnMouseDown) - if not minimap_OnMouseUp then - function minimap_OnMouseUp(this, arg1) - if not this.dragged and type(this.self.OnFuBarMouseUp) == "function" then - this.self:OnFuBarMouseUp(arg1) - end - if this.self.minimapIcon:GetTexture():sub(1, 16) == "Interface\\Icons\\" then - this.self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95) - else - this.self.minimapIcon:SetTexCoord(0, 1, 0, 1) - end - end - end - frame:SetScript("OnMouseUp", minimap_OnMouseUp) - frame:RegisterForDrag("LeftButton") - frame:SetScript("OnDragStart", self.OnDragStart) - frame:SetScript("OnDragStop", self.OnDragStop) - - if getPluginOption(plugin, 'tooltipType', "GameTooltip") == "Tablet-2.0" then - -- Note that we have to do this after :SetScript("OnEnter"), etc, - -- so that Tablet-2.0 can override it properly. - RegisterTablet20(plugin) - Tablet20:Register(frame, pluginToFrame[plugin]) - end - end - pluginToFrame[plugin]:Hide() - pluginToMinimapFrame[plugin]:Show() - self:ReadjustLocation(plugin) - table.insert(self.plugins, plugin) - local exists = false - return true -end - -function MinimapContainer:RemovePlugin(index) - if CheckFuBar() and FuBar:IsChangingProfile() then - return - end - if type(index) == "table" then - index = self:IndexOfPlugin(index) - if not index then - return - end - end - local t = self.plugins - local plugin = t[index] - assert(pluginToPanel[plugin] == self, "Plugin has improper panel field") - plugin:SetPanel(nil) - table.remove(t, index) - return true -end - -function MinimapContainer:ReadjustLocation(plugin) - local frame = pluginToMinimapFrame[plugin] - if plugin.db and plugin.db.profile.minimapPositionWild then - frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", plugin.db.profile.minimapPositionX, plugin.db.profile.minimapPositionY) - elseif not plugin.db and plugin.minimapPositionWild then - frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", plugin.minimapPositionX, plugin.minimapPositionY) - else - local position - if plugin.db then - position = plugin.db.profile.minimapPosition or getPluginOption(plugin, 'defaultMinimapPosition', nil) or math.random(1, 360) - else - position = plugin.minimapPosition or getPluginOption(plugin, 'defaultMinimapPosition', nil) or math.random(1, 360) - end - local angle = math.rad(position or 0) - local x,y - local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND" - local cos = math.cos(angle) - local sin = math.sin(angle) - - local round = true - if minimapShape == "ROUND" then - -- do nothing - elseif minimapShape == "SQUARE" then - round = false - elseif minimapShape == "CORNER-TOPRIGHT" then - if cos < 0 or sin < 0 then - round = false - end - elseif minimapShape == "CORNER-TOPLEFT" then - if cos > 0 or sin < 0 then - round = false - end - elseif minimapShape == "CORNER-BOTTOMRIGHT" then - if cos < 0 or sin > 0 then - round = false - end - elseif minimapShape == "CORNER-BOTTOMLEFT" then - if cos > 0 or sin > 0 then - round = false - end - elseif minimapShape == "SIDE-LEFT" then - if cos > 0 then - round = false - end - elseif minimapShape == "SIDE-RIGHT" then - if cos < 0 then - round = false - end - elseif minimapShape == "SIDE-TOP" then - if sin < 0 then - round = false - end - elseif minimapShape == "SIDE-BOTTOM" then - if sin > 0 then - round = false - end - elseif minimapShape == "TRICORNER-TOPRIGHT" then - if cos < 0 and sin < 0 then - round = false - end - elseif minimapShape == "TRICORNER-TOPLEFT" then - if cos > 0 and sin < 0 then - round = false - end - elseif minimapShape == "TRICORNER-BOTTOMRIGHT" then - if cos < 0 and sin > 0 then - round = false - end - elseif minimapShape == "TRICORNER-BOTTOMLEFT" then - if cos > 0 and sin > 0 then - round = false - end - end - - if round then - x = cos * 80 - y = sin * 80 - else - x = 80 * 2^0.5 * cos - y = 80 * 2^0.5 * sin - if x < -80 then - x = -80 - elseif x > 80 then - x = 80 - end - if y < -80 then - y = -80 - elseif y > 80 then - y = 80 - end - end - frame:SetPoint("CENTER", Minimap, "CENTER", x, y) - end -end - -function MinimapContainer:GetPlugin(index) - return self.plugins[index] -end - -function MinimapContainer:GetNumPlugins() - return #self.plugins -end - -function MinimapContainer:IndexOfPlugin(plugin) - for i,p in ipairs(self.plugins) do - if p == plugin then - return i, "MINIMAP" - end - end -end - -function MinimapContainer:HasPlugin(plugin) - return self:IndexOfPlugin(plugin) ~= nil -end - -function MinimapContainer:GetPluginSide(plugin) - local index = self:IndexOfPlugin(plugin) - assert(index, "Plugin not in panel") - return "MINIMAP" -end - -function MinimapContainer.OnDragStart(this) - this.dragged = true - this:LockHighlight() - this:SetScript("OnUpdate", MinimapContainer.OnUpdate) - if this.self.minimapIcon:GetTexture():sub(1, 16) == "Interface\\Icons\\" then - this.self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95) - else - this.self.minimapIcon:SetTexCoord(0, 1, 0, 1) - end -end - -function MinimapContainer.OnDragStop(this) - this:SetScript("OnUpdate", nil) - this:UnlockHighlight() -end - -function MinimapContainer.OnUpdate(this, elapsed) - if not IsAltKeyDown() then - local mx, my = Minimap:GetCenter() - local px, py = GetCursorPosition() - local scale = UIParent:GetEffectiveScale() - px, py = px / scale, py / scale - local position = math.deg(math.atan2(py - my, px - mx)) - if position <= 0 then - position = position + 360 - elseif position > 360 then - position = position - 360 - end - if this.self.db then - this.self.db.profile.minimapPosition = position - this.self.db.profile.minimapPositionX = nil - this.self.db.profile.minimapPositionY = nil - this.self.db.profile.minimapPositionWild = nil - else - this.self.minimapPosition = position - this.self.minimapPositionX = nil - this.self.minimapPositionY = nil - this.self.minimapPositionWild = nil - end - else - local px, py = GetCursorPosition() - local scale = UIParent:GetEffectiveScale() - px, py = px / scale, py / scale - if this.self.db then - this.self.db.profile.minimapPositionX = px - this.self.db.profile.minimapPositionY = py - this.self.db.profile.minimapPosition = nil - this.self.db.profile.minimapPositionWild = true - else - this.self.minimapPositionX = px - this.self.minimapPositionY = py - this.self.minimapPosition = nil - this.self.minimapPositionWild = true - end - end - MinimapContainer:ReadjustLocation(this.self) -end - -FuBarPlugin:SetExportedMethods( - "SetFuBarOption", - "GetTitle", - "GetName", - "GetCategory", - "SetFontSize", - "GetFrame", - "Show", - "Hide", - "GetPanel", - "IsFuBarTextColored", - "ToggleFuBarTextColored", - "IsFuBarMinimapAttached", - "ToggleFuBarMinimapAttached", - "UpdateFuBarPlugin", - "UpdateFuBarText", - "UpdateFuBarTooltip", - "SetFuBarIcon", - "GetFuBarIcon", - "CheckWidth", - "SetFuBarText", - "GetFuBarText", - "IsFuBarIconShown", - "ToggleFuBarIconShown", - "ShowFuBarIcon", - "HideFuBarIcon", - "IsFuBarTextShown", - "ToggleFuBarTextShown", - "ShowFuBarText", - "HideFuBarText", - "IsFuBarTooltipDetached", - "ToggleFuBarTooltipDetached", - "DetachFuBarTooltip", - "ReattachFuBarTooltip", - "GetDefaultPosition", - "SetPanel", - "IsDisabled", - "CreateBasicPluginFrame", - "CreatePluginChildFrame", - "OpenMenu" -) - -Rock:FinalizeLibrary(MAJOR_VERSION)
--- a/modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/LibFuBarPlugin-3.0.toc Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -## Interface: 20300 -## LoadOnDemand: 1 -## Title: LibFuBarPlugin-3.0 -## Notes: A library to provide a means create a FuBar-compatible plugin. -## Notes-zhTW: 一個提供支援FuBar所需功能的插件。 -## Notes-esES: Una biblioteca para crear plugins compatibles con Fubar. -## Author: ckknight -## eMail: ckknight@gmail.com -## Version: 2.0 $Revision: 44269 $ -## X-Category: Library -## Dependencies: LibRock-1.0 -## OptionalDeps: FuBar -## X-License: LGPL v2.1 - -lib.xml \ No newline at end of file
--- a/modules/FuBar_ReActionFu/lib/LibFuBarPlugin-3.0/lib.xml Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ -..\FrameXML\UI.xsd"> - <Script file="LibFuBarPlugin-3.0.lua" /> -</Ui> \ No newline at end of file
--- a/modules/FuBar_ReActionFu/lib/LibRock-1.0/Changelog-LibRock-1.0-r63317.txt Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ ------------------------------------------------------------------------- -r63317 | ckknight | 2008-03-01 12:57:51 -0500 (Sat, 01 Mar 2008) | 2 lines -Changed paths: - M /trunk/LibRock-1.0/LibRock-1.0.lua - -LibRock-1.0 - support LibStub-based mixins that have rawget(library, "Embed") which is a function on em. -ROCK-136 ------------------------------------------------------------------------- -r61418 | pb_ee1 | 2008-02-15 05:25:45 -0500 (Fri, 15 Feb 2008) | 2 lines -Changed paths: - M /trunk/LibRock-1.0 - -LibRock-1.0: -- Adding tsvn:logtemplate, i said -_-' ------------------------------------------------------------------------- -r61417 | pb_ee1 | 2008-02-15 05:24:03 -0500 (Fri, 15 Feb 2008) | 3 lines -Changed paths: - M /trunk/LibRock-1.0/LibRock-1.0.lua - -LibRock-1.0: -- coller -> collez -- Adding tsvn:logtemplate ------------------------------------------------------------------------- -r61415 | pettigrow | 2008-02-15 05:13:24 -0500 (Fri, 15 Feb 2008) | 1 line -Changed paths: - M /trunk/LibRock-1.0/LibRock-1.0.lua - -LibRock-1.0: frFR Update ------------------------------------------------------------------------- -r61118 | ckknight | 2008-02-13 01:32:54 -0500 (Wed, 13 Feb 2008) | 1 line -Changed paths: - M /trunk/LibRock-1.0/LibRock-1.0.lua - M /trunk/LibRockComm-1.0/LibRockComm-1.0.lua - M /trunk/LibRockConfig-1.0/LibRockConfig-1.0.lua - M /trunk/LibRockConsole-1.0/LibRockConsole-1.0.lua - M /trunk/LibRockDB-1.0/LibRockDB-1.0.lua - M /trunk/LibRockEvent-1.0/LibRockEvent-1.0.lua - M /trunk/LibRockHook-1.0/LibRockHook-1.0.lua - M /trunk/LibRockLocale-1.0/LibRockLocale-1.0.lua - M /trunk/LibRockModuleCore-1.0/LibRockModuleCore-1.0.lua - M /trunk/LibRockTimer-1.0/LibRockTimer-1.0.lua - -.LibRock-1.0 - don't use negative reversion numbers because the LibStub patch for supporting that was never accepted. -------------------------------------------------------------------------
--- a/modules/FuBar_ReActionFu/lib/LibRock-1.0/LibRock-1.0.lua Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2968 +0,0 @@ ---[[ -Name: LibRock-1.0 -Revision: $Rev: 63317 $ -Developed by: ckknight (ckknight@gmail.com) -Website: http://www.wowace.com/ -Description: Library to allow for library and addon creation and easy table recycling functions. -License: LGPL v2.1 -]] - -local MAJOR_VERSION = "LibRock-1.0" -local MINOR_VERSION = tonumber(("$Revision: 63317 $"):match("(%d+)")) - 60000 - -local _G = _G -local GetLocale = _G.GetLocale -local CATEGORIES -if GetLocale() == "deDE" then - CATEGORIES = { - ["Action Bars"] = "Aktionsleisten", - ["Auction"] = "Auktion", - ["Audio"] = "Audio", - ["Battlegrounds/PvP"] = "Schlachtfeld/PvP", - ["Buffs"] = "Stärkungszauber", - ["Chat/Communication"] = "Chat/Kommunikation", - ["Druid"] = "Druide", - ["Hunter"] = "Jäger", - ["Mage"] = "Magier", - ["Paladin"] = "Paladin", - ["Priest"] = "Priester", - ["Rogue"] = "Schurke", - ["Shaman"] = "Schamane", - ["Warlock"] = "Hexenmeister", - ["Warrior"] = "Krieger", - ["Healer"] = "Heiler", - ["Tank"] = "Tank", - ["Caster"] = "Zauberer", - ["Combat"] = "Kampf", - ["Compilations"] = "Zusammenstellungen", - ["Data Export"] = "Datenexport", - ["Development Tools"] = "Entwicklungstools", - ["Guild"] = "Gilde", - ["Frame Modification"] = "Frameveränderungen", - ["Interface Enhancements"] = "Interfaceverbesserungen", - ["Inventory"] = "Inventar", - ["Library"] = "Bibliotheken", - ["Map"] = "Karte", - ["Mail"] = "Post", - ["Miscellaneous"] = "Diverses", - ["Quest"] = "Quest", - ["Raid"] = "Schlachtzug", - ["Tradeskill"] = "Beruf", - ["UnitFrame"] = "Einheiten-Fenster", - } -elseif GetLocale() == "frFR" then - CATEGORIES = { - ["Action Bars"] = "Barres d'action", - ["Auction"] = "Hôtel des ventes", - ["Audio"] = "Audio", - ["Battlegrounds/PvP"] = "Champs de bataille/JcJ", - ["Buffs"] = "Buffs", - ["Chat/Communication"] = "Chat/Communication", - ["Druid"] = "Druide", - ["Hunter"] = "Chasseur", - ["Mage"] = "Mage", - ["Paladin"] = "Paladin", - ["Priest"] = "Prêtre", - ["Rogue"] = "Voleur", - ["Shaman"] = "Chaman", - ["Warlock"] = "Démoniste", - ["Warrior"] = "Guerrier", - ["Healer"] = "Soigneur", - ["Tank"] = "Tank", - ["Caster"] = "Casteur", - ["Combat"] = "Combat", - ["Compilations"] = "Compilations", - ["Data Export"] = "Exportation de données", - ["Development Tools"] = "Outils de développement", - ["Guild"] = "Guilde", - ["Frame Modification"] = "Modification des fenêtres", - ["Interface Enhancements"] = "Améliorations de l'interface", - ["Inventory"] = "Inventaire", - ["Library"] = "Bibliothèques", - ["Map"] = "Carte", - ["Mail"] = "Courrier", - ["Miscellaneous"] = "Divers", - ["Quest"] = "Quêtes", - ["Raid"] = "Raid", - ["Tradeskill"] = "Métiers", - ["UnitFrame"] = "Fenêtres d'unité", - } -elseif GetLocale() == "koKR" then - CATEGORIES = { - ["Action Bars"] = "액션바", - ["Auction"] = "경매", - ["Audio"] = "음향", - ["Battlegrounds/PvP"] = "전장/PvP", - ["Buffs"] = "버프", - ["Chat/Communication"] = "대화/의사소통", - ["Druid"] = "드루이드", - ["Hunter"] = "사냥꾼", - ["Mage"] = "마법사", - ["Paladin"] = "성기사", - ["Priest"] = "사제", - ["Rogue"] = "도적", - ["Shaman"] = "주술사", - ["Warlock"] = "흑마법사", - ["Warrior"] = "전사", - ["Healer"] = "힐러", - ["Tank"] = "탱커", - ["Caster"] = "캐스터", - ["Combat"] = "전투", - ["Compilations"] = "복합", - ["Data Export"] = "자료 출력", - ["Development Tools"] = "개발 도구", - ["Guild"] = "길드", - ["Frame Modification"] = "구조 변경", - ["Interface Enhancements"] = "인터페이스 강화", - ["Inventory"] = "인벤토리", - ["Library"] = "라이브러리", - ["Map"] = "지도", - ["Mail"] = "우편", - ["Miscellaneous"] = "기타", - ["Quest"] = "퀘스트", - ["Raid"] = "공격대", - ["Tradeskill"] = "전문기술", - ["UnitFrame"] = "유닛 프레임", - } -elseif GetLocale() == "zhTW" then - CATEGORIES = { - ["Action Bars"] = "動作列", - ["Auction"] = "拍賣", - ["Audio"] = "音效", - ["Battlegrounds/PvP"] = "戰場/PvP", - ["Buffs"] = "增益", - ["Chat/Communication"] = "聊天/通訊", - ["Druid"] = "德魯伊", - ["Hunter"] = "獵人", - ["Mage"] = "法師", - ["Paladin"] = "聖騎士", - ["Priest"] = "牧師", - ["Rogue"] = "盜賊", - ["Shaman"] = "薩滿", - ["Warlock"] = "術士", - ["Warrior"] = "戰士", - ["Healer"] = "治療者", - ["Tank"] = "坦克", - ["Caster"] = "施法者", - ["Combat"] = "戰鬥", - ["Compilations"] = "整合", - ["Data Export"] = "資料匯出", - ["Development Tools"] = "開發工具", - ["Guild"] = "公會", - ["Frame Modification"] = "框架修改", - ["Interface Enhancements"] = "介面增強", - ["Inventory"] = "庫存", - ["Library"] = "程式庫", - ["Map"] = "地圖", - ["Mail"] = "郵件", - ["Miscellaneous"] = "雜項", - ["Quest"] = "任務", - ["Raid"] = "團隊", - ["Tradeskill"] = "交易技能", - ["UnitFrame"] = "頭像框架", - } -elseif GetLocale() == "zhCN" then - CATEGORIES = { - ["Action Bars"] = "动作条", - ["Auction"] = "拍卖", - ["Audio"] = "音频", - ["Battlegrounds/PvP"] = "战场/PvP", - ["Buffs"] = "增益魔法", - ["Chat/Communication"] = "聊天/交流", - ["Druid"] = "德鲁伊", - ["Hunter"] = "猎人", - ["Mage"] = "法师", - ["Paladin"] = "圣骑士", - ["Priest"] = "牧师", - ["Rogue"] = "潜行者", - ["Shaman"] = "萨满祭司", - ["Warlock"] = "术士", - ["Warrior"] = "战士", - ["Healer"] = "治疗", - ["Tank"] = "坦克", - ["Caster"] = "远程输出", - ["Combat"] = "战斗", - ["Compilations"] = "编译", - ["Data Export"] = "数据导出", - ["Development Tools"] = "开发工具", - ["Guild"] = "公会", - ["Frame Modification"] = "框架修改", - ["Interface Enhancements"] = "界面增强", - ["Inventory"] = "背包", - ["Library"] = "库", - ["Map"] = "地图", - ["Mail"] = "邮件", - ["Miscellaneous"] = "杂项", - ["Quest"] = "任务", - ["Raid"] = "团队", - ["Tradeskill"] = "商业技能", - ["UnitFrame"] = "头像框架", - } -elseif GetLocale() == "esES" then - CATEGORIES = { - ["Action Bars"] = "Barras de Acción", - ["Auction"] = "Subasta", - ["Audio"] = "Audio", - ["Battlegrounds/PvP"] = "Campos de Batalla/JcJ", - ["Buffs"] = "Buffs", - ["Chat/Communication"] = "Chat/Comunicación", - ["Druid"] = "Druida", - ["Hunter"] = "Cazador", - ["Mage"] = "Mago", - ["Paladin"] = "Paladín", - ["Priest"] = "Sacerdote", - ["Rogue"] = "Pícaro", - ["Shaman"] = "Chamán", - ["Warlock"] = "Brujo", - ["Warrior"] = "Guerrero", - ["Healer"] = "Sanador", - ["Tank"] = "Tanque", - ["Caster"] = "Conjurador", - ["Combat"] = "Combate", - ["Compilations"] = "Compilaciones", - ["Data Export"] = "Exportar Datos", - ["Development Tools"] = "Herramientas de Desarrollo", - ["Guild"] = "Hermandad", - ["Frame Modification"] = "Modificación de Marcos", - ["Interface Enhancements"] = "Mejoras de la Interfaz", - ["Inventory"] = "Inventario", - ["Library"] = "Biblioteca", - ["Map"] = "Mapa", - ["Mail"] = "Correo", - ["Miscellaneous"] = "Misceláneo", - ["Quest"] = "Misión", - ["Raid"] = "Banda", - ["Tradeskill"] = "Habilidad de Comercio", - ["UnitFrame"] = "Marco de Unidades", - } -else -- enUS - CATEGORIES = { - ["Action Bars"] = "Action Bars", - ["Auction"] = "Auction", - ["Audio"] = "Audio", - ["Battlegrounds/PvP"] = "Battlegrounds/PvP", - ["Buffs"] = "Buffs", - ["Chat/Communication"] = "Chat/Communication", - ["Druid"] = "Druid", - ["Hunter"] = "Hunter", - ["Mage"] = "Mage", - ["Paladin"] = "Paladin", - ["Priest"] = "Priest", - ["Rogue"] = "Rogue", - ["Shaman"] = "Shaman", - ["Warlock"] = "Warlock", - ["Warrior"] = "Warrior", - ["Healer"] = "Healer", - ["Tank"] = "Tank", - ["Caster"] = "Caster", - ["Combat"] = "Combat", - ["Compilations"] = "Compilations", - ["Data Export"] = "Data Export", - ["Development Tools"] = "Development Tools", - ["Guild"] = "Guild", - ["Frame Modification"] = "Frame Modification", - ["Interface Enhancements"] = "Interface Enhancements", - ["Inventory"] = "Inventory", - ["Library"] = "Library", - ["Map"] = "Map", - ["Mail"] = "Mail", - ["Miscellaneous"] = "Miscellaneous", - ["Quest"] = "Quest", - ["Raid"] = "Raid", - ["Tradeskill"] = "Tradeskill", - ["UnitFrame"] = "UnitFrame", - } -end - -local select = _G.select -local tostring = _G.tostring -local pairs = _G.pairs -local ipairs = _G.ipairs -local error = _G.error -local setmetatable = _G.setmetatable -local getmetatable = _G.getmetatable -local type = _G.type -local pcall = _G.pcall -local next = _G.next -local tonumber = _G.tonumber -local strmatch = _G.strmatch -local table_remove = _G.table.remove -local debugstack = _G.debugstack -local LoadAddOn = _G.LoadAddOn -local GetAddOnInfo = _G.GetAddOnInfo -local GetAddOnMetadata = _G.GetAddOnMetadata -local GetNumAddOns = _G.GetNumAddOns -local DisableAddOn = _G.DisableAddOn -local EnableAddOn = _G.EnableAddOn -local IsAddOnLoadOnDemand = _G.IsAddOnLoadOnDemand -local IsLoggedIn = _G.IsLoggedIn -local geterrorhandler = _G.geterrorhandler -local assert = _G.assert -local collectgarbage = _G.collectgarbage -local table_sort = _G.table.sort -local table_concat = _G.table.concat - --- #AUTODOC_NAMESPACE Rock - - -local LibStub = _G.LibStub - -local Rock = LibStub:GetLibrary(MAJOR_VERSION, true) or _G.Rock -local oldRock -if not Rock then - Rock = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION) - if not Rock then - return - end - Rock.name = MAJOR_VERSION -else - Rock, oldRock = Rock:NewLibrary(MAJOR_VERSION, MINOR_VERSION) - if not Rock then - return - end -end -_G.Rock = Rock - -local L = setmetatable({}, {__index=function(self,key) self[key] = key; return key end}) -if GetLocale() == "zhCN" then - L["Advanced options"] = "高级选项" - L["Advanced options for developers and power users."] = "开发者与高级用户的高级选项" - L["Unit tests"] = "框体测试" - L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "开启框体测试,仅供开发者使用。\n\n需要重载用户界面。" - L["Contracts"] = "侦错协定" - L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "启用侦错协定,这是给插件作者用来通报错误所使用。" - L["Reload UI"] = "重载UI" - L["Reload the User Interface for some changes to take effect."] = "部分功能更改需要重载用户界面才会生效。" - L["Reload"] = "重载" - L["Give donation"] = "捐赠" - L["Donate"] = "捐赠" - L["Give a much-needed donation to the author of this addon."] = "给插件作者捐赠支持插件开发。" - L["File issue"] = "通报错误" - L["Report"] = "报告" - L["File a bug or request a new feature or an improvement to this addon."] = "发送错误报告或请求新功能及要改进的部分。" - L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C复制网址,Alt-Tab切换到桌面,打开浏览器,在地址栏贴上网址。" - L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C复制网址,Cmd-Tab切换到电脑桌面,打开浏览器,在地址栏贴上网址。" - L["Enabled"] = "开启" - L["Enable or disable this addon."] = "启用这个插件。" - -elseif GetLocale() == "zhTW" then - L["Advanced options"] = "進階選項" - L["Advanced options for developers and power users."] = "插件作者、進階用戶選項" - L["Unit tests"] = "單元測試" - L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "啟用單元測試,這是給插件作者使用的功能。\n\n需要重載介面才能使用。" - L["Contracts"] = "偵錯協定" - L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "啟用偵錯協定,這是給插件作者用來通報錯誤所使用。" - L["Reload UI"] = "重載介面" - L["Reload the User Interface for some changes to take effect."] = "重新載入使用者介面,部分功能才會生效。" - L["Reload"] = "重載" - L["Give donation"] = "捐贈" - L["Donate"] = "捐贈" - L["Give a much-needed donation to the author of this addon."] = "捐贈金錢給插件作者。" - L["File issue"] = "通報錯誤" - L["Report"] = "報告" - L["File a bug or request a new feature or an improvement to this addon."] = "發出錯誤報告或請求新功能及要改進的部分。" - L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C複製網址,Alt-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。" - L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C複製網址,Cmd-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。" - L["Enabled"] = "啟用" - L["Enable or disable this addon."] = "啟用這個插件。" -elseif GetLocale() == "koKR" then - L["Advanced options"] = "상세 옵션" - L["Advanced options for developers and power users."] = "개발자와 파워 사용자를 위한 상세 옵션입니다." - L["Unit tests"] = "유닛 테스트" - L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "유닛 테스트를 사용합니다. 이것은 개발자만을 위한 옵션입니다.\n\n변경된 결과를 적용하기 위해 당신의 UI를 재실행 합니다." - L["Contracts"] = "계약" - L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "계약을 사용합니다. 이것은 개발자와 버그 파일을 알릴 분이면 누구나 사용 가능합니다. 계약이 가능하지 않으면 버그 파일을 보내지 마십시오. 이것은 당신의 애드온 속도를 약간 떨어뜨립니다." - L["Reload UI"] = "UI 재실행" - L["Reload the User Interface for some changes to take effect."] = "변경된 결과를 적용하기 위해 사용자 인터페이스를 재실행합니다." - L["Reload"] = "재실행" - L["Give donation"] = "기부" - L["Donate"] = "기부" - L["Give a much-needed donation to the author of this addon."] = "이 애드온의 제작자에게 필요한 기부를 합니다." - L["File issue"] = "파일 이슈" - L["Report"] = "보고" - L["File a bug or request a new feature or an improvement to this addon."] = "버그 파일을 알리거나 새로운 기능 또는 이 애드온에 대한 개선을 부탁합니다." - L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C로 복사합니다. Alt-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다." - L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C로 복사합니다. Cmd-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다." - L["Enabled"] = "사용" - L["Enable or disable this addon."] = "이 애드온을 사용하거나 사용하지 않습니다." -elseif GetLocale() == "frFR" then - L["Advanced options"] = "Options avancées" - L["Advanced options for developers and power users."] = "Options avancées à l'attention des développeurs et des utilisateurs expérimentés." - L["Reload UI"] = "Recharger IU" - L["Reload the User Interface for some changes to take effect."] = "Recharge l'interface utilisateur afin que certains changements prennent effet." - L["Reload"] = "Recharger" - L["Give donation"] = "Faire un don" - L["Donate"] = "Don" - L["Give a much-needed donation to the author of this addon."] = "Permet de faire un don bien mérité à l'auteur de cet addon." - L["File issue"] = "Problème" - L["Report"] = "Signaler" - L["File a bug or request a new feature or an improvement to this addon."] = "Permet de signaler un bogue ou de demander une amélioration à cet addon." - L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C pour copier, puis Alt-Tab pour sortir du jeu. Ouvrez votre navigateur internet et collez le lien dans la barre d'adresse." - L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C pour copier, puis Alt-Tab pour sortir du jeu. Ouvrez votre navigateur internet et collez le lien dans la barre d'adresse." - L["Enabled"] = "Activé" - L["Enable or disable this addon."] = "Active ou désactive cet addon." -end - -local isStandalone = debugstack():match("[Oo%.][Nn%.][Ss%.]\\([^\\]+)\\") == MAJOR_VERSION or nil -local unitTestDB, enableContracts - -local weakKey = { __mode = 'k' } - --- frame to manage events from -Rock.frame = oldRock and oldRock.frame or _G.CreateFrame("Frame") -local frame = Rock.frame --- dict of libraries in { ["major"] = object } form -Rock.libraries = oldRock and oldRock.libraries or { [MAJOR_VERSION] = Rock } -local libraries = Rock.libraries --- set of libraries which have gone through the finalization process in { [object] = true } form -Rock.finalizedLibraries = setmetatable(oldRock and oldRock.finalizedLibraries or { }, weakKey) -local finalizedLibraries = Rock.finalizedLibraries --- set of libraries which have been tried to be loaded. -Rock.scannedLibraries = oldRock and oldRock.scannedLibraries or {} -local scannedLibraries = Rock.scannedLibraries --- exportedMethods[library] = { "method1", "method2" } -Rock.exportedMethods = setmetatable(oldRock and oldRock.exportedMethods or {}, weakKey) -local exportedMethods = Rock.exportedMethods --- mixinToObject[mixin][object] = true -Rock.mixinToObject = setmetatable(oldRock and oldRock.mixinToObject or {}, weakKey) -local mixinToObject = Rock.mixinToObject --- dict of addons in { ["name"] = object } form -Rock.addons = oldRock and oldRock.addons or {} -local addons = Rock.addons --- set of libraries that should be finalized before ADDON_LOADED. -Rock.pendingLibraries = setmetatable(oldRock and oldRock.pendingLibraries or { }, weakKey) -local pendingLibraries = Rock.pendingLibraries --- list of addons in order of created that need to be initialized by ADDON_LOADED. -Rock.pendingAddons = oldRock and oldRock.pendingAddons or {} -local pendingAddons = Rock.pendingAddons --- dictionary of addons to their folder names -Rock.addonToFolder = oldRock and oldRock.addonToFolder or {} -local addonToFolder = Rock.addonToFolder --- set of folders which have been loaded -Rock.foldersLoaded = oldRock and oldRock.foldersLoaded or {} -local foldersLoaded = Rock.foldersLoaded --- list of addons in order of created that need to be enabled by PLAYER_LOGIN. -Rock.pendingAddonsEnable = oldRock and oldRock.pendingAddonsEnable or {} -local pendingAddonsEnable = Rock.pendingAddonsEnable --- set of addons which have been enabled at least once. -Rock.addonsAlreadyEnabled = oldRock and oldRock.addonsAlreadyEnabled or {} -local addonsAlreadyEnabled = Rock.addonsAlreadyEnabled --- set of addons which have no database and are set to be inactive. -Rock.inactiveAddons = oldRock and oldRock.inactiveAddons or {} -local inactiveAddons = Rock.inactiveAddons --- set of addons which are currently enabled (not necessarily should be) -Rock.currentlyEnabledAddons = oldRock and oldRock.currentlyEnabledAddons or {} -local currentlyEnabledAddons = Rock.currentlyEnabledAddons --- dictionary of namespace to list of functions which will be run. -Rock.unitTests = oldRock and oldRock.unitTests or {} -local unitTests = Rock.unitTests --- metatable for addons -Rock.addon_mt = oldRock and oldRock.addon_mt or {} -local addon_mt = Rock.addon_mt -for k in pairs(addon_mt) do - addon_mt[k] = nil -end -function addon_mt:__tostring() - return tostring(self.name) -end - -local function better_tostring(self) - if type(self) == "table" and self.name then - return tostring(self.name) - end - return tostring(self) -end - -local function figureCurrentAddon(pos) - local stack = debugstack(pos+1, 1, 0) - local folder = stack:match("[Oo%.][Nn%.][Ss%.]\\([^\\]+)\\") - if folder then - return folder - end - - local partFolder = stack:match("...([^\\]+)\\") - if partFolder then - local partFolder_len = #partFolder - for i = 1, GetNumAddOns() do - local name = GetAddOnInfo(i) - if #name >= partFolder_len then - local partName = name:sub(-partFolder_len) - if partName == partFolder then - return name - end - end - end - end - return nil -end - ---[[--------------------------------------------------------------------------- -Returns: - string - the localized name of the given category. -Arguments: - string - the English name of the category. -Example: - local uf = Rock:GetLocalizedCategory("UnitFrame") ------------------------------------------------------------------------------]] -function Rock:GetLocalizedCategory(name) - if type(name) ~= "string" then - error(("Bad argument #2 to `GetLocalizedCategory'. Expected %q, got %q."):format("string", type(name)), 2) - end - local cat = CATEGORIES[name] - if cat then - return cat - end - local name_lower = name:lower() - for k in pairs(CATEGORIES) do - if k:lower() == name_lower then - return k - end - end - return _G.UNKNOWN or "Unknown" -end - -local weak = {__mode = 'kv'} - -Rock.recycleData = oldRock and oldRock.recycleData or {} -local recycleData = Rock.recycleData -if recycleData.pools then - setmetatable(recycleData.pools, weak) -end -if recycleData.debugPools then - setmetatable(recycleData.debugPools, weak) -end -if recycleData.newList then - setmetatable(recycleData.newList, weak) -end -if recycleData.newDict then - setmetatable(recycleData.newDict, weak) -end -if recycleData.newSet then - setmetatable(recycleData.newSet, weak) -end -if recycleData.del then - setmetatable(recycleData.del, weak) -end - -local tmp = {} -local function myUnpack(t, start) - if not start then - start = 1 - end - local value = t[start] - if value == nil then - return - end - t[start] = nil - return value, myUnpack(t, start+1) -end - ---[[--------------------------------------------------------------------------- -Notes: - * Returns functions for the specified namespace based on what is provided. - * function types: - ; "newList" : to create a list - ; "newDict" : to create a dictionary - ; "newSet" : to create a set - ; "del" : to delete a table - ; "unpackListAndDel" : deletes a table and returns what its contents were as a list, in order. - ; "unpackSetAndDel" : deletes a table and returns what its contents were as a set, in no particular order. - ; "unpackDictAndDel" : deletes a table and returns what its contents were as a dictionary, in no particular order. - * If you provide "Debug" as the last argument, then the namespace can be debugged with ''':DebugRecycle''' - * It is '''not recommended''' to use table recycling with tables that have more than 128 keys, as it is typically faster to let lua's garbage collector handle it. -Arguments: - string - the namespace. ''Note: this doesn't necessarily have to be a string.'' -Example: - local newList, newDict, newSet, del, unpackListAndDel, unpackSetAndDel, unpackDictAndDel = Rock:GetRecyclingFunctions("MyNamespace", "newList", "newDict", "newSet", "del", "unpackListAndDel", "unpackSetAndDel", "unpackDictAndDel") - - local t = newList('alpha', 'bravo') -- same as t = {'alpha', 'bravo'} - local u = newDict('alpha', 'bravo') -- same as t = {['alpha'] = 'bravo'} - local v = newSet('alpha', 'bravo') -- same as t = {['alpha'] = true, ['bravo'] = true} - t = del(t) -- you want to clear your reference as well as deleting. - u = del(u) - v = del(v) - - -- for debugging - local newList = Rock:GetRecyclingFunctions("MyNamespace", "newList", "Debug") - local t = newList() - Rock:DebugRecycle("MyNamespace") - t = del(t) - - -- unpacking functions - unpackListAndDel(newList(...)) => ... - unpackSetAndDel(newSet(...)) => ... - unpackDictAndDel(newDict(...)) => ... - newList(unpackListAndDel(t)) => t - newSet(unpackSetAndDel(t)) => t - newDict(unpackDictAndDel(t)) => t - -- as you can see, they are inverses of each other. ------------------------------------------------------------------------------]] -function Rock:GetRecyclingFunctions(namespace, ...) - local pools = recycleData.pools - if not pools then - pools = setmetatable({}, weak) - recycleData.pools = pools - end - if namespace == "newList" or namespace == "newSet" or namespace == "newDict" or namespace == "del" or namespace == "unpackListAndDel" or namespace == "unpackSetAndDel" or namespace == "unpackDictAndDel" then - error(("Bad argument #2 to `GetRecyclingFunctions'. Cannot be %q"):format(namespace), 2) - end - local pool = pools[namespace] - if not pool then - pool = setmetatable({}, weak) - pools[namespace] = pool - end - local n = select('#', ...) - local debug = select(n, ...) == "Debug" - if debug then - n = n - 1 - local debugPools = recycleData.debugPools - if not debugPools then - debugPools = setmetatable({}, weak) - recycleData.debugPools = debugPools - end - debug = debugPools[namespace] - if not debug then - debug = { num = 0 } - debugPools[namespace] = debug - end - elseif recycleData.debugPools and recycleData.debugPools[namespace] then - debug = recycleData.debugPools[namespace] - end - for i = 1, n do - local func = select(i, ...) - local recycleData_func = recycleData[func] - if not recycleData_func then - recycleData_func = setmetatable({}, weak) - recycleData[func] = recycleData_func - end - if func == "newList" then - local newList = recycleData_func[namespace] - if not newList then - function newList(...) - local t = next(pool) - local n = select('#', ...) - if t then - pool[t] = nil - for i = 1, n do - t[i] = select(i, ...) - end - else - t = { ... } - end - - if debug then - debug[t] = debugstack(2) - debug.num = debug.num + 1 - end - - return t, n - end - recycleData_func[namespace] = newList - end - tmp[i] = newList - elseif func == "newDict" then - local newDict = recycleData_func[namespace] - if not newDict then - function newDict(...) - local t = next(pool) - if t then - pool[t] = nil - else - t = {} - end - - for i = 1, select('#', ...), 2 do - t[select(i, ...)] = select(i+1, ...) - end - - if debug then - debug[t] = debugstack(2) - debug.num = debug.num + 1 - end - - return t - end - recycleData_func[namespace] = newDict - end - tmp[i] = newDict - elseif func == "newSet" then - local newSet = recycleData_func[namespace] - if not newSet then - function newSet(...) - local t = next(pool) - if t then - pool[t] = nil - else - t = {} - end - - for i = 1, select('#', ...) do - t[select(i, ...)] = true - end - - if debug then - debug[t] = debugstack(2) - debug.num = debug.num + 1 - end - - return t - end - recycleData_func[namespace] = newSet - end - tmp[i] = newSet - elseif func == "del" then - local del = recycleData_func[namespace] - if not del then - function del(t) - if not t then - error(("Bad argument #1 to `del'. Expected %q, got %q."):format("table", type(t)), 2) - end - if pool[t] then - local _, ret = pcall(error, "Error, double-free syndrome.", 3) - geterrorhandler()(ret) - end - setmetatable(t, nil) - for k in pairs(t) do - t[k] = nil - end - t[true] = true - t[true] = nil - pool[t] = true - - if debug then - debug[t] = nil - debug.num = debug.num - 1 - end - return nil - end - recycleData_func[namespace] = del - end - tmp[i] = del - elseif func == "unpackListAndDel" then - local unpackListAndDel = recycleData_func[namespace] - if not unpackListAndDel then - local function f(t, start, finish) - if start > finish then - for k in pairs(t) do - t[k] = nil - end - t[true] = true - t[true] = nil - pool[t] = true - return - end - return t[start], f(t, start+1, finish) - end - function unpackListAndDel(t, start, finish) - if not t then - error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2) - end - if not start then - start = 1 - end - if not finish then - finish = #t - end - setmetatable(t, nil) - if debug then - debug[t] = nil - debug.num = debug.num - 1 - end - return f(t, start, finish) - end - end - tmp[i] = unpackListAndDel - elseif func == "unpackSetAndDel" then - local unpackSetAndDel = recycleData_func[namespace] - if not unpackSetAndDel then - local function f(t, current) - current = next(t, current) - if current == nil then - for k in pairs(t) do - t[k] = nil - end - t[true] = true - t[true] = nil - pool[t] = true - return - end - return current, f(t, current) - end - function unpackSetAndDel(t) - if not t then - error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2) - end - setmetatable(t, nil) - if debug then - debug[t] = nil - debug.num = debug.num - 1 - end - return f(t, nil) - end - end - tmp[i] = unpackSetAndDel - elseif func == "unpackDictAndDel" then - local unpackDictAndDel = recycleData_func[namespace] - if not unpackDictAndDel then - local function f(t, current) - local value - current, value = next(t, current) - if current == nil then - for k in pairs(t) do - t[k] = nil - end - t[true] = true - t[true] = nil - pool[t] = true - return - end - return current, value, f(t, current) - end - function unpackDictAndDel(t) - if not t then - error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2) - end - setmetatable(t, nil) - if debug then - debug[t] = nil - debug.num = debug.num - 1 - end - return f(t, nil) - end - end - tmp[i] = unpackDictAndDel - else - error(("Bad argument #%d to `GetRecyclingFunctions': %q, %q, %q, %q, %q, %q, or %q expected, got %s"):format(i+2, "newList", "newDict", "newSet", "del", "unpackListAndDel", "unpackSetAndDel", "unpackDictAndDel", type(func) == "string" and ("%q"):format(func) or tostring(func)), 2) - end - end - return myUnpack(tmp) -end - ---[[--------------------------------------------------------------------------- -Notes: - * Prints information about the specified recycling namespace, including what tables are still in play and where they come from and how many there are. - * This goes in tandem with ''':GetRecyclingFunctions''' -Arguments: - string - the namespace. ''Note: this doesn't necessarily have to be a string.'' -Example: - local newList = Rock:GetRecyclingFunctions("MyNamespace", "newList", "Debug") - local t = newList() - Rock:DebugRecycle("MyNamespace") - t = del(t) ------------------------------------------------------------------------------]] -function Rock:DebugRecycle(namespace) - local debug = recycleData.debugPools and recycleData.debugPools[namespace] - if not debug then - return - end - for k, v in pairs(debug) do - if k ~= "num" then - _G.DEFAULT_CHAT_FRAME:AddMessage(v) - _G.DEFAULT_CHAT_FRAME:AddMessage("------") - end - end - _G.DEFAULT_CHAT_FRAME:AddMessage(("%s: %d tables in action."):format(tostring(namespace), debug.num)) -end - -local newList, del, unpackListAndDel, unpackDictAndDel = Rock:GetRecyclingFunctions(MAJOR_VERSION, "newList", "del", "unpackListAndDel", "unpackDictAndDel") - ---[[--------------------------------------------------------------------------- -Notes: - * Adds a unit test for the specified namespace - * The function provided is called, and it should be where tests are performed, if a problem occurs, an error should fire. If no problems occur, it should return silently. - * You can have as many tests per namespace as you want. -Arguments: - string - the namespace. - function - the function to call. -Example: - Rock:AddUnitTest("LibMonkey-1.0", function() - local LibMonkey = Rock("LibMonkey-1.0") - assert(LibMonkey:Fling() == "Poo") - end) ------------------------------------------------------------------------------]] -function Rock:AddUnitTest(namespace, func) - if not isStandalone then - return - end - if type(namespace) ~= "string" then - error(("Bad argument #2 to `AddUnitTest'. Expected %q, got %q."):format("string", type(namespace)), 2) - end - if namespace:find("^Lib[A-Z]") then - local addon = figureCurrentAddon(2) - if addon ~= namespace then - return - end - end - if type(func) ~= "function" then - error(("Bad argument #3 to `AddUnitTest'. Expected %q, got %q."):format("function", type(func)), 2) - end - local addon = figureCurrentAddon(2) - if libraries[namespace] and addon ~= namespace then - -- only work on standalone libraries. - return - end - local unitTests_namespace = unitTests[namespace] - if not unitTests_namespace then - unitTests_namespace = newList() - unitTests[namespace] = unitTests_namespace - end - if not unitTests_namespace.addon then - unitTests_namespace.addon = addon - end - if unitTestDB and not unitTestDB[namespace] then - return - end - unitTests_namespace[#unitTests_namespace+1] = func -end - -local LibRockEvent -local LibRockModuleCore -local OpenDonationFrame, OpenIssueFrame -function Rock:OnLibraryLoad(major, library) - if major == "LibRockEvent-1.0" then - LibRockEvent = library - LibRockEvent:Embed(Rock) - elseif major == "LibRockModuleCore-1.0" then - LibRockModuleCore = library - elseif major == "LibRockConfig-1.0" then - if isStandalone then - library.rockOptions.args.advanced = { - type = 'group', - groupType = 'inline', - name = L["Advanced options"], - desc = L["Advanced options for developers and power users."], - order = -1, - args = { - unitTests = { - type = 'multichoice', - name = L["Unit tests"], - desc = L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."], - get = function(key) - return unitTestDB[key] - end, - set = function(key, value) - unitTestDB[key] = value or nil - end, - choices = function() - local t = newList() - for k in pairs(unitTests) do - t[k] = k - end - return "@dict", unpackDictAndDel(t) - end - }, - contracts = { - type = 'boolean', - name = L["Contracts"], - desc = L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."], - get = function() - return enableContracts - end, - set = function(value) - _G.LibRock_1_0DB.contracts = value or nil - enableContracts = value - end, - } - } - } - end - library.rockOptions.args.reloadui = { - type = 'execute', - name = L["Reload UI"], - desc = L["Reload the User Interface for some changes to take effect."], - buttonText = L["Reload"], - func = function() - _G.ReloadUI() - end, - order = -2, - } - Rock.donate = "Paypal:ckknight AT gmail DOT com" - library.rockOptions.args.donate = { - type = 'execute', - name = L["Give donation"], - buttonText = L["Donate"], - desc = L["Give a much-needed donation to the author of this addon."], - func = OpenDonationFrame, - passValue = Rock, - order = -3, - } - Rock.issueTracker = "Wowace:10027" - library.rockOptions.args.issue = { - type = 'execute', - name = L["File issue"], - buttonText = L["Report"], - desc = L["File a bug or request a new feature or an improvement to this addon."], - func = OpenIssueFrame, - passValue = Rock, - order = -4, - } - end -end - -addon_mt.__index = {} -local addon_mt___index = addon_mt.__index ---[[--------------------------------------------------------------------------- -#FORCE_DOC -Notes: - * This is exported to all addons. - * This information is retrieved from LibRockModuleCore-1.0 if it is a module, otherwise from LibRockDB-1.0 if it uses that as a mixin, otherwise it keeps a variable locally. -Returns: - boolean - whether the addon is in an active state or not. -Example: - local active = MyAddon:IsActive() ------------------------------------------------------------------------------]] -function addon_mt___index:IsActive() - if LibRockModuleCore then - local core = LibRockModuleCore:HasModule(self) - if core then - return core:IsModuleActive(self) - end - end - - local self_db = self.db - if self_db then - local disabled - local self_db_raw = self_db.raw - if self_db_raw then - local self_db_raw_disabled = self_db_raw.disabled - if self_db_raw_disabled then - local profile = type(self.GetProfile) == "function" and select(2, self:GetProfile()) or false - disabled = self_db_raw_disabled[profile] - end - else - return false - end - return not disabled - end - - return not inactiveAddons[self] -end ---[[--------------------------------------------------------------------------- -#FORCE_DOC -Notes: - * This is exported to all addons. - * If it enables the addon, it will call :OnEnable(first) on the addon and :OnEmbedEnable(addon, first) on all its mixins. - * If it disables the addon, it will call :OnDisable(first) on the addon and :OnEmbedDisable(addon, first) on all its mixins. - * This information is stored by LibRockModuleCore-1.0 if it is a module, otherwise from LibRockDB-1.0 if it uses that as a mixin, otherwise it keeps a variable locally. -Arguments: - [optional] boolean - whether the addon should be in an active state or not. Default: not :IsActive() -Returns: - boolean - whether the addon is in an active state or not. -Example: - MyAddon:ToggleActive() -- switch - MyAddon:ToggleActive(true) -- force on - MyAddon:ToggleActive(false) -- force off ------------------------------------------------------------------------------]] -function addon_mt___index:ToggleActive(state) - if state and state ~= true then - error(("Bad argument #2 to `ToggleActive'. Expected %q or %q, got %q."):format("boolean", "nil", type(state)), 2) - end - if LibRockModuleCore then - local core = LibRockModuleCore:HasModule(self) - if core then - return core:ToggleModuleActive(self, state) - end - end - - local self_db = self.db - if self_db then - local self_db_raw = self_db.raw - if not self_db_raw then - error("Error saving to database with `ToggleActive'. db.raw not available.", 2) - end - local self_db_raw_disabled = self_db_raw.disabled - if not self_db_raw_disabled then - self_db_raw_disabled = newList() - self_db_raw.disabled = self_db_raw_disabled - end - local profile = type(self.GetProfile) == "function" and select(2, self:GetProfile()) or false - if state == nil then - state = not not self_db_raw_disabled[profile] - elseif (not self_db_raw_disabled[profile]) == state then - return - end - self_db_raw_disabled[profile] = not state or nil - if next(self_db_raw_disabled) == nil then - self_db_raw.disabled = del(self_db_raw_disabled) - end - else - if state == nil then - state = not not inactiveAddons[self] - elseif (not inactiveAddons[self]) == state then - return - end - inactiveAddons[self] = not state or nil - end - - Rock:RecheckEnabledStates() - - return state -end - -local function noop() end - -do - local preconditions = setmetatable({}, weakKey) - local postconditions = setmetatable({}, weakKey) - local postconditionsOld = setmetatable({}, weakKey) - - local currentMethod = nil - - local function hook(object, method) - local object_method = object[method] - object[method] = function(...) - local pre = preconditions[object_method] - local post = postconditions[object_method] - if pre then - local old_currentMethod = currentMethod - currentMethod = method - pre(...) - currentMethod = old_currentMethod - end - if not post then - return object_method(...) - end - local oldFunc = postconditionsOld[object_method] - local old - if oldFunc then - old = newList() - oldFunc(old, ...) - end - - local old_currentMethod = currentMethod - currentMethod = nil - local ret, n = newList(object_method(...)) - - currentMethod = method - if old then - post(old, ret, ...) - old = del(old) - else - post(ret, ...) - end - currentMethod = old_currentMethod - return unpackListAndDel(ret, 1, n) - end - end - - local function precondition(object, method, func) - if type(object) ~= "table" then - error(("Bad argument #1 to `precondition'. Expected %q, got %q."):format("table", type(object)), 2) - end - if type(object[method]) ~= "function" then - error(("Method %q not found on object %s. Expected %q, got %q."):format(tostring(method), tostring(object), "function", type(object[method])), 2) - end - if type(func) ~= "function" then - error(("Bad argument #3 to `precondition'. Expected %q, got %q."):format("function", type(func)), 2) - end - - local object_method = object[method] - if preconditions[object_method] then - error("Cannot call `preconditon' on the same method twice.", 2) - end - preconditions[object_method] = func - - if not postconditions[object_method] then - hook(object, method) - end - end - - local function postcondition(object, method, func, fillOld) - if type(object) ~= "table" then - error(("Bad argument #1 to `postcondition'. Expected %q, got %q."):format("table", type(object)), 2) - end - if type(object[method]) ~= "function" then - error(("Method %q not found on object %s. Expected %q, got %q."):format(tostring(method), tostring(object), "function", type(object[method])), 2) - end - if type(func) ~= "function" then - error(("Bad argument #3 to `postcondition'. Expected %q, got %q."):format("function", type(func)), 2) - end - if fillOld and type(fillOld) ~= "function" then - error(("Bad argument #4 to `postcondition'. Expected %q or %q, got %q."):format("function", "nil", type(func)), 2) - end - - local object_method = object[method] - if postconditions[object_method] then - error("Cannot call `postcondition' on the same method twice.", 2) - end - postconditions[object_method] = func - postconditionsOld[object_method] = fillOld - - if not preconditions[object_method] then - hook(object, method) - end - end - - local function argCheck(value, position, ...) - if not currentMethod then - error("Cannot call `argCheck' outside of a pre/post-condition.", 2) - end - if type(position) ~= "number" then - error(("Bad argument #2 to `argCheck'. Expected %q, got %q"):format("number", type(position)), 2) - end - local type_value = type(value) - for i = 1, select('#', ...) do - local v = select(i, ...) - if type(v) ~= "string" then - error(("Bad argument #%d to `argCheck'. Expected %q, got %q"):format(i+1, "string", type(v)), 2) - end - if v == type_value then - return - end - end - local t = newList(...) - t[#t] = nil - for i,v in ipairs(t) do - t[i] = ("%q"):format(v) - end - local s - if #t == 0 then - s = ("%q"):format((...)) - elseif #t == 1 then - s = ("%q or %q"):format(...) - else - s = table_concat(t, ", ") .. ", or " .. ("%q"):format(select(#t+1, ...)) - end - t = del(t) - - error(("Bad argument #%d to `%s'. Expected %s, got %q."):format(position, tostring(currentMethod), s, type_value), 4) - end - - --[[--------------------------------------------------------------------------- - Notes: - * Returns functions for the specified namespace based on what is provided. - * function types: - ; "precondition" : to set the pre-condition for a method. - ; "postcondition" : to set the post-condition for a method. - ; "argCheck" : to check the type of an argument, to be executed within a pre-condition. - * preconditon is in the form of <tt>precondition(object, "methodName", func(self, ...))</tt> - * postcondition is in the form of either <tt>postcondition(object, "methodName", func(returnValues, self, ...))</tt> or <tt>postcondition(object, "methodName", func(oldValues, returnValues, self, ...), populateOld(oldValues, self, ...))</tt> - ** returnValues is the list of return values, empty if no return values were sent. - ** if the populateOld function is provided, then the empty oldValues table is provided and expected to be filled, and then given to the func. - * argCheck is in the form of <tt>argCheck(value, n, "type1" [, "type2", ...])</tt> - ** value is the value provided to the function you're checking. - ** n is the argument position. ''Note: 1 is the position of `self'. 2 would be the first "real" position.'' - ** the tuple of types can be any string, but specifically "nil", "boolean", "string", "number", "function", "userdata", "table", etc. - Arguments: - string - the namespace. ''Note: this doesn't necessarily have to be a string.'' - Example: - local precondition, postcondition, argCheck = Rock:GetRecyclingFunctions("Stack", "precondition", "postcondition", "argCheck") - - local stack = {} - stack.IsEmpty = function(self) - return self[1] == nil - end - stack.GetLength = function(self) - return #self - end - stack.Push = function(self, value) - self[#self+1] = value - end - precondition(stack, "Push", function(self, value) - argCheck(value, 2, "string") -- only accept strings, no other values - end) - postcondition(stack, "Push", function(old, ret, self, value) - assert(self:GetLength() == old.length+1) - assert(not self:IsEmpty()) - end, function(old, self) - old.length = self:GetLength() - end) - stack.Pop = function(self) - local value = self[#self] - self[#self] = nil - return value - end - precondition(stack, "Pop", function(self) - assert(self:GetLength() >= 1) - end) - postcondition(stack, "Pop", function(old, ret, self) - assert(self:GetLength() == old.length-1) - end, function(old, self) - old.length = self:GetLength() - end) - stack.Peek = function(self) - return self[#self] - end - precondition(stack, "Peek", function(self) - assert(self:GetLength() >= 1) - end) - postcondition(stack, "Peek", function(old, ret, self) - assert(self:GetLength() == old.length) - end, function(old, self) - old.length = self:GetLength() - end) - - local t = setmetatable({}, {__index=stack}) - t:Push("Alpha") - t:Push("Bravo") - t:Push(5) -- error, only strings - assert(t:Pop() == "Bravo") - assert(t:Pop() == "Alpha") - t:Pop() -- error, out of values - -----------------------------------------------------------------------------]] - function Rock:GetContractFunctions(namespace, ...) - if namespace == "precondition" or namespace == "postcondition" or namespace == "argCheck" then - error(("Bad argument #2 to `GetContractFunctions'. Cannot be %q."):format(namespace), 2) - end - local t = newList() - if enableContracts then - for i = 1, select('#', ...) do - local v = select(i, ...) - if v == "precondition" then - t[i] = precondition - elseif v == "postcondition" then - t[i] = postcondition - elseif v == "argCheck" then - t[i] = argCheck - else - error(("Bad argument #%d to `GetContractFunctions'. Expected %q, %q, or %q, got %q."):format(i+2, "precondition", "postcondition", "argCheck", tostring(v))) - end - end - else - for i = 1, select('#', ...) do - t[i] = noop - end - end - return unpackListAndDel(t) - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * convert a revision string to a number -Arguments: - string - revision string -Returns: - string or number - the string given or the number retrieved from it. ------------------------------------------------------------------------------]] -local function coerceRevisionToNumber(version) - if type(version) == "string" then - return tonumber(version:match("(%-?%d+)")) or version - else - return version - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * try to enable the standalone library specified -Arguments: - string - name of the library. -Returns: - boolean - whether the library is properly enabled and loadable. ------------------------------------------------------------------------------]] -local function TryToEnable(addon) - local islod = IsAddOnLoadOnDemand(addon) - if islod then - local _, _, _, enabled = GetAddOnInfo(addon) - EnableAddOn(addon) - local _, _, _, _, loadable = GetAddOnInfo(addon) - if not loadable and not enabled then - DisableAddOn(addon) - end - - return loadable - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * try to load the standalone library specified -Arguments: - string - name of the library. -Returns: - boolean - whether the library is loaded. ------------------------------------------------------------------------------]] -local function TryToLoadStandalone(major) - major = major:lower() - if scannedLibraries[major] then - return - end - scannedLibraries[major] = true - local name, _, _, enabled, loadable, state = GetAddOnInfo(major) - if state == "MISSING" or not IsAddOnLoadOnDemand(major) then - -- backwards compatibility for X-AceLibrary - local field = "X-AceLibrary-" .. major - local loaded - for i = 1, GetNumAddOns() do - if GetAddOnMetadata(i, field) then - name, _, _, enabled, loadable = GetAddOnInfo(i) - - loadable = (enabled and loadable) or TryToEnable(name) - if loadable then - loaded = true - LoadAddOn(name) - end - end - end - - return loaded - elseif (enabled and loadable) or TryToEnable(major) then - LoadAddOn(major) - return true - else - return false - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * Return the LibStub library, casing is unimportant. -Arguments: - string - name of the library. -Returns: - table or nil - library - number - minor version ------------------------------------------------------------------------------]] -local function GetLibStubLibrary(major) - local lib, minor = LibStub:GetLibrary(major, true) - if lib then - return lib, minor - end - major = major:lower() - for m, lib in LibStub:IterateLibraries() do - if m:lower() == major then - return LibStub:GetLibrary(m) - end - end - return nil, nil -end - -local finishLibraryRegistration ---[[--------------------------------------------------------------------------- -Notes: - * create a new library if the version provided is not out of date. -Arguments: - string - name of the library. - number - version of the library. -Returns: - library, oldLibrary - * table or nil - the library with which to manipulate - * table or nil - the old version of the library to upgrade from -Example: - local LibMonkey, oldLib = Rock:NewLibrary("LibMonkey-1.0", 50) - if not LibMonkey then - -- opt out now, out of date - return - end ------------------------------------------------------------------------------]] -function Rock:NewLibrary(major, version) - if type(major) ~= "string" then - error(("Bad argument #2 to `NewLibrary'. Expected %q, got %q."):format("string", type(major)), 2) - end - if not major:match("^Lib[A-Z][A-Za-z%d%-]*%-%d+%.%d+$") then - error(("Bad argument #2 to `NewLibrary'. Must match %q, got %q."):format("^Lib[A-Z][A-Za-z%d%-]*%-%d+%.%d+$", major), 2) - end - TryToLoadStandalone(major) - version = coerceRevisionToNumber(version) - if type(version) ~= "number" then - error(("Bad argument #3 to `NewLibrary'. Expected %q, got %q."):format("number", type(version)), 2) - end - local library, oldMinor = LibStub:GetLibrary(major, true) - if oldMinor and oldMinor >= version then - -- in case LibStub is acting funny - return nil, nil - end - local library, oldMinor = LibStub:NewLibrary(major, version) - if not library then - return nil, nil - end - local unitTests_major = unitTests[major] - if unitTests_major then - for k,v in pairs(unitTests_major) do - unitTests_major[k] = nil - end - end - for k, v in pairs(recycleData) do - v[major] = nil - end - local mixinToObject_library = mixinToObject[library] - - local oldLib - if oldMinor then - -- previous version exists - local mixins = newList() - for mixin, objectSet in pairs(mixinToObject) do - if objectSet[library] then - mixins[mixin] = true - end - end - for mixin in pairs(mixins) do - mixin:Unembed(library) - end - mixins = del(mixins) - oldLib = newList() - for k, v in pairs(library) do - oldLib[k] = v - library[k] = nil - end - setmetatable(oldLib, getmetatable(library)) - setmetatable(library, nil) - end - finishLibraryRegistration(major, version, library, figureCurrentAddon(2)) - - return library, oldLib -end -function finishLibraryRegistration(major, version, library, folder) - library.name = major - - libraries[major] = library - pendingLibraries[library] = folder - local exportedMethods_library = exportedMethods[library] - if exportedMethods_library then - local mixinToObject_library = mixinToObject[library] - if mixinToObject_library then - for object in pairs(mixinToObject_library) do - for _,v in ipairs(exportedMethods_library) do - object[v] = nil - end - end - end - exportedMethods[library] = del(exportedMethods_library) - end - if library ~= Rock then - Rock:Embed(library) - end - - frame:Show() -end -if not oldRock then - finishLibraryRegistration(MAJOR_VERSION, MINOR_VERSION, Rock, figureCurrentAddon(1)) -end - --- #NODOC -local function __removeLibrary(libName) - libraries[libName] = nil - if LibStub.libs then - LibStub.libs[libName] = nil - end - if LibStub.minors then - LibStub.minors[libName] = nil - end - local lastCount - repeat - lastCount = collectgarbage('count') - collectgarbage('collect') - until lastCount == collectgarbage('count') -end -local function run(_,a) - if a < 1/30 then - collectgarbage('step') - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * properly finalizes the library, essentially stating that it has loaded properly. - * This will call :OnLibraryLoad("major", library) on every other library - * This will also call :OnLibraryLoad("major", library) on the library provided, using every other library as the arguments. - * An error will occur if this is not done before ADDON_LOADED. -Arguments: - string - name of the library. -Example: - local LibMonkey, oldLib = Rock:NewLibrary("LibMonkey-1.0", 50) - if not LibMonkey then - -- opt out now, out of date - return - end - Rock:FinalizeLibrary("LibMonkey-1.0") ------------------------------------------------------------------------------]] -function Rock:FinalizeLibrary(major) - if type(major) ~= "string" then - error(("Bad argument #2 to `FinalizeLibrary'. Expected %q, got %q."):format("string", type(major)), 2) - end - local library = libraries[major] - if not library then - error(("Bad argument #2 to `FinalizeLibrary'. %q is not a library."):format("string", major), 2) - end - pendingLibraries[library] = nil - local library_OnLibraryLoad = library.OnLibraryLoad - if library_OnLibraryLoad then - for maj, lib in LibStub:IterateLibraries() do -- for all libraries - if maj ~= major then - local success, ret = pcall(library_OnLibraryLoad, library, maj, lib) - if not success then - geterrorhandler()(ret) - break - end - end - end - end - if finalizedLibraries[library] then - return - end - finalizedLibraries[library] = true - for maj, lib in pairs(libraries) do -- just Rock libraries - if maj ~= major then - local lib_OnLibraryLoad = lib.OnLibraryLoad - if lib_OnLibraryLoad then - local success, ret = pcall(lib_OnLibraryLoad, lib, major, library) - if not success then - geterrorhandler()(ret) - end - end - end - end - if LibRockEvent then - self:DispatchEvent("LibraryLoad", major, library) - end -end - -local function manualFinalize(major, library) - if libraries[major] then -- non-Rock libraries only - return - end - if finalizedLibraries[library] then -- don't do it twice - return - end - finalizedLibraries[library] = true - for maj, lib in pairs(libraries) do -- just Rock libraries - if maj ~= major then - local lib_OnLibraryLoad = lib.OnLibraryLoad - if lib_OnLibraryLoad then - local success, ret = pcall(lib_OnLibraryLoad, lib, major, library) - if not success then - geterrorhandler()(ret) - end - end - end - end - if LibRockEvent then - Rock:DispatchEvent("LibraryLoad", major, library) - end -end - ---[[--------------------------------------------------------------------------- -Arguments: - string - name of the library. - [optional] boolean - whether to not load a library if it is not found. Default: false - [optional] boolean - whether to not error if a library is not found. Default: false -Returns: - library - * table or nil - the library requested -Example: - local LibMonkey = Rock:GetLibrary("LibMonkey-1.0") - -- or - local LibMonkey = Rock("LibMonkey-1.0") ------------------------------------------------------------------------------]] -function Rock:GetLibrary(major, dontLoad, dontError) - if type(major) ~= "string" then - error(("Bad argument #2 to `GetLibrary'. Expected %q, got %q."):format("string", type(major)), 2) - end - if dontLoad and dontLoad ~= true then - error(("Bad argument #3 to `GetLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontLoad)), 2) - end - if dontError and dontError ~= true then - error(("Bad argument #4 to `GetLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontError)), 2) - end - if not dontLoad then - TryToLoadStandalone(major) - end - - local library = GetLibStubLibrary(major) - if not library then - if dontError then - return nil - end - error(("Library %q not found."):format(major), 2) - end - - return library -end - -setmetatable(Rock, { __call = Rock.GetLibrary }) - ---[[--------------------------------------------------------------------------- -Arguments: - string - name of the library. -Returns: - boolean - whether the library exists and is a proper mixin which can be embedded. -Example: - local isMixin = Rock:IsLibraryMixin("LibMonkey-1.0") ------------------------------------------------------------------------------]] -function Rock:IsLibraryMixin(name) - local library = self:GetLibrary(name, false, true) - if not library then - return false - end - return not not exportedMethods[library] -end - ---[[--------------------------------------------------------------------------- -Arguments: - string - name of the library. - [optional] boolean - whether to not load a library if it is not found. Default: false -Returns: - library - * table or nil - the library requested -Example: - local hasLibMonkey = Rock:HasLibrary("LibMonkey-1.0") ------------------------------------------------------------------------------]] -function Rock:HasLibrary(major, dontLoad) - if type(major) ~= "string" then - error(("Bad argument #2 to `HasLibrary'. Expected %q, got %q."):format("string", type(major)), 2) - end - if dontLoad and dontLoad ~= true then - error(("Bad argument #3 to `HasLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontLoad)), 2) - end - if not dontLoad then - TryToLoadStandalone(major) - end - return not not GetLibStubLibrary(major) -end - ---[[--------------------------------------------------------------------------- -Notes: - * This is exported to all libraries -Returns: - major, minor - * string - name of the library - * number - version of the library -Example: - local major, minor = Rock:GetLibraryVersion() -- will be "LibRock-1.0", 12345 - local major, minor = LibMonkey:GetLibraryVersion() -- will be "LibMonkey-1.0", 50 ------------------------------------------------------------------------------]] -function Rock:GetLibraryVersion() - if type(self) ~= "table" then - return nil, nil - end - local major - local name = self.name - if name and GetLibStubLibrary(name) == self then - major = name - else - for m, instance in LibStub:IterateLibraries() do - if instance == self then - major = m - break - end - end - if not major then - return nil, nil - end - end - local _, minor = GetLibStubLibrary(major) - return major, minor -end - ---[[--------------------------------------------------------------------------- -Returns: - an iterator to traverse all registered libraries. -Example: - for major, library in Rock:IterateLibraries() do - -- do something with major and library - end ------------------------------------------------------------------------------]] -function Rock:IterateLibraries() - return LibStub:IterateLibraries() -end - ---[[--------------------------------------------------------------------------- -Notes: - * This is exported to all libraries - * Allows you to set precisely what methods for the library to export. - * This automatically turns a library into a mixin. -Arguments: - tuple - the list of method names to export. -Example: - local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50) - LibMonkey.FlingPoo = function(self) - return "Splat!" - end - LibMonkey:SetExportedMethods("FlingPoo") - -- later - local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0") - assert(Darwin:FlingPoo() == "Splat!") ------------------------------------------------------------------------------]] -function Rock:SetExportedMethods(...) - if exportedMethods[self] then - error("Cannot call `SetExportedMethods' more than once.", 2) - end - local t = newList(...) - if #t == 0 then - error("Must supply at least 1 method to `SetExportedMethods'.", 2) - end - for i,v in ipairs(t) do - if type(self[v]) ~= "function" then - error(("Bad argument #%d to `SetExportedMethods'. Method %q does not exist."):format(i+1, tostring(v)), 2) - end - end - exportedMethods[self] = t - - local mixinToObject_library = mixinToObject[self] - if mixinToObject_library then - for object in pairs(mixinToObject_library) do - for _,method in ipairs(t) do - object[method] = self[method] - end - end - end -end - ---[[--------------------------------------------------------------------------- -Notes: - * This is exported to all libraries - * Embeds all the methods previously set to export onto a table. - * This will call :OnEmbed(object) on the library if it is available. -Arguments: - table - the table with which to export methods onto. -Returns: - The table provided, after embedding. -Example: - local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50) - LibMonkey.FlingPoo = function(self) - return "Splat!" - end - LibMonkey:SetExportedMethods("FlingPoo") - -- later - local Darwin = {} - Rock("LibMonkey-1.0"):Embed(Darwin) - assert(Darwin:FlingPoo() == "Splat!") ------------------------------------------------------------------------------]] -function Rock:Embed(object) - if not exportedMethods[self] then - error(("Cannot call `Embed' for library %q if `SetExportedMethods' has not been called."):format(tostring(self.name)), 2) - end - if type(object) ~= "table" then - error(("Bad argument #2 to `Embed'. Expected %q, got %q."):format("table", type(object)), 2) - end - - for i,v in ipairs(exportedMethods[self]) do - if type(self[v]) ~= "function" then - error(("Problem embedding method %q from library %q. Expected %q, got %q."):format(tostring(v), better_tostring(self), "function", type(self[v]))) - end - object[v] = self[v] - end - - if not mixinToObject[self] then - -- weak because objects come and go - mixinToObject[self] = setmetatable(newList(), weakKey) - end - if mixinToObject[self][object] then - error(("Cannot embed library %q into the same object %q more than once."):format(better_tostring(self), better_tostring(object)), 2) - end - mixinToObject[self][object] = true - if type(rawget(object, 'mixins')) == "table" then - object.mixins[self] = true - end - - local self_OnEmbed = self.OnEmbed - if self_OnEmbed then - local success, ret = pcall(self_OnEmbed, self, object) - if not success then - geterrorhandler()(ret) - end - end - - return object -end - ---[[--------------------------------------------------------------------------- -Notes: - * This is exported to all libraries - * Unembeds all the methods previously set to export onto a table. - * This will error if the library is not embedded on the object - * This will call :OnUnembed(object) on the library if it is available. -Arguments: - table - the table with which to export methods onto. -Returns: - The table provided, after embedding. -Example: - local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50) - LibMonkey.FlingPoo = function(self) - return "Splat!" - end - LibMonkey:SetExportedMethods("FlingPoo") - -- later - local Darwin = {} - Rock("LibMonkey-1.0"):Embed(Darwin) - assert(Darwin:FlingPoo() == "Splat!") - Rock("LibMonkey-1.0"):Unembed(Darwin) - assert(Darwin.FlingPoo == nil) ------------------------------------------------------------------------------]] -function Rock:Unembed(object) - if not exportedMethods[self] then - error(("Cannot call `Unembed' for library %q if `SetExportedMethods' has not been called."):format(better_tostring(self)), 2) - end - - if not mixinToObject[self] or not mixinToObject[self][object] then - error(("Cannot unembed library %q from object %q, since it is not embedded originally."):format(better_tostring(self), better_tostring(object)), 2) - end - local mixinToObject_self = mixinToObject[self] - mixinToObject_self[object] = nil - if not next(mixinToObject_self) then - mixinToObject[self] = del(mixinToObject_self) - end - - local mixin_OnUnembed = self.OnUnembed - if mixin_OnUnembed then - local success, ret = pcall(mixin_OnUnembed, self, object) - if not success then - geterrorhandler()(ret) - end - end - - for i,v in ipairs(exportedMethods[self]) do - object[v] = nil - end -end - -local function embedAce2Mixin(mixin, object) - if not mixinToObject[mixin] then - mixinToObject[mixin] = setmetatable(newList(), weakKey) - end - mixinToObject[mixin][object] = true - mixin:embed(object) -end - -local function embedLibStubMixin(mixin, object) - if not mixinToObject[mixin] then - mixinToObject[mixin] = setmetatable(newList(), weakKey) - end - mixinToObject[mixin][object] = true - mixin:Embed(object) -end - ---[[--------------------------------------------------------------------------- -Notes: - * create a new addon with the specified name. -Arguments: - string - name of the addon. - tuple - list of mixins with which to embed into this addon. -Returns: - addon - * table - the addon with which to manipulate -Example: - local MyAddon = Rock:NewAddon("MyAddon", "Mixin-1.0", "OtherMixin-2.0") ------------------------------------------------------------------------------]] -function Rock:NewAddon(name, ...) - if type(name) ~= "string" then - error(("Bad argument #2 to `NewAddon'. Expected %q, got %q"):format("string", type(name)), 2) - end - if name:match("^Lib[A-Z]") then - error(("Bad argument #2 to `NewAddon'. Cannot start with %q, got %q."):format("Lib", name), 2) - end - if self == Rock and name:match("_") then - error(("Bad argument #2 to `NewAddon'. Cannot contain underscores, got %q."):format(name), 2) - end - - if addons[name] then - error(("Bad argument #2 to `NewAddon'. Addon %q already created."):format(name), 2) - end - local addon = setmetatable(newList(), addon_mt) - addon.name = name - - local mixinSet = newList() - - for i = 1, select('#', ...) do - local libName = select(i, ...) - if mixinSet[libName] then - error(("Bad argument #%d to `NewAddon'. %q already stated."):format(i+2, tostring(libName)), 2) - end - mixinSet[libName] = true - TryToLoadStandalone(libName) - local library = Rock:GetLibrary(libName, false, true) - if not library then - error(("Bad argument #%d to `NewAddon'. Library %q is not found."):format(i+2, tostring(libName)), 2) - end - - local style = 'rock' - - if not exportedMethods[library] then - local good = false - if AceLibrary then - local AceOO = AceLibrary:HasInstance("AceOO-2.0", false) and AceLibrary("AceOO-2.0") - if AceOO.inherits(library, AceOO.Mixin) then - good = true - style = 'ace2' - end - end - if not good and type(rawget(library, 'Embed')) == "function" then - good = true - style = 'libstub' - end - if not good then - error(("Bad argument #%d to `NewAddon'. Library %q is not a mixin."):format(i+2, tostring(libName)), 2) - end - end - - if library == Rock then - error(("Bad argument #%d to `NewAddon'. Cannot use %q as a mixin."):format(i+2, tostring(libName)), 2) - end - - if style == 'rock' then - library:Embed(addon) - elseif style == 'ace2' then - embedAce2Mixin(library, addon) - elseif style == 'libstub' then - embedLibStubMixin(library, addon) - end - end - - mixinSet = del(mixinSet) - - addons[name] = addon - pendingAddons[#pendingAddons+1] = addon - pendingAddonsEnable[#pendingAddonsEnable+1] = addon - addonToFolder[addon] = figureCurrentAddon(self == Rock and 2 or 4) - - frame:Show() - - return addon -end - ---[[--------------------------------------------------------------------------- -Arguments: - string - name of the addon. -Returns: - addon - * table or nil - the addon requested -Example: - local MyAddon = Rock:GetAddon("MyAddon") ------------------------------------------------------------------------------]] -function Rock:GetAddon(name) - if type(name) ~= "string" then - return nil - end - local addon = addons[name] - if addon then - return addon - end - name = name:lower() - for k, v in pairs(addons) do - if k:lower() == name then - return v - end - end - return nil -end - ---[[--------------------------------------------------------------------------- -Arguments: - string or table - name of the addon or the addon itself. -Returns: - boolean - whether the addon requested exists. -Example: - local hasMyAddon = Rock:HasAddon("MyAddon") - -- or - local hasMyAddon = Rock:HasAddon(MyAddon) ------------------------------------------------------------------------------]] -function Rock:HasAddon(name) - if type(name) == "string" then - local addon = addons[name] - if addon then - return true - end - name = name:lower() - for k, v in pairs(addons) do - if k:lower() == name then - return true - end - end - elseif type(name) == "table" then - for k,v in pairs(addons) do - if v == name then - return true - end - end - end - return false -end - ---[[--------------------------------------------------------------------------- -Returns: - an iterator to traverse all addons created with Rock. -Example: - for name, addon in Rock:IterateAddons() do - -- do something with name and addon - end ------------------------------------------------------------------------------]] -function Rock:IterateAddons() - return pairs(addons) -end - ---[[--------------------------------------------------------------------------- -Arguments: - string - major version of the mixin library -Returns: - an iterator to traverse all objects that the given mixin has embedded into -Example: - local LibMonkey = Rock:NewLibrary("LibMonkey-1.0") - local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0") - for object in LibMonkey:IterateMixinObjects("LibMonkey-1.0") do - assert(object == Darwin) - end ------------------------------------------------------------------------------]] -function Rock:IterateMixinObjects(mixinName) - local mixin - if type(mixinName) == "table" then - mixin = mixinName - else - if type(mixinName) ~= "string" then - error(("Bad argument #2 to `IterateMixinObjects'. Expected %q or %q, got %q."):format("table", "string", type(mixinName)), 2) - end - mixin = libraries[mixinName] - end - local mixinToObject_mixin = mixinToObject[mixin] - if not mixinToObject_mixin then - return noop - end - return pairs(mixinToObject_mixin) -end - -local function iter(object, mixin) - mixin = next(mixinToObject, mixin) - if not mixin then - return nil - elseif mixinToObject[mixin][object] then - return mixin - end - return iter(object, mixin) -- try next mixin -end ---[[--------------------------------------------------------------------------- -Returns: - an iterator to traverse all mixins that an object has embedded -Example: - local LibMonkey = Rock:NewLibrary("LibMonkey-1.0") - local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0") - for mixin in Rock:IterateObjectMixins(Darwin) do - assert(mixin == LibMonkey) - end ------------------------------------------------------------------------------]] -function Rock:IterateObjectMixins(object) - if type(object) ~= "table" then - error(("Bad argument #2 to `IterateObjectMixins'. Expected %q, got %q."):format("table", type(object)), 2) - end - return iter, object, nil -end - ---[[--------------------------------------------------------------------------- -Arguments: - table - the object to check - string - the mixin to check -Returns: - boolean - whether the object has the given mixin embedded into it. -Example: - local LibMonkey = Rock:NewLibrary("LibMonkey-1.0") - local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0") - assert(Rock:DoesObjectUseMixin(Darwin, "LibMonkey-1.0")) ------------------------------------------------------------------------------]] -function Rock:DoesObjectUseMixin(object, mixinName) - if type(object) ~= "table" then - error(("Bad argument #2 to `IterateObjectMixins'. Expected %q, got %q."):format("table", type(object)), 2) - end - local mixin - if type(mixinName) == "table" then - mixin = mixinName - else - if type(mixinName) ~= "string" then - error(("Bad argument #3 to `IterateMiDoesObjectUseMixininObjects'. Expected %q or %q, got %q."):format("table", "string", type(mixinName)), 2) - end - mixin = libraries[mixinName] - end - if not mixin then - return false - end - - local mixinToObject_mixin = mixinToObject[mixin] - if not mixinToObject_mixin then - return false - end - return not not mixinToObject_mixin[object] -end - -Rock.UID_NUM = oldRock and oldRock.UID_NUM or 0 ---[[--------------------------------------------------------------------------- -Notes: - * This UID is not unique across sessions. If you save a UID in a saved variable, the same UID can be generated in another session. -Returns: - number - a unique number. -Example: - local UID = Rock:GetUID() ------------------------------------------------------------------------------]] -function Rock:GetUID() - local num = Rock.UID_NUM + 1 - Rock.UID_NUM = num - return num -end - -local function unobfuscateEmail(email) - return email:gsub(" AT ", "@"):gsub(" DOT ", ".") -end -local function fix(char) - return ("%%%02x"):format(char:byte()) -end -local function urlencode(text) - return text:gsub("[^0-9A-Za-z]", fix) -end - -local url -local function makeURLFrame() - makeURLFrame = nil - local function bumpFrameLevels(frame, amount) - frame:SetFrameLevel(frame:GetFrameLevel()+amount) - local children = newList(frame:GetChildren()) - for _,v in ipairs(children) do - bumpFrameLevels(v, amount) - end - children = del(children) - end - -- some code borrowed from Prat here - StaticPopupDialogs["ROCK_SHOW_URL"] = { - text = not IsMacClient() and L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] or L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."], - button2 = ACCEPT, - hasEditBox = 1, - hasWideEditBox = 1, - showAlert = 1, -- HACK : it's the only way I found to make de StaticPopup have sufficient width to show WideEditBox :( - - OnShow = function() - local editBox = _G[this:GetName() .. "WideEditBox"] - editBox:SetText(url) - editBox:SetFocus() - editBox:HighlightText(0) - editBox:SetScript("OnTextChanged", function() StaticPopup_EditBoxOnTextChanged() end) - - local button = _G[this:GetName() .. "Button2"] - button:ClearAllPoints() - button:SetWidth(200) - button:SetPoint("CENTER", editBox, "CENTER", 0, -30) - - _G[this:GetName() .. "AlertIcon"]:Hide() -- HACK : we hide the false AlertIcon - this:SetFrameStrata("FULLSCREEN_DIALOG") - bumpFrameLevels(this, 30) - end, - OnHide = function() - local editBox = _G[this:GetName() .. "WideEditBox"] - editBox:SetScript("OnTextChanged", nil) - this:SetFrameStrata("DIALOG") - bumpFrameLevels(this, -30) - end, - OnAccept = function() end, - OnCancel = function() end, - EditBoxOnEscapePressed = function() this:GetParent():Hide() end, - EditBoxOnTextChanged = function() - this:SetText(url) - this:SetFocus() - this:HighlightText(0) - end, - timeout = 0, - whileDead = 1, - hideOnEscape = 1 - } -end - -function OpenDonationFrame(self) - if makeURLFrame then - makeURLFrame() - end - - local donate = self.donate - if type(donate) ~= "string" then - donate = "Wowace" - end - local style, data = (":"):split(donate, 2) - style = style:lower() - if style ~= "website" and style ~= "paypal" then - style = "wowace" - end - if style == "wowace" then - url = "http://www.wowace.com/wiki/Donations" - elseif style == "website" then - url = data - else -- PayPal - local text = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" .. urlencode(unobfuscateEmail(data)) - local name - if type(self.title) == "string" then - name = self.title - elseif type(self.name) == "string" then - name = self.name - end - if name == MAJOR_VERSION then - name = "Rock" - end - if name then - name = name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") - text = text .. "&item_name=" .. urlencode(name) - end - url = text - end - - StaticPopup_Show("ROCK_SHOW_URL") -end -function OpenIssueFrame(self) - if makeURLFrame then - makeURLFrame() - end - - local issueTracker = self.issueTracker - if type(issueTracker) ~= "string" then - return - end - local style, data = (":"):split(issueTracker, 2) - style = style:lower() - if style ~= "website" and style ~= "wowace" then - return - end - if style == "wowace" then - url = "http://jira.wowace.com/secure/CreateIssue.jspa?pid=" .. data - elseif style == "website" then - url = data - end - - StaticPopup_Show("ROCK_SHOW_URL") -end -local function donate_hidden(addon) - return type(addon.donate) ~= "string" -end - -local function issue_hidden(addon) - return type(addon.issueTracker) ~= "string" -end - --- #NODOC -function Rock:GetRockConfigOptions(addon) - return 'active', { - type = 'boolean', - name = L["Enabled"], - desc = L["Enable or disable this addon."], - get = 'IsActive', - set = 'ToggleActive', - handler = addon, - order = -1, - }, 'donate', { - type = 'execute', - name = L["Give donation"], - buttonText = L["Donate"], - desc = L["Give a much-needed donation to the author of this addon."], - func = OpenDonationFrame, - hidden = donate_hidden, - passValue = addon, - order = -2, - }, 'issue', { - type = 'execute', - name = L["File issue"], - buttonText = L["Report"], - desc = L["File a bug or request a new feature or an improvement to this addon."], - func = OpenIssueFrame, - hidden = issue_hidden, - passValue = addon, - order = -3, - } -end - -local function initAddon(addon, name) - name = addonToFolder[addon] or name or "" - -- TOC checks - if addon.title == nil then - addon.title = GetAddOnMetadata(name, "Title") - end - if type(addon.title) == "string" then - addon.title = addon.title:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):gsub("%-Rock%-$", ""):trim() - end - if addon.notes == nil then - addon.notes = GetAddOnMetadata(name, "Notes") - end - if type(addon.notes) == "string" then - addon.notes = addon.notes:trim() - end - if addon.version == nil then - addon.version = GetAddOnMetadata(name, "Version") - end - if type(addon.version) == "string" then - addon.version = addon.version:trim() - end - if addon.author == nil then - addon.author = GetAddOnMetadata(name, "Author") - end - if type(addon.author) == "string" then - addon.author = addon.author:trim() - end - if addon.credits == nil then - addon.credits = GetAddOnMetadata(name, "X-Credits") - end - if type(addon.credits) == "string" then - addon.credits = addon.credits:trim() - end - if addon.donate == nil then - addon.donate = GetAddOnMetadata(name, "X-Donate") - end - if type(addon.donate) == "string" then - addon.donate = addon.donate:trim() - end - if addon.issueTracker == nil then - addon.issueTracker = GetAddOnMetadata(name, "X-IssueTracker") - end - if type(addon.issueTracker) == "string" then - addon.issueTracker = addon.issueTracker:trim() - end - if addon.category == nil then - addon.category = GetAddOnMetadata(name, "X-Category") - end - if type(addon.category) == "string" then - addon.category = addon.category:trim() - end - if addon.email == nil then - addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email") - end - if type(addon.email) == "string" then - addon.email = addon.email:trim() - end - if addon.license == nil then - addon.license = GetAddOnMetadata(name, "X-License") - end - if type(addon.license) == "string" then - addon.license = addon.license:trim() - end - if addon.website == nil then - addon.website = GetAddOnMetadata(name, "X-Website") - end - if type(addon.website) == "string" then - addon.website = addon.website:trim() - end - - for mixin in Rock:IterateObjectMixins(addon) do - local mixin_OnEmbedInitialize = mixin.OnEmbedInitialize - if mixin_OnEmbedInitialize then - local success, ret = pcall(mixin_OnEmbedInitialize, mixin, addon) - if not success then - geterrorhandler()(ret) - end - end - end - - local addon_OnInitialize = addon.OnInitialize - if addon_OnInitialize then - local success, ret = pcall(addon_OnInitialize, addon) - if not success then - geterrorhandler()(ret) - end - end - - if LibRockEvent then - Rock:DispatchEvent("AddonInitialized", addon) - end -end - - -local function manualEnable(addon) - for i,v in ipairs(pendingAddons) do - if v == addon then - return - end - end - if currentlyEnabledAddons[addon] then - return false - end - currentlyEnabledAddons[addon] = true - - local first = not addonsAlreadyEnabled[addon] - addonsAlreadyEnabled[addon] = true - - for mixin in Rock:IterateObjectMixins(addon) do - local mixin_OnEmbedEnable = mixin.OnEmbedEnable - if mixin_OnEmbedEnable then - local success, ret = pcall(mixin_OnEmbedEnable, mixin, addon, first) - if not success then - geterrorhandler()(ret) - end - end - end - local addon_OnEnable = addon.OnEnable - if addon_OnEnable then - local success, ret = pcall(addon_OnEnable, addon, first) - if not success then - geterrorhandler()(ret) - end - end - - if LibRockEvent then - Rock:DispatchEvent("AddonEnabled", addon, first) - end - - return true, first -end - -local function manualDisable(addon) - if not currentlyEnabledAddons[addon] then - return false - end - currentlyEnabledAddons[addon] = nil - - for mixin in Rock:IterateObjectMixins(addon) do - local mixin_OnEmbedDisable = mixin.OnEmbedDisable - if mixin_OnEmbedDisable then - local success, ret = pcall(mixin_OnEmbedDisable, mixin, addon) - if not success then - geterrorhandler()(ret) - end - end - end - local addon_OnDisable = addon.OnDisable - if addon_OnDisable then - local success, ret = pcall(addon_OnDisable, addon) - if not success then - geterrorhandler()(ret) - end - end - - if LibRockEvent then - Rock:DispatchEvent("AddonDisabled", addon) - end - return true -end - -local function enableAddon(addon) - for i,v in ipairs(pendingAddons) do - if v == addon then - return - end - end - if addon_mt___index.IsActive(addon) then - manualEnable(addon) - end -end - --- #NODOC --- This is used by internal Rock libraries after updating the active state. -function Rock:RecheckEnabledStates() - local changed = false - for _,addon in pairs(addons) do - local good = true - for _,a in ipairs(pendingAddonsEnable) do - if addon == a then - good = false - break - end - end - if good then - if addon_mt___index.IsActive(addon) then - if manualEnable(addon) then - changed = true - end - else - if manualDisable(addon) then - changed = true - end - end - end - end - if changed then - return self:RecheckEnabledStates() - end -end - -frame:UnregisterAllEvents() -frame:RegisterEvent("ADDON_LOADED") -frame:RegisterEvent("PLAYER_LOGIN") -local function runMainAddonLoadedChunk(name) - local tmp = newList() - tmp, pendingAddons = pendingAddons, tmp - for i, addon in ipairs(tmp) do - local folder = addonToFolder[addon] - if name and folder and not foldersLoaded[folder] then - for j = i, #tmp do - pendingAddons[#pendingAddons+1] = tmp[j] - tmp[j] = nil - end - break - end - initAddon(addon, name) - end - - if IsLoggedIn() then - for i, addon in ipairs(tmp) do - for j, v in ipairs(pendingAddonsEnable) do - if v == addon then - table_remove(pendingAddonsEnable, i) - break - end - end - enableAddon(addon) - end - for i, addon in ipairs(pendingAddonsEnable) do - local good = true - for j, v in ipairs(pendingAddons) do - if v == addon then - good = false - break - end - end - if not good then - break - end - pendingAddonsEnable[i] = nil - enableAddon(addon) - end - end - tmp = del(tmp) - for library, addonName in pairs(pendingLibraries) do - if not name or foldersLoaded[addonName] then - local success, ret = pcall(error, ("Library %q not finalized before ADDON_LOADED."):format(better_tostring(library)), 3) - geterrorhandler()(ret) - Rock:FinalizeLibrary((library:GetLibraryVersion())) - end - end - - if isStandalone then - local LibRock_1_0DB = _G.LibRock_1_0DB - if type(LibRock_1_0DB) ~= "table" then - LibRock_1_0DB = {} - _G.LibRock_1_0DB = LibRock_1_0DB - end - if type(LibRock_1_0DB.unitTests) ~= "table" then - LibRock_1_0DB.unitTests = {} - end - enableContracts = LibRock_1_0DB.contracts or false - unitTestDB = LibRock_1_0DB.unitTests - for namespace, data in pairs(unitTests) do - if not unitTestDB[namespace] then - if data then - del(data) - unitTests[namespace] = false - end - elseif data and (not name or data.addon == name) then - local stats = newList() - for i,v in ipairs(data) do - data[i] = nil - - local libs = newList() - for k,v in pairs(libraries) do - libs[k] = v - end - - local success, ret = pcall(v) - if not success then - geterrorhandler()(ret) - stats[i] = ret - else - stats[i] = false - end - - for k in pairs(libraries) do - if not libs[k] then - __removeLibrary(k) - end - end - libs = del(libs) - - local lastCount - repeat - lastCount = collectgarbage('count') - collectgarbage('collect') - until lastCount == collectgarbage('count') - end - del(data) - unitTests[namespace] = false - if #stats >= 1 then - local pass, fail = 0, 0 - for i,v in ipairs(stats) do - if v then - fail = fail + 1 - else - pass = pass + 1 - end - end - - local color - if fail == 0 then - _G.DEFAULT_CHAT_FRAME:AddMessage(("|cff00ff00%s: %d unit test(s) passed."):format(namespace, pass)) - elseif pass > 0 then - _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s: %d unit test(s) passed, %d unit test(s) failed."):format(namespace, pass, fail)) - else - _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s: %d unit test(s) failed."):format(namespace, fail)) - end - for i,v in ipairs(stats) do - if v then - _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s|r"):format(tostring(v))) - end - end - if fail > 0 then - _G.DEFAULT_CHAT_FRAME:AddMessage("|cffff0000----------|r") - end - end - stats = del(stats) - end - end - end - if isStandalone and name == MAJOR_VERSION then - Rock("LibRockEvent-1.0", false, true) -- load if possible - Rock("LibRockConsole-1.0", false, true) -- load if possible - I like the default chat commands - Rock("LibRockComm-1.0", false, true) -- load if possible - has version checking and the like - Rock("LibRockConfig-1.0", false, true) -- load if possible - LibRock-1.0 registers with it. - end - - for major, library in LibStub:IterateLibraries() do - manualFinalize(major, library) - end - - if IsLoggedIn() then - collectgarbage('collect') - end -end - -frame:Show() -frame:SetScript("OnUpdate", function(this, elapsed) - -- capture all un-initialized addons. - runMainAddonLoadedChunk() - collectgarbage('collect') - this:SetScript("OnUpdate", run) -end) -frame:SetScript("OnEvent", function(this, event, ...) - if event == "ADDON_LOADED" then - -- this creates a new table and flushes the old in case someone LoDs an addon inside ADDON_LOADED. - local name = ... - foldersLoaded[name] = true - runMainAddonLoadedChunk(name) - frame:Show() - elseif event == "PLAYER_LOGIN" then - for i, addon in ipairs(pendingAddonsEnable) do - local good = true - for _, a in ipairs(pendingAddons) do - if a == addon then - good = false - break - end - end - if good then - pendingAddonsEnable[i] = nil - enableAddon(addon) - end - end - collectgarbage('collect') - end -end) - -Rock:SetExportedMethods("SetExportedMethods", "Embed", "Unembed", "GetLibraryVersion") - -Rock:FinalizeLibrary(MAJOR_VERSION) - -for major, library in LibStub:IterateLibraries() do - manualFinalize(major, library) -end - -Rock:AddUnitTest(MAJOR_VERSION, function() - -- test recycling - local newList, newDict, newSet, del = Rock:GetRecyclingFunctions(MAJOR_VERSION .. "_UnitTest", "newList", "newDict", "newSet", "del", "Debug") - local t = newList("Alpha", "Bravo", "Charlie") - assert(t[1] == "Alpha") - assert(t[2] == "Bravo") - assert(t[3] == "Charlie") - t = del(t) - t = newList("Alpha", "Bravo", "Charlie") - -- check recycled table - assert(t[1] == "Alpha") - assert(t[2] == "Bravo") - assert(t[3] == "Charlie") - t = del(t) - t = newDict("Alpha", "Bravo", "Charlie", "Delta") - assert(t.Alpha == "Bravo") - assert(t.Charlie == "Delta") - t = del(t) - t = newSet("Alpha", "Bravo", "Charlie") - assert(t.Alpha) - assert(t.Bravo) - assert(t.Charlie) - t = del(t) - - local debug = recycleData.debugPools[MAJOR_VERSION .. "_UnitTest"] - assert(debug.num == 0) - t = newList() - assert(debug.num == 1) - t[1] = newList() - assert(debug.num == 2) - t[2] = newList() - assert(debug.num == 3) - t[1] = del(t[1]) - assert(debug.num == 2) - t[2] = del(t[2]) - assert(debug.num == 1) - t = del(t) - assert(debug.num == 0) -end) - -Rock:AddUnitTest(MAJOR_VERSION, function() - -- test :GetUID() - local t = {} - for i = 1, 10000 do - local uid = Rock:GetUID() - if t[i] then - error(("UID match for iteration %d, UID %s"):format(i, uid)) - end - t[i] = true - end -end) - -Rock:AddUnitTest(MAJOR_VERSION, function() - -- test basic creation and deletion - assert(not LibStub:GetLibrary("LibRockFakeLib-1.0", true)) - assert(not Rock:HasLibrary("LibRockFakeLib-1.0")) - local lib = Rock:NewLibrary("LibRockFakeLib-1.0", 1) - Rock:FinalizeLibrary("LibRockFakeLib-1.0") - lib = nil - assert(LibStub:GetLibrary("LibRockFakeLib-1.0", true)) - assert(Rock:HasLibrary("LibRockFakeLib-1.0")) - local good = false - for _, lib in pairs(libraries) do - if lib.name == "LibRockFakeLib-1.0" then - good = true - break - end - end - assert(good) - __removeLibrary("LibRockFakeLib-1.0") - for _, lib in pairs(libraries) do - assert(lib.name ~= "LibRockFakeLib-1.0") - end - assert(not LibStub:GetLibrary("LibRockFakeLib-1.0", true)) - assert(not Rock:HasLibrary("LibRockFakeLib-1.0")) -end) - -Rock:AddUnitTest(MAJOR_VERSION, function() - -- test library creation and the like - assert(not Rock:HasLibrary("LibRockFakeLib-1.0")) - for name in Rock:IterateLibraries() do - assert(name ~= "LibRockFakeLib-1.0") - end - - local myLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 1) - assert(myLib) - assert(myLib.name == "LibRockFakeLib-1.0") - assert(not oldLib) - - assert(myLib:GetLibraryVersion() == "LibRockFakeLib-1.0") - assert(select(2, myLib:GetLibraryVersion()) == 1) - - local good = false - for name in Rock:IterateLibraries() do - if name == "LibRockFakeLib-1.0" then - good = true - break - end - end - assert(good) - assert(Rock:HasLibrary("LibRockFakeLib-1.0")) - assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib) - assert(Rock("LibRockFakeLib-1.0") == myLib) - - assert(not Rock:IsLibraryMixin("LibRockFakeLib-1.0")) - function myLib:DoSomething() - return "Something" - end - myLib:SetExportedMethods("DoSomething") - assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0")) - local t = {} - assert(not Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0")) - assert(not t.DoSomething) - for mixin in Rock:IterateObjectMixins(t) do - assert(false) - end - for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do - assert(false) - end - myLib:Embed(t) - assert(t:DoSomething() == "Something") - assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0")) - for mixin in Rock:IterateObjectMixins(t) do - assert(mixin == myLib) - end - for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do - assert(object == t) - end - - Rock:FinalizeLibrary("LibRockFakeLib-1.0") - - local myNewLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 2) - assert(myNewLib == myLib) - assert(oldLib) - assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib) - - function myLib:DoSomething() - return "Something else" - end - function myLib:TrySomething() - return "Blah" - end - myLib:SetExportedMethods("DoSomething", "TrySomething") - assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0")) - assert(t:DoSomething() == "Something else") - assert(t:TrySomething() == "Blah") - assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0")) - for mixin in Rock:IterateObjectMixins(t) do - assert(mixin == myLib) - end - for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do - assert(object == t) - end - - Rock:FinalizeLibrary("LibRockFakeLib-1.0") - - local myNewLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 3) - assert(myNewLib == myLib) - assert(oldLib) - assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib) - - function myLib:DoSomething() - return "Something" - end - myLib:SetExportedMethods("DoSomething") - assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0")) - assert(t:DoSomething() == "Something") - assert(t.TrySomething == nil) - assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0")) - for mixin in Rock:IterateObjectMixins(t) do - assert(mixin == myLib) - end - for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do - assert(object == t) - end - - Rock:FinalizeLibrary("LibRockFakeLib-1.0") - - assert(not Rock:NewLibrary("LibRockFakeLib-1.0", 2)) -- out of date - assert(not Rock:NewLibrary("LibRockFakeLib-1.0", 3)) -- same revision -end) - -Rock:AddUnitTest(MAJOR_VERSION, function() - assert(not Rock:HasAddon("RockFakeAddon")) - for name in Rock:IterateAddons() do - assert(name ~= "RockFakeAddon") - end - - local myAddon = Rock:NewAddon("RockFakeAddon") - - assert(myAddon) - assert(myAddon.name == "RockFakeAddon") - - local good = false - for name in Rock:IterateAddons() do - if name == "RockFakeAddon" then - good = true - break - end - end - assert(good) - assert(Rock:HasAddon("RockFakeAddon")) - assert(Rock:GetAddon("RockFakeAddon") == myAddon) -end) - -Rock:AddUnitTest(MAJOR_VERSION, function() - -- test :OnLibraryLoad - local lib = Rock:NewLibrary("LibRockFakeLib-1.0", 1) - local triggered = false - function lib:OnLibraryLoad(major, instance) - if major == "LibRockFakeLib-2.0" then - triggered = true - end - end - Rock:FinalizeLibrary("LibRockFakeLib-1.0") - - local lib = Rock:NewLibrary("LibRockFakeLib-2.0", 1) - assert(not triggered) - Rock:FinalizeLibrary("LibRockFakeLib-2.0") - assert(triggered) - triggered = false - local lib = Rock:NewLibrary("LibRockFakeLib-2.0", 2) - assert(not triggered) - Rock:FinalizeLibrary("LibRockFakeLib-2.0") - assert(not triggered) -end)
--- a/modules/FuBar_ReActionFu/lib/LibRock-1.0/LibRock-1.0.toc Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -## Interface: 20300 - -## Title: LibRock-1.0 -## Notes: AddOn development framework -## Author: ckknight -## X-Website: http://www.wowace.com -## X-Category: Library -## X-Donate: Paypal:ckknight AT gmail DOT com -## X-eMail: ckknight AT gmail DOT com -## X-License: LGPL v2.1 -## SavedVariables: LibRock_1_0DB -## OptionalDeps: !BugGrabber, !Swatter - -lib.xml \ No newline at end of file
--- a/modules/FuBar_ReActionFu/lib/LibRock-1.0/LibStub/LibStub.lua Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ --- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info --- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke -local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! -local LibStub = _G[LIBSTUB_MAJOR] - -if not LibStub or LibStub.minor < LIBSTUB_MINOR then - LibStub = LibStub or {libs = {}, minors = {} } - _G[LIBSTUB_MAJOR] = LibStub - LibStub.minor = LIBSTUB_MINOR - - 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 - - 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 - - function LibStub:IterateLibraries() return pairs(self.libs) end - setmetatable(LibStub, { __call = LibStub.GetLibrary }) -end
--- a/modules/FuBar_ReActionFu/lib/LibRock-1.0/lib.xml Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ -..\FrameXML\UI.xsd"> - <Script file="LibStub\LibStub.lua" /> - <Script file="LibRock-1.0.lua" /> -</Ui> \ No newline at end of file
--- a/modules/FuBar_ReActionFu/lib/embeds.xml Wed Apr 02 23:44:06 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd"> - - <Include file="LibRock-1.0\lib.xml"/> - <Include file="LibFuBarPlugin-3.0\lib.xml"/> - - <Script file="AceLibrary\AceLibrary.lua"/> - <Script file="Dewdrop-2.0\Dewdrop-2.0.lua"/> - <Script file="Tablet-2.0\Tablet-2.0.lua"/> - -</Ui>
--- a/modules/modules.xml Wed Apr 02 23:44:06 2008 +0000 +++ b/modules/modules.xml Thu Apr 03 16:59:16 2008 +0000 @@ -9,13 +9,6 @@ <!-- action button modules --> <Include file="ReAction_Action\ReAction_Action.xml"/> - - -<!-- deprecated -<Include file="FuBar_ReActionFu\FuBar_ReActionFu.xml"/> ---> - - <!-- in progress <Include file="ReAction_PetAction\ReAction_PetAction.xml"/> -->