vanilla-wow-addons – Rev 1
?pathlinks?
--[[
Name: Jostle-2.0
Revision: $Rev: 9867 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://wiki.wowace.com/index.php/Jostle-2.0
SVN: http://svn.wowace.com/root/trunk/JostleLib/Jostle-2.0
Description: A library to handle rearrangement of blizzard's frames when bars are added to the sides of the screen.
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0
]]
local MAJOR_VERSION = "Jostle-2.0"
local MINOR_VERSION = "$Revision: 9867 $"
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
local AceEvent
local Jostle = {}
local blizzardFrames = {
'PlayerFrame',
'TargetFrame',
'MinimapCluster',
'PartyMemberFrame1',
'TicketStatusFrame',
'WorldStateAlwaysUpFrame',
'MainMenuBar',
'MultiBarRight',
'CT_PlayerFrame_Drag',
'CT_TargetFrame_Drag',
'Gypsy_PlayerFrameCapsule',
'Gypsy_TargetFrameCapsule',
'TemporaryEnchantFrame',
'DEFAULT_CHAT_FRAME',
'ChatFrame2',
'GroupLootFrame1',
'TutorialFrameParent',
'FramerateLabel',
'QuestTimerFrame',
'DurabilityFrame',
'CastingBarFrame',
}
local blizzardFramesData = {}
local _G = getfenv(0)
function Jostle:PLAYER_AURAS_CHANGED()
self:ScheduleEvent(self.Refresh, 0, self)
end
function Jostle:AceEvent_FullyInitialized()
for k,v in pairs(blizzardFramesData) do
blizzardFramesData[k] = nil
end
self:ScheduleEvent(self.Refresh, 0, self)
end
function Jostle:ToggleWorldMap(orig)
orig()
self:Refresh()
end
function Jostle:TicketStatusFrame_OnEvent(orig)
orig()
self:Refresh(TicketStatusFrame, TemporaryEnchantFrame)
end
function Jostle:FCF_UpdateDockPosition(orig)
orig()
self:Refresh(DEFAULT_CHAT_FRAME)
end
function Jostle:FCF_UpdateCombatLogPosition(orig)
orig()
self:Refresh(ChatFrame2)
end
function Jostle:UIParent_ManageFramePositions(orig)
orig()
self:Refresh(GroupLootFrame1, TutorialFrameParent, FramerateLabel, QuestTimerFrame, DurabilityFrame)
end
function Jostle:WorldMapFrameCloseButton_OnClick(orig)
orig()
self:Refresh()
end
function Jostle:UIParent_ManageRightSideFrames(orig)
for _,frame in ipairs(blizzardFrames) do
frame = _G[frame]
local frameData = blizzardFramesData[frame]
if frameData and not (frameData.lastX and frameData.lastY and (frameData.lastX ~= frame:GetLeft() or frameData.lastY ~= frame:GetTop())) then
frameData.lastX = nil
frameData.lastY = nil
end
end
orig()
self:Refresh()
end
function Jostle:GetScreenTop()
local bottom = GetScreenHeight()
for _,frame in ipairs(self.topFrames) do
if frame.IsVisible and frame:IsVisible() and frame.GetBottom and frame:GetBottom() and frame:GetBottom() < bottom then
bottom = frame:GetBottom()
end
end
return bottom
end
function Jostle:GetScreenBottom()
local top = 0
for _,frame in ipairs(self.bottomFrames) do
if frame.IsVisible and frame:IsVisible() and frame.GetTop and frame:GetTop() and frame:GetTop() > top then
top = frame:GetTop()
end
end
return top
end
function Jostle:RegisterTop(frame)
for k,f in ipairs(self.bottomFrames) do
if f == frame then
table.remove(self.bottomFrames, k)
break
end
end
for _,f in ipairs(self.topFrames) do
if f == frame then
return
end
end
table.insert(self.topFrames, frame)
self:Refresh()
return true
end
function Jostle:RegisterBottom(frame)
for k,f in ipairs(self.topFrames) do
if f == frame then
table.remove(self.topFrames, k)
break
end
end
for _,f in ipairs(self.bottomFrames) do
if f == frame then
return
end
end
table.insert(self.bottomFrames, frame)
self:Refresh()
return true
end
function Jostle:Unregister(frame)
for k,f in ipairs(self.topFrames) do
if f == frame then
table.remove(self.topFrames, k)
self:Refresh()
return true
end
end
for k,f in ipairs(self.bottomFrames) do
if f == frame then
table.remove(self.bottomFrames, k)
self:Refresh()
return true
end
end
end
function Jostle:IsTopAdjusting()
return self.topAdjust
end
function Jostle:EnableTopAdjusting()
if not self.topAdjust then
self.topAdjust = not self.topAdjust
self:Refresh()
end
end
function Jostle:DisableTopAdjusting()
if self.topAdjust then
self.topAdjust = not self.topAdjust
self:Refresh()
end
end
function Jostle:IsBottomAdjusting()
return self.bottomAdjust
end
function Jostle:EnableBottomAdjusting()
if not self.bottomAdjust then
self.bottomAdjust = not self.bottomAdjust
self:Refresh()
end
end
function Jostle:DisableBottomAdjusting()
if self.bottomAdjust then
self.bottomAdjust = not self.bottomAdjust
self:Refresh()
end
end
local function getsecond(_, value)
return value
end
local tmp = {}
function Jostle:Refresh(f1, f2, f3, f4, f5, f6, f7, f8)
if not AceEvent then
self:error("%s requires AceEvent-2.0", MAJOR_VERSION)
end
if not AceEvent:IsFullyInitialized() then
return
end
local frames
if f1 then
for k in pairs(tmp) do
tmp[k] = nil
end
tmp.n = 0
table.insert(tmp, f1)
table.insert(tmp, f2)
table.insert(tmp, f3)
table.insert(tmp, f4)
table.insert(tmp, f5)
table.insert(tmp, f6)
table.insert(tmp, f7)
table.insert(tmp, f8)
frames = tmp
else
frames = blizzardFrames
end
local screenHeight = GetScreenHeight()
for _,frame in ipairs(frames) do
if type(frame) == "string" then
frame = _G[frame]
end
if frame and not blizzardFramesData[frame] and frame.GetTop and frame:GetCenter() and getsecond(frame:GetCenter()) then
if getsecond(frame:GetCenter()) <= screenHeight / 2 or frame == MultiBarRight then
blizzardFramesData[frame] = {y = frame:GetBottom(), top = false}
else
blizzardFramesData[frame] = {y = frame:GetTop() - screenHeight, top = true}
end
end
end
local topOffset = self:IsTopAdjusting() and self:GetScreenTop() or GetScreenHeight()
local bottomOffset = self:IsBottomAdjusting() and self:GetScreenBottom() or 0
for _,frame in ipairs(frames) do
if type(frame) == "string" then
frame = _G[frame]
end
if ((frame and frame.IsUserPlaced and not frame:IsUserPlaced()) or ((frame == DEFAULT_CHAT_FRAME or frame == ChatFrame2) and SIMPLE_CHAT == "1") or frame == FramerateLabel) and (frame ~= ChatFrame2 or SIMPLE_CHAT == "1") then
local frameData = blizzardFramesData[frame]
if (getsecond(frame:GetPoint(1)) ~= UIParent and getsecond(frame:GetPoint(1)) ~= WorldFrame) then
-- do nothing
elseif frame == PlayerFrame and (CT_PlayerFrame_Drag or Gypsy_PlayerFrameCapsule) then
-- do nothing
elseif frame == TargetFrame and (CT_TargetFrame_Drag or Gypsy_TargetFrameCapsule) then
-- do nothing
elseif frame == PartyMemberFrame1 and (CT_MovableParty1_Drag or Gypsy_PartyFrameCapsule) then
-- do nothing
elseif frame == MainMenuBar and Gypsy_HotBarCapsule then
-- do nothing
elseif frame == DurabilityFrame and DurabilityFrame:IsShown() and (DurabilityFrame:GetLeft() > GetScreenWidth() or DurabilityFrame:GetRight() < 0 or DurabilityFrame:GetBottom() > GetScreenHeight() or DurabilityFrame:GetTop() < 0) then
DurabilityFrame:Hide()
elseif frame == FramerateLabel and ((frameData.lastX and frameData.lastX ~= frame:GetLeft()) or WorldFrame:GetHeight() ~= UIParent:GetHeight()) then
-- do nothing
elseif frame == TemporaryEnchantFrame or frame == CastingBarFrame or frame == TutorialFrameParent or frame == FramerateLabel or frame == QuestTimerFrame or frame == DurabilityFrame or frame == QuestWatchFrame or not (frameData.lastX and frameData.lastY and (frameData.lastX ~= frame:GetLeft() or frameData.lastY ~= frame:GetTop())) then
local anchor
local anchorAlt
local width, height = GetScreenWidth(), GetScreenHeight()
local x
if frame:GetRight() and frame:GetLeft() then
local anchorFrame = UIParent
if frame == MainMenuBar or frame == GroupLootFrame1 then
x = 0
anchor = ""
elseif frame:GetRight() <= width / 2 then
x = frame:GetLeft()
anchor = "LEFT"
else
x = frame:GetRight() - width
anchor = "RIGHT"
end
local y = blizzardFramesData[frame].y
local offset = 0
if blizzardFramesData[frame].top then
anchor = "TOP" .. anchor
offset = topOffset - screenHeight
else
anchor = "BOTTOM" .. anchor
offset = bottomOffset
end
if frame == MinimapCluster and not MinimapBorderTop:IsShown() then
offset = offset + MinimapBorderTop:GetHeight() * 3/5
elseif frame == TemporaryEnchantFrame and TicketStatusFrame:IsVisible() then
offset = offset - TicketStatusFrame:GetHeight()
elseif frame == DEFAULT_CHAT_FRAME then
y = MainMenuBar:GetHeight() + 32
if PetActionBarFrame:IsVisible() or ShapeshiftBarFrame:IsVisible() then
offset = offset + ShapeshiftBarFrame:GetHeight()
end
if MultiBarBottomLeft:IsVisible() then
offset = offset + MultiBarBottomLeft:GetHeight() - 21
end
elseif frame == ChatFrame2 then
y = MainMenuBar:GetHeight() + 32
if MultiBarBottomRight:IsVisible() then
offset = offset + MultiBarBottomRight:GetHeight() - 21
end
elseif frame == CastingBarFrame then
y = MainMenuBar:GetHeight() + 17
if PetActionBarFrame:IsVisible() or ShapeshiftBarFrame:IsVisible() then
offset = offset + ShapeshiftBarFrame:GetHeight()
end
if MultiBarBottomLeft:IsVisible() or MultiBarBottomRight:IsVisible() then
offset = offset + MultiBarBottomLeft:GetHeight()
end
elseif frame == GroupLootFrame1 or frame == TutorialFrameParent or frame == FramerateLabel then
if MultiBarBottomLeft:IsVisible() or MultiBarBottomRight:IsVisible() then
offset = offset + MultiBarBottomLeft:GetHeight()
end
elseif frame == QuestTimerFrame or frame == DurabilityFrame or frame == QuestWatchFrame then
anchorFrame = MinimapCluster
x = 0
y = 0
offset = 0
if frame ~= QuestTimerFrame and QuestTimerFrame:IsVisible() then
y = y - QuestTimerFrame:GetHeight()
end
if frame == QuestWatchFrame and DurabilityFrame:IsVisible() then
y = y - DurabilityFrame:GetHeight()
end
if frame == DurabilityFrame then
x = -20
end
anchor = "TOPRIGHT"
anchorAlt = "BOTTOMRIGHT"
if MultiBarRight:IsVisible() then
x = x - MultiBarRight:GetWidth()
if MultiBarLeft:IsVisible() then
x = x - MultiBarLeft:GetWidth()
end
end
end
if frame == FramerateLabel then
anchorFrame = WorldFrame
end
frame:ClearAllPoints()
frame:SetPoint(anchor, anchorFrame, anchorAlt or anchor, x, y + offset)
blizzardFramesData[frame].lastX = frame:GetLeft()
blizzardFramesData[frame].lastY = frame:GetTop()
end
end
end
end
end
local function activate(self, oldLib, oldDeactivate)
Jostle = self
if oldLib then
self.hooks = oldLib.hooks
self.topFrames = oldLib.topFrames
self.bottomFrames = oldLib.bottomFrames
self.topAdjust = oldLib.topAdjust
self.bottomAdjust = oldLib.bottomAdjust
end
if not self.hooks then
self.hooks = {}
end
if not self.topFrames then
self.topFrames = {}
end
if not self.bottomFrames then
self.bottomFrames = {}
end
if self.topAdjust == nil then
self.topAdjust = true
end
if self.bottomAdjust == nil then
self.bottomAdjust = true
end
if not self.hooks.ToggleWorldMap then
self.hooks.ToggleWorldMap = true
local orig = ToggleWorldMap
function ToggleWorldMap()
if self.ToggleWorldMap then
return self.ToggleWorldMap(self, orig)
else
return orig()
end
end
end
if not self.hooks.WorldMapFrameCloseButton_OnClick then
self.hooks.WorldMapFrameCloseButton_OnClick = true
local orig = WorldMapFrameCloseButton:GetScript("OnClick")
WorldMapFrameCloseButton:SetScript("OnClick", function()
if self.WorldMapFrameCloseButton_OnClick then
return self.WorldMapFrameCloseButton_OnClick(self, orig)
else
return orig()
end
end)
end
if not self.hooks.TicketStatusFrame_OnEvent then
self.hooks.TicketStatusFrame_OnEvent = true
local orig = TicketStatusFrame_OnEvent
function TicketStatusFrame_OnEvent()
if self.TicketStatusFrame_OnEvent then
return self.TicketStatusFrame_OnEvent(self, orig)
else
return orig()
end
end
end
if not self.hooks.FCF_UpdateDockPosition then
self.hooks.FCF_UpdateDockPosition = true
local orig = FCF_UpdateDockPosition
function FCF_UpdateDockPosition()
if self.FCF_UpdateDockPosition then
return self.FCF_UpdateDockPosition(self, orig)
else
return orig()
end
end
end
if not self.hooks.FCF_UpdateCombatLogPosition then
self.hooks.FCF_UpdateCombatLogPosition = true
local orig = FCF_UpdateCombatLogPosition
function FCF_UpdateCombatLogPosition()
if self.FCF_UpdateCombatLogPosition then
return self.FCF_UpdateCombatLogPosition(self, orig)
else
return orig()
end
end
end
if not self.hooks.UIParent_ManageFramePositions then
self.hooks.UIParent_ManageFramePositions = true
local orig = UIParent_ManageFramePositions
function UIParent_ManageFramePositions()
if self.UIParent_ManageFramePositions then
return self.UIParent_ManageFramePositions(self, orig)
else
return orig()
end
end
end
if not self.hooks.UIParent_ManageRightSideFrames then
self.hooks.UIParent_ManageRightSideFrames = true
local orig = UIParent_ManageRightSideFrames
function UIParent_ManageRightSideFrames()
if self.UIParent_ManageRightSideFrames then
return self.UIParent_ManageRightSideFrames(self, orig)
else
return orig()
end
end
end
if oldDeactivate then
oldDeactivate(oldLib)
end
end
local function external(self, major, instance)
if major == "AceEvent-2.0" then
AceEvent = instance
instance:embed(self)
self:UnregisterAllEvents()
self:CancelAllScheduledEvents()
self:RegisterEvent("PLAYER_AURAS_CHANGED")
if instance:IsFullyInitialized() then
self:ScheduleEvent(self.Refresh, 0, self)
else
self:RegisterEvent("AceEvent_FullyInitialized")
end
end
end
AceLibrary:Register(Jostle, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)