--[[ Name: Bazooka Author(s): mitch0 Website: http://www.wowace.com/projects/bazooka/ Description: Bazooka is a FuBar like broker display License: Public Domain ]] local AppName, Bazooka = ... local OptionsAppName = AppName .. "_Options" local VERSION = AppName .. "-v3.0.5" local LDB = LibStub:GetLibrary("LibDataBroker-1.1") local LSM = LibStub:GetLibrary("LibSharedMedia-3.0", true) local LibDualSpec = LibStub:GetLibrary("LibDualSpec-1.0", true) local Jostle = LibStub:GetLibrary("LibJostle-3.0", true) local L = LibStub("AceLocale-3.0"):GetLocale(AppName) -- internal vars -- Remove all related ifs when the opacity setting for embedded icons gets fixed local EnableOpacityWorkaround = false -- loaded from global options -- Remove all related ifs when the setting for gradient background gets fixed local EnableGradientWorkaround = true local _ -- throwaway local uiScale = 1.0 -- just to be safe... local function makeColor(r, g, b, a) return { ["r"] = r, ["g"] = g, ["b"] = b, ["a"] = a } end local function colorToHex(color) return ("%02x%02x%02x%02x"):format((color.a and color.a * 255 or 255), color.r*255, color.g*255, color.b*255) end local function getTexture(textureName, region, ...) if not region then return end if region.GetTexture and region:GetTexture() == textureName then return region end return getTexture(textureName, ...) end -- cached stuff local _G = _G local IsClassic = false or (_G.WOW_PROJECT_ID == _G.WOW_PROJECT_CLASSIC) or (_G.WOW_PROJECT_ID == _G.WOW_PROJECT_BURNING_CRUSADE_CLASSIC) or (_G.WOW_PROJECT_ID == _G.WOW_PROJECT_WRATH_CLASSIC) local IsAltKeyDown = _G.IsAltKeyDown local IsShiftKeyDown = _G.IsShiftKeyDown local IsModifierKeyDown = _G.IsModifierKeyDown local GetCursorPosition = _G.GetCursorPosition local GetAddOnInfo = _G.GetAddOnInfo local GetScreenWidth = _G.GetScreenWidth local GetScreenHeight = _G.GetScreenHeight local UIParent = _G.UIParent local CreateFrame = _G.CreateFrame local InCombatLockdown = _G.InCombatLockdown local tinsert = _G.tinsert local tremove = _G.tremove local tostring = _G.tostring local tonumber = _G.tonumber local print = _G.print local pairs = _G.pairs local type = _G.type local unpack = _G.unpack local wipe = _G.wipe local math = _G.math local GameTooltip = _G.GameTooltip local IsInPetBattle = _G.C_PetBattles and _G.C_PetBattles.IsInBattle or function() return false end local strtrim = _G.strtrim local strsub = _G.strsub local strlen = _G.strlen local strsplit = _G.strsplit -- hard-coded config stuff local Defaults = { bgTexture = "Blizzard Tooltip", bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], -- bgTexture = "Blizzard Dialog Background", -- bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]], -- edgeTexture = "Blizzard Tooltip", -- edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeTexture = "None", edgeFile = false, fontName = "Friz Quadrata TT", fontPath = GameFontNormal:GetFont(), minFrameWidth = 10, minFrameHeight = 10, maxFrameWidth = 2000, maxFrameHeight = 50, fadeOutDelay = 0.5, fadeOutDuration = 0.5, fadeInDuration = 0.25, } local BarDefaults = { hidden = false, marked = false, fadeInCombat = false, fadeOutOfCombat = false, disableMouseInCombat = true, disableMouseOutOfCombat = false, disableDuringPetBattle = true, fadeAlpha = 0.4, point = "TOP", relPoint = "TOP", x = 0, y = -50, tweakLeft = 0, tweakRight = 0, tweakTop = 0, tweakBottom = 0, leftMargin = 8, rightMargin = 8, leftSpacing = 8, rightSpacing = 8, centerSpacing = 16, iconTextSpacing = 2, font = Defaults.fontName, fontSize = 12, fontOutline = "", fontShadow = true, iconSize = 16, labelColor = makeColor(0.9, 0.9, 0.9), textColor = makeColor(1.0, 0.82, 0), suffixColor = makeColor(0, 0.82, 0), pluginOpacity = 1.0, attach = 'none', fitToContentWidth = false, strata = "MEDIUM", frameWidth = 256, frameHeight = 20, bgEnabled = true, bgTextureType = 'background', bgTexture = Defaults.bgTexture, bgBorderTexture = Defaults.edgeTexture, bgTile = false, bgTileSize = 32, bgEdgeSize = 16, bgColor = makeColor(0, 0, 0, 1.0), bgGradientColor = makeColor(0, 0, 0, 0), bgBorderColor = makeColor(0.8, 0.6, 0.0, 1.0), } local PluginDefaults = { enabled = false, bar = 1, area = 'left', pos = nil, hideTipOnClick = true, disableTooltip = false, disableTooltipInCombat = true, disableMouseInCombat = false, disableMouseOutOfCombat = false, forceHideTip = false, showIcon = true, showLabel = true, showTitle = true, showText = true, showValue = false, showSuffix = false, useLabelAsTitle = false, shrinkThreshold = 5, overrideTooltipScale = false, tooltipScale = 1.0, iconBorderClip = 0.07, alignment = "LEFT", } local Icon = [[Interface\AddOns\]] .. AppName .. [[\bzk_locked.tga]] local UnlockedIcon = [[Interface\AddOns\]] .. AppName .. [[\bzk_unlocked.tga]] local HighlightImage = [[Interface\AddOns\]] .. AppName .. [[\highlight.tga]] local EmptyPluginWidth = 1 local NearSquared = 32 * 32 local MinDropPlaceHLDX = 3 local BzkDialogDisablePlugin = 'BAZOOKA_DISABLE_PLUGIN' local MaxTweakPts = 5 Bazooka = LibStub("AceAddon-3.0"):NewAddon(Bazooka, AppName, "AceEvent-3.0") _G.Bazooka = Bazooka Bazooka:SetDefaultModuleState(false) Bazooka.version = VERSION Bazooka.AppName = AppName Bazooka.Defaults = Defaults Bazooka.draggedFrame = nil Bazooka.bars = {} Bazooka.attachedBars = { ['top'] = {}, ['bottom'] = {}, } Bazooka.plugins = {} Bazooka.numBars = 0 Bazooka.AreaNames = { left = L["left"], cleft = L["cleft"], center = L["center"], cright = L["cright"], right = L["right"], } Bazooka.AttachNames = { top = L["top"], bottom = L["bottom"], none = L["none"], } -- Default DB stuff local defaults = { global = { plugins = PluginDefaults, bars = BarDefaults, autoApply = true, }, profile = { locked = false, adjustFrames = true, simpleTip = true, enableHL = true, disableDBIcon = true, numBars = 1, fadeOutDelay = Defaults.fadeOutDelay, fadeOutDuration = Defaults.fadeOutDuration, fadeInDuration = Defaults.fadeInDuration, bars = { ["**"] = BarDefaults, [1] = { attach = 'top', }, [2] = { attach = 'bottom', }, }, plugins = { ["*"] = { ["**"] = PluginDefaults, }, ["launcher"] = { ["**"] = { enabled = true, bar = 1, area = 'left', pos = nil, hideTipOnClick = true, disableTooltip = false, disableTooltipInCombat = true, disableMouseInCombat = false, disableMouseOutOfCombat = false, forceHideTip = false, showIcon = true, showLabel = false, showTitle = true, showText = false, shrinkThreshold = 0, overrideTooltipScale = false, tooltipScale = 1.0, iconBorderClip = 0.07, }, [AppName] = { pos = 1, }, }, ["data source"] = { ["**"] = { enabled = true, bar = 1, area = 'right', pos = nil, hideTipOnClick = true, disableTooltip = false, disableTooltipInCombat = true, disableMouseInCombat = false, disableMouseOutOfCombat = false, forceHideTip = false, showIcon = true, showLabel = false, showTitle = false, showText = true, shrinkThreshold = PluginDefaults.shrinkThreshold, overrideTooltipScale = false, tooltipScale = 1.0, iconBorderClip = 0.07, }, }, }, }, } local function deepCopy(src) local res = {} for k, v in pairs(src) do if type(v) == 'table' then v = deepCopy(v) end res[k] = v end return res end local function setDeepCopyIndex(proto) proto.__index = function(t, k) local v = proto[k] if type(v) == 'table' then v = deepCopy(v) end t[k] = v return v end end local function updateUIScale() uiScale = UIParent:GetEffectiveScale() end local function getScaledCursorPosition() local x, y = GetCursorPosition() return x / uiScale, y / uiScale end local function distance2(x1, y1, x2, y2) return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) end local function getDistance2Frame(x, y, frame) local left, bottom, width, height = frame:GetRect() local dx, dy = 0, 0 if left > x then dx = left - x elseif x > left + width then dx = x - (left + width) end if bottom > y then dy = bottom - y elseif y > bottom + height then dy = y - (bottom + height) end return dx * dx + dy * dy end local function setupTooltip(owner, ttFrame, dx, dy) ttFrame = ttFrame or GameTooltip if not owner then return ttFrame end if ttFrame.SetOwner then ttFrame:SetOwner(owner, "ANCHOR_NONE") end if ttFrame.ClearLines then ttFrame:ClearLines() end ttFrame:ClearAllPoints() local cx, cy = owner:GetCenter() if cy < GetScreenHeight() / 2 then ttFrame:SetPoint("BOTTOM", owner, "TOP", dx, dy) else ttFrame:SetPoint("TOP", owner, "BOTTOM", dx, dy) end return ttFrame end local function stripColors(text) return tostring(text):gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") end --------------------------------- -- BEGIN Bar stuff local function sumPluginsWidth(plugins) local w = 0 for i = 1, #plugins do w = w + plugins[i].frame:GetWidth() end return w end local Bar = { id = nil, name = nil, db = nil, frame = nil, centerFrame = nil, allPlugins = {}, plugins = { left = {}, cleft = {}, center = {}, cright = {}, right = {}, }, inset = 0, backdrop = nil, hl = nil, attach = nil, pos = nil, } setDeepCopyIndex(Bar) Bar.OnEnter = function(frame) local self = frame.bzkBar or frame.bzkPlugin.bar self.isMouseInside = true if InCombatLockdown() then if self.db.fadeInCombat then self:fadeIn() end else if self.db.fadeOutOfCombat then self:fadeIn() end end end Bar.OnLeave = function(frame) local self = frame.bzkBar or frame.bzkPlugin.bar self.isMouseInside = false if InCombatLockdown() then if self.db.fadeInCombat then self:fadeOut() end else if self.db.fadeOutOfCombat then self:fadeOut() end end end Bar.OnDragStart = function(frame, button) if Bazooka.locked then return end if Bazooka.tipOwner then Bazooka.tipOwner:hideTip(true) Bazooka.tipOwner = nil end local self = frame.bzkBar updateUIScale() frame:SetAlpha(0.7) Bazooka.draggedFrame = frame if button == "LeftButton" then Bazooka:detachBar(self) Bazooka:updateAnchors() self.isMoving = true frame:StartMoving() else self.isMoving = nil if IsAltKeyDown() then frame:StartSizing(self:getSizingPoint(getScaledCursorPosition())) end end end Bar.OnDragStop = function(frame) if not Bazooka.draggedFrame then return end local self = frame.bzkBar Bazooka.draggedFrame = nil frame:StopMovingOrSizing() frame:SetAlpha(1.0) local attach, pos = self.db.attach, nil Bazooka:detachBar(self) -- double detach doesn't hurt (in case we move) if not Bazooka.locked then if self.isMoving then if IsAltKeyDown() then if attach == 'none' then attach = 'top' else attach = 'none' end end if attach == 'none' then self.db.point, _, self.db.relPoint, self.db.x, self.db.y = frame:GetPoint() else local cx, cy = frame:GetCenter() if cy < GetScreenHeight() / 2 then attach = 'bottom' cy = frame:GetBottom() or cy local bars = Bazooka.attachedBars[attach] for i = 1, #bars do local cb = bars[i] local cby = tonumber(cb.frame:GetBottom()) if cy <= cby then pos = cb.db.pos break end end else attach = 'top' cy = frame:GetTop() or cy local bars = Bazooka.attachedBars[attach] for i = 1, #bars do local cb = bars[i] local cby = tonumber(cb.frame:GetTop()) if cy >= cby then pos = cb.db.pos break end end end end else pos = self.db.pos end self.db.frameWidth = self.frame:GetWidth() self.db.frameHeight = self.frame:GetHeight() else attach, pos = self.db.attach, self.db.pos end self.isMoving = nil Bazooka:attachBar(self, attach, pos) Bazooka:updateAnchors() Bazooka:updateBarOptions() end Bar.OnMouseDown = function(frame, button, ...) if Bazooka.locked then return end local self = frame.bzkBar if button == 'RightButton' and not IsAltKeyDown() then Bazooka:openConfigDialog(Bazooka.barOpts, Bazooka:getSubAppName("bars"), self:getOptionsName()) end end -- BEGIN EnableOpacityWorkaround Bar.setAlphaByParts = function(frame, alpha) frame.bzkAlpha = alpha local self = frame.bzkBar if self.db.bgEnabled then if self.bgt then self:setGradientBg() else self.frame:SetBackdropColor(self.db.bgColor.r, self.db.bgColor.g, self.db.bgColor.b, self.db.bgColor.a * alpha) end self.frame:SetBackdropBorderColor(self.db.bgBorderColor.r, self.db.bgBorderColor.g, self.db.bgBorderColor.b, self.db.bgBorderColor.a * alpha) end for name, plugin in pairs(self.allPlugins) do plugin.frame:SetAlpha(plugin.frame:GetAlpha()) end end Bar.getAlphaByParts = function(frame) return frame.bzkAlpha end -- END EnableOpacityWorkaround -- BEGIN EnableGradientWorkaround Bar.fixGradientOnSizeChanged = function(frame, w, h) local self = frame.bzkBar self:setGradientBg() end -- END EnableGradientWorkaround Bar.initialOnUpdateFixFontMetricHack = function(frame) -- fix miscalculated font metrics local self = frame.bzkBar self:globalSettingsChanged() frame:SetScript("OnUpdate", nil) end function Bar:New(id, db) local bar = setmetatable({}, Bar) bar:enable(id, db) bar:applySettings() return bar end function Bar:getOptionsName() return "bar" .. self.id end function Bar:createFadeAnim() self.fadeAnimGrp = self.frame:CreateAnimationGroup() self.fadeAnim = self.fadeAnimGrp:CreateAnimation() self.fadeAnim.bzkBar = self self.fadeAnim:SetScript("OnUpdate", function(anim) if not anim:IsDelaying() then anim:GetRegionParent():SetAlpha(anim.startAlpha + (anim.change * anim:GetSmoothProgress())) end end) self.fadeAnim:SetScript("OnPlay", function(anim) anim.startAlpha = anim:GetRegionParent():GetAlpha() end) self.fadeAnim:SetScript("OnFinished", function(anim, requested) -- FIXME: schedule fadeOut if necessary end) self.fadeAnim.SetChange = function(anim, change) anim.change = change end end function Bar:setFullyHidden(flag) if flag then self.isFullyHidden = true elseif self.isFullyHidden then -- force text update on plugins, the updates were disabled self.isFullyHidden = nil for name, plugin in pairs(self.allPlugins) do if plugin.text then plugin:setText() end end end end local function calcFadeAnimDuration(change, fullChange, fullDuration) if fullChange < 0.05 and fullChange > -0.05 then return 0 end return fullDuration * change / fullChange end function Bar:fadeIn(initAlpha) if self.fadeAnim then self.fadeAnimGrp:Stop() end if initAlpha then self.frame:SetAlpha(initAlpha) end self:setFullyHidden(false) local alpha = self.frame:GetAlpha() local change = 1.0 - alpha if change < 0.05 then self.frame:SetAlpha(1.0) return end local fullChange = 1.0 - self.db.fadeAlpha if alpha < self.db.fadeAlpha then fullChange = 1.0 end local duration = calcFadeAnimDuration(change, fullChange, Bazooka.db.profile.fadeInDuration) if duration < 0.01 then self.frame:SetAlpha(1.0) return end if not self.fadeAnim then self:createFadeAnim() end self.fadeAnim:SetStartDelay(0) self.fadeAnim:SetDuration(duration) self.fadeAnim:SetChange(change) self.fadeAnimGrp:Play() end function Bar:fadeOut(delay, fadeAlpha, initAlpha) if self.fadeAnim then self.fadeAnimGrp:Stop() end if initAlpha then self.frame:SetAlpha(initAlpha) end fadeAlpha = fadeAlpha or self.db.fadeAlpha if fadeAlpha < 0.05 then fadeAlpha = 0 self:setFullyHidden(true) -- this will disable text updates (see Plugin:setText() and Bar:fadeIn()), partial fix for ticket-37 else self:setFullyHidden(false) end local alpha = self.frame:GetAlpha() local change = fadeAlpha - alpha if change < 0.05 and change > -0.05 then self.frame:SetAlpha(fadeAlpha) return end local fullChange, fullDuration if alpha < fadeAlpha then fullChange = fadeAlpha fullDuration = Bazooka.db.profile.fadeInDuration else fullChange = fadeAlpha - 1.0 fullDuration = Bazooka.db.profile.fadeOutDuration end delay = delay or Bazooka.db.profile.fadeOutDelay local duration = calcFadeAnimDuration(change, fullChange, fullDuration) if duration < 0.01 then if delay < 0.01 then self.frame:SetAlpha(fadeAlpha) return end duration = 0.01 -- if duration is too small (maybe only if 0, but meh) the animation doesn't work properly end if not self.fadeAnim then self:createFadeAnim() end self.fadeAnim:SetStartDelay(delay) self.fadeAnim:SetDuration(duration) self.fadeAnim:SetChange(change) self.fadeAnimGrp:Play() end function Bar:enable(id, db) self.id = id self.name = Bazooka:getBarName(id) self.db = db if not self.frame then self.frame = CreateFrame("Frame", "BazookaBar_" .. id, UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil) self.frame.bzkBar = self self.frame:SetScript("OnUpdate", Bar.initialOnUpdateFixFontMetricHack) if EnableOpacityWorkaround then self.frame.bzkAlpha = self.frame:GetAlpha() self.frame.SetAlpha = Bar.setAlphaByParts self.frame.GetAlpha = Bar.getAlphaByParts end self.frame:EnableMouse(true) self.frame:SetClampedToScreen(false) self.frame:SetClampRectInsets(MaxTweakPts, -MaxTweakPts, -MaxTweakPts, MaxTweakPts) self.frame:RegisterForDrag("LeftButton", "RightButton") self.frame:SetScript("OnEnter", Bar.OnEnter) self.frame:SetScript("OnLeave", Bar.OnLeave) self.frame:SetScript("OnDragStart", Bar.OnDragStart) self.frame:SetScript("OnDragStop", Bar.OnDragStop) self.frame:SetScript("OnMouseDown", Bar.OnMouseDown) self.frame:SetMovable(true) self.frame:SetResizable(true) if self.frame.SetResizeBounds then self.frame:SetResizeBounds(Defaults.minFrameWidth, Defaults.minFrameHeight, Defaults.maxFrameWidth, Defaults.maxFrameHeight) else self.frame:SetMinResize(Defaults.minFrameWidth, Defaults.minFrameHeight) self.frame:SetMaxResize(Defaults.maxFrameWidth, Defaults.maxFrameHeight) end self.centerFrame = CreateFrame("Frame", nil, self.frame) self.centerFrame:EnableMouse(false) self.centerFrame:SetPoint("TOP", self.frame, "TOP", 0, 0) self.centerFrame:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 0) end self:updateCenterWidth() self.frame:Show() end function Bar:disable() if self.frame then self.frame:Hide() end for name, plugin in pairs(self.allPlugins) do plugin:disable() end wipe(self.allPlugins) for area, plugins in pairs(self.plugins) do wipe(plugins) end end function Bar:getTopBottom() if self.db.attach == 'top' then if self.parent then local top, bottom, pt, pb = self.parent:getTopBottom() local mt = pb + tonumber(self.db.tweakTop) local mb = mt - self.db.frameHeight return math.max(top, mt), math.min(bottom, mb), mt, mb else local mt = tonumber(self.db.tweakTop) local mb = mt - self.db.frameHeight return mt, mb, mt, mb end elseif self.db.attach == 'bottom' then if self.parent then local top, bottom, pt, pb = self.parent:getTopBottom() local mb = pt + tonumber(self.db.tweakBottom) local mt = mb + self.db.frameHeight return math.max(top, mt), math.min(bottom, mb), mt, mb else local mb = tonumber(self.db.tweakBottom) local mt = mb + self.db.frameHeight return mt, mb, mt, mb end end end function Bar:getAreaCoords(area) if area == 'left' then local left, bottom, width, height = self.frame:GetRect() return left, bottom + height / 2 elseif area == 'cleft' then local left, bottom, width, height = self.centerFrame:GetRect() return left, bottom + height / 2 elseif area == 'cright' then local left, bottom, width, height = self.centerFrame:GetRect() return left + width, bottom + height / 2 elseif area == 'right' then local left, bottom, width, height = self.frame:GetRect() return left + width, bottom + height / 2 else -- center local left, bottom, width, height = self.centerFrame:GetRect() return left + width / 2, bottom + height / 2 end end function Bar:getDropPlace(x, y) local dstArea, dstPos local minDist = math.huge if self.db.hidden then return dstArea, dstPos, minDist end for area, plugins in pairs(self.plugins) do if #plugins == 0 then local dist = distance2(x, y, self:getAreaCoords(area)) if dist < minDist then dstArea, dstPos, minDist = area, 1, dist end else for i = 1, #plugins do local pos, dist = plugins[i]:getDropPlace(x, y) if dist < minDist then dstArea, dstPos, minDist = area, pos, dist end end end end return dstArea, dstPos, minDist end function Bar:getSpacing(area) if area == 'left' then return self.db.leftSpacing elseif area == 'right' then return self.db.rightSpacing else return self.db.centerSpacing end end function Bar:getHighlightCenter(area, pos) local plugins = self.plugins[area] if #plugins == 0 then local x = self:getAreaCoords(area) return x end if pos < 0 then pos = -pos for i = 1, #plugins do local plugin = plugins[i] if pos <= plugin.db.pos then return plugin.frame:GetRight() end end else for i = 1, #plugins do local plugin = plugins[i] if pos <= plugin.db.pos then return plugin.frame:GetLeft() end end end return plugins[#plugins].frame:GetRight() end function Bar:highlight(area, pos) if not area then if self.hl then self.hl:Hide() self.lastHLArea, self.lastHLPos = nil local tt = setupTooltip() if tt:IsOwned(self.frame) then tt:Hide() end Bar.OnLeave(self.frame) end return end Bar.OnEnter(self.frame) if not self.hl then self.hlFrame = CreateFrame("Frame", "BazookaBarHLF_" .. self.id, self.frame) self.hlFrame:SetFrameLevel(self.frame:GetFrameLevel() + 5) self.hlFrame:EnableMouse(false) self.hlFrame:SetAllPoints() self.hl = self.hlFrame:CreateTexture("BazookaBarHL_" .. self.id, "OVERLAY") self.hl:SetTexture(HighlightImage) end local hlcx = self:getHighlightCenter(area, pos) local center = hlcx - self.frame:GetLeft() local dx = math.floor(self:getSpacing(area) / 2 + 0.5) if dx < MinDropPlaceHLDX then dx = MinDropPlaceHLDX end self.hl:ClearAllPoints() self.hl:SetPoint("TOP", self.frame, "TOP", 0, 0) self.hl:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 0) self.hl:SetPoint("LEFT", self.frame, "LEFT", center - dx, 0) self.hl:SetPoint("RIGHT", self.frame, "LEFT", center + dx, 0) self.hl:Show() if area ~= self.lastHLArea or pos ~= self.lastHLPos then self.lastHLArea, self.lastHLPos = area, pos local dx = hlcx - self.frame:GetCenter() local tt = setupTooltip(self.frame, nil, dx, 0) tt:SetText(("%s - %s"):format(self.name, L[area])) tt:Show() tt:FadeOut() end end function Bar:detachPlugin(plugin) local plugins = self.plugins[plugin.area] local lp, rp, index for i = 1, #plugins do local p = plugins[i] if index then rp = p break end if p == plugin then index = i else lp = p end end if not index then return -- this should never happen end tremove(plugins, index) self.allPlugins[plugin.name] = nil plugin.frame:ClearAllPoints() self:setRightAttachPoint(lp, rp) self:setLeftAttachPoint(rp, lp) if plugin.area == 'center' then self:updateCenterWidth() end plugin.area = nil self:updateWidth() end function Bar:attachPlugin(plugin, area, pos) area = area or "left" plugin.bar = self plugin.area = area plugin.db.bar = self.id plugin.db.area = area local plugins = self.plugins[area] local lp, rp if not pos then local count = #self.plugins[area] if count > 0 then lp = plugins[count] plugin.db.pos = lp.db.pos + 1 else plugin.db.pos = 1 end tinsert(plugins, plugin) else if pos < 0 then pos = 1 - pos end plugin.db.pos = pos local rpi for i = 1, #plugins do local p = plugins[i] if pos <= p.db.pos then if not rp then rp = p rpi = i end if pos < p.db.pos then break end pos = pos + 1 p.db.pos = pos elseif not rp then lp = p end end if rpi then tinsert(plugins, rpi, plugin) else tinsert(plugins, plugin) end end self.allPlugins[plugin.name] = plugin plugin.frame:SetParent(self.frame) self:setAttachPoints(lp, plugin, rp) plugin:globalSettingsChanged() if area == "center" then self:updateCenterWidth() end end function Bar:setLeftAttachPoint(plugin, lp) if not plugin then return end local area = plugin.area if area == "left" then if lp then plugin.frame:SetPoint("LEFT", lp.frame, "RIGHT", self.db.leftSpacing, 0) else plugin.frame:SetPoint("LEFT", self.frame, "LEFT", (self.inset + self.db.leftMargin), 0) end elseif area == "center" then if lp then plugin.frame:SetPoint("LEFT", lp.frame, "RIGHT", self.db.centerSpacing, 0) else plugin.frame:SetPoint("LEFT", self.centerFrame, "LEFT", self.db.centerSpacing, 0) end elseif area == "cright" then if lp then plugin.frame:SetPoint("LEFT", lp.frame, "RIGHT", self.db.centerSpacing, 0) else plugin.frame:SetPoint("LEFT", self.centerFrame, "RIGHT", 0, 0) end end end function Bar:setRightAttachPoint(plugin, rp) if not plugin then return end local area = plugin.area if area == "cleft" then if rp then plugin.frame:SetPoint("RIGHT", rp.frame, "LEFT", -self.db.centerSpacing, 0) else plugin.frame:SetPoint("RIGHT", self.centerFrame, "LEFT", 0, 0) end elseif area == "right" then if rp then plugin.frame:SetPoint("RIGHT", rp.frame, "LEFT", -self.db.rightSpacing, 0) else plugin.frame:SetPoint("RIGHT", self.frame, "RIGHT", -(self.inset + self.db.rightMargin), 0) end end end function Bar:setAttachPoints(lp, plugin, rp) plugin.frame:ClearAllPoints() plugin.frame:SetPoint("TOP", self.frame, "TOP") plugin.frame:SetPoint("BOTTOM", self.frame, "BOTTOM") self:setLeftAttachPoint(plugin, lp) self:setRightAttachPoint(plugin, rp) self:setRightAttachPoint(lp, plugin) self:setLeftAttachPoint(rp, plugin) end function Bar:updateLayout() for area, plugins in pairs(self.plugins) do for i = 1, #plugins do self:setAttachPoints(plugins[i - 1], plugins[i], plugins[i + 1]) end end self:updateCenterWidth() self:updateWidth() end function Bar:updateCenterWidth() local cw = sumPluginsWidth(self.plugins.center) local numGaps = #self.plugins.center + 1 cw = cw + (numGaps * self.db.centerSpacing) if cw <= 0 then cw = 1 end self.centerFrame:SetWidth(cw) end local function numSideGaps(numPlugins) if numPlugins == 0 then return 0 else return numPlugins - 1 end end function Bar:updateWidth() if self.db.fitToContentWidth and self.db.attach == 'none' then local w = 2 * self.inset local numCenterPlugins = #self.plugins.cleft + #self.plugins.center + #self.plugins.cright if numCenterPlugins > 0 then local lw = sumPluginsWidth(self.plugins.left) + self.db.leftSpacing * numSideGaps(#self.plugins.left) + self.db.leftMargin + sumPluginsWidth(self.plugins.cleft) + self.db.centerSpacing * #self.plugins.cleft local rw = sumPluginsWidth(self.plugins.right) + self.db.rightSpacing * numSideGaps(#self.plugins.right) + self.db.rightMargin + sumPluginsWidth(self.plugins.cright) + self.db.centerSpacing * #self.plugins.cright if lw > rw then w = w + lw + lw + self.centerFrame:GetWidth() else w = w + rw + rw + self.centerFrame:GetWidth() end elseif #self.plugins.left > 0 then if #self.plugins.right > 0 then w = w + sumPluginsWidth(self.plugins.left) + self.db.leftSpacing * numSideGaps(#self.plugins.left) + self.db.leftMargin + sumPluginsWidth(self.plugins.right) + self.db.rightSpacing * numSideGaps(#self.plugins.right) + self.db.rightMargin + self.db.centerSpacing else w = w + sumPluginsWidth(self.plugins.left) + self.db.leftSpacing * numSideGaps(#self.plugins.left) + self.db.leftMargin + self.db.rightMargin end elseif #self.plugins.right > 0 then w = w + sumPluginsWidth(self.plugins.right) + self.db.rightSpacing * numSideGaps(#self.plugins.right) + self.db.rightMargin + self.db.leftMargin else w = self.db.frameWidth end if w < Defaults.minFrameWidth then w = Defaults.minFrameWidth end self.frame:SetWidth(w) end end function Bar:setId(id) if id == self.id then return end self.id = id self.name = Bazooka:getBarName(id) for name, plugin in pairs(self.allPlugins) do plugin.db.bar = id end end function Bar:toggleHidden(hiddenFlag) if hiddenFlag == nil then hiddenFlag = not self.db.hidden end if self.db.hidden == hiddenFlag then return end self.db.hidden = hiddenFlag if hiddenFlag then self:disableAndHide() else self:enableAndShow() end end function Bar:applySettings() if self.db.attach == 'none' then if self.db.frameWidth == 0 then self.db.frameWidth = GetScreenWidth() - self.db.tweakLeft + self.db.tweakRight end self.frame:SetWidth(self.db.frameWidth) end self.frame:SetHeight(self.db.frameHeight) self.frame:SetFrameStrata(self.db.strata) self:applyFontSettings() self:applyBGSettings() if self.db.hidden then self:disableAndHide(true) else self:enableAndShow(true) end end function Bar:getSizingPoint(x, y) if self.db.attach == 'top' then return "BOTTOM" elseif self.db.attach == 'bottom' then return "TOP" else -- none local left, bottom, width, height = self.frame:GetRect() -- lazy min()... local dl, dr, db, dt = x - left, left + width - x, y - bottom, bottom + height - y if dl <= width / 10 + 1 then return "LEFT" elseif dr <= width / 10 + 1 then return "RIGHT" elseif dt < db then return "TOP" else return "BOTTOM" end end end function Bar:toggleMouse(flag) if flag then self.frame:EnableMouse(true) else self.frame:EnableMouse(false) self.isMouseInside = false end end function Bar:setGradientBg() if self.bgt then if EnableOpacityWorkaround then local alpha = self.frame.bzkAlpha self.bgt:SetGradientAlpha(self.db.bgGradient, self.db.bgColor.r, self.db.bgColor.g, self.db.bgColor.b, self.db.bgColor.a * alpha, self.db.bgGradientColor.r, self.db.bgGradientColor.g, self.db.bgGradientColor.b, self.db.bgGradientColor.a * alpha) else self.bgt:SetGradientAlpha(self.db.bgGradient, self.db.bgColor.r, self.db.bgColor.g, self.db.bgColor.b, self.db.bgColor.a, self.db.bgGradientColor.r, self.db.bgGradientColor.g, self.db.bgGradientColor.b, self.db.bgGradientColor.a) end end end function Bar:applyBGSettings() if not self.db.bgEnabled then self.frame:SetBackdrop(nil) return end self.bg = self.bg or { insets = {} } local bg = self.bg if LSM then bg.bgFile = LSM:Fetch(self.db.bgTextureType, self.db.bgTexture, true) if not bg.bgFile then bg.bgFile = Defaults.bgFile LSM.RegisterCallback(self, "LibSharedMedia_Registered", "mediaUpdate") end if self.db.bgBorderTexture == 'None' then -- hack for beta green thing bg.edgeFile = false else bg.edgeFile = LSM:Fetch("border", self.db.bgBorderTexture, true) if not bg.edgeFile then bg.edgeFile = Defaults.edgeFile LSM.RegisterCallback(self, "LibSharedMedia_Registered", "mediaUpdate") end end else bg.bgFile = Defaults.bgFile bg.edgeFile = Defaults.edgeFile end bg.tile = self.db.bgTile bg.tileSize = self.db.bgTileSize bg.edgeSize = (bg.edgeFile and bg.edgeFile ~= [[Interface\None]]) and self.db.bgEdgeSize or 0 if not self.db.bgInset then self.db.bgInset = Bazooka:getInsetForEdgeSize(self.db.bgEdgeSize) end local inset = math.min(bg.edgeSize, self.db.bgInset) if inset ~= self.inset then self.inset = inset self:updateLayout() end bg.insets.left = inset bg.insets.right = inset bg.insets.top = inset bg.insets.bottom = inset self.frame:SetBackdrop(bg) self.frame:SetBackdropColor(self.db.bgColor.r, self.db.bgColor.g, self.db.bgColor.b, self.db.bgColor.a) self.frame:SetBackdropBorderColor(self.db.bgBorderColor.r, self.db.bgBorderColor.g, self.db.bgBorderColor.b, self.db.bgBorderColor.a) if self.db.bgGradient and self.db.bgGradient ~= "" and self.db.bgGradientColor then self.bgt = getTexture(bg.bgFile, self.frame:GetRegions()) self:setGradientBg() if EnableGradientWorkaround then self.frame:SetScript("OnSizeChanged", Bar.fixGradientOnSizeChanged) end else self.bgt = nil if EnableGradientWorkaround then self.frame:SetScript("OnSizeChanged", nil) end end end function Bar:applyFontSettings() if LSM then self.dbFontPath = LSM:Fetch("font", self.db.font, true) if not self.dbFontPath then LSM.RegisterCallback(self, "LibSharedMedia_Registered", "mediaUpdate") self.dbFontPath = Defaults.fontPath return end end self:globalSettingsChanged() end function Bar:mediaUpdate(event, mediaType, key) if mediaType == 'background' or mediaType == 'statusbar' then if key == self.db.bgTexture then self:applyBGSettings() end elseif mediaType == 'border' then if key == self.db.bgBorderTexture then self:applyBGSettings() end elseif mediaType == 'font' then if key == self.db.font then self:applyFontSettings() end end end function Bar:globalSettingsChanged() for name, plugin in pairs(self.allPlugins) do plugin:globalSettingsChanged() end end function Bar:attachTop(prevBar) if prevBar then self.frame:SetPoint("TOPLEFT", prevBar.frame, "BOTTOMLEFT", self.db.tweakLeft, self.db.tweakTop) self.frame:SetPoint("TOPRIGHT", prevBar.frame, "BOTTOMRIGHT", self.db.tweakRight, self.db.tweakTop) else self.frame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", self.db.tweakLeft, self.db.tweakTop) self.frame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", self.db.tweakRight, self.db.tweakTop) end end function Bar:attachBottom(prevBar) if prevBar then self.frame:SetPoint("BOTTOMLEFT", prevBar.frame, "TOPLEFT", self.db.tweakLeft, self.db.tweakBottom) self.frame:SetPoint("BOTTOMRIGHT", prevBar.frame, "TOPRIGHT", self.db.tweakRight, self.db.tweakBottom) else self.frame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", self.db.tweakLeft, self.db.tweakBottom) self.frame:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", self.db.tweakRight, self.db.tweakBottom) end end function Bar:enableAndShow(skipFadeAnim) if IsInPetBattle() and self.db.disableDuringPetBattle then self:disableAndHide(skipFadeAnim) elseif InCombatLockdown() then self:toggleMouse(not self.db.disableMouseInCombat) if self.db.fadeInCombat and not self.isMouseInside then self:fadeOut(0, nil, skipFadeAnim and self.db.fadeAlpha or nil) else self:fadeIn(skipFadeAnim and 1.0 or nil) end for name, plugin in pairs(self.allPlugins) do plugin:toggleMouse(not plugin.db.disableMouseInCombat) end else self:toggleMouse(not self.db.disableMouseOutOfCombat) if self.db.fadeOutOfCombat and not self.isMouseInside then self:fadeOut(0, nil, skipFadeAnim and self.db.fadeAlpha or nil) else self:fadeIn(skipFadeAnim and 1.0 or nil) end for name, plugin in pairs(self.allPlugins) do plugin:toggleMouse(not plugin.db.disableMouseOutOfCombat) end end end function Bar:disableAndHide(skipFadeAnim) self:toggleMouse(false) for name, plugin in pairs(self.allPlugins) do plugin:toggleMouse(false) end self:fadeOut(0, 0, skipFadeAnim and 0) end Bazooka.Bar = Bar -- END Bar stuff -- BEGIN Plugin stuff local Plugin = { name = nil, dataobj = nil, db = nil, frame = nil, icon = nil, text = nil, label = nil, hl = nil, iconSize = BarDefaults.iconSize, iconTextSpacing = BarDefaults.iconTextSpacing, fontSize = BarDefaults.fontSize, labelColorHex = colorToHex(BarDefaults.labelColor), suffixColorHex = colorToHex(BarDefaults.suffixColor), } setDeepCopyIndex(Plugin) Plugin.OnEnter = function(frame, ...) local self = frame.bzkPlugin self.bar.OnEnter(frame) if Bazooka.draggedFrame then return end if Bazooka.db.profile.enableHL then self:highlight(true) end self:showTip() end Plugin.OnLeave = function(frame, ...) local self = frame.bzkPlugin self.bar.OnLeave(frame) self:highlight(nil) self:hideTip() end Plugin.OnMouseDown = function(frame, ...) local self = frame.bzkPlugin if self.db.hideTipOnClick then self:hideTip(true) end end Plugin.OnMouseWheel = function(frame, ...) local self = frame.bzkPlugin if self.db.hideTipOnClick then self:hideTip(true) end if self.dataobj.OnMouseWheel then self.dataobj.OnMouseWheel(frame, ...) end end Plugin.OnClick = function(frame, ...) local self = frame.bzkPlugin if self.dataobj.OnClick then self.dataobj.OnClick(frame, ...) end end Plugin.OnDoubleClick = function(frame, ...) local self = frame.bzkPlugin if self.dataobj.OnDoubleClick then self.dataobj.OnDoubleClick(frame, ...) elseif self.dataobj.OnClick then self.dataobj.OnClick(frame, ...) end end Plugin.OnUpdate = function(frame) local x, y = getScaledCursorPosition() if x ~= Bazooka.lastX or y ~= Bazooka.lastY then Bazooka.lastX, Bazooka.lastY = x, y Bazooka:highlight(Bazooka:getDropPlace(x, y)) end end Plugin.OnDragStart = function(frame) if Bazooka.locked then return end if Bazooka.tipOwner then Bazooka.tipOwner:hideTip(true) Bazooka.tipOwner = nil end local self = frame.bzkPlugin self:highlight(nil) self:detach() updateUIScale() frame:SetAlpha(0.7) Bazooka.draggedFrame, Bazooka.lastX, Bazooka.lastY = frame, nil, nil frame:StartMoving() frame:SetScript("OnUpdate", Plugin.OnUpdate) end Plugin.OnDragStop = function(frame) if not Bazooka.draggedFrame then return end local self = frame.bzkPlugin Bazooka.draggedFrame = nil frame:SetScript("OnUpdate", nil) frame:StopMovingOrSizing() frame:SetAlpha(1.0) Bazooka:highlight(nil) if Bazooka.locked then self:reattach() return end local bar, area, pos = Bazooka:getDropPlace(getScaledCursorPosition()) if bar then bar:attachPlugin(self, area, pos) Bazooka:updatePluginOptions() else self:reattach() Bazooka:openStaticDialog(BzkDialogDisablePlugin, self, self:getTitle()) end end -- BEGIN EnableOpacityWorkaround Plugin.setAlphaByParts = function(frame, alpha) frame.bzkAlpha = alpha local self = frame.bzkPlugin if self.bar then alpha = alpha * self.bar.frame:GetAlpha() end if self.icon then self.icon:SetAlpha(alpha) end if self.text then self.text:SetAlpha(alpha) end end Plugin.getAlphaByParts = function(frame) return frame.bzkAlpha end -- END EnableOpacityWorkaround function Plugin:New(name, dataobj, db) local plugin = setmetatable({}, Plugin) plugin.name = name plugin.dataobj = dataobj if dataobj.tocname then local addonName, addonTitle = GetAddOnInfo(dataobj.tocname or name) plugin.title = name .. '[' .. (addonTitle or addonName) .. ']' else plugin.title = name end plugin.db = db plugin:applySettings() return plugin end function Plugin:getTitle() if self.db.useLabelAsTitle and self.dataobj.label then local title = stripColors(self.dataobj.label) if title ~= "" then return title end end return self.title end function Plugin:setTipScale(tt) if self.db.overrideTooltipScale then self.origTipScale = tt:GetScale() tt:SetScale(self.db.tooltipScale) end end function Plugin:resetTipScale(tt) if self.origTipScale then tt:SetScale(self.origTipScale) self.origTipScale = nil end end function Plugin:showTip(modifierKey, modifierState) if Bazooka.checkForceHide then Bazooka.checkForceHide:forceHideFrames(UIParent:GetChildren()) Bazooka.checkForceHide = nil end local origTipType = self.tipType if Bazooka.tipOwner then Bazooka.tipOwner:hideTip(true) Bazooka.tipOwner = nil end if self.db.disableTooltip or (self.db.disableTooltipInCombat and InCombatLockdown()) then return end if self.db.manualTooltip then if Bazooka.db.profile.manualTooltipToggle then if not IsModifierKeyDown() then return end else if not IsModifierKeyDown() and not origTipType then return end end end Bazooka.tipOwner = self if Bazooka.db.profile.simpleTip and IsAltKeyDown() and not modifierKey then self.tipType = 'simple' local tt = setupTooltip(self.frame) tt:SetText(self:getTitle()) tt:Show() return end local dataobj = self.dataobj if dataobj.tooltip then self.tipType = 'tooltip' local tt = setupTooltip(self.frame, dataobj.tooltip) self:setTipScale(tt) tt:Show() elseif dataobj.OnEnter then self.tipType = 'OnEnter' GameTooltip:Hide() self:setTipScale(GameTooltip) dataobj.OnEnter(self.frame) elseif dataobj.OnTooltipShow then self.tipType = 'OnTooltipShow' local tt = setupTooltip(self.frame) self:setTipScale(tt) dataobj.OnTooltipShow(tt) tt:Show() elseif Bazooka.db.profile.simpleTip then self.tipType = 'simple' local tt = setupTooltip(self.frame) self:setTipScale(tt) tt:SetText(self:getTitle()) tt:Show() end end function Plugin:toggleMouse(flag) self.frame:EnableMouse(flag) self.frame:EnableMouseWheel(flag) end -- hides frames that are not Bazooka's but are anchored to our frame -- useage: plugin:forceHideFrames(UIParent:GetChildren()) function Plugin:forceHideFrames(frame, ...) if not frame then return end if not frame:IsForbidden() then if not frame.bzkPlugin then -- we assume that if the frame is anchored to us, it's _only_ anchored to us local _, relativeTo = frame:GetPoint() if relativeTo == self.frame then frame:Hide() end end end return self:forceHideFrames(...) end function Plugin:hideTip(force) if not Bazooka.tipOwner then return end Bazooka.tipOwner = nil if not self.tipType then return end if self.tipType == 'simple' then local tt = setupTooltip() tt:Hide() self:resetTipScale(tt) elseif self.tipType == 'OnTooltipShow' then if self.dataobj.OnLeave then self.dataobj.OnLeave(self.frame) end local tt = setupTooltip() tt:Hide() self:resetTipScale(tt) elseif self.tipType == 'OnEnter' then if self.dataobj.OnLeave then self.dataobj.OnLeave(self.frame) end self:resetTipScale(GameTooltip) elseif self.tipType == 'tooltip' then local tt = self.dataobj.tooltip tt:Hide() self:resetTipScale(tt) end self.tipType = nil if self.db.forceHideTip then if force then self:forceHideFrames(UIParent:GetChildren()) else Bazooka.checkForceHide = self end end end function Plugin:getDropPlace(x, y) local left, bottom, width, height = self.frame:GetRect() local ld = distance2(x, y, left, bottom + height / 2) local rd = distance2(x, y, left + width, bottom + height / 2) if ld < rd then return self.db.pos, ld else return -self.db.pos, rd end end function Plugin:highlight(flag) if flag then if not self.hl then self.hl = self.frame:CreateTexture("BazookaHL_" .. self.name, "OVERLAY") self.hl:SetTexture(HighlightImage) self.hl:SetAllPoints() end self.frame:SetAlpha(1.0) self.hl:Show() else local bdb = self.bar and self.bar.db or BarDefaults self.frame:SetAlpha(bdb.pluginOpacity) if self.hl then self.hl:Hide() end end end function Plugin:globalSettingsChanged() local bdb = self.bar and self.bar.db or BarDefaults self.labelColorHex = colorToHex(bdb.labelColor) self.suffixColorHex = colorToHex(bdb.suffixColor) self.iconTextSpacing = bdb.iconTextSpacing self.iconSize = bdb.iconSize self.fontSize = bdb.fontSize if self.text then local dbFontPath = self.bar and self.bar.dbFontPath or bdb.fontPath local fontPath, fontSize, fontOutline = self.text:GetFont() fontOutline = fontOutline or "" if dbFontPath ~= fontPath or bdb.fontSize ~= fontSize or bdb.fontOutline ~= fontOutline then self.text:SetFont(dbFontPath, self.fontSize, bdb.fontOutline) end if bdb.fontShadow then self.text:SetShadowOffset(1, -1) else self.text:SetShadowOffset(0, 0) end self.text:SetTextColor(bdb.textColor.r, bdb.textColor.g, bdb.textColor.b, bdb.textColor.a) self:setText() end if self.icon then self.icon:SetWidth(self.iconSize) self.icon:SetHeight(self.iconSize) end self.frame:SetAlpha(bdb.pluginOpacity) self:updateLayout(true) if bdb.hidden then self:toggleMouse(false) elseif InCombatLockdown() then self:toggleMouse(not self.db.disableMouseInCombat) else self:toggleMouse(not self.db.disableMouseOutOfCombat) end end function Plugin:createIcon() self.icon = self.frame:CreateTexture("BazookaPluginIcon_" .. self.name, "ARTWORK") self.icon:ClearAllPoints() local iconSize = BarDefaults.iconSize self.icon:SetWidth(iconSize) self.icon:SetHeight(iconSize) end function Plugin:createText() self.text = self.frame:CreateFontString("BazookaPluginText_" .. self.name, "ARTWORK", "GameFontNormal") self.text:SetFont(Defaults.fontPath, BarDefaults.fontSize, BarDefaults.fontOutline) self.text:SetWordWrap(false) end function Plugin:updateLayout(forced) local align = self.db.alignment or "LEFT" if self.icon then self.icon:ClearAllPoints() self.icon:SetPoint(align, self.frame, align, 0, 0) end local w = 0 if self.db.showText or self.db.showValue or self.db.showLabel then local tw = self.text:GetStringWidth() local iw = self.db.showIcon and self.icon:GetWidth() or 0 if tw > 0 then if self.db.maxTextWidth and self.db.maxTextWidth < tw then tw = self.db.maxTextWidth end local offset = (iw > 0) and (iw + self.iconTextSpacing) or 0 self.text:ClearAllPoints() if align == "LEFT" then self.text:SetPoint(align, self.frame, align, offset, 0) else self.text:SetPoint(align, self.frame, align, -offset, 0) end self.text:SetJustifyH(align) w = offset + tw elseif iw > 0 then w = iw else w = EmptyPluginWidth end elseif self.db.showIcon then local iw = self.icon:GetWidth() if iw > 0 then w = iw else w = EmptyPluginWidth end else w = EmptyPluginWidth end local ow = self.origWidth or self.frame:GetWidth() if forced or w > ow or w < ow - self.db.shrinkThreshold then self.origWidth = w self.frame:SetWidth(w) if self.bar then if self.area == 'center' then self.bar:updateCenterWidth() end self.bar:updateWidth() end end end function Plugin:enable() if not self.frame then self.frame = CreateFrame("Button", "BazookaPlugin_" .. self.name, UIParent) self.frame.bzkPlugin = self if EnableOpacityWorkaround then self.frame.bzkAlpha = self.frame:GetAlpha() self.frame.SetAlpha = Plugin.setAlphaByParts self.frame.GetAlpha = Plugin.getAlphaByParts end self.frame:RegisterForDrag("LeftButton") self.frame:RegisterForClicks("AnyUp") self.frame:SetMovable(true) self.frame:SetScript("OnEnter", Plugin.OnEnter) self.frame:SetScript("OnLeave", Plugin.OnLeave) self.frame:SetScript("OnClick", Plugin.OnClick) self.frame:SetScript("OnDoubleClick", Plugin.OnDoubleClick) self.frame:SetScript("OnMouseDown", Plugin.OnMouseDown) self.frame:SetScript("OnDragStart", Plugin.OnDragStart) self.frame:SetScript("OnDragStop", Plugin.OnDragStop) self.frame:SetScript("OnMouseWheel", Plugin.OnMouseWheel) if self.dataobj.OnReceiveDrag then self.frame:SetScript("OnReceiveDrag", self.dataobj.OnReceiveDrag) end self.frame:EnableMouse(true) self.frame:EnableMouseWheel(true) end self.frame:Show() end function Plugin:disable() if self.frame then self.frame:ClearAllPoints() self.frame:Hide() self.bar = nil end LDB.UnregisterAllCallbacks(self) end function Plugin:updateLDBCallback(attr, method, reg) local callback = ("LibDataBroker_AttributeChanged_%s_%s"):format(self.name, attr) if reg then LDB.RegisterCallback(self, callback, method) else LDB.UnregisterCallback(self, callback) end end function Plugin:updateLDBCallbacks() self:updateLDBCallback("icon", "setIcon", self.db.showIcon) self:updateLDBCallback("iconCoords", "setIconCoords", self.db.showIcon) self:updateLDBCallback("iconR", "setIconColor", self.db.showIcon) self:updateLDBCallback("iconG", "setIconColor", self.db.showIcon) self:updateLDBCallback("iconB", "setIconColor", self.db.showIcon) self:updateLDBCallback("label", "updateLabel", self.db.showLabel) self:updateLDBCallback("text", "setText", self.db.showText) self:updateLDBCallback("value", "setText", self.db.showValue) self:updateLDBCallback("suffix", "setText", self.db.showSuffix) end function Plugin:applySettings() if not self.db.enabled then self:detach() self:disable() return end self:enable() if self.db.showIcon then if not self.icon then self:createIcon() end self:setIcon() self:setIconColor() self:setIconCoords() self.icon:Show() elseif self.icon then self.icon:Hide() end if self.db.showText or self.db.showValue or self.db.showLabel then if not self.text then self:createText() end self.text:SetWidth(self.db.maxTextWidth or 0) if self.db.showLabel then self:updateLabel() else self:setText() end self.text:Show() elseif self.text then self.text:SetFormattedText("") self.text:Hide() end if not self.bar or self.bar.id ~= self.db.bar or self.area ~= self.db.area then self:detach() Bazooka:attachPlugin(self) end self:globalSettingsChanged() self:updateLabel() self:updateLayout(true) self:updateLDBCallbacks() end function Plugin:setIcon() if not self.db.showIcon then return end local dataobj = self.dataobj local icon = self.icon icon:SetTexture(dataobj.icon) if self.db.iconBorderClip > 0 and not dataobj.iconCoords then local tl, br = self.db.iconBorderClip, (1 - self.db.iconBorderClip) icon:SetTexCoord(tl, br, tl, br) end end function Plugin:setIconColor() if not self.db.showIcon then return end local dataobj = self.dataobj if dataobj.iconR then self.icon:SetVertexColor(dataobj.iconR, dataobj.iconG, dataobj.iconB) end end function Plugin:setIconCoords() if not self.db.showIcon then return end local dataobj = self.dataobj if dataobj.iconCoords then self.icon:SetTexCoord(unpack(dataobj.iconCoords)) end end function Plugin:setText() if self.bar and self.bar.isFullyHidden then return end local dataobj = self.dataobj if self.db.showLabel and self.label then if self.db.showText and dataobj.text then if self.db.showValue and dataobj.value then if self.db.showSuffix and dataobj.suffix then if self.db.stripColors then self.text:SetFormattedText("|c%s%s:|r %s %s |c%s%s|r", self.labelColorHex, stripColors(self.label), stripColors(dataobj.text), stripColors(dataobj.value), self.suffixColorHex, stripColors(dataobj.suffix)) else self.text:SetFormattedText("|c%s%s:|r %s %s |c%s%s|r", self.labelColorHex, self.label, dataobj.text, dataobj.value, self.suffixColorHex, dataobj.suffix) end else if self.db.stripColors then self.text:SetFormattedText("|c%s%s:|r %s %s", self.labelColorHex, stripColors(self.label), stripColors(dataobj.text), stripColors(dataobj.value)) else self.text:SetFormattedText("|c%s%s:|r %s %s", self.labelColorHex, self.label, dataobj.text, dataobj.value) end end else if self.db.stripColors then self.text:SetFormattedText("|c%s%s:|r %s", self.labelColorHex, stripColors(self.label), stripColors(dataobj.text)) else self.text:SetFormattedText("|c%s%s:|r %s", self.labelColorHex, self.label, dataobj.text) end end elseif self.db.showValue and dataobj.value then if self.db.showSuffix and dataobj.suffix then if self.db.stripColors then self.text:SetFormattedText("|c%s%s:|r %s |c%s%s|r", self.labelColorHex, stripColors(self.label), stripColors(dataobj.value), self.suffixColorHex, stripColors(dataobj.suffix)) else self.text:SetFormattedText("|c%s%s:|r %s |c%s%s|r", self.labelColorHex, self.label, dataobj.value, self.suffixColorHex, dataobj.suffix) end else if self.db.stripColors then self.text:SetFormattedText("|c%s%s:|r %s", self.labelColorHex, stripColors(self.label), stripColors(dataobj.value)) else self.text:SetFormattedText("|c%s%s:|r %s", self.labelColorHex, self.label, dataobj.value) end end else if self.db.stripColors then self.text:SetFormattedText("|c%s%s|r", self.labelColorHex, stripColors(self.label)) else self.text:SetFormattedText("|c%s%s|r", self.labelColorHex, self.label) end end self:updateLayout() elseif self.db.showText and dataobj.text then if self.db.showValue and dataobj.value then if self.db.showSuffix and dataobj.suffix then if self.db.stripColors then self.text:SetFormattedText("%s %s |c%s%s|r", stripColors(dataobj.text), stripColors(dataobj.value), self.suffixColorHex, stripColors(dataobj.suffix)) else self.text:SetFormattedText("%s %s |c%s%s|r", dataobj.text, dataobj.value, self.suffixColorHex, dataobj.suffix) end else if self.db.stripColors then self.text:SetFormattedText("%s %s", stripColors(dataobj.text), stripColors(dataobj.value)) else self.text:SetFormattedText("%s %s", dataobj.text, dataobj.value) end end else if self.db.stripColors then self.text:SetFormattedText("%s", stripColors(dataobj.text)) else self.text:SetFormattedText("%s", dataobj.text) end end self:updateLayout() elseif self.db.showValue and dataobj.value then if self.db.showSuffix and dataobj.suffix then if self.db.stripColors then self.text:SetFormattedText("%s |c%s%s|r", stripColors(dataobj.value), self.suffixColorHex, stripColors(dataobj.suffix)) else self.text:SetFormattedText("%s |c%s%s|r", dataobj.value, self.suffixColorHex, dataobj.suffix) end else if self.db.stripColors then self.text:SetFormattedText("%s", stripColors(dataobj.value)) else self.text:SetFormattedText("%s", dataobj.value) end end self:updateLayout() elseif self.text then self.text:SetFormattedText("") self:updateLayout() end end function Plugin:updateLabel() self.label = self.dataobj.label if not self.label and self.db.showTitle then self.label = self.title end self:setText() end function Plugin:reattach() if self.bar then self.bar:attachPlugin(self, self.db.area, self.db.pos) end end function Plugin:detach() if self.bar then self.bar:detachPlugin(self) if self.frame then self.frame:SetFrameStrata("HIGH") end end end Bazooka.Plugin = Plugin -- END Plugin stuff -- BEGIN AceAddon stuff function Bazooka:OnInitialize() self.db = LibStub("AceDB-3.0"):New("BazookaDB", defaults, true) EnableOpacityWorkaround = self.db.global.enableOpacityWorkaround self:initAnchors() if LibDualSpec then LibDualSpec:EnhanceDatabase(self.db, AppName) end self:setupLDB() self.db.RegisterCallback(self, "OnProfileChanged", "profileChanged") self.db.RegisterCallback(self, "OnProfileCopied", "profileChanged") self.db.RegisterCallback(self, "OnProfileReset", "profileChanged") self.db.RegisterCallback(self, "OnDatabaseShutdown", "OnDisable") self:profileChanged() self:loadOptions() if not IsClassic then hooksecurefunc("OrderHall_CheckCommandBar", function() if self.db.global.hideOrderHallCommandBar then if OrderHallCommandBar then OrderHallCommandBar:Hide() end end end ) end end function Bazooka:OnEnable(first) self.enabled = true self:init() self:RegisterEvent("PLAYER_REGEN_DISABLED", "onEnteringCombat") self:RegisterEvent("PLAYER_REGEN_ENABLED", "onLeavingCombat") if not IsClassic then self:RegisterEvent("PET_BATTLE_OPENING_START", "onPetBattleStart") self:RegisterEvent("PET_BATTLE_CLOSE", "onPetBattleEnd") end self:RegisterEvent("MODIFIER_STATE_CHANGED") LDB.RegisterCallback(self, "LibDataBroker_DataObjectCreated", "dataObjectCreated") end function Bazooka:OnDisable() self.enabled = false self:UnregisterAllEvents() LDB.UnregisterAllCallbacks(self) for i = 1, #self.bars do self.bars[i].frame:Hide() end for name, plugin in pairs(self.plugins) do plugin:disable() end end -- END AceAddon stuff -- BEGIN handlers function Bazooka:onEnteringCombat() self:lock() for i = 1, #self.bars do local bar = self.bars[i] if not bar.db.hidden then bar:toggleMouse(not bar.db.disableMouseInCombat) if bar.db.fadeInCombat and not bar.isMouseInside then bar:fadeOut(0) else bar:fadeIn() end for name, plugin in pairs(bar.allPlugins) do plugin:toggleMouse(not plugin.db.disableMouseInCombat) end end end end function Bazooka:onLeavingCombat() if not self.db.profile.locked then self:unlock() end for i = 1, #self.bars do local bar = self.bars[i] if not bar.db.hidden then bar:toggleMouse(not bar.db.disableMouseOutOfCombat) if bar.db.fadeOutOfCombat and not bar.isMouseInside then bar:fadeOut(0) else bar:fadeIn() end for name, plugin in pairs(bar.allPlugins) do plugin:toggleMouse(not plugin.db.disableMouseOutOfCombat) end end end end function Bazooka:onPetBattleStart() self:lock() for i = 1, #self.bars do local bar = self.bars[i] if not bar.db.hidden then if bar.db.disableDuringPetBattle then bar:disableAndHide() end end end end function Bazooka:onPetBattleEnd() for i = 1, #self.bars do local bar = self.bars[i] if not bar.db.hidden then bar:enableAndShow() end end end function Bazooka:MODIFIER_STATE_CHANGED(event, key, state) local tipOwner = Bazooka.tipOwner if tipOwner and (tipOwner.db.manualTooltip or Bazooka.db.profile.simpleTip) then tipOwner:showTip(key, state) end end function Bazooka:dataObjectCreated(event, name, dataobj) self:createPlugin(name, dataobj) self:updatePluginOptions() end function Bazooka:profileChanged() if not self.enabled then return end self:init() end -- END handlers function Bazooka:initAnchors() self.topTop, self.topBottom = 1, 0 if not self.TopAnchor then self.TopAnchor = CreateFrame("Frame", "Bazooka_TopAnchor", UIParent) self.TopAnchor:EnableMouse(false) end self:setTopAnchorPoints() self.bottomTop, self.bottomBottom = 0, -1 if not self.BottomAnchor then self.BottomAnchor = CreateFrame("Frame", "Bazooka_BottomAnchor", UIParent) self.BottomAnchor:EnableMouse(false) end self:setBottomAnchorPoints() end function Bazooka:setTopAnchorPoints() self.TopAnchor:ClearAllPoints() self.TopAnchor:SetPoint("TOP", UIParent, "TOP", 0, self.topTop) self.TopAnchor:SetPoint("BOTTOM", UIParent, "TOP", 0, self.topBottom) self.TopAnchor:SetPoint("LEFT", UIParent, "LEFT", 0, 0) self.TopAnchor:SetPoint("RIGHT", UIParent, "RIGHT", 0, 0) end function Bazooka:setBottomAnchorPoints() self.BottomAnchor:ClearAllPoints() self.BottomAnchor:SetPoint("TOP", UIParent, "BOTTOM", 0, self.bottomTop) self.BottomAnchor:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, self.bottomBottom) self.BottomAnchor:SetPoint("LEFT", UIParent, "LEFT", 0, 0) self.BottomAnchor:SetPoint("RIGHT", UIParent, "RIGHT", 0, 0) end function Bazooka:getBarName(id) return L["Bar#%d"]:format(id) end function Bazooka:init() self.attachedBars.top = {} self.attachedBars.bottom = {} for i = 1, #self.bars do self.bars[i]:disable() end for name, plugin in pairs(self.plugins) do plugin:disable() end self.numBars = 0 local numBars = self.db.profile.numBars if not numBars or numBars <= 0 then numBars = 1 end for i = 1, numBars do self:createBar() end for name, dataobj in LDB:DataObjectIterator() do self:createPlugin(name, dataobj) end self:applySettings() self:updateMainOptions() self:updateBarOptions() self:updatePluginOptions() self:updateAnchors() end function Bazooka:createBar() self.numBars = self.numBars + 1 if self.numBars > self.db.profile.numBars then self.db.profile.numBars = self.numBars end local id = self.numBars local db = self.db.profile.bars[id] local bar = self.bars[id] if not db.pos then db.tweakTop, db.tweakBottom, db.tweakLeft, db.tweakRight = 0, 0, 0, 0 end if bar then bar:enable(id, db) bar:applySettings() else bar = Bar:New(id, db) self.bars[bar.id] = bar end self:attachBar(bar, bar.db.attach, bar.db.pos) self:updateAnchors() return bar end local function insertBar(bars, pos, bar) local pb, nb, nbi for i = 1, #bars do local b = bars[i] if pos <= b.db.pos then if not nb then nb = b nbi = i end if pos < b.db.pos then break end pos = pos + 1 b.db.pos = pos elseif not nb then pb = b end end if nbi then tinsert(bars, nbi, bar) else tinsert(bars, bar) end return pb, nb end function Bazooka:attachBarImpl(bar, attach, pos, attachFunc) local bars = self.attachedBars[attach] if not pos then if #bars > 0 then pos = bars[#bars].db.pos + 1 else pos = 1 end end local prevBar, nextBar = insertBar(bars, pos, bar) bar[attachFunc](bar, prevBar) if nextBar then nextBar[attachFunc](nextBar, bar) end return pos end function Bazooka:attachBar(bar, attach, pos) attach = attach or 'none' bar.db.attach = attach bar.frame:ClearAllPoints() if attach == 'top' then pos = self:attachBarImpl(bar, attach, pos, "attachTop") elseif attach == 'bottom' then pos = self:attachBarImpl(bar, attach, pos, "attachBottom") else pos = 0 bar.frame:SetWidth(bar.db.frameWidth) bar.frame:SetHeight(bar.db.frameHeight) bar.frame:SetPoint(bar.db.point, UIParent, bar.db.relPoint, bar.db.x, bar.db.y) end bar.db.pos = pos end function Bazooka:detachBarImpl(bar, attach, attachFunc) local bars = self.attachedBars[attach] local prevBar for i = 1, #bars do local cb = bars[i] if cb == bar then tremove(bars, i) cb = bars[i] if cb then cb[attachFunc](cb, prevBar) end break end prevBar = cb end end function Bazooka:detachBar(bar) self:detachBarImpl(bar, 'top', "attachTop") self:detachBarImpl(bar, 'bottom', "attachBottom") end function Bazooka:removeBar(bar) if self.numBars <= 1 then return end self:detachBar(bar) for name, plugin in pairs(bar.allPlugins) do plugin.db.bar, plugin.db.area, plugin.db.pos = 1, 'left', nil Bazooka:disablePlugin(plugin) end bar:disable() self.numBars = self.numBars - 1 self.db.profile.numBars = self.numBars for i = bar.id, self.numBars do self.db.profile.bars[i] = self.db.profile.bars[i + 1] self.bars[i] = self.bars[i + 1] self.bars[i]:setId(i) end self.db.profile.bars[self.numBars + 1] = nil -- hackish way to get back default overrides local t = self.db.profile.bars[self.numBars + 1] if defaults.profile.bars[self.numBars + 1] then for k, v in pairs(defaults.profile.bars[self.numBars + 1]) do t[k] = v end end self.bars[self.numBars + 1] = nil self:updateAnchors() end function Bazooka:disableDBIcon() if self.isDBIconDisabled then return end local DBIcon = LibStub:GetLibrary("LibDBIcon-1.0", true) if DBIcon and DBIcon.DisableLibrary then DBIcon:DisableLibrary() self.isDBIconDisabled = true end end function Bazooka:enableDBIcon() if not self.isDBIconDisabled then return end local DBIcon = LibStub:GetLibrary("LibDBIcon-1.0", true) if DBIcon and DBIcon.EnableLibrary then DBIcon:EnableLibrary() self.isDBIconDisabled = nil end end function Bazooka:createPlugin(name, dataobj) local pt = dataobj.type or (dataobj.text and "data source" or "launcher") local db = self.db.profile.plugins[pt][name] local plugin = self.plugins[name] if plugin then plugin.db = db plugin.dataobj = dataobj plugin:applySettings() else plugin = Plugin:New(name, dataobj, db) self.plugins[name] = plugin end if self.db.profile.disableDBIcon then self:disableDBIcon() end self:updatePluginOptions() return plugin end function Bazooka:disablePlugin(plugin) plugin.db.enabled = false plugin:applySettings() end function Bazooka:attachPlugin(plugin) local bar = self.bars[plugin.db.bar] if not bar then self.bars[1]:attachPlugin(plugin) else bar:attachPlugin(plugin, plugin.db.area, plugin.db.pos) end end function Bazooka:applySettings() if not self:IsEnabled() then self:OnDisable() return end self:toggleLocked(self.db.profile.locked == true) for i = 1, #self.bars do local bar = self.bars[i] if bar.db.hidden then bar:disableAndHide(true) end end if self.db.profile.disableDBIcon then self:disableDBIcon() else self:enableDBIcon() end if Jostle then if self.db.profile.adjustFrames then Jostle:RegisterTop(self.TopAnchor) Jostle:RegisterBottom(self.BottomAnchor) Jostle:EnableTopAdjusting() Jostle:EnableBottomAdjusting() else Jostle:Unregister(self.TopAnchor) Jostle:Unregister(self.BottomAnchor) Jostle:DisableTopAdjusting() Jostle:DisableBottomAdjusting() end end end function Bazooka:getBarsTopBottom(bars) local barsTop, barsBottom, prevBar for i = 1, #bars do local bar = bars[i] bar.parent = prevBar local top, bottom = bar:getTopBottom() if not barsTop or barsTop < top then barsTop = top end if not barsBottom or barsBottom > bottom then barsBottom = bottom end prevBar = bar end return barsTop, barsBottom end function Bazooka:updateAnchors() local topTop, topBottom = self:getBarsTopBottom(self.attachedBars['top']) local bottomTop, bottomBottom = self:getBarsTopBottom(self.attachedBars['bottom']) if not topTop then topTop, topBottom = 1, 0 end if not bottomTop then bottomTop, bottomBottom = 0, -1 end local needJostleRefresh if self.topTop ~= topTop or self.topBottom ~= topBottom then self.topTop, self.topBottom = topTop, topBottom self:setTopAnchorPoints() needJostleRefresh = true end if self.bottomTop ~= bottomTop or self.bottomBottom ~= bottomBottom then self.bottomTop, self.bottomBottom = bottomTop, bottomBottom self:setBottomAnchorPoints() needJostleRefresh = true end if needJostleRefresh and Jostle and self.db.profile.adjustFrames then Jostle:Refresh() end end function Bazooka:lock() self.locked = true for i = 1, #self.ldbs do self.ldbs[i].icon = Icon end self:closeStaticDialog(BzkDialogDisablePlugin) end function Bazooka:unlock() self.locked = false for i = 1, #self.ldbs do self.ldbs[i].icon = UnlockedIcon end end function Bazooka:toggleLocked(flag) if flag == nil then flag = not self.db.profile.locked end if flag ~= self.db.profile.locked then self:updateMainOptions() end self.db.profile.locked = flag if flag then self:lock() else self:unlock() end end local function extraLauncherName(idx) return Bazooka.AppName .. "_" .. idx end function Bazooka:setupLDB(forceEnableExtraLaunchers) self.ldbOnClick = self.ldbOnClick or function(frame, button) if IsShiftKeyDown() or button == "MiddleButton" then self:toggleLocked() elseif button == "LeftButton" then self:toggleBars() elseif button == "RightButton" then self:openConfigDialog() end end self.ldbOnTooltipShow = self.ldbOnTooltipShow or function(tt) tt:AddLine(self.AppName) tt:AddLine(L["|cffeda55fLeft Click|r to toggle marked bars"]) tt:AddLine(L["|cffeda55fShift Click|r to lock/unlock frames"]) tt:AddLine(L["|cffeda55fRight Click|r to open the configuration window"]) end local ldbIcon = self.db.profile.locked and Icon or UnlockedIcon if not self.ldbs then self.ldbs = {} local ldb = { type = "launcher", icon = ldbIcon, OnClick = self.ldbOnClick, OnTooltipShow = self.ldbOnTooltipShow, } LDB:NewDataObject(self.AppName, ldb) self.ldbs[1] = ldb end if self.db.profile.extraLaunchers then for i = 2, self.db.profile.numBars do if not self.ldbs[i] then local ldb = { type = "launcher", icon = ldbIcon, OnClick = self.ldbOnClick, OnTooltipShow = self.ldbOnTooltipShow, bzkName = extraLauncherName(i), } local pdb = self.db.profile.plugins["launcher"][ldb.bzkName] if not pdb.pos then pdb.bar = i pdb.pos = 1 end LDB:NewDataObject(ldb.bzkName, ldb) self.ldbs[i] = ldb elseif forceEnableExtraLaunchers then local plugin = self.plugins[self.ldbs[i].bzkName] if plugin then plugin.db.enabled = true plugin:applySettings() end end end else for i = 2, #self.ldbs do local ldb = self.ldbs[i] local plugin = self.plugins[ldb.bzkName] if plugin then self:disablePlugin(plugin) end end end self:updatePluginOptions() end function Bazooka:getDropPlace(x, y) local dstBar, dstArea, dstPos local minDist = math.huge for i = 1, #self.bars do local bar = self.bars[i] local area, pos, dist = bar:getDropPlace(x, y) if dist < minDist then dstBar, dstArea, dstPos, minDist = bar, area, pos, dist end end if minDist < NearSquared or getDistance2Frame(x, y, dstBar.frame) < NearSquared then return dstBar, dstArea, dstPos end end function Bazooka:highlight(bar, area, pos) if self.hlBar and self.hlBar ~= bar then self.hlBar:highlight(nil) end self.hlBar = bar if bar then bar:highlight(area, pos) end end function Bazooka:getInsetForEdgeSize(edgeSize) return math.floor(edgeSize / 4) end function Bazooka:toggleBar(hiddenFlag, barId, ...) if not barId then return end barId = tonumber(barId) or -1 local bar = self.bars[barId] if bar then bar:toggleHidden(hiddenFlag) end self:toggleBar(hiddenFlag, ...) end function Bazooka:toggleBars(hiddenFlag, params) if not params then for i = 1, #self.bars do local bar = self.bars[i] if bar.db.marked then bar:toggleHidden(hiddenFlag) end end else self:toggleBar(hiddenFlag, strsplit(' ', params)) end end function Bazooka:getSubAppName(name) return self.AppName .. '.' .. name end -- BEGIN LoD Options muckery function Bazooka:loadOptions() self.optionsLoaded, self.optionsLoadError = LoadAddOn(OptionsAppName) end function Bazooka:openConfigDialog() -- this function will be overwritten by the Options module when loaded print(OptionsAppName .. " not loaded: " .. tostring(self.optionsLoadError)) self.openConfigDialog = function() end end -- END LoD Options muckery -- static dialog setup function Bazooka:openStaticDialog(dialog, frameArg, textArg1, textArg2) local dialogFrame = StaticPopup_Show(dialog, textArg1, textArg2) if dialogFrame then dialogFrame.data = frameArg end end function Bazooka:closeStaticDialog(dialog) StaticPopup_Hide(dialog) end function Bazooka:profileCmd(profileName) profileName = strtrim(profileName or "") if profileName == "" then local curr = self.db:GetCurrentProfile() for i, p in ipairs(self.db:GetProfiles()) do if (p == curr) then print("|cFF33cc33" .. p .. "|r") else print(p) end end else for i, p in ipairs(self.db:GetProfiles()) do if (p == profileName) then self.db:SetProfile(profileName) return end end print("|cFFcc3333? " .. profileName .. "|r") end end StaticPopupDialogs[BzkDialogDisablePlugin] = { text = L["Disable %s plugin?"], button1 = _G.YES, button2 = _G.NO, OnAccept = function(frame) if not frame.data then return end Bazooka:disablePlugin(frame.data) Bazooka:updatePluginOptions() end, timeout = 0, whileDead = 1, hideOnEscape = 1, } -- Stubs for Bazooka_Options function Bazooka:updateMainOptions() end function Bazooka:updateBarOptions() end function Bazooka:updatePluginOptions() end -- register slash command SLASH_BAZOOKA1 = "/bazooka" SlashCmdList["BAZOOKA"] = function(msg) msg = strtrim(msg or "") local cmd, params = strsplit(' ', msg, 2) if cmd == "locked" then Bazooka:toggleLocked() elseif cmd == "hidebars" then Bazooka:toggleBars(true, params) elseif cmd == "showbars" then Bazooka:toggleBars(false, params) elseif cmd == "togglebars" then Bazooka:toggleBars(nil, params) elseif cmd == "profile" then Bazooka:profileCmd(params) else Bazooka:openConfigDialog() end end -- CONFIGMODE CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {} CONFIGMODE_CALLBACKS[AppName] = function(action) if action == "ON" then Bazooka:toggleLocked(false) elseif action == "OFF" then Bazooka:toggleLocked(true) end end -- Create our TopAnchor and BottomAnchor so that integrators can use them as soon as we are loaded Bazooka:initAnchors() --[[ Anchor test local topFrame = CreateFrame("Frame") topFrame:SetPoint("TOPLEFT", Bazooka.TopAnchor, "BOTTOMLEFT") topFrame:SetPoint("TOPRIGHT", Bazooka.TopAnchor, "BOTTOMRIGHT") topFrame:SetHeight(20) local tft = topFrame:CreateTexture() tft:SetAllPoints() tft:SetTexture(.8, 0.2, 0.2, 0.5) local bottomFrame = CreateFrame("Frame") bottomFrame:SetPoint("BOTTOMLEFT", Bazooka.BottomAnchor, "TOPLEFT") bottomFrame:SetPoint("BOTTOMRIGHT", Bazooka.BottomAnchor, "TOPRIGHT") bottomFrame:SetHeight(20) local bft = bottomFrame:CreateTexture() bft:SetAllPoints() bft:SetTexture(.8, 0.4, 0.2, 0.5) --]]