FUBAR_VERSION = tonumber((string.gsub("$Revision: 9716 $", "^.-(%d+).-$", "%1"))) local AceOO = AceLibrary("AceOO-2.0") local Jostle = AceLibrary("Jostle-2.0") local AceEvent = AceLibrary("AceEvent-2.0") local SPACING_FROM_SIDES = 5 local bgFile = "Interface\\AddOns\\FuBar\\background" local function getsecond(_, value) return value end local L = AceLibrary("AceLocale-2.0"):new("FuBar") local _G = getfenv(0) FuBar_Panel = AceOO.Class() local FuBar_Panel = FuBar_Panel FuBar_Panel.id = 0 FuBar_Panel.instances = {} FuBar_Panel.sealed = true function FuBar_Panel:ToString() return "FuBar_Panel" end function FuBar_Panel:SetBackground(bg) if bgFile ~= bg then bgFile = bg for _,v in ipairs(self.instances) do v:UpdateTexture() end end end function FuBar_Panel:IsBackground(bg) return bgFile == bg end local frame_OnMouseUp = function() if arg1 == "RightButton" then this.panel:OpenMenu() elseif arg1 == "LeftButton" then this.panel:StopDrag() HideDropDownMenu(1) end end local frame_OnMouseDown = function() if arg1 == "LeftButton" then this.panel:StartDrag() end end local frame_OnDragStart = function() this.panel:StartDrag() end local frame_OnDragStop = function() this.panel:StopDrag() end local frame_OnEnter = function() FuBar:Panel_OnEnter(this.panel:GetAttachPoint()) end local frame_OnLeave = function() FuBar:Panel_OnLeave(this.panel:GetAttachPoint()) end local frame_OnSizeChanged = function() local panel = this.panel if this.lastWidth == GetScreenWidth() then panel.data.widthPercent = panel.frame:GetWidth() / GetScreenWidth() else this.lastWidth = GetScreenWidth() end panel:UpdateCenteredPosition() panel:UpdateTexture() end local left_OnEnter = function() if not this.panel:IsLocked() then SetCursor("ATTACK_ERROR_CURSOR") end end local left_OnLeave = ResetCursor local right_OnEnter = left_OnEnter local right_OnLeave = left_OnLeave local left_OnMouseDown = function() if arg1 == "LeftButton" then this.panel:StartSizing('LEFT') end end local left_OnMouseUp = function() if arg1 == "RightButton" then this.panel:OpenMenu() elseif arg1 == "LeftButton" then this.panel:StopDrag() end end local right_OnMouseDown = function() if arg1 == "LeftButton" then this.panel:StartSizing('RIGHT') end end local right_OnMouseUp = left_OnMouseUp local backdropsPerPanel = ceil(GetScreenWidth() / 256) local topTexture local bottomTexture function FuBar_Panel.prototype:init(attachPoint) self.class.super.prototype.init(self) self.class.id = self.class.id + 1 if not FuBar.db.profile.panels then FuBar.db.profile.panels = {} end if not FuBar.db.profile.panels[self.class.id] then table.insert(FuBar.db.profile.panels, {}) end if not FuBar.db.profile.detached then FuBar.db.profile.detached = {} end self.data = FuBar.db.profile.panels[self.class.id] if not self.data then FuBar.db.profile.panels[self.class.id] = {} self.data = FuBar.db.profile.panels[self.class.id] end self.id = self.class.id self.plugins = { left = {}, center = {}, right = {}, } self.frame = _G["FuBarFrame" .. self.id] if not self.frame then local frame = CreateFrame("Frame", "FuBarFrame" .. self.id, UIParent) self.frame = frame if not topTexture then topTexture = frame:CreateTexture("FuBarFrameTopTexture", "ARTWORK") bottomTexture = frame:CreateTexture("FuBarFrameBottomTexture", "ARTWORK") topTexture:SetTexture(1, 1, 1) topTexture:SetGradientAlpha("VERTICAL", 1, 1, 1, 0, 1, 1, 1, 0.5 * FuBar:GetTransparency()) bottomTexture:SetTexture(1, 1, 1) bottomTexture:SetGradientAlpha("VERTICAL", 1, 1, 1, 0.5 * FuBar:GetTransparency(), 1, 1, 1, 0) topTexture:Hide() bottomTexture:Hide() end frame:SetFrameStrata("HIGH") frame:SetFrameLevel(6) frame:EnableMouse(true) frame:SetMovable(true) frame:SetResizable(true) frame:SetWidth(500) frame:SetHeight(24) frame:SetPoint('TOP', UIParent, 'TOP') local left = CreateFrame("Frame", frame:GetName() .. 'LEFT', frame) left:SetPoint('TOPLEFT', frame, 'TOPLEFT') left:SetPoint('BOTTOMRIGHT', frame, 'BOTTOMLEFT', 5, 0) left:EnableMouse(true) left:Show() local right = CreateFrame("Frame", frame:GetName() .. 'RIGHT', frame) right:SetPoint('TOPRIGHT', frame, 'TOPRIGHT') right:SetPoint('BOTTOMLEFT', frame, 'BOTTOMRIGHT', -5, 0) right:EnableMouse(true) right:Show() frame.left = left frame.right = right frame.lastWidth = GetScreenWidth() frame:SetScript("OnMouseUp", frame_OnMouseUp) frame:SetScript("OnMouseDown", frame_OnMouseDown) frame:SetScript("OnDragStart", frame_OnDragStart) frame:SetScript("OnDragStop", frame_OnDragStop) frame:SetScript("OnEnter", frame_OnEnter) frame:SetScript("OnLeave", frame_OnLeave) frame:SetScript("OnSizeChanged", frame_OnSizeChanged) left:SetScript("OnEnter", left_OnEnter) left:SetScript("OnLeave", left_OnLeave) right:SetScript("OnEnter", right_OnEnter) right:SetScript("OnLeave", right_OnLeave) left:SetScript("OnMouseDown", left_OnMouseDown) left:SetScript("OnMouseUp", left_OnMouseUp) right:SetScript("OnMouseDown", right_OnMouseDown) right:SetScript("OnMouseUp", right_OnMouseUp) frame.bgTextures = {} local lastTexture for i = 1, backdropsPerPanel do local texture = frame:CreateTexture(frame:GetName() .. "Texture" .. i, "BACKGROUND") texture:SetWidth(256) texture:SetHeight(256) if not lastTexture then texture:SetPoint('TOPLEFT', frame, 'TOPLEFT') else texture:SetPoint('LEFT', lastTexture, 'RIGHT') end texture:SetTexture(bgFile) table.insert(frame.bgTextures, texture) lastTexture = texture end end self.bgTextures = self.frame.bgTextures self.frame.panel = self self.frame.left.panel = self self.frame.right.panel = self if not self.class.instances[self.id] then table.insert(self.class.instances, self) else self.class.instances[self.id] = self end if not self.data.attachPoint then self.data.attachPoint = attachPoint or 'TOP' end if not self.data.plugins then self.data.plugins = { left = {}, right = {}, center = {}, } end if not self.frame:IsShown() then self.frame:Show() end self.stopUpdates = {} for _,v in ipairs(self.class.instances) do v:Update() v:UpdateTexture() end if self.data.attachPoint == 'TOP' then Jostle:RegisterTop(self.frame) self.frame:SetFrameStrata("HIGH") self.frame:SetFrameLevel(6) elseif self.data.attachPoint == 'BOTTOM' then Jostle:RegisterBottom(self.frame) self.frame:SetFrameStrata("HIGH") self.frame:SetFrameLevel(6) else self.frame:SetFrameStrata("MEDIUM") self.frame:SetFrameLevel(1) end AceEvent:TriggerEvent("FuBar_ChangedPanels") Jostle:Refresh() end function FuBar_Panel.prototype:del(force) assert(force or self.class.id > 1, "Cannot destroy only panel.") if topTexture.attachedTo == self then topTexture:ClearAllPoints() topTexture:Hide() topTexture.attachedTo = nil end if bottomTexture.attachedTo == self then bottomTexture:ClearAllPoints() bottomTexture:Hide() bottomTexture.attachedTo = nil end for h = 1, 3 do local t, position if h == 1 then t = self.plugins.left position = 'LEFT' elseif h == 2 then t = self.plugins.center position = 'CENTER' else t = self.plugins.right position = 'RIGHT' end for i = table.getn(t), 1, -1 do local plugin = t[i] self:RemovePlugin(i, position) plugin:Hide() end end for i = self.id + 1, self.class.id do if self.class.instances[i]:GetAttachPoint() == self.data.attachPoint then self:SwitchWithPanel(i) end end Jostle:Unregister(self.frame) if not force then self:SetAttachPoint('NONE') end self.frame:Hide() if not force then table.remove(FuBar.db.profile.panels, self.id) end self.data = nil self.plugins = nil table.remove(self.class.instances, self.id) self.class.id = self.class.id - 1 AceEvent:TriggerEvent("FuBar_ChangedPanels") for i = 1, self.class.id do local panel = self.class.instances[i] panel.id = i panel:UpdateTexture() panel:Update() end Jostle:Refresh() end function FuBar_Panel.prototype:WarnDestroy() if self:GetNumPlugins('LEFT') + self:GetNumPlugins('CENTER') + self:GetNumPlugins('RIGHT') == 0 then self:del() else if not StaticPopupDialogs["FUBAR_DESTROY_PANEL"] then StaticPopupDialogs["FUBAR_DESTROY_PANEL"] = { text = L["Are you sure you want to remove this panel?"], button1 = L["Remove panel"], button2 = CANCEL, timeout = 0, whileDead = 1, hideOnEscape = 1, } end StaticPopupDialogs["FUBAR_DESTROY_PANEL"].OnAccept = function() self:del() end StaticPopup_Show("FUBAR_DESTROY_PANEL") end end function FuBar_Panel.prototype:SwitchWithPanel(id, preventUpdate) local other = self.class.instances[id] if not other or self.data.attachPoint ~= other.data.attachPoint then return end other.id, self.id = self.id, other.id other.frame, self.frame = self.frame, other.frame self.frame.panel = self other.frame.panel = other self.frame.left.panel = self other.frame.right.panel = other self.class.instances[other.id] = other self.class.instances[self.id] = self FuBar.db.profile.panels[other.id], FuBar.db.profile.panels[self.id] = FuBar.db.profile.panels[self.id], FuBar.db.profile.panels[other.id] self.bgTextures, other.bgTextures = other.bgTextures, self.bgTextures if not preventUpdate then other:Update() self:Update() end for i = 1, self.class.id do self.class.instances[i]:UpdateTexture() end AceEvent:TriggerEvent("FuBar_ChangedPanels") Jostle:Refresh() end function FuBar_Panel.prototype:GetAttachPoint() if not self.data then ReloadUI() return end return self.data.attachPoint end function FuBar_Panel.prototype:SetAttachPoint(point) if self.data.attachPoint == point then return end Jostle:Unregister(self.frame) if point == 'NONE' then self.data.yPercent = 0.5 - (FuBarFrame1:GetHeight()/2 / GetScreenHeight()) self.frame:SetFrameStrata("MEDIUM") self.frame:SetFrameLevel(1) elseif point == 'TOP' or point == 'BOTTOM' then self.data.yPercent = nil self.frame:SetFrameStrata("HIGH") self.frame:SetFrameLevel(6) else assert(false, "Improper attach point given: " .. point) end local previous = self.data.attachPoint self.data.attachPoint = point for i = self.id, self.class.id do local panel = self.class.instances[i] if previous == panel:GetAttachPoint() or point == panel:GetAttachPoint() then panel:Update() end end self:Update() Jostle:Refresh() if self:IsLocked() then self:ToggleLocked() end if self.data.attachPoint == 'TOP' then Jostle:RegisterTop(self.frame) elseif self.data.attachPoint == 'BOTTOM' then Jostle:RegisterBottom(self.frame) end for i = 1, self.class.id do self.class.instances[i]:UpdateTexture() end AceEvent:TriggerEvent("FuBar_ChangedPanels") Jostle:Refresh() end function FuBar_Panel.prototype:IsLocked() return self.data and self.data.lock end function FuBar_Panel.prototype:ToggleLocked() if self.data then self.data.lock = not self.data.lock return self.data.lock end end function FuBar_Panel.prototype:GetPositionFromEdge() local num = 1 local set = 0 if self.data.attachPoint == 'TOP' then for i = 1, self.class.id do local panel = self.class.instances[i] if panel == self then set = num num = num + 1 elseif panel and panel:GetAttachPoint() == 'TOP' then num = num + 1 end end elseif self.data.attachPoint == 'BOTTOM' then for i = 1, self.class.id do local panel = self.class.instances[i] if panel == self then set = num num = num + 1 elseif panel and panel:GetAttachPoint() == 'BOTTOM' then num = num + 1 end end else return end return num - set end function FuBar_Panel.prototype:UpdateTexture() if topTexture.attachedTo == self then topTexture:ClearAllPoints() topTexture:Hide() topTexture.attachedTo = nil end if bottomTexture.attachedTo == self then bottomTexture:ClearAllPoints() bottomTexture:Hide() bottomTexture.attachedTo = nil end local point = self:GetAttachPoint() local height = FuBar:GetFontSize() + FuBar:GetThickness() self.frame:SetHeight(height) local uiscale = 768 / GetScreenHeight() local texsize = 256 / uiscale local realLeft = self.frame:GetLeft() or 0 local left = mod(self.frame:GetLeft() or 0, texsize) local width = self.frame:GetWidth() or 0 local fromEdge = self:GetPositionFromEdge() if fromEdge and self.bgTextures then local y1, y2 if self.data.attachPoint == 'TOP' then y1, y2 = 1-((height) / texsize) * fromEdge, 1-(height / 256) * (fromEdge - 1) else y1, y2 = ((height + 2) / texsize) * (fromEdge - 1), ((height+2) / 256) * fromEdge end for i,texture in ipairs(self.bgTextures) do texture:SetTexture(bgFile) local x = (i - 1) * texsize local xr = i * texsize texture:Show() texture:SetHeight(height) local x1, x2 = 0, 1 local changed = false if i == 1 then x1 = left / texsize texture:SetWidth(texsize - left) changed = true end if width + left < xr then if i == 1 then texture:SetWidth(width) x2 = mod(width + left - x, texsize) / texsize else texture:SetWidth(mod(width + left - x, texsize)) x2 = mod(width + left - x, texsize) / texsize end elseif not changed then texture:SetWidth(texsize) end texture:SetPoint('TOPLEFT', self.frame, 'TOPLEFT', x + x1*texsize - left, 0) texture:SetTexCoord(x1, x2, y1, y2) texture:SetVertexColor(1, 1, 1, FuBar:GetTransparency()) end elseif self.bgTextures then local y1, y2 = 0.5 - height / texsize / 2, 0.5 + height / texsize / 2 for i,texture in ipairs(self.bgTextures) do texture:SetTexture(bgFile) local x = (i - 1) * texsize local xr = i * texsize texture:Show() texture:SetHeight(height) local changed = false local x1, x2 = 0, 1 if width < xr then texture:SetWidth(mod(width - x, texsize)) x2 = mod(width - x, texsize) / texsize else texture:SetWidth(texsize) end texture:SetTexCoord(x1, x2, y1, y2) texture:SetVertexColor(1, 1, 1, FuBar:GetTransparency()) end end end function FuBar_Panel.prototype:AddPlugin(plugin, index, side, isDefaultSide) if FuBar:IsChangingProfile() then return end if plugin:GetPanel() then plugin:GetPanel():RemovePlugin(plugin) end plugin:SetPanel(self) if FuBar.db.profile.detached then FuBar.db.profile.detached[plugin:GetTitle()] = nil end plugin:GetFrame():SetParent(self.frame) if not FuBar.db.profile.places then FuBar.db.profile.places = {} end if FuBar.db.profile.places.left and FuBar.db.profile.places.left[plugin:GetTitle()] then FuBar.db.profile.places.left[plugin:GetTitle()] = nil if not side or isDefaultSide then side = 'LEFT' end end if FuBar.db.profile.places.center and FuBar.db.profile.places.center[plugin:GetTitle()] then FuBar.db.profile.places.center[plugin:GetTitle()] = nil if not side or isDefaultSide then side = 'CENTER' end end if FuBar.db.profile.places.right and FuBar.db.profile.places.right[plugin:GetTitle()] then FuBar.db.profile.places.right[plugin:GetTitle()] = nil if not side or isDefaultSide then side = 'RIGHT' end end if not side then side = 'LEFT' end local positioned = false for h = 1, 3 do local t, dt if h == 1 then t = self.plugins.left dt = self.data.plugins.left elseif h == 2 then t = self.plugins.center dt = self.data.plugins.center else t = self.plugins.right dt = self.data.plugins.right end for i, value in ipairs(dt) do if value == plugin:GetTitle() then for j = i - 1, 1, -1 do local otherName = dt[j] for k, p in ipairs(t) do if p:GetTitle() == otherName then table.insert(t, k + 1, plugin) positioned = true break end end if positioned then break end end if not positioned then table.insert(t, 1, plugin) positioned = true end break end end if positioned then break end end if not positioned then local t, dt if side == 'RIGHT' then t, dt = self.plugins.right, self.data.plugins.right elseif side == 'CENTER' then t, dt = self.plugins.center, self.data.plugins.center else t, dt = self.plugins.left, self.data.plugins.left end if not index then table.insert(t, plugin) table.insert(dt, plugin:GetTitle()) else if index == 1 then table.insert(t, index, plugin) table.insert(dt, 1, plugin:GetTitle()) else table.insert(t, index, plugin) local name = t[index - 1]:GetTitle() local done = false for k, v in ipairs(dt) do if name == v then table.insert(dt, k + 1, plugin:GetTitle()) done = true break end end if not done then table.insert(dt, plugin:GetTitle()) end end end end plugin:GetFrame():Show() if plugin.minimapFrame then plugin.minimapFrame:Hide() end if not positioned then assert(self:GetPluginSide(plugin) == side) end self:Update() return true end function FuBar_Panel.prototype:RemovePlugin(index, side) if FuBar:IsChangingProfile() then return end if type(index) == "table" then index, side = self:IndexOfPlugin(index) if not index then return end end local t, dt if not FuBar.db.profile.places then FuBar.db.profile.places = {} end if side == 'RIGHT' then if not FuBar.db.profile.places.right then FuBar.db.profile.places.right = {} end t, dt = self.plugins.right, self.data.plugins.right FuBar.db.profile.places.right[t[index]:GetTitle()] = true elseif side == 'CENTER' then if not FuBar.db.profile.places.center then FuBar.db.profile.places.center = {} end t, dt = self.plugins.center, self.data.plugins.center FuBar.db.profile.places.center[t[index]:GetTitle()] = true else if not FuBar.db.profile.places.left then FuBar.db.profile.places.left = {} end t, dt = self.plugins.left, self.data.plugins.left FuBar.db.profile.places.left[t[index]:GetTitle()] = true end local plugin = t[index] assert(plugin:GetPanel() == self, "Plugin has improper panel field") plugin:SetPanel(nil) if not self.class.stopUpdates then plugin:GetFrame():Hide() if plugin.minimapFrame then plugin.minimapFrame:Hide() end end for i = 1, table.getn(dt) do if dt[i] == plugin:GetTitle() then table.remove(dt, i) end end table.remove(t, index) FuBar.db.profile.detached[plugin:GetTitle()] = true self:Update() end function FuBar_Panel.prototype:GetPlugin(index, side) if not self.plugins then ReloadUI() return end if side == 'RIGHT' then return self.plugins.right[index] elseif side == 'CENTER' then return self.plugins.center[index] else return self.plugins.left[index] end end function FuBar_Panel.prototype:GetNumPlugins(side) if side == 'RIGHT' then return table.getn(self.plugins.right) elseif side == 'CENTER' then return table.getn(self.plugins.center) else return table.getn(self.plugins.left) end end function FuBar_Panel.prototype:IndexOfPlugin(plugin) for i = 1, self:GetNumPlugins('LEFT') do if self.plugins.left[i] == plugin then return i, 'LEFT' end end for i = 1, self:GetNumPlugins('CENTER') do if self.plugins.center[i] == plugin then return i, 'CENTER' end end for i = 1, self:GetNumPlugins('RIGHT') do if self.plugins.right[i] == plugin then return i, 'RIGHT' end end end function FuBar_Panel.prototype:HasPlugin(plugin) return self:IndexOfPlugin(plugin) ~= nil end function FuBar_Panel.prototype:GetPluginSide(plugin) local index, side = self:IndexOfPlugin(plugin) assert(index, "Plugin not in panel") return side end function FuBar_Panel.prototype:SetPluginSide(plugin, side) local oldSide = self:GetPluginSide(plugin) if oldSide ~= side then self:RemovePlugin(plugin) self:AddPlugin(plugin, nil, side) self:Update() end end function FuBar_Panel:PreventUpdate() self.stopUpdates = true end function FuBar_Panel:StopPreventUpdate(code) self.stopUpdates = false end function FuBar_Panel.prototype:Update() if self.class.stopUpdates then return end if not self.data.widthPercent or self.data.widthPercent > 1 then self.data.widthPercent = 1 end local width = self.data.widthPercent * GetScreenWidth() self.frame:SetWidth(width) if not self.data.xPercent or not self.data.yPercent then self.data.xPercent = 0.5 - self.data.widthPercent / 2 self.data.yPercent = 0.5 end if self:GetAttachPoint() == 'TOP' then self.frame:ClearAllPoints() local hasTop = nil for i = self.id - 1, 1, -1 do if self.class.instances[i] and self.class.instances[i]:GetAttachPoint() == 'TOP' then hasTop = self.class.instances[i] break end end if not hasTop then self.frame:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', self.data.xPercent * GetScreenWidth(), 1) else self.frame:SetPoint('TOPLEFT', hasTop.frame, 'BOTTOMLEFT', self.data.xPercent * GetScreenWidth() - (hasTop.frame:GetLeft() or 0), 0) end elseif self:GetAttachPoint(panelId) == 'BOTTOM' then self.frame:ClearAllPoints() local hasBottom = nil for i = self.id - 1, 1, -1 do if self.class.instances[i] and self.class.instances[i]:GetAttachPoint() == 'BOTTOM' then hasBottom = self.class.instances[i] break end end if not hasBottom then self.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', self.data.xPercent * GetScreenWidth(), -1) else self.frame:SetPoint('BOTTOMLEFT', hasBottom.frame, 'TOPLEFT', self.data.xPercent * GetScreenWidth() - hasBottom.frame:GetLeft(), 0) end else self.frame:ClearAllPoints() self.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', self.data.xPercent * GetScreenWidth(), self.data.yPercent * GetScreenHeight()) end local num = 0 for h = 1, 3 do local t, side if h == 1 then t = self.plugins.left side = 'LEFT' elseif h == 2 then t = self.plugins.center side = 'CENTER' else t = self.plugins.right side = 'RIGHT' end local i = 1 while i <= self:GetNumPlugins(side) do assert(t[i], "nil plugin spot") if type(t[i].IsDisabled) == "function" and t[i]:IsDisabled() then self:RemovePlugin(i, side) i = i - 1 end i = i + 1 end end for h = 1, 3 do local t, side if h == 1 then t = self.plugins.left side = 'LEFT' elseif h == 2 then t = self.plugins.center side = 'CENTER' else t = self.plugins.right side = 'RIGHT' end for i = 1, self:GetNumPlugins(side) do t[i]:CheckWidth() t[i].frame:SetParent(self.frame) t[i].frame:ClearAllPoints() end end for h = 1, 3 do local t, side, alpha, bravo, sideSpacing, spacing if h == 1 then t = self.plugins.left side = 'LEFT' alpha, bravo = 'LEFT', 'RIGHT' sideSpacing = SPACING_FROM_SIDES spacing = FuBar:GetLeftSpacing() elseif h == 2 then t = self.plugins.center side = 'CENTER' alpha, bravo = 'LEFT', 'RIGHT' sideSpacing = SPACING_FROM_SIDES spacing = FuBar:GetCenterSpacing() else t = self.plugins.right side = 'RIGHT' alpha, bravo = 'RIGHT', 'LEFT' sideSpacing = -SPACING_FROM_SIDES spacing = -FuBar:GetRightSpacing() end for i = 1, self:GetNumPlugins(side) do t[i].frame:Show() if i == 1 then t[i].frame:SetPoint(alpha, self.frame, alpha, sideSpacing, 0) else t[i].frame:SetPoint(alpha, t[i-1].frame, bravo, spacing, 0) end end end self:UpdateCenteredPosition() self:CheckForOverlap() end function FuBar_Panel.prototype:UpdateCenteredPosition() if self:GetPlugin(1, 'CENTER') then local num = self:GetNumPlugins('CENTER') local width = num * FuBar:GetCenterSpacing() for i = 1, num do width = width + self.plugins.center[i].frame:GetWidth() end local frame = self:GetPlugin(1, 'CENTER').frame frame:ClearAllPoints() frame:SetPoint('LEFT', self.frame, 'LEFT', (self.data.widthPercent * GetScreenWidth() - width) / 2, 0) end end function FuBar_Panel.prototype:GetSavedOrder(side) if side == 'RIGHT' then return self.data.plugins.right elseif side == 'CENTER' then return self.data.plugins.center else return self.data.plugins.left end end function FuBar_Panel.prototype:ResetSavedOrder(side) local t if side == 'RIGHT' then t = self.data.plugins.right elseif side == 'CENTER' then t = self.data.plugins.center else t = self.data.plugins.left end for key in pairs(t) do t[key] = nil end end local Dewdrop = AceLibrary("Dewdrop-2.0") function FuBar_Panel.prototype:OpenMenu() if Dewdrop:IsOpen(self.frame) then Dewdrop:Close() return end self.class.selectedPanel = self.id if not Dewdrop:IsRegistered(self.class.instances[1].frame) then Dewdrop:Register(self.class.instances[1].frame, 'children', FuBar.menu, 'point', function(parent) if parent:GetTop() < GetScreenHeight() / 2 then return 'BOTTOM', 'TOP' else return 'TOP', 'BOTTOM' end end, 'cursorX', true, 'dontHook', true ) end Dewdrop:Open(self.frame, self.class.instances[1].frame) end local closePanel function FuBar_Panel.prototype:StartSizing(direction) DropDownList1:Hide() if not self:IsLocked() then local x, y = FuBar:GetScaledCursorPosition() local left, right = self.frame:GetLeft(), self.frame:GetRight() if self:GetAttachPoint() ~= 'NONE' then self.lastWidth = self.frame:GetWidth() end self.frame:StartSizing(direction) self.sizeFrom = direction closePanel = nil for i = self.id + 1, self.class.id do local panel = self.class.instances[i] if panel:GetAttachPoint() == self:GetAttachPoint() then closePanel = panel local x, y = closePanel.frame:GetLeft(), closePanel.frame:GetBottom() closePanel.frame:ClearAllPoints() closePanel.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', x, y) break end end end end local lastX, lastY function FuBar_Panel.prototype:StartDrag() if not self:IsLocked() and self:GetAttachPoint() == 'NONE' then self.frame:StartMoving() elseif not self:IsLocked() then self.frame:StartMoving() closePanel = nil for i = self.id + 1, self.class.id do local panel = self.class.instances[i] if panel and panel:GetAttachPoint() == self:GetAttachPoint() then closePanel = panel local x, y = closePanel.frame:GetLeft(), closePanel.frame:GetBottom() closePanel.frame:ClearAllPoints() closePanel.frame:SetPoint('BOTTOMLEFT', UIParent, 'BOTTOMLEFT', x, y) break end end lastX, lastY = self.frame:GetCenter() end end function FuBar_Panel.prototype:StopDrag() self.frame:StopMovingOrSizing() local x, y = self.frame:GetCenter() local offsetX = 0 if self.frame:GetWidth() < 50 then if self.sizeFrom == 'LEFT' then offsetX = self.frame:GetWidth() - 50 end self.frame:SetWidth(50) elseif self.frame:GetWidth() > GetScreenWidth() then if self.sizeFrom == 'RIGHT' then offsetX = self.frame:GetWidth() - self.frame:GetRight() else offsetX = -self.frame:GetLeft() end self.frame:SetWidth(GetScreenWidth()) end self.sizeFrom = nil self.data.xPercent = (self.frame:GetLeft() + offsetX) / GetScreenWidth() self.data.yPercent = self.frame:GetBottom() / GetScreenHeight() self.data.widthPercent = self.frame:GetWidth() / GetScreenWidth() if self.data.xPercent < 0 then self.data.xPercent = 0 elseif self.data.xPercent + self.data.widthPercent > 1 then self.data.xPercent = 1 - self.data.widthPercent end self:Update() if closePanel then closePanel:Update() closePanel = nil end if lastY then if self:GetAttachPoint() == 'TOP' then if y < GetScreenHeight() / 2 then self:SetAttachPoint('BOTTOM') end else if y > GetScreenHeight() /2 then self:SetAttachPoint('TOP') end end if self:GetAttachPoint() == 'TOP' then local position = 0 for i = 1, self.class.id do if i ~= self.id then local other = self.class.instances[i] if other:GetAttachPoint() == 'TOP' then if y <= getsecond(other.frame:GetCenter()) then position = i end end else if y <= lastY then position = i end end end lastY = nil if position < self.id then position = position + 1 end local shift = position - self.id local num = 0 if shift < 0 then for i = 1, -shift do num = num + 1 if self.class.instances[self.id - num]:GetAttachPoint() == 'TOP' then self:SwitchWithPanel(self.id - num) num = 0 end end elseif shift > 0 then for i = 1, shift do num = num + 1 if self.class.instances[self.id + num]:GetAttachPoint() == 'TOP' then self:SwitchWithPanel(self.id + num) num = 0 end end end elseif self:GetAttachPoint() == 'BOTTOM' then local position = 0 for i = 1, self.class.id do if i ~= self.id then local other = self.class.instances[i] if other:GetAttachPoint() == 'BOTTOM' then if y >= getsecond(other.frame:GetCenter()) then position = i end end else if y >= lastY then position = i end end end lastY = nil if position < self.id then position = position + 1 end local shift = position - self.id local num = 0 if shift < 0 then for i = 1, -shift do num = num + 1 if self.class.instances[self.id - num]:GetAttachPoint() == 'BOTTOM' then self:SwitchWithPanel(self.id - num) num = 0 end end elseif shift > 0 then for i = 1, shift do num = num + 1 if self.class.instances[self.id + num]:GetAttachPoint() == 'BOTTOM' then self:SwitchWithPanel(self.id + num) num = 0 end end end end end self:UpdateTexture() end function FuBar_Panel.prototype:HasOverlap() local leftNum, centerNum, rightNum = self:GetNumPlugins('LEFT'), self:GetNumPlugins('CENTER'), self:GetNumPlugins('RIGHT') local left = self:GetPlugin(leftNum, 'LEFT') local right = self:GetPlugin(rightNum, 'RIGHT') local centerLeft = self:GetPlugin(1, 'CENTER') local centerRight = self:GetPlugin(centerNum, 'CENTER') if centerLeft then if left and left.frame:GetRight() and centerLeft.frame:GetLeft() then if left and left.frame:GetRight() >= centerLeft.frame:GetLeft() - 5 then return true end end return right and right.frame:GetLeft() and centerRight.frame:GetRight() and right.frame:GetLeft() <= centerRight.frame:GetRight() + 5 elseif left and right then if left.frame:GetRight() and right.frame:GetLeft() then return left.frame:GetRight() >= right.frame:GetLeft() - 5 end elseif left then if left.frame:GetRight() and self.frame:GetRight() then return left.frame:GetRight() > self.frame:GetRight() - 5 end elseif right then if right.frame:GetLeft() and self.frame:GetLeft() then return right.frame:GetLeft() < self.frame:GetLeft() + 5 end end return false end function FuBar_Panel.prototype:CheckForOverlap() if FuBar:IsOverflowing() and self:HasOverlap() then local side = 'CENTER' local plugin = self:GetPlugin(self:GetNumPlugins(side), side) if not plugin then side = 'LEFT' plugin = self:GetPlugin(self:GetNumPlugins(side), side) if not plugin then side = 'RIGHT' plugin = self:GetPlugin(self:GetNumPlugins(side), side) end end local panel for i = self.id + 1, self.class.id do if self.class.instances[i]:GetAttachPoint() == self:GetAttachPoint() then panel = self.class.instances[i] end end if not panel then panel = FuBar_Panel:new(self:GetAttachPoint()) end FuBar_Panel:PreventUpdate() self:RemovePlugin(plugin) panel:AddPlugin(plugin, 1, side) FuBar_Panel:StopPreventUpdate() panel:Update() self:Update() end end