You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

547 lines
15 KiB

3 years ago
local ADDON_NAME, Internal = ...
local External = _G[ADDON_NAME]
local L = Internal.L
BtWTodoItemMixin = {}
function BtWTodoItemMixin:OnLoad()
self:RegisterForDrag("LeftButton");
end
function BtWTodoItemMixin:Init(data)
if self.type == "todo" then
Internal.UnregisterEventsFor(self)
end
Mixin(self, data)
if self.type == "todo" then
self.todo:SetCharacter(self.character)
self.todo:RegisterEventsFor(self, self.character:IsPlayer())
Internal.RegisterEvent(self, "MODIFIER_STATE_CHANGED", "RefreshTooltip")
end
self:Update()
end
function BtWTodoItemMixin:Update()
if self.type == "corner" then
self.Text:SetText("")
elseif self.type == "character" then
self.Text:SetText(self.character:GetDisplayName())
self.Text:SetJustifyH("CENTER")
elseif self.type == "title" then
self.Text:SetText(self.todo:GetName())
self.Text:SetJustifyH("LEFT")
elseif self.type == "todo" then
self.todo:SetCharacter(self.character)
self.Text:SetText(self.todo:GetText())
self.Text:SetJustifyH("CENTER")
elseif self.type == "category" then
self.Text:SetText(self.category)
end
if GetMouseFocus() == self and self:IsVisible() then
self:OnEnter()
end
end
function BtWTodoItemMixin:RefreshTooltip()
if GetMouseFocus() == self and self:IsVisible() then
self:OnEnter()
end
end
function BtWTodoItemMixin:RegisterEvents(...)
for i=1,select('#', ...) do
Internal.RegisterEvent(self, (select(i, ...)), "Update")
end
end
function BtWTodoItemMixin:OnClick(...)
if self.type == "todo" and self.todo:SupportsClick() then
self.todo:SetCharacter(self.character)
self.todo:Click(...)
self:Update()
end
end
function BtWTodoItemMixin:OnDragStart()
local frame = self:GetParent():GetParent():GetParent():GetParent()
if frame.OnDragStart then
frame.OnDragStart(frame)
end
end
function BtWTodoItemMixin:OnDragStop()
local frame = self:GetParent():GetParent():GetParent():GetParent()
if frame.OnDragStop then
frame.OnDragStop(frame)
end
end
function BtWTodoItemMixin:OnEnter()
if self.type == "todo" and self.todo:SupportsTooltip() then
self.todo:SetCharacter(self.character)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
local refreshRate = self.todo:UpdateTooltip(GameTooltip)
GameTooltip:Show()
if refreshRate then
self.tooltipTimer = 0
self.tooltipRefreshRate = refreshRate
self:SetScript("OnUpdate", self.OnUpdate)
else
self:SetScript("OnUpdate", nil)
end
end
end
function BtWTodoItemMixin:OnUpdate(elapsed)
if not self:IsMouseOver() or not self:IsVisible() then
self:SetScript("OnUpdate", nil)
return
end
self.tooltipTimer = self.tooltipTimer + elapsed
if self.tooltipTimer >= self.tooltipRefreshRate then
self.tooltipTimer = 0
self.todo:SetCharacter(self.character)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
local refreshRate = self.todo:UpdateTooltip(GameTooltip)
GameTooltip:Show()
if refreshRate then
self.tooltipRefreshRate = refreshRate
else
self:SetScript("OnUpdate", nil)
end
end
end
function BtWTodoItemMixin:OnLeave()
GameTooltip:Hide()
end
BtWTodoRowMixin = {}
function BtWTodoRowMixin:OnLoad()
self.pool = CreateFramePool(self.frameType or "Button", self, self.frameTemplate or "BtWTodoItemTemplate")
PixelUtil.SetHeight(self.Left, 1)
PixelUtil.SetPoint(self.Left, "LEFT", self, "LEFT", 0, -1);
PixelUtil.SetPoint(self.Left, "RIGHT", self.Text, "LEFT", -10, -1);
PixelUtil.SetHeight(self.Right, 1)
PixelUtil.SetPoint(self.Right, "RIGHT", self, "RIGHT", 0, -1);
PixelUtil.SetPoint(self.Right, "LEFT", self.Text, "RIGHT", 10, -1);
end
function BtWTodoRowMixin:Init(data, itemWidth, itemHeight)
Mixin(self, data)
self.itemWidth = itemWidth
self.itemHeight = itemHeight
self:SetHeight(itemHeight)
self:Update()
end
function BtWTodoRowMixin:GetCharacters()
return {}
end
function BtWTodoRowMixin:Update()
self.pool:ReleaseAll()
if self.type == "category" then
local category = External.GetCategory(self.category)
self.Text:SetText(category.name)
self.Text:SetTextColor(category.color:GetRGBA())
self.Left:SetColorTexture(category.color:GetRGBA())
self.Right:SetColorTexture(category.color:GetRGBA())
self.Text:Show()
self.Left:Show()
self.Right:Show()
elseif self.type == "character" then
self.Text:SetText(self:GetCharacters()[1]:GetDisplayName())
self.Text:SetTextColor(1, 1, 1, 1)
self.Text:Show()
self.Left:Hide()
self.Right:Hide()
elseif self.type == "characters" then
local frame = self.pool:Acquire()
frame:Init({ type = "corner" })
frame:SetSize(self.itemWidth, self.itemHeight)
frame:SetPoint("LEFT")
frame:Show()
local previousFrame = frame
for _,character in ipairs(self:GetCharacters()) do
local frame = self.pool:Acquire()
frame:Init({ type = "character", character = character })
frame:SetSize(self.itemWidth, self.itemHeight)
frame:SetPoint("LEFT", previousFrame, "RIGHT")
frame:Show()
previousFrame = frame
end
self.Text:Hide()
self.Left:Hide()
self.Right:Hide()
elseif self.type == "todos" then
local frame = self.pool:Acquire()
frame:Init({ type = "title", todo = self.todo })
frame:SetSize(self.itemWidth, self.itemHeight)
frame:SetPoint("LEFT")
frame:Show()
local previousFrame = frame
for _,character in ipairs(self:GetCharacters()) do
local frame = self.pool:Acquire()
frame:Init({ type = "todo", todo = self.todo, character = character })
frame:SetSize(self.itemWidth, self.itemHeight)
frame:SetPoint("LEFT", previousFrame, "RIGHT")
frame:Show()
previousFrame = frame
end
self.Text:Hide()
self.Left:Hide()
self.Right:Hide()
end
end
function BtWTodoRowMixin:OnDragStart()
local frame = self:GetParent():GetParent():GetParent()
if frame.OnDragStart then
frame.OnDragStart(frame)
end
end
function BtWTodoRowMixin:OnDragStop()
local frame = self:GetParent():GetParent():GetParent()
if frame.OnDragStop then
frame.OnDragStop(frame)
end
end
BtWTodoScrollRowMixin = {}
function BtWTodoScrollRowMixin:OnLoad()
BtWTodoRowMixin.OnLoad(self)
self:RegisterForDrag("LeftButton");
end
function BtWTodoScrollRowMixin:GetCharacters()
return self:GetParent():GetParent():GetParent():GetCharacters()
end
BtWTodoTooltipRowMixin = {}
function BtWTodoTooltipRowMixin:OnLoad()
BtWTodoRowMixin.OnLoad(self)
self:EnableMouse(false)
end
function BtWTodoTooltipRowMixin:GetCharacters()
return self:GetParent():GetParent():GetParent():GetCharacters()
end
BtWTodoViewMixin = {}
function BtWTodoViewMixin:OnLoad()
local view = CreateScrollBoxListLinearView();
view:SetElementExtent(self:GetItemHeight())
if Internal.IsDragonflight() then
view:SetElementInitializer(self.rowTemplate or "BtWTodoScrollRowTemplate", function(list, elementData)
list:Init(elementData, self:GetItemWidth(), self:GetItemHeight());
end);
else
view:SetElementInitializer(self.rowType or "Frame", self.rowTemplate or "BtWTodoScrollRowTemplate", function(list, elementData)
list:Init(elementData, self:GetItemWidth(), self:GetItemHeight());
end);
end
ScrollUtil.InitScrollBoxListWithScrollBar(self.ScrollBox, self.ScrollBar, view);
end
function BtWTodoViewMixin:UpdateView()
if self:GetCharacters() == nil or self:GetTodos() == nil then
return
end
local listDatas = {};
if #self:GetCharacters() == 1 then
listDatas[#listDatas+1] = { type = "character" }
else
listDatas[#listDatas+1] = { type = "characters" }
end
local previousCategory = nil
for _,todo in ipairs(self:GetTodos()) do
if todo.category ~= previousCategory then
listDatas[#listDatas+1] = { category = todo.category, type = "category" }
previousCategory = todo.category
end
listDatas[#listDatas+1] = { todo = todo, type = "todos" }
end
self.ScrollBar:Hide()
if self.ScrollBar:IsShown() then
self:SetWidth((self:GetCharacterCount() + 1) * self:GetItemWidth() + self:GetPaddingHorizontal() + 20) -- 20 is the gap/width for scrollbar
else
self:SetWidth((self:GetCharacterCount() + 1) * self:GetItemWidth() + self:GetPaddingHorizontal())
end
self:SetHeight(#listDatas * self:GetItemHeight() + self:GetPaddingVertical())
local dataProvider = CreateDataProvider(listDatas);
self.ScrollBox:SetDataProvider(dataProvider);
end
function BtWTodoViewMixin:Update()
self.ScrollBox:ForEachFrame(function(list)
list:Update();
end);
end
function BtWTodoViewMixin:SetPadding(top, left, bottom, right)
top = math.max(top, 0)
left = math.max(left, 0)
bottom = math.max(bottom, 0)
right = math.max(right, 0)
self.paddingHorizontal = left + right
self.paddingVertical = top + bottom
self.ScrollBox:SetPoint("TOPLEFT", left, -top)
self.ScrollBox:SetPoint("BOTTOMRIGHT", -right, bottom)
self.ScrollBar:SetPoint("TOPRIGHT", -right + 20, -top + 10)
self.ScrollBar:SetPoint("BOTTOM", 0, bottom - 10)
end
function BtWTodoViewMixin:GetPaddingHorizontal()
return self.paddingHorizontal or 1
end
function BtWTodoViewMixin:GetPaddingVertical()
return self.paddingVertical or 1
end
function BtWTodoViewMixin:SetItemSize(w, h)
self:SetItemWidth(w)
self:SetItemHeight(h)
end
function BtWTodoViewMixin:SetItemWidth(value)
self.itemWidth = math.max(value, 1)
end
function BtWTodoViewMixin:GetItemWidth()
return self.itemWidth or 1
end
function BtWTodoViewMixin:SetItemHeight(value)
self.itemHeight = math.max(value, 1)
self.ScrollBox:GetView():SetElementExtent(self:GetItemHeight())
end
function BtWTodoViewMixin:GetItemHeight()
return self.itemHeight or 1
end
function BtWTodoViewMixin:SetCharacters(characters)
self.characters = characters
self:UpdateView()
end
function BtWTodoViewMixin:GetCharacters()
return self.characters
end
function BtWTodoViewMixin:GetCharacterCount()
return #self.characters
end
function BtWTodoViewMixin:SetTodos(todos)
self.todos = todos
self:UpdateView()
end
function BtWTodoViewMixin:GetTodos()
return self.todos
end
function BtWTodoViewMixin:GetTodoCount()
return #self.todos
end
BtWTodoDraggableViewMixin = {}
function BtWTodoDraggableViewMixin:OnLoad()
self:RegisterForDrag("LeftButton");
BtWTodoViewMixin.OnLoad(self)
end
function BtWTodoDraggableViewMixin:OnDragStart()
self:StartMoving();
end
function BtWTodoDraggableViewMixin:OnDragStop()
self:StopMovingOrSizing();
end
local frames = {}
BtWTodoFrameMixin = {}
function BtWTodoFrameMixin:OnLoad()
frames[#frames+1] = self
BtWTodoDraggableViewMixin.OnLoad(self)
self:SetItemSize(self.itemWidth or 100, self.itemHeight or 24)
self:SetPadding(self.paddingTop or 12, self.paddingLeft or 16, self.paddingBottom or 12, self.paddingRight or 16)
end
function BtWTodoFrameMixin:OnShow()
BtWTodoWindows[self.id].show = true
self:Init()
end
function BtWTodoFrameMixin:OnHide()
BtWTodoWindows[self.id].show = nil
end
function BtWTodoFrameMixin:SetList(id)
local list = Internal.GetList(id)
if not list then
error("Unknown list " .. tostring(id))
end
local todos = {}
for _,item in ipairs(list.todos) do
if not item.hidden then
xpcall(function ()
local todo = External.CreateTodoByID(item.id)
todo.category = item.category
todos[#todos+1] = todo
end, geterrorhandler())
end
end
self:SetTodos(todos)
end
function BtWTodoFrameMixin:Init()
if not self.initialized then
local settings = BtWTodoWindows[self.id]
if not settings then
error("Missing settings for window " .. tostring(self.id))
end
self:SetItemSize(settings.itemWidth or 100, settings.itemHeight or 24)
local characters = {}
local addedPlayer = false
for _,character in ipairs(settings.characters) do
local result
if character == "PLAYER" then
result = Internal.GetPlayer()
else
result = Internal.GetCharacter(character)
end
if not result:IsPlayer() or not addedPlayer then
characters[#characters+1] = result
if result:IsPlayer() then
addedPlayer = true
end
end
end
self:SetCharacters(characters)
self:SetList(settings.list)
self.initialized = true
end
end
BtWTodoMainFrameMixin = {}
function BtWTodoMainFrameMixin:OnLoad()
BtWTodoFrameMixin.OnLoad(self)
if self.SetTitle then
self:SetTitle(ADDON_NAME)
elseif self.TitleText then
self.TitleText:SetText(ADDON_NAME)
self.TitleText:SetHeight(24)
end
tinsert(UISpecialFrames, self:GetName());
end
BtWTodoTooltipFrameMixin = {}
function BtWTodoTooltipFrameMixin:OnLoad()
BackdropTemplateMixin.OnBackdropLoaded(self)
BtWTodoFrameMixin.OnLoad(self)
if self.TooltipBackdropOnLoad then
self:TooltipBackdropOnLoad()
end
-- Disable mouse events to prevent flickering
self.ScrollBox.ScrollTarget:EnableMouse(false)
self.ScrollBox.ScrollTarget:EnableMouseWheel(false)
end
function External.ToggleMainFrame()
BtWTodoMainFrame:SetShown(not BtWTodoMainFrame:IsShown())
end
function External.ToggleSmallFrame()
BtWTodoSmallFrame:SetShown(not BtWTodoSmallFrame:IsShown())
end
function External.RunAction(actionStr)
local action, subAction = Internal.SplitAction(actionStr)
if action == "toggleWindow" then
if subAction == "main" then
External.ToggleMainFrame()
elseif subAction == "small" then
External.ToggleSmallFrame()
end
elseif action == "openConfig" then
External.OpenConfiguration()
end
end
Internal.RegisterEvent("FRAME_CHANGED", function (event, id)
for _,frame in ipairs(frames) do
if frame.id and BtWTodoWindows[frame.id] then
frame.initialized = nil
frame:Init()
end
end
end)
Internal.RegisterEvent("LIST_CHANGED", function (event, id)
for _,frame in ipairs(frames) do
if frame.id and BtWTodoWindows[frame.id] and BtWTodoWindows[frame.id].list == id then
frame:SetList(id)
end
end
end)
Internal.RegisterEvent("TODOS_CHANGED", function ()
for _,frame in ipairs(frames) do
-- Should just refresh individual todos not entire frame
if frame.id and BtWTodoWindows[frame.id] then
frame:SetList(BtWTodoWindows[frame.id].list)
end
end
end)
local function ADDON_LOADED(_, addon)
if addon == ADDON_NAME then
-- We do this in 2 steps incase someone wipes BtWTodoWindows
if not BtWTodoWindows then
BtWTodoWindows = {}
end
if not BtWTodoWindows.tooltip then
BtWTodoWindows.tooltip = {
list = "btwtodo:default",
characters = {},
addPlayer = true,
itemWidth = 120,
itemHeight = 24,
}
end
if not BtWTodoWindows.main then
BtWTodoWindows.main = {
show = false,
list = "btwtodo:default",
characters = {},
addPlayer = true,
itemWidth = 120,
itemHeight = 24,
}
end
if not BtWTodoWindows.small then
BtWTodoWindows.small = {
show = true,
list = "btwtodo:default",
characters = {"PLAYER"},
itemWidth = 120,
itemHeight = 24,
}
end
Internal.UnregisterEvent("ADDON_LOADED", ADDON_LOADED)
end
end
Internal.RegisterEvent("ADDON_LOADED", ADDON_LOADED)
Internal.RegisterEvent("PLAYER_LOGIN", function ()
for _,settings in pairs(BtWTodoWindows) do
if settings.addPlayer then
local player = Internal.GetPlayer()
if not tContains(settings.characters, player.key) then
tinsert(settings.characters, player.key)
end
end
end
if BtWTodoWindows.main.show then
BtWTodoMainFrame:Show()
end
if BtWTodoWindows.small.show then
BtWTodoSmallFrame:Show()
end
end)