vanilla-wow-addons – Rev 1
?pathlinks?
local MAJOR_VERSION = "1.2"
local MINOR_VERSION = tonumber(string.sub("$Revision: 8308 $", 12, -3))
if FuBarPlugin and FuBarPlugin.versions[MAJOR_VERSION] and FuBarPlugin.versions[MAJOR_VERSION].minor >= MINOR_VERSION and FuBarPlugin.MinimapContainer and FuBarPlugin.MinimapContainer.versions[MAJOR_VERSION] and FuBarPlugin.MinimapContainer.versions[MAJOR_VERSION].minor >= MINOR_VERSION then
return
end
local loc = {
ARGUMENT_VISIBLE = "visible",
ARGUMENT_COLOR = "color",
ARGUMENT_SHOWICON = "showIcon",
ARGUMENT_SHOWTEXT = "showText",
ARGUMENT_PROFILE = "profile",
TEXT_TOGGLE_VISIBILITY = "Toggle Visibility.",
TEXT_TOGGLE_WHETHER_TO_SHOW_THE_ICON = "Toggle whether to show the icon.",
TEXT_TOGGLE_WHETHER_TO_SHOW_TEXT = "Toggle whether to show text.",
TEXT_LIST_PROFILING_INFO = "List profiling information",
MENU_SHOW_ICON = "Show icon",
MENU_SHOW_TEXT = "Show text",
MENU_SHOW_COLORED_TEXT = "Show colored text",
MENU_DETACH_TOOLTIP = "Detach tooltip",
MENU_LOCK_TOOLTIP = "Lock tooltip",
MENU_ON_LEFT_SIDE = "On left side",
MENU_IN_CENTER = "In center",
MENU_ON_RIGHT_SIDE = "On right side",
MENU_ATTACH = "Attach to minimap",
MENU_HIDE = "Hide",
MENU_DISABLE = "Disable",
MENU_ABOUT = "About",
MAP_ONOFF = {[0]="|cffff0000Off|r",[1]="|cff00ff00On|r"},
PATTERN_MERGE_WITH_CHILD = "Merge with %s",
PATTERN_SWITCH_TO_CHILD = "Switch to %s",
}
if GetLocale() == "deDE" then
loc.TEXT_TOGGLE_VISIBILITY = "Sichtbarkeit umschalten."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_THE_ICON = "Iconanzeige umschalten."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_TEXT = "Textanzeige umschalten."
loc.TEXT_LIST_PROFILING_INFO = "Liste Profilinformationen"
loc.MENU_SHOW_ICON = "Zeige Icon"
loc.MENU_SHOW_TEXT = "Zeige Text"
loc.MENU_SHOW_COLORED_TEXT = "Farbigen Text anzeigen"
loc.MENU_DETACH_TOOLTIP = "Tooltip l\195\182sen"
loc.MENU_LOCK_TOOLTIP = "Tooltip verankern"
loc.MENU_ON_LEFT_SIDE = "Auf linker Seite anzeigen"
loc.MENU_IN_CENTER = "In der Mitte anzeigen"
loc.MENU_ON_RIGHT_SIDE = "Auf rechter Seite anzeigen"
loc.MENU_HIDE = "Ausblenden"
loc.MENU_DISABLE = "Deaktivieren"
loc.MENU_ABOUT = "\195\156ber"
loc.MAP_ONOFF[0] = "|cffff0000Aus|r"
loc.MAP_ONOFF[1] = "|cff00ff00An|r"
loc.PATTERN_MERGE_WITH_CHILD = "Mit %s verbinden"
loc.PATTERN_SWITCH_TO_CHILD = "Zu %s wechseln"
elseif GetLocale() == "frFR" then
loc.TEXT_TOGGLE_VISIBILITY = "Bascule la visibilite."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_THE_ICON = "Bascule la dissimulation ou l'affichage de l'icone."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_TEXT = "Bascule la dissimulation ou l'affichage du text."
-- loc.TEXT_LIST_PROFILING_INFO = "List profiling information" -- CHECK
loc.MENU_SHOW_ICON = "Afficher l'icon"
loc.MENU_SHOW_TEXT = "Afficher le text"
-- loc.MENU_SHOW_COLORED_TEXT = "Show colored text" -- CHECK
-- loc.MENU_DETACH_TOOLTIP = "Detach tooltip" -- CHECK
-- loc.MENU_LOCK_TOOLTIP = "Lock tooltip" -- CHECK
-- loc.MENU_ON_LEFT_SIDE = "On left side" -- CHECK
-- loc.MENU_IN_CENTER = "In center" -- CHECK
-- loc.MENU_ON_RIGHT_SIDE = "On right side" -- CHECK
loc.MENU_HIDE = "Dissimule"
loc.MENU_DISABLE = "Desactive"
loc.MENU_ABOUT = "A propos"
-- loc.MAP_ONOFF[0] = "|cffff0000Off|r" -- CHECK
-- loc.MAP_ONOFF[1] = "|cff00ff00On|r" -- CHECK
loc.PATTERN_MERGE_WITH_CHILD = "Fusione avec %s"
loc.PATTERN_SWITCH_TO_CHILD = "Echange avec %s"
elseif ( GetLocale() == "zhCN" ) then
loc.TEXT_TOGGLE_VISIBILITY = "是否可见."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_THE_ICON = "是否显示图标."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_TEXT = "是否显示文本."
loc.TEXT_LIST_PROFILING_INFO = "显示配置文件信息"
loc.MENU_SHOW_ICON = "显示图标"
loc.MENU_SHOW_TEXT = "显示文本"
loc.MENU_SHOW_COLORED_TEXT = "显示彩色文本"
loc.MENU_DETACH_TOOLTIP = "分离提示信息"
loc.MENU_LOCK_TOOLTIP = "锁定提示信息"
loc.MENU_ON_LEFT_SIDE = "靠左侧"
loc.MENU_IN_CENTER = "居中"
loc.MENU_ON_RIGHT_SIDE = "靠右侧"
loc.MENU_ATTACH = "吸附在小地图周围"
loc.MENU_HIDE = "隐藏"
loc.MENU_DISABLE = "禁用"
loc.MENU_ABOUT = "关于"
loc.MAP_ONOFF = {[0]="|cffff0000关闭|r",[1]="|cff00ff00开启|r"}
loc.PATTERN_MERGE_WITH_CHILD = "与 %s 合并"
loc.PATTERN_SWITCH_TO_CHILD = "切换至 %s"
elseif ( GetLocale() == "koKR" ) then
loc.ARGUMENT_VISIBLE = "visible"
loc.ARGUMENT_COLOR = "color"
loc.ARGUMENT_SHOWICON = "showIcon"
loc.ARGUMENT_SHOWTEXT = "showText"
loc.ARGUMENT_PROFILE = "profile"
loc.TEXT_TOGGLE_VISIBILITY = "Toggle Visibility."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_THE_ICON = "Toggle whether to show the icon."
loc.TEXT_TOGGLE_WHETHER_TO_SHOW_TEXT = "Toggle whether to show text."
loc.TEXT_LIST_PROFILING_INFO = "List profiling information"
loc.MENU_SHOW_ICON = "아이콘 보이기"
loc.MENU_SHOW_TEXT = "Show text"
loc.MENU_SHOW_COLORED_TEXT = "Show colored text"
loc.MENU_DETACH_TOOLTIP = "툴팁 분리"
loc.MENU_LOCK_TOOLTIP = "툴팁 잠그기"
loc.MENU_ON_LEFT_SIDE = "왼쪽으로"
loc.MENU_IN_CENTER = "가운데로"
loc.MENU_ON_RIGHT_SIDE = "오른쪽으로"
loc.MENU_HIDE = "숨기기"
loc.MENU_DISABLE = "끄기"
loc.MENU_ABOUT = "About"
loc.MAP_ONOFF[0]="|cffff0000꺼짐|r"
loc.MAP_ONOFF[1]="|cff00ff00켜짐|r"
PATTERN_MERGE_WITH_CHILD = "Merge with %s"
PATTERN_SWITCH_TO_CHILD = "Switch to %s"
end
local dewdrop = DewdropLib:GetInstance('1.0')
local tablet = TabletLib:GetInstance('1.0')
if FUBAR_REVISION and MINOR_VERSION > FUBAR_REVISION then
FUBAR_REVISION = MINOR_VERSION
end
-------------IRIEL'S-STUB-CODE--------------
local stub = {};
-- Instance replacement method, replace contents of old with that of new
function stub:ReplaceInstance(old, new)
for k,v in pairs(old) do old[k]=nil; end
for k,v in pairs(new) do old[k]=v; end
end
-- Get a new copy of the stub
function stub:NewStub()
local newStub = {};
self:ReplaceInstance(newStub, self);
newStub.lastVersion = '';
newStub.versions = {};
return newStub;
end
-- Get instance version
function stub:GetInstance(version)
if (not version) then version = self.lastVersion; end
local versionData = self.versions[version];
if (not versionData) then
message("Cannot find library instance with version '"
.. version .. "'");
return;
end
return versionData.instance;
end
-- Register new instance
function stub:Register(newInstance)
local version,minor = newInstance:GetLibraryVersion();
self.lastVersion = version;
local versionData = self.versions[version];
if (not versionData) then
-- This one is new!
versionData = { instance = newInstance,
minor = minor,
old = {}
};
self.versions[version] = versionData;
newInstance:LibActivate(self);
return newInstance;
end
if (minor <= versionData.minor) then
-- This one is already obsolete
if (newInstance.LibDiscard) then
newInstance:LibDiscard();
end
return versionData.instance;
end
-- This is an update
local oldInstance = versionData.instance;
local oldList = versionData.old;
versionData.instance = newInstance;
versionData.minor = minor;
local skipCopy = newInstance:LibActivate(self, oldInstance, oldList);
table.insert(oldList, oldInstance);
if (not skipCopy) then
for i, old in ipairs(oldList) do
self:ReplaceInstance(old, newInstance);
end
end
return newInstance;
end
-- Bind stub to global scope if it's not already there
if (not FuBarPlugin) then
FuBarPlugin = stub:NewStub();
end
if (not FuBarPlugin.MinimapContainer) then
FuBarPlugin.MinimapContainer = stub:NewStub();
end
-- Nil stub for garbage collection
stub = nil;
-----------END-IRIEL'S-STUB-CODE------------
local RegisterTablet
-- FuBarPlugin
do
local compost
if CompostLib then
compost = CompostLib:GetInstance('compost-1')
end
local epsilon = 1e-5
local lib = AceAddon:new()
local function VersionToNumber(version)
if version == nil then
return 0
elseif type(version) == "number" then
return version
end
local num = 0
local place = 1
string.gsub(version, "(%d+)", function (w)
num = num + tonumber(w) * math.pow(10, place * 2)
if place > 0 then
place = place - 1
else
place = place - 2
end
end)
return num
end
function lib:assert(condition, message)
if not condition then
local stack = debugstack()
local first = string.gsub(stack, "\n.*", "")
local file = string.gsub(first, "^(.*\\.*).lua:%d+: .*", "%1")
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
if not message then
local _,_,second = string.find(stack, "\n(.-)\n")
message = "assertion failed! " .. second
end
if self.name then
local _,_,title = string.find(self.name, "FuBar %- (.+)")
if not title then
title = self.name
end
message = title .. ": " .. message
end
local i = 1
for s in string.gfind(stack, "\n([^\n]*)") do
i = i + 1
if not string.find(s, file .. "%.lua:%d+:") then
error(message, i)
return
end
end
error(message, 2)
return
end
return condition
end
function lib:argCheck(arg, num, kind, kind2, kind3, kind4)
if tostring(type(arg)) ~= kind then
if kind2 then
if tostring(type(arg)) ~= kind2 then
if kind3 then
if tostring(type(arg)) ~= kind3 then
if kind4 then
if tostring(type(arg)) ~= kind4 then
local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
self:assert(false, format("Bad argument #%s to `%s' (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind or "---", kind2 or "---", kind3 or "---", kind4 or "---", type(arg)))
end
else
local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
self:assert(false, format("Bad argument #%s to `%s' (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind or "---", kind2 or "---", kind3 or "---", type(arg)))
end
end
else
local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
self:assert(false, format("Bad argument #%s to `%s' (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind or "---", kind2 or "---", type(arg)))
end
end
else
local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
self:assert(false, format("Bad argument #%s to `%s' (%s expected, got %s)", tonumber(num) or 0/0, func, kind or "---", type(arg)))
end
end
end
function lib:GetTitle()
self:assert(self.name, "You must provide self.name")
local _,_,title = string.find(self.name, "FuBar %- (.+)")
if not title then
title = self.name
end
return title
end
function lib:DisableHideWithoutStandby()
self.hideWithoutStandby = false
if not self._hideWithoutStandbyEnabled then
return
end
self._hideWithoutStandbyEnabled = false
for index, value in self.cmd.options do
if value.method == "_ToggleVisible" then
table.remove(self.cmd.options, index)
break
end
end
self._ToggleVisible = nil
self.Report = self._Report
self._Report = nil
if self.data.hidden then
self:DisableAddon()
end
self.data.hidden = nil
end
function lib:EnableHideWithoutStandby()
self.hideWithoutStandby = true
if self._hideWithoutStandbyEnabled then
return
end
self._hideWithoutStandbyEnabled = true
table.insert(self.cmd.options, {
option = loc.ARGUMENT_VISIBLE,
desc = loc.TEXT_TOGGLE_VISIBILITY,
method = "_ToggleVisible"
})
function self:_ToggleVisible()
if self.data.hidden then
self:Show()
else
self:Hide()
end
self.cmd:status(loc.ARGUMENT_VISIBLE, not self.data.hidden and 1 or 0, loc.MAP_ONOFF)
end
if self.Report then
self._Report = self.Report
function self:Report()
self:_Report()
ace:print(" - ", format(ACE_CMD_REPORT_LINE, loc.ARGUMENT_VISIBLE, loc.MAP_ONOFF[not self.data.hidden and 1 or 0]))
end
else
function self:Report()
local report = compost and compost:Acquire(
compost:AcquireHash(
'text', loc.ARGUMENT_VISIBLE,
'val', not self.data.hidden and 1 or 0,
'map', loc.MAP_ONOFF
)
) or {{
text = loc.ARGUMENT_VISIBLE,
val = not self.data.hidden and 1 or 0,
map = loc.MAP_ONOFF
}}
self.cmd:report(report)
if compost then
compost:Reclaim(report, 1)
end
end
end
end
function lib:IsTextColored()
if self.data then
return not self.data.uncolored
else
return true
end
end
function lib:ToggleMinimapAttached()
if FuBar and not self.cannotAttachToMinimap then
local value = self:IsMinimapAttached()
if value then
self.panel:RemovePlugin(self)
FuBar:GetPanel(1):AddPlugin(self, nil, self.defaultPosition)
else
self.panel:RemovePlugin(self)
FuBarPlugin.MinimapContainer:GetInstance(MAJOR_VERSION):AddPlugin(self)
end
end
end
function lib:IsMinimapAttached()
return self.panel == FuBarPlugin.MinimapContainer:GetInstance(MAJOR_VERSION)
end
function lib:ToggleTextColored(loud)
self.data.uncolored = not self.data.uncolored or nil
if loud then
self.cmd:status(loc.ARGUMENT_COLOR, not self.data.uncolored and 1 or 0, loc.MAP_ONOFF)
end
self:UpdateText()
return not self.data.uncolored
end
function lib:Update()
self:UpdateData()
self:UpdateText()
self:UpdateTooltip()
end
function lib:UpdateDisplay()
self:UpdateText()
self:UpdateTooltip()
end
local function inheritDefaults(t, defaults)
if not defaults then
return
end
for k,v in pairs(defaults) do
if type(v) == "table" then
if type(t[k]) ~= "table" then
t[k] = {}
end
inheritDefaults(t[k], v)
elseif t[k] == v then
t[k] = nil
end
end
for k,v in pairs(t) do
if v == 1 and defaults[k] == true then
t[k] = nil
elseif v == true and defaults[k] == 1 then
t[k] = nil
end
end
setmetatable(t, { __index = defaults })
end
function lib:_OnAceProfileLoaded()
if self.db then
local t = self.db._table
if not t.profiles then
t.profiles = {}
end
if not t.profiles[self.profilePath[2]] then
t.profiles[self.profilePath[2]] = {}
end
if self.data ~= self.db._table.profiles[self.profilePath[2]] then
self.data = self.db._table.profiles[self.profilePath[2]]
else
return
end
elseif FuBar then
local FuBarDB = FuBar2DB or FuBarDB
if not FuBarDB.pluginDB[self:GetTitle()] then
FuBarDB.pluginDB[self:GetTitle()] = {}
end
if not FuBarDB.pluginDB[self:GetTitle()].profiles then
FuBarDB.pluginDB[self:GetTitle()].profiles = {}
end
if not FuBarDB.pluginDB[self:GetTitle()].profiles["default"] then
FuBarDB.pluginDB[self:GetTitle()].profiles["default"] = {}
end
if self.data ~= FuBarDB.pluginDB[self:GetTitle()].profiles["default"] then
self.data = FuBarDB.pluginDB[self:GetTitle()].profiles["default"]
else
return
end
end
inheritDefaults(self.data, self.defaults)
if type(self.ACE_PROFILE_LOADED) == "function" then
self:ACE_PROFILE_LOADED()
end
self.data.version = self.version
self:Update()
end
function lib:Show(panelId)
if self.frame:IsShown() or (self.minimapFrame and self.minimapFrame:IsShown()) then
return
end
if panelId ~= false then
self.data.hidden = nil
end
if self:IsLoadOnDemand() and FuBar then
local data = FuBar.db and FuBar.db.profile or FuBar.data
if not data.loadOnDemand then
data.loadOnDemand = {}
end
if not data.loadOnDemand[self.folderName] then
data.loadOnDemand[self.folderName] = {}
end
data.loadOnDemand[self.folderName].disabled = nil
end
if self.disabled then
self.panelIdTmp = panelId
self:EnableAddon()
self.panelIdTmp = nil
if not self.db then
self.data.disabled = nil
end
elseif self.data and not self.data.hidden then
if panelId == 0 or not FuBar then
FuBarPlugin.MinimapContainer:GetInstance(MAJOR_VERSION):AddPlugin(self)
else
FuBar:ShowPlugin(self, panelId or self.panelIdTmp)
end
self:Update()
end
end
function lib:Hide()
if not self.frame:IsShown() and (not self.minimapFrame or not self.minimapFrame:IsShown()) then
return
end
if self.hideWithoutStandby then
self.data.hidden = true
end
if not self.hideWithoutStandby then
if not self.overrideTooltip and not self.cannotDetachTooltip and self:IsTooltipDetached() and self.data.detachedTooltip.detached then
self:ReattachTooltip()
self.data.detachedTooltip.detached = true
end
if not self.db then
self.data.disabled = true
end
if not FuBar or not FuBar:IsChangingProfile() then
self:DisableAddon()
if self:IsLoadOnDemand() and FuBar then
local data = FuBar.db and FuBar.db.profile or FuBar.data
if not data.loadOnDemand then
data.loadOnDemand = {}
end
if not data.loadOnDemand[self.folderName] then
data.loadOnDemand[self.folderName] = {}
end
data.loadOnDemand[self.folderName].disabled = true
end
end
end
if self.panel then
self.panel:RemovePlugin(self)
end
self.frame:Hide()
if self.minimapFrame then
self.minimapFrame:Hide()
end
end
function lib:AddImpliedMenuOptions(level)
self:argCheck(level, 2, "number", "nil")
if self.hasIcon and not self.hasNoText then
dewdrop:AddLine(
'text', loc.MENU_SHOW_ICON,
'func', function()
self:ToggleIconShown()
end,
'checked', self:IsIconShown(),
'level', level
)
end
if not self.cannotHideText and self.hasIcon and not self.hasNoText then
dewdrop:AddLine(
'text', loc.MENU_SHOW_TEXT,
'func', function()
self:ToggleTextShown()
end,
'checked', self:IsTextShown(),
'leve', level
)
end
if not self.userDefinedFrame and not self.hasNoText and not self.hasNoColor then
dewdrop:AddLine(
'text', loc.MENU_SHOW_COLORED_TEXT,
'arg1', self,
'func', "ToggleTextColored",
'checked', self:IsTextColored(),
'level', level
)
end
if not self.overrideTooltip and not self.cannotDetachTooltip then
dewdrop:AddLine(
'text', loc.MENU_DETACH_TOOLTIP,
'func', function()
if self:IsTooltipDetached() then
self:ReattachTooltip()
else
self:DetachTooltip()
end
end,
'checked', self:IsTooltipDetached(),
'level', level
)
dewdrop:AddLine(
'text', loc.MENU_LOCK_TOOLTIP,
'arg1', tablet,
'func', "ToggleLocked",
'arg2', self.frame,
'checked', tablet:IsLocked(self.frame),
'disabled', not self:IsTooltipDetached(),
'level', level
)
end
if not self:IsMinimapAttached() then
dewdrop:AddLine(
'text', loc.MENU_ON_LEFT_SIDE,
'arg1', self.panel,
'func', self.panel:GetPluginSide(self) ~= "LEFT" and "SetPluginSide",
'arg2', self,
'arg3', "LEFT",
'checked', self.panel:GetPluginSide(self) == "LEFT",
'level', level,
'closeWhenClicked', self.panel:GetPluginSide(self) ~= "LEFT",
'isRadio', true
)
dewdrop:AddLine(
'text', loc.MENU_IN_CENTER,
'arg1', self.panel,
'func', self.panel:GetPluginSide(self) ~= "CENTER" and "SetPluginSide",
'arg2', self,
'arg3', "CENTER",
'checked', self.panel:GetPluginSide(self) == "CENTER",
'level', level,
'closeWhenClicked', self.panel:GetPluginSide(self) ~= "CENTER",
'isRadio', true
)
dewdrop:AddLine(
'text', loc.MENU_ON_RIGHT_SIDE,
'arg1', self.panel,
'func', self.panel:GetPluginSide(self) ~= "RIGHT" and "SetPluginSide",
'arg2', self,
'arg3', "RIGHT",
'checked', self.panel:GetPluginSide(self) == "RIGHT",
'level', level,
'closeWhenClicked', self.panel:GetPluginSide(self) ~= "RIGHT",
'isRadio', true
)
end
if not self.cannotAttachToMinimap or self:IsMinimapAttached() then
dewdrop:AddLine(
'text', loc.MENU_ATTACH,
'arg1', self,
'func', "ToggleMinimapAttached",
'checked', self:IsMinimapAttached(),
'level', level,
'closeWhenClicked', true
)
end
if self.hideWithoutStandby then
dewdrop:AddLine(
'text', loc.MENU_HIDE,
'arg1', self,
'func', "Hide",
'level', level,
'closeWhenClicked', true
)
end
dewdrop:AddLine(
'text', loc.MENU_DISABLE,
'arg1', self,
'func', "DisableAddon",
'level', level,
'closeWhenClicked', true
)
dewdrop:AddLine(
'level', level
)
dewdrop:AddLine(
'text', loc.MENU_ABOUT,
'arg1', self.cmd,
'func', "DisplayAddonInfo",
'level', level
)
end
function lib:SetIcon(path)
if not path then
return
end
if path == 1 then
path = true
end
self:argCheck(path, 2, "string", "boolean")
self:assert(self.hasIcon, "Cannot set icon unless self.hasIcon is set. (" .. self:GetTitle() .. ")")
if not self.iconFrame then
return
end
if type(path) ~= "string" then
path = format("Interface\\AddOns\\%s\\icon", self.folderName)
elseif not string.find(path, '^Interface[\\/]') then
path = format("Interface\\AddOns\\%s\\%s", self.folderName, path)
end
if string.sub(path, 1, 16) == "Interface\\Icons\\" then
self.iconFrame:SetTexCoord(0.05, 0.95, 0.05, 0.95)
else
self.iconFrame:SetTexCoord(0, 1, 0, 1)
end
self.iconFrame:SetTexture(path)
if self.minimapIcon then
if string.sub(path, 1, 16) == "Interface\\Icons\\" then
self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
else
self.minimapIcon:SetTexCoord(0, 1, 0, 1)
end
self.minimapIcon:SetTexture(path)
end
end
function lib:GetIcon()
if self.hasIcon then
return self.iconFrame:GetTexture()
end
end
function lib:CheckWidth(force)
self:argCheck(force, 2, "boolean", "nil")
if (self.iconFrame and self.iconFrame:IsShown()) or (self.textFrame and self.textFrame:IsShown()) then
if self.data and not self:IsIconShown() then
self.iconFrame:SetWidth(epsilon)
end
local width
if not self.hasNoText then
self.textFrame:SetHeight(0)
self.textFrame:SetWidth(500)
width = self.textFrame:GetStringWidth() + 1
self.textFrame:SetWidth(width)
self.textFrame:SetHeight(self.textFrame:GetHeight())
end
if self.hasNoText or not self.textFrame:IsShown() then
self.frame:SetWidth(self.iconFrame:GetWidth())
if self.panel and self.panel:GetPluginSide(self) == "CENTER" then
self.panel:UpdateCenteredPosition()
end
elseif force or not self.textWidth or self.textWidth < width or self.textWidth - 8 > width then
self.textWidth = width
self.textFrame:SetWidth(width)
if self.iconFrame and self.iconFrame:IsShown() then
self.frame:SetWidth(width + self.iconFrame:GetWidth())
else
self.frame:SetWidth(width)
end
if self.panel and self.panel:GetPluginSide(self) == "CENTER" then
self.panel:UpdateCenteredPosition()
end
end
end
end
function lib:SetText(text)
if not self.textFrame then
return
end
self:assert(not self.hasNoText, "Cannot set text if self.hasNoText has been set. (" .. self:GetTitle() .. ")")
self:argCheck(text, 2, "string", "number")
if text == "" then
if self.hasIcon then
self:ShowIcon()
else
text = self:GetTitle()
end
end
if not self:IsTextColored() then
text = string.gsub(text, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1")
end
self.textFrame:SetText(text)
self:CheckWidth()
end
function lib:GetText()
self:assert(self.textFrame, "Cannot get text without a self.textFrame (" .. self:GetTitle() .. ")")
if not self.hasNoText then
return self.textFrame:GetText() or ""
end
end
function lib:IsIconShown()
if not self.hasIcon then
return false
elseif self.hasNoText then
return true
elseif not self.data then
return true
elseif not self.data.showIcon then
return true
else
return (self.data.showIcon == 1 or self.data.showIcon == true) and true or false
end
end
function lib:ToggleIconShown(loud)
self:assert(self.iconFrame, "Cannot toggle icon without a self.iconFrame (" .. self:GetTitle() .. ")")
self:assert(self.hasIcon, "Cannot show icon unless self.hasIcon is set. (" .. self:GetTitle() .. ")")
self:assert(not self.hasNoText, "Cannot hide icon if self.hasNoText is set. (" .. self:GetTitle() .. ")")
self:assert(self.textFrame, "Cannot hide icon if self.textFrame is not set. (" .. self:GetTitle() .. ")")
self:assert(self.iconFrame, "Cannot hide icon if self.iconFrame is not set. (" .. self:GetTitle() .. ")")
local value = not self:IsIconShown()
self.data.showIcon = value and 1 or 0
if loud then
self.cmd:status(loc.ARGUMENT_SHOWICON, value and 1 or 0, loc.MAP_ONOFF)
end
if value then
if self.textFrame:IsShown() and self.textFrame:GetText() == self:GetTitle() then
self.textFrame:Hide()
self.textFrame:SetText("")
end
self.iconFrame:Show()
self.iconFrame:SetWidth(self.iconFrame:GetHeight())
else
if not self.textFrame:IsShown() or not self.textFrame:GetText() then
self.textFrame:Show()
self.textFrame:SetText(self:GetTitle())
end
self.iconFrame:Hide()
self.iconFrame:SetWidth(epsilon)
end
self:CheckWidth(true)
return value
end
function lib:ShowIcon()
if not self:IsIconShown() then
self:ToggleIconShown()
end
end
function lib:HideIcon()
if self:IsIconShown() then
self:ToggleIconShown()
end
end
function lib:IsTextShown()
if not self.hasIcon then
return false
elseif self.hasNoText then
return false
elseif not self.data then
return true
elseif not self.data.showText then
return true
else
return (self.data.showText == 1 or self.data.showText == true) and true or false
end
end
function lib:ToggleTextShown(loud)
self:assert(not self.cannotHideText, "Cannot hide text unless self.cannotHideText is unset. (" .. self:GetTitle() .. ")")
self:assert(self.hasIcon, "Cannot show text unless self.hasIcon is set. (" .. self:GetTitle() .. ")")
self:assert(not self.hasNoText, "Cannot hide text if self.hasNoText is set. (" .. self:GetTitle() .. ")")
self:assert(self.textFrame, "Cannot hide text if self.textFrame is not set. (" .. self:GetTitle() .. ")")
self:assert(self.iconFrame, "Cannot hide text if self.iconFrame is not set. (" .. self:GetTitle() .. ")")
local value = not self:IsTextShown()
self.data.showText = value and 1 or 0
if loud then
self.cmd:status(loc.ARGUMENT_SHOWTEXT, value and 1 or 0, loc.MAP_ONOFF)
end
if value then
self.textFrame:Show()
self:UpdateText()
else
self.textFrame:SetText("")
self.textFrame:SetWidth(epsilon)
self.textFrame:Hide()
if not self:IsIconShown() then
DropDownList1:Hide()
end
self:ShowIcon()
end
self:CheckWidth(true)
return value
end
function lib:ShowText()
if not self:IsTextShown() then
self:ToggleTextShown()
end
end
function lib:HideText()
if self:IsTextShown() then
self:ToggleTextShown()
end
end
function lib:OpenChildFrame(child)
self:argCheck(child, 2, "table")
if FuBarPlugin.lastChildFrame then
FuBarPlugin.lastChildFrame:Hide()
end
FuBarPlugin.lastChildFrame = child
local frame = self.frame
local width, height = GetScreenWidth(), GetScreenHeight()
local anchor
if frame:GetLeft() <= width/2 then
anchor = "LEFT"
else
anchor = "RIGHT"
end
child:ClearAllPoints()
if frame:GetTop() <= height/2 then
child:SetPoint("BOTTOM" .. anchor, frame, "TOP" .. anchor)
local left = child:GetLeft()
child:ClearAllPoints()
child:SetPoint("LEFT", UIParent, "LEFT", left, 0)
child:SetPoint("BOTTOM", frame, "TOP")
else
child:SetPoint("TOP" .. anchor, frame, "BOTTOM" .. anchor)
local left = child:GetLeft()
child:ClearAllPoints()
child:SetPoint("LEFT", UIParent, "LEFT", left, 0)
child:SetPoint("TOP", frame, "BOTTOM")
end
child:Show()
end
local onClickTypes = {"OnClick", "OnDoubleClick", "OnMouseDown", "OnMouseUp"}
function lib:HookIntoPlugin(mother, style)
self:argCheck(mother, 2, "table", "nil")
self:argCheck(style, 3, "string", "nil")
if self.hookedPlugin then
ace:print(self:GetTitle() .. ": Cannot hook into a plugin while already hooked into another.")
return false
end
if not mother or type(mother) ~= "table" or getmetatable(self).__index ~= getmetatable(mother).__index then
ace:debug(self:GetTitle() .. ": Cannot hook into given plugin.")
return false
end
local showTitle = false
if style then
local a, b = string.find(style, "_TITLE")
if a and b then
showTitle = true
style = string.sub(style, 1, a - 1) .. string.sub(style, b + 1)
end
end
if style ~= "INLINE" and style ~= "SWITCH" and style ~= "SWITCHTEXT" then
style = "INLINE"
end
local child = self
local merged = false
local current = "MOTHER"
local mother__UpdateTooltip = mother._UpdateTooltip
local child_UpdateTooltip = child.UpdateTooltip
local mother_UpdateText = mother.UpdateText
local child_UpdateText = child.UpdateText
local child_Show = child.Show
local mother_funcs = {}
local mother_MenuSettings = mother.MenuSettings
local manualStandby = false
local motherIcon = mother:GetIcon()
local childIcon = child:GetIcon()
local merge, unmerge, switch
switch = function()
if current == "MOTHER" then
self.data["switch." .. mother:GetTitle()] = "CHILD"
current = "CHILD"
getmetatable(mother).__index.SetIcon(mother, childIcon)
else
self.data["switch." .. mother:GetTitle()] = "MOTHER"
current = "MOTHER"
getmetatable(mother).__index.SetIcon(mother, motherIcon)
end
mother:UpdateText()
mother:UpdateTooltip()
dewdrop:Close()
end
function self:SwitchPluginHook()
switch()
end
function self:IsCurrentPluginHookSwitch()
return current ~= "MOTHER"
end
merge = function()
merged = true
self.data["merge." .. mother:GetTitle()] = 1
if style == "INLINE" or style == "SWITCHTEXT" then
function mother:_UpdateTooltip()
mother__UpdateTooltip(mother)
if showTitle and not mother:IsTooltipDetached() then
tablet:AddCategory(
'text', child:GetTitle(),
'font', tablet:GetHeaderFontObject(),
'justify', "CENTER",
'isTitle', true
)
end
child:_UpdateTooltip()
end
elseif style == "SWITCH" then
function mother:_UpdateTooltip()
if current == "MOTHER" then
mother__UpdateTooltip(mother)
else
mother.tooltip:SetTitle(child:GetTitle())
child.tooltip = mother.tooltip
child:_UpdateTooltip()
end
end
end
function child:UpdateTooltip()
mother:UpdateTooltip()
end
local text
if style == "INLINE" then
function mother:SetText(t)
text = t
end
function child:SetText(t)
if text == "" or not text then
text = t
else
text = text .. " " .. t
end
end
elseif style == "SWITCH" or style == "SWITCHTEXT" then
function mother:SetText(t)
if current == "MOTHER" then
text = t
end
end
function child:SetText(t)
if current ~= "MOTHER" then
text = t
end
end
end
if style == "INLINE" then
function mother:UpdateText()
text = ""
if mother_UpdateText then
mother_UpdateText(mother)
end
if child_UpdateText then
child_UpdateText(child)
end
getmetatable(mother).__index.SetText(mother, text)
text = nil
end
elseif style == "SWITCH" or style == "SWITCHTEXT" then
function mother:UpdateText()
text = ""
if current == "MOTHER" and mother_UpdateText then
mother_UpdateText(mother)
end
if current ~= "MOTHER" and child_UpdateText then
child_UpdateText(child)
end
getmetatable(mother).__index.SetText(mother, text)
text = nil
end
end
child.UpdateText = mother.UpdateText
for _,name in onClickTypes do
local name = name
mother_funcs[name] = mother[name]
local child_func = child[name]
if style == "INLINE" then
if mother_funcs[name] and child_func then
mother[name] = function(self, alpha)
mother_funcs[name](mother, alpha)
child_func(child, alpha)
end
elseif child_func then
mother[name] = child_func
end
elseif style == "SWITCH" or style == "SWITCHTEXT" then
if mother_funcs[name] and child_func then
mother[name] = function(self, alpha)
if current == "MOTHER" and mother_funcs[name] ~= "nil" then
mother_funcs[name](mother, alpha)
elseif current ~= "MOTHER" and child_func then
child_func(child, alpha)
end
end
elseif child_func then
mother[name] = function(self, alpha)
if current ~= "MOTHER" and child_func then
child_func(child, alpha)
end
end
elseif mother_funcs[name] then
mother[name] = function(self, alpha)
if current == "MOTHER" and mother_funcs[name] ~= "nil" then
mother_funcs[name](mother, alpha)
end
end
end
end
if not mother_funcs[name] then
mother_funcs[name] = "nil"
end
end
if style == "SWITCH" or style == "SWITCHTEXT" then
function mother:SetIcon(path)
motherIcon = path
getmetatable(mother).__index.SetIcon(mother, path)
end
function child:SetIcon(path)
childIcon = path
getmetatable(mother).__index.SetIcon(mother, path)
end
end
function child:Show(panelId)
if panelId and panelId ~= 0 then
unmerge()
end
child_Show(self, panelId)
end
if not child.hideWithoutStandby then
manualStandby = true
child:EnableHideWithoutStandby()
end
child:Hide()
mother:UpdateText()
mother:UpdateTooltip()
end
unmerge = function()
merged = false
self.data["merge." .. mother:GetTitle()] = 0
mother._UpdateTooltip = mother__UpdateTooltip
child.UpdateTooltip = child_UpdateTooltip
mother.SetText = nil
child.SetText = nil
mother.SetIcon = nil
child.SetIcon = nil
mother.UpdateText = mother_UpdateText
child.UpdateText = child_UpdateText
for name,func in pairs(mother_funcs) do
if func == "nil" then
mother[name] = nil
else
mother[name] = func
end
end
child.Show = child_Show
if manualStandby then
child:DisableHideWithoutStandby()
manualStandby = false
end
mother:SetIcon(motherIcon)
mother:UpdateText()
mother:UpdateTooltip()
child:Show()
end
function mother:MenuSettings(level, value)
if level == 1 then
dewdrop:AddLine(
'text', format(loc.PATTERN_MERGE_WITH_CHILD, child:GetTitle()),
'func', function()
if merged then
unmerge()
else
if child.disabled then
child:EnableAddon()
end
merge()
end
end,
'checked', merged,
'hasArrow', merged and (style == "SWITCH" or style == "SWITCHTEXT"),
'value', child:GetTitle()
)
elseif level == 2 and value == child:GetTitle() then
dewdrop:AddLine(
'text', format(loc.PATTERN_SWITCH_TO_CHILD, child:GetTitle()),
'func', switch,
'checked', current ~= "MOTHER"
)
end
if merged then
if (style ~= "SWITCH" or (style == "SWITCH" and current == "MOTHER")) and mother_MenuSettings then
if level == 1 then
dewdrop:AddLine()
end
mother_MenuSettings(mother, level, value)
end
if (style ~= "SWITCH" or (style == "SWITCH" and current == "CHILD")) and child.MenuSettings then
if level == 1 then
dewdrop:AddLine()
dewdrop:AddLine(
'text', child:GetTitle(),
'isTitle', true
)
end
child:MenuSettings(level, value)
end
else
if mother_MenuSettings then
if level == 1 then
dewdrop:AddLine()
end
mother_MenuSettings(mother, level, value)
end
end
end
if not self.data["merge." .. mother:GetTitle()] then
self.data["merge." .. mother:GetTitle()] = 1
end
if (style == "SWITCH" or style == "SWITCHTEXT") and not self.data["switch." .. mother:GetTitle()] then
self.data["switch." .. mother:GetTitle()] = "MOTHER"
end
if self.data["merge." .. mother:GetTitle()] == 1 then
merge()
end
if style == "SWITCH" or style == "SWITCHTEXT" then
if self.data["switch." .. mother:GetTitle()] == "MOTHER" then
self.data["switch." .. mother:GetTitle()] = "CHILD"
else
self.data["switch." .. mother:GetTitle()] = "MOTHER"
end
current = self.data["switch." .. mother:GetTitle()]
switch()
end
self.hookedPlugin = mother
return true
end
function lib:IsTooltipDetached()
if not tablet.registry[self.frame] then
self:UpdateTooltip()
end
return not tablet:IsAttached(self.frame)
end
function lib:DetachTooltip()
self:UpdateTooltip()
tablet:Detach(self.frame)
end
function lib:ReattachTooltip()
self:UpdateTooltip()
tablet:Attach(self.frame)
end
function lib:GetName()
return self.name
end
function lib:GetCategory()
return self.category
end
function lib:GetFrame()
return self.frame
end
function lib:GetPanel()
return self.panel
end
function lib:GetDefaultPosition()
return self.defaultPosition or "LEFT"
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
function lib:SetPanel(panel)
if panel then
self:assert(IsCorrectPanel(panel), "Panel does not have the correct API.")
end
self.panel = panel
end
function lib:SetFontSize(size)
self:assert(not self.userDefinedFrame, "You must provide a SetFontSize(size) method if you provide your own frame.")
if self.hasIcon then
self:assert(self.iconFrame, (self.name and self.name .. ": " or "") .. "No iconFrame found")
self.iconFrame:SetWidth(size + 3)
self.iconFrame:SetHeight(size + 3)
end
if not self.hasNoText then
self:assert(self.textFrame, (self.name and self.name .. ": " or "") .. "No textFrame found")
local font, _, flags = self.textFrame:GetFont()
self.textFrame:SetFont(font, size, flags)
end
self:CheckWidth()
end
function lib:SetLoadOnDemand(lod)
self:argCheck(lod, 2, "boolean")
self._loadOnDemand = lod
end
function lib:IsLoadOnDemand()
return self._loadOnDemand
end
function lib:IsDisabled()
return self.disabled
end
local function cleanDefaults(t, defaults, notFirst)
if defaults then
for k,v in pairs(defaults) do
if type(v) == "table" then
if type(t[k]) == "table" then
cleanDefaults(t[k], v, true)
if next(t[k]) == nil then
t[k] = nil
end
end
elseif t[k] == v then
t[k] = nil
elseif t[k] == true and v == TRUE then
t[k] = nil
elseif t[k] == TRUE and v == true then
t[k] = nil
end
end
for k,v in pairs(t) do
if v == false and not defaults[k] then
t[k] = nil
end
end
end
if not notFirst then
if next(t) == "version" and next(t, "version") == nil then
t.version = nil
return true
end
end
return false
end
function RegisterTablet(self)
if not tablet:IsRegistered(self.frame) then
local FuBar_data = FuBar and (FuBar.db and FuBar.db.profile or FuBar.data)
tablet:Register(self.frame,
'children', function()
tablet:SetTitle(self:GetTitle())
self:_UpdateTooltip()
end,
'clickable', self.clickableTooltip,
'data', FuBar and FuBar_data.tooltip or self.data.detachedTooltip,
'detachedData', self.data.detachedTooltip,
'point', function(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,
'menu', function(level, value, valueN_1, valueN_2, valueN_3, valueN_4)
if self.MenuSettings then
self:MenuSettings(level, value, true, valueN_1, valueN_2, valueN_3, valueN_4)
end
end
)
end
end
function lib:RegisterForLoad()
if not self.defaults then
self.defaults = {}
end
if not self.defaults.detachedTooltip then
self.defaults.detachedTooltip = {}
end
if not self.cmd then
local title = string.lower(self:GetTitle())
self.cmd = AceChatCmd:new({"/" .. string.gsub(title, " ", "_"), "/" .. string.gsub(title, " ", "")}, {})
end
_,_,self.folderName = string.find(debugstack(2, 1, 0), "\\AddOns\\(.*)\\")
self.versionNumber = VersionToNumber(self.version)
if not self.frame then
local name = "FuBarPlugin" .. self:GetTitle() .. "Frame"
local frame = getglobal(name)
if not frame or not getglobal(name .. "Text") or not getglobal(name .. "Icon") then
frame = getmetatable(self).__index.CreateBasicPluginFrame(self, name)
local icon = frame:CreateTexture(name .. "Icon", "ARTWORK")
icon:SetWidth(16)
icon:SetHeight(16)
icon:SetPoint("LEFT", frame, "LEFT")
local text = frame:CreateFontString(name .. "Text", "ARTWORK")
text:SetWidth(134)
text:SetHeight(24)
text:SetPoint("LEFT", icon, "RIGHT", 0, 1)
text:SetFontObject(GameFontNormal)
end
self.frame = frame
self.textFrame = getglobal(self.frame:GetName() .. "Text")
self.iconFrame = getglobal(self.frame:GetName() .. "Icon")
else
self.userDefinedFrame = true
end
self.frame.plugin = self
self.frame:SetParent(UIParent)
self.frame:SetPoint("RIGHT", UIParent, "LEFT", -5, 0)
self.frame:Hide()
if not self.UpdateData then
self.UpdateData = function(self) end
end
if not self.UpdateText then
if self.hasNoText then
self.UpdateText = function(self) end
else
self.UpdateText = function(self)
self:SetText(self:GetTitle())
end
end
end
if not self.UpdateTooltip then
self.UpdateTooltip = function(self) end
end
if self.hasIcon then
self:SetIcon(self.hasIcon)
if not self.cmd.options then
self.cmd.options = {}
end
table.insert(self.cmd.options, {
option = loc.ARGUMENT_SHOWICON,
desc = loc.TEXT_TOGGLE_WHETHER_TO_SHOW_THE_ICON,
method = "ToggleIconShown"
})
local old_Enable = self.Enable
function self:Enable()
if old_Enable then
old_Enable(self)
end
if self:IsIconShown() then
self.iconFrame:Show()
else
self.iconFrame:Hide()
end
self:CheckWidth(true)
end
local old_Report = self.Report
if old_Report then
function self:Report()
old_Report(self)
ace:print(" - ", format(ACE_CMD_REPORT_LINE, loc.ARGUMENT_SHOWICON, loc.MAP_ONOFF[self:IsIconShown() and 1 or 0]))
end
else
function self:Report()
local report = compost and compost:Acquire(
compost:AcquireHash(
'text', loc.ARGUMENT_SHOWICON,
'val', self:IsIconShown() and 1 or 0,
'map', loc.MAP_ONOFF
)
) or {{
text = loc.ARGUMENT_SHOWICON,
val = self:IsIconShown() and 1 or 0,
map = loc.MAP_ONOFF
}}
self.cmd:report(report)
if compost then
compost:Reclaim(report, 1)
end
end
end
end
if not self.textFrame or not self.hasIcon then
self.cannotHideText = true
end
if not self.cannotHideText then
table.insert(self.cmd.options, {
option = loc.ARGUMENT_SHOWTEXT,
desc = loc.TEXT_TOGGLE_WHETHER_TO_SHOW_TEXT,
method = "ToggleTextShown"
})
local old_Enable = self.Enable
function self:Enable()
if old_Enable then
old_Enable(self)
end
if self:IsTextShown() then
self.textFrame:Show()
else
self.textFrame:Hide()
end
self:CheckWidth(true)
end
local old_Report = self.Report
if old_Report then
function self:Report()
old_Report(self)
ace:print(" - ", format(ACE_CMD_REPORT_LINE, loc.ARGUMENT_SHOWTEXT, loc.MAP_ONOFF[self:IsTextShown() and 1 or 0]))
end
else
function self:Report()
local report = compost and compost:Acquire(
compost:AcquireHash(
'text', loc.ARGUMENT_SHOWTEXT,
'val', self:IsTextShown() and 1 or 0,
'map', loc.MAP_ONOFF
)
) or {{
text = loc.ARGUMENT_SHOWTEXT,
val = self:IsTextShown() and 1 or 0,
map = loc.MAP_ONOFF
}}
self.cmd:report(report)
compost:Reclaim(report, 1)
end
end
end
if self.hideWithoutStandby then
self:EnableHideWithoutStandby()
end
local old_Enable = self.Enable
function self:Enable()
if old_Enable then
old_Enable(self)
end
if not self.hideWithoutStandby or not self.data.hidden then
self:Show()
end
self:RegisterEvent("ACE_PROFILE_LOADED", "_OnAceProfileLoaded")
if not self.overrideTooltip and not self.cannotDetachTooltip and self.data.detachedTooltip and self.data.detachedTooltip.detached then
self:DetachTooltip()
end
end
if self.db then
local old_Initialize = self.Initialize
function self:Initialize()
local t = self.db._table
if not t.profiles then
t.profiles = {}
end
if not t.profiles[self.profilePath[2]] then
t.profiles[self.profilePath[2]] = {}
end
if not t.realms then
t.realms = {}
end
if not t.realms[GetRealmName() .. UnitFactionGroup("player")] then
t.realms[GetRealmName() .. UnitFactionGroup("player")] = {}
end
if type(self.chardb) ~= "string" then
if not t.chars then
t.chars = {}
end
if not t.chars[GetRealmName() .. UnitName("player")] then
t.chars[GetRealmName() .. UnitName("player")] = {}
end
self.charData = t.chars[GetRealmName() .. UnitName("player")]
else
local c = getglobal(self.chardb)
if type(c) ~= "table" then
setglobal(self.chardb, {})
c = getglobal(self.chardb)
end
self.charData = c
end
if not t.classes then
t.classes = {}
end
if not t.classes[UnitClass("player")] then
t.classes[UnitClass("player")] = {}
end
if not t.full then
t.full = {}
end
self.data = t.profiles[self.profilePath[2]]
inheritDefaults(self.data, self.defaults)
self.realmData = t.realms[GetRealmName() .. UnitFactionGroup("player")]
inheritDefaults(self.realmData, self.realmDefaults)
inheritDefaults(self.charData, self.charDefaults)
self.classData = t.classes[UnitClass("player")]
inheritDefaults(self.classData, self.classDefaults)
self.fullData = t.full
inheritDefaults(self.fullData, self.fullDefaults)
self.data.version = VersionToNumber(self.data.version)
self.charData.version = VersionToNumber(self.charData.version)
self.classData.version = VersionToNumber(self.classData.version)
self.realmData.version = VersionToNumber(self.realmData.version)
self.fullData.version = VersionToNumber(self.fullData.version)
if self.data.version >= 500 then
self.data.version = self.data.version / 100
self.charData.version = self.charData.version / 100
self.classData.version = self.classData.version / 100
self.realmData.version = self.realmData.version / 100
self.fullData.version = self.fullData.version / 100
end
if old_Initialize then
old_Initialize(self)
end
self.data.version = VersionToNumber(self.version)
self.charData.version = VersionToNumber(self.version)
self.classData.version = VersionToNumber(self.version)
self.realmData.version = VersionToNumber(self.version)
self.fullData.version = VersionToNumber(self.version)
end
elseif FuBar then
local old_Initialize = self.Initialize
function self:Initialize()
local FuBarDB = FuBar2DB or FuBarDB
if not FuBarDB.pluginDB then
FuBarDB.pluginDB = {}
end
if not FuBarDB.pluginDB[self:GetTitle()] then
FuBarDB.pluginDB[self:GetTitle()] = {}
end
local t = FuBarDB.pluginDB[self:GetTitle()]
if not t.profiles then
t.profiles = {}
end
if not t.profiles.default then
t.profiles.default = {}
end
if not t.realms then
t.realms = {}
end
if not t.realms[GetRealmName() .. UnitFactionGroup("player")] then
t.realms[GetRealmName() .. UnitFactionGroup("player")] = {}
end
if type(self.chardb) ~= "string" then
if not t.chars then
t.chars = {}
end
if not t.chars[GetRealmName() .. UnitName("player")] then
t.chars[GetRealmName() .. UnitName("player")] = {}
end
self.charData = t.chars[GetRealmName() .. UnitName("player")]
else
local c = getglobal(self.chardb)
if type(c) ~= "table" then
setglobal(self.chardb, {})
c = getglobal(self.chardb)
end
self.charData = c
end
if not t.classes then
t.classes = {}
end
if not t.classes[UnitClass("player")] then
t.classes[UnitClass("player")] = {}
end
if not t.full then
t.full = {}
end
self.data = t.profiles["default"]
inheritDefaults(self.data, self.defaults)
self.realmData = t.realms[GetRealmName() .. UnitFactionGroup("player")]
inheritDefaults(self.realmData, self.realmDefaults)
inheritDefaults(self.charData, self.charDefaults)
self.classData = t.classes[UnitClass("player")]
inheritDefaults(self.classData, self.classDefaults)
self.fullData = t.full
inheritDefaults(self.fullData, self.fullDefaults)
if old_Initialize then
old_Initialize(self)
end
self.data.version = VersionToNumber(self.version)
self.charData.version = VersionToNumber(self.version)
self.classData.version = VersionToNumber(self.version)
self.realmData.version = VersionToNumber(self.version)
self.fullData.version = VersionToNumber(self.version)
if self.data.disabled then
self:DisableAddon()
end
end
else
local old_Initialize = self.Initialize
function self:Initialize()
self.data = {}
self.charData = {}
self.classData = {}
self.realmData = {}
self.fullData = {}
if old_Initialize then
old_Initialize(self)
end
self.data.version = VersionToNumber(self.version)
self.charData.version = VersionToNumber(self.version)
self.classData.version = VersionToNumber(self.version)
self.realmData.version = VersionToNumber(self.version)
self.fullData.version = VersionToNumber(self.version)
end
end
local old_Disable = self.Disable
function self:Disable()
if old_Disable then
old_Disable(self)
end
self:Hide()
end
if not self.overrideTooltip then
self._UpdateTooltip = self.UpdateTooltip
function self:UpdateTooltip()
RegisterTablet(self)
tablet:Refresh(self.frame)
end
end
local self_Initialize = self.Initialize
function self:Initialize()
self_Initialize(self)
local profilePlugin = FuBar and FuBar:GetPluginProfiling()
if self == profilePlugin then
local start = GetTime()
local tree = {}
local treeMemories = {}
local treeTimes = {}
local memories = {}
local times = {}
local aname = self.name
for name,value in pairs(self) do
if type(value) == "function" and name ~= "Initialize" then
local oldFunction = value
local name = name
local rName = name
if name == "UpdateTooltip" then
name = "tablet:Refresh"
elseif name == "_UpdateTooltip" then
name = "UpdateTooltip"
end
if strsub(name, 1, 1) ~= "_" then
memories[name] = 0
times[name] = 0
self[rName] = function(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
local pos = table.getn(tree)
table.insert(tree, name)
table.insert(treeMemories, 0)
table.insert(treeTimes, 0)
local t, mem = GetTime(), gcinfo()
local r1, r2, r3, r4, r5, r6, r7, r8 = oldFunction(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
mem, t = gcinfo() - mem, GetTime() - t
if pos > 0 then
treeMemories[pos] = treeMemories[pos] + mem
treeTimes[pos] = treeTimes[pos] + t
end
local otherMem = table.remove(treeMemories)
if mem - otherMem > 0 then
memories[name] = memories[name] + mem - otherMem
end
times[name] = times[name] + t - table.remove(treeTimes)
table.remove(tree)
return r1, r2, r3, r4, r5, r6, r7, r8
end
end
end
end
if not self.cmd.options then
self.cmd.options = {}
end
table.insert(self.cmd.options, {
option = loc.ARGUMENT_PROFILE,
desc = loc.TEXT_LIST_PROFILING_INFO,
method = "_ListProfileInfo"
})
function self:_ListProfileInfo()
local duration = GetTime() - start
for name in pairs(memories) do
local mem = memories[name]
local time = times[name]
DEFAULT_CHAT_FRAME:AddMessage(string.format("%.3fs / %.3fs (%.3f%%) || %s (%d KiB)", times[name], duration, times[name] / duration * 100, name, memories[name]))
end
end
function self:GetProfileInfo()
return GetTime() - start, times, memories
end
end
end
if self.defaultPosition ~= "LEFT" and self.defaultPosition ~= "CENTER" and self.defaultPosition ~= "RIGHT" and self.defaultPosition ~= "MINIMAP" then
self.defaultPosition = "LEFT"
end
if type(self.defaultMinimapPosition) ~= "number" then
self.defaultMinimapPosition = math.random(1, 360)
end
self.frame:RegisterEvent("PLAYER_LOGOUT")
local OnEvent = self.frame:GetScript("OnEvent")
self.frame:SetScript("OnEvent", function()
if OnEvent then
OnEvent()
end
if event == "PLAYER_LOGOUT" then
local t
if self.db then
t = self.db._table
elseif FuBar then
local FuBarDB = FuBar2DB or FuBarDB
t = FuBarDB.pluginDB[self:GetTitle()]
else
return
end
if cleanDefaults(self.data, self.defaults) then
if self.db then
t.profiles[self.profilePath[2]] = nil
else
t.profiles["default"] = nil
end
if not next(t.profiles) then
t.profiles = nil
end
end
if cleanDefaults(self.charData, self.charDefaults) then
if type(self.chardb) ~= "string" then
t.chars[ace.char.realm .. ace.char.name] = nil
if not next(t.chars) then
t.chars = nil
end
else
setglobal(self.chardb, nil)
end
end
if cleanDefaults(self.fullData, self.fullDefaults) then
t.full = nil
end
if cleanDefaults(self.realmData, self.realmDefaults) then
t.realms[ace.char.realm .. ace.char.faction] = nil
if not next(t.realms) then
t.realms = nil
end
end
if cleanDefaults(self.classData, self.classDefaults) then
t.classes[ace.char.class] = nil
if not next(t.classes) then
t.classes = nil
end
end
if not next(t) then
if self.db then
setglobal(self.db.name, nil)
else
local FuBarDB = FuBar2DB or FuBarDB
FuBarDB.pluginDB[self:GetTitle()] = nil
end
end
end
end)
local old_Initialize = self.Initialize
local initialized = false
function self:Initialize()
if initialized then
return
end
initialized = true
if old_Initialize then
old_Initialize(self)
end
end
local enabled = false
local old_Enable = self.Enable
function self:Enable()
if not enabled and old_Enable then
enabled = true
old_Enable(self)
elseif not old_Enable then
enabled = true
end
end
local old_Disable = self.Disable
function self:Disable()
if enabled and old_Disable then
enabled = false
old_Disable(self)
elseif not old_Disable then
enabled = false
end
end
AceAddon.RegisterForLoad(self)
if FuBar then
FuBar:RegisterPlugin(self)
end
end
function lib:GetLibraryVersion()
return MAJOR_VERSION, MINOR_VERSION
end
function lib:LibActivate(stub, oldLib, oldList)
end
function lib:LibDeactivate()
end
function lib:new(o)
local mt = { __index = self }
if type(o) ~= "table" then
o = {}
end
return setmetatable(o, mt)
end
function lib:CreateBasicPluginFrame(name)
local frame = CreateFrame("Button", name, UIParent)
frame:SetFrameStrata("HIGH")
frame:EnableMouse(true)
frame:EnableMouseWheel(true)
frame:SetMovable(true)
frame:SetWidth(150)
frame:SetHeight(24)
frame:SetPoint("CENTER", UIParent, "CENTER")
frame:SetScript("OnClick", function()
if type(self.OnClick) == "function" then
self:OnClick()
end
end)
frame:SetScript("OnDoubleClick", function()
if type(self.OnDoubleClick) == "function" then
self:OnDoubleClick()
end
end)
frame:SetScript("OnMouseDown", function()
if arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
self:OpenMenu()
return
else
HideDropDownMenu(1)
if type(self.OnMouseDown) == "function" then
self:OnMouseDown(arg1)
end
end
end)
frame:SetScript("OnMouseUp", function()
if type(self.OnMouseUp) == "function" then
self:OnMouseUp(arg1)
end
end)
return frame
end
function lib:CreatePluginChildFrame(frameType, name, parent)
assert(self.frame, "You must have self.frame declared in order to add child frames")
self:argCheck(frameType, 1, "string")
local child = CreateFrame(frameType, name, parent)
if parent then
child:SetFrameLevel(parent:GetFrameLevel() + 2)
end
child:SetScript("OnEnter", function()
if self.frame:GetScript("OnEnter") then
self.frame:GetScript("OnEnter")()
end
end)
child:SetScript("OnLeave", function()
if self.frame:GetScript("OnLeave") then
self.frame:GetScript("OnLeave")()
end
end)
if child:HasScript("OnClick") then
child:SetScript("OnClick", function()
if self.frame:HasScript("OnClick") and self.frame:GetScript("OnClick") then
self.frame:GetScript("OnClick")()
end
end)
end
if child:HasScript("OnDoubleClick") then
child:SetScript("OnDoubleClick", function()
if self.frame:HasScript("OnDoubleClick") and self.frame:GetScript("OnDoubleClick") then
self.frame:GetScript("OnDoubleClick")()
end
end)
end
child:SetScript("OnMouseDown", function()
if self.frame:GetScript("OnMouseDown") then
self.frame:GetScript("OnMouseDown")()
end
end)
child:SetScript("OnMouseUp", function()
if self.frame:GetScript("OnMouseUp") then
self.frame:GetScript("OnMouseUp")()
end
end)
return child
end
function lib:OpenMenu(frame)
if not frame then
frame = self:GetFrame()
end
if not frame or not self:GetFrame() or dewdrop:IsOpen(frame) then
dewdrop:Close()
return
end
tablet:Close()
if not dewdrop:IsRegistered(self:GetFrame()) then
dewdrop:Register(self:GetFrame(),
'children', function(level, value, valueN_1, valueN_2, valueN_3, valueN_4)
if level == 1 then
dewdrop:AddLine(
'text', self:GetTitle(),
'isTitle', true
)
end
if self.MenuSettings then
self:MenuSettings(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4)
end
if level == 1 and not self.overrideMenu then
if self.MenuSettings then
dewdrop:AddLine()
end
self:AddImpliedMenuOptions()
end
if level == 1 then
dewdrop:AddLine(
'text', CLOSE,
'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
dewdrop:Open(self:GetFrame())
else
dewdrop:Open(frame, self:GetFrame())
end
end
FuBarPlugin:Register(lib)
lib = nil
if not FuBarPlugin.new then
function FuBarPlugin:new(o)
self:GetInstance(MAJOR_VERSION):assert(type(o) == "table", "You must provide a table to register")
local name
if o.name then
name = o.name .. ": "
else
name = ""
end
self:GetInstance(MAJOR_VERSION):assert(o.fuCompatible, name .. "You must provide a fuCompatible field.")
local compatNumber = VersionToNumber(o.fuCompatible)
if compatNumber >= 500 then
compatNumber = compatNumber / 100
end
if compatNumber < 101 then
return self.versions["1.0"] and self:GetInstance("1.0"):new(o)
elseif compatNumber < 103 then
return self.versions["1.2"] and self:GetInstance("1.2"):new(o)
end
end
end
end
-- MinimapContainer
do
local lib = {}
local initialized = false
function lib:Initialize()
if initialized then
return
end
initialized = true
self.plugins = {}
end
function lib:AddPlugin(plugin)
if FuBar and FuBar:IsChangingProfile() then
return
end
self:Initialize()
if plugin.panel ~= nil then
plugin.panel:RemovePlugin(plugin)
end
plugin.panel = self
if not plugin.minimapFrame then
local frame = CreateFrame("Button", plugin.frame:GetName() .. "MinimapButton", Minimap)
plugin.minimapFrame = frame
RegisterTablet(plugin)
tablet:Register(frame, plugin.frame)
frame.plugin = plugin
frame:SetWidth(31)
frame:SetHeight(31)
frame:SetFrameStrata("LOW")
frame:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
local icon = frame:CreateTexture(frame:GetName() .. "Icon", "BACKGROUND")
plugin.minimapIcon = icon
local path = plugin:GetIcon() or (plugin.iconFrame and plugin.iconFrame:GetTexture()) or "Interface\\Icons\\INV_Misc_QuestionMark"
icon:SetTexture(path)
if string.sub(path, 1, 16) == "Interface\\Icons\\" then
icon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
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.plugin = plugin
if type(plugin.OnClick) == "function" then
frame:SetScript("OnClick", function()
if not this.dragged then
plugin:OnClick(arg1)
end
end)
end
if type(plugin.OnDoubleClick) == "function" then
frame:SetScript("OnDoubleClick", function()
plugin:OnDoubleClick(arg1)
end)
end
frame:SetScript("OnMouseDown", function()
this.dragged = false
if arg1 == "LeftButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
HideDropDownMenu(1)
if type(plugin.OnMouseDown) == "function" then
plugin:OnMouseDown(arg1)
end
elseif arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
plugin:OpenMenu(frame)
else
HideDropDownMenu(1)
if type(plugin.OnMouseDown) == "function" then
plugin:OnMouseDown(arg1)
end
end
if plugin.OnClick or plugin.OnMouseDown or plugin.OnMouseUp or plugin.OnDoubleClick then
if string.sub(this.plugin.minimapIcon:GetTexture(), 1, 16) == "Interface\\Icons\\" then
plugin.minimapIcon:SetTexCoord(0.14, 0.86, 0.14, 0.86)
else
plugin.minimapIcon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
end
end
end)
frame:SetScript("OnMouseUp", function()
if not this.dragged and type(plugin.OnMouseUp) == "function" then
plugin:OnMouseUp(arg1)
end
if string.sub(this.plugin.minimapIcon:GetTexture(), 1, 16) == "Interface\\Icons\\" then
plugin.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
else
plugin.minimapIcon:SetTexCoord(0, 1, 0, 1)
end
end)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", self.OnDragStart)
frame:SetScript("OnDragStop", self.OnDragStop)
end
plugin.frame:Hide()
plugin.minimapFrame:Show()
self:ReadjustLocation(plugin)
table.insert(self.plugins, plugin)
local exists = false
return true
end
function lib:RemovePlugin(index)
if FuBar and FuBar:IsChangingProfile() then
return
end
self:Initialize()
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(plugin.panel == self, "Plugin has improper panel field")
plugin:SetPanel(nil)
table.remove(t, index)
return true
end
function lib:ReadjustLocation(plugin)
local frame = plugin.minimapFrame
if not plugin.data.minimapPositionWild then
local position = plugin.data.minimapPosition or plugin.defaultMinimapPosition or math.random(1, 360)
local angle = math.rad(position or 0)
local x = math.cos(angle) * 80
local y = math.sin(angle) * 80
frame:SetPoint("CENTER", Minimap, "CENTER", x, y)
else
frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", plugin.data.minimapPositionX, plugin.data.minimapPositionY)
end
end
function lib:GetPlugin(index)
return self.plugins[index]
end
function lib:GetNumPlugins()
return table.getn(self.plugins)
end
function lib:IndexOfPlugin(plugin)
for i,p in ipairs(self.plugins) do
if p == plugin then
return i, "MINIMAP"
end
end
end
function lib:HasPlugin(plugin)
return self:IndexOfPlugin(plugin) ~= nil
end
function lib:GetPluginSide(plugin)
local index = self:IndexOfPlugin(plugin)
assert(index, "Plugin not in panel")
return "MINIMAP"
end
function lib.OnDragStart()
this.dragged = true
this:LockHighlight()
this:SetScript("OnUpdate", FuBarPlugin.MinimapContainer:GetInstance(MAJOR_VERSION).OnUpdate)
if string.sub(this.plugin.minimapIcon:GetTexture(), 1, 16) == "Interface\\Icons\\" then
this.plugin.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
else
this.plugin.minimapIcon:SetTexCoord(0, 1, 0, 1)
end
end
function lib.OnDragStop()
this:SetScript("OnUpdate", nil)
this:UnlockHighlight()
end
function lib.OnUpdate()
if not IsAltKeyDown() then
local mx, my = Minimap:GetCenter()
local px, py = GetCursorPosition()
local scale = UIParent:GetEffectiveScale()
px, py = px / scale, py / scale
local lastPosition = this.plugin.data.minimapPosition
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
this.plugin.data.minimapPosition = position
this.plugin.data.minimapPositionX = nil
this.plugin.data.minimapPositionY = nil
this.plugin.data.minimapPositionWild = nil
else
local px, py = GetCursorPosition()
local scale = UIParent:GetEffectiveScale()
px, py = px / scale, py / scale
this.plugin.data.minimapPositionX = px
this.plugin.data.minimapPositionY = py
this.plugin.data.minimapPosition = nil
this.plugin.data.minimapPositionWild = true
end
FuBarPlugin.MinimapContainer:GetInstance(MAJOR_VERSION):ReadjustLocation(this.plugin)
end
function lib:GetLibraryVersion()
return MAJOR_VERSION, MINOR_VERSION
end
function lib:LibActivate(stub, oldLib, oldList)
end
function lib:LibDeactivate()
end
FuBarPlugin.MinimapContainer:Register(lib)
lib = nil
end