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