# HG changeset patch
# User Nenue
# Date 1478011730 14400
# Node ID e8679ecb48d8dae5cbbc667ecb576267bb2d09c9
# Parent d0114b51cdeab84801dc0a23c0b6639fe5ba52d2
ClassPlan:
- Available missions are now recorded; the mission list can be toggled between in-progress and available by clicking the heading.
diff -r d0114b51cdea -r e8679ecb48d8 ClassPlan.lua
--- a/ClassPlan.lua Fri Oct 28 19:54:00 2016 -0400
+++ b/ClassPlan.lua Tue Nov 01 10:48:50 2016 -0400
@@ -1,57 +1,27 @@
local wipe, tinsert, sort = table.wipe, tinsert, table.sort
local pairs, ipairs = pairs, ipairs
local floor, mod, time = floor, mod, time
+local max, min = math.max, math.min
local GetTime = GetTime
local GI_currentTime = time()
+local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop
-local BOUND_FRAMES = {}
-local blockTemplate = {
- point = 'TOPLEFT',
- relativePoint ='TOPLEFT',
+local CG_GetBuildings = C_Garrison.GetBuildings
+local CG_GetFollowerShipments = C_Garrison.GetFollowerShipments
+local CG_GetLooseShipments = C_Garrison.GetLooseShipments
+local CG_GetTalentTrees = C_Garrison.GetTalentTrees
+local CG_GetCompleteTalent = C_Garrison.GetCompleteTalent
+local CG_GetLandingPageShipmentInfo = C_Garrison.GetLandingPageShipmentInfo
+local CG_GetLandingPageShipmentInfoByContainerID = C_Garrison.GetLandingPageShipmentInfoByContainerID
+
+local CP_REPLACE_LANDINGPAGE = true
+local CP_HEADER_SIZE = 24
+local CP_BACKGROUND_COLOR = {
+ inProgress = {0, 0, 0, 0.5},
+ shipmentsReady = {0, 0, 0, 0.25},
+ complete = {0.5, 0.5, 0.5, 0.5}
}
-SLASH_CLASSPLAN1 = "/classplan"
-SLASH_CLASSPLAN2 = "/cp"
-SlashCmdList.CLASSPLAN = function(args)
- ClassOrderPlan:Toggle()
-end
-
-ClassOrderPlanCore = {
- events = {},
- freeBlocks = {},
- blocks = {},
- sortedItems = {},
- timers = {},
- shipments = {},
- playerFirst = false,
- prototypes = {},
- Queued = {}
-}
-
-ClassPlanMissionMixin = {
- templateName = 'ClassPlanMissionEntry',
- events = {
- 'GARRISON_MISSION_LIST_UPDATE',
- 'GARRISON_MISSION_STARTED',
- 'GARRISON_MISSION_FINISHED',
- 'GARRISON_LANDINGPAGE_SHIPMENTS'},}
-ClassPlanShipmentMixin = {
- templateName = 'ClassPlanShipmentEntry',
- parent = false,
- point = 'TOPRIGHT',
- relativePoint ='TOPRIGHT',
- events = {
- 'GARRISON_LANDINGPAGE_SHIPMENTS',
- 'GARRISON_TALENT_UPDATE',
- "GARRISON_TALENT_COMPLETE",
- "GARRISON_SHIPMENT_RECEIVED",
- 'GARRISON_FOLLOWER_LIST_UPDATE',
- 'GARRISON_SHOW_LANDING_PAGE'},
-}
-setmetatable(ClassPlanShipmentMixin, {__index = ClassPlanMissionMixin})
-local core, MissionsHandler, ShipmentsHandler = ClassOrderPlanCore, ClassPlanMissionMixin, ClassPlanShipmentMixin
-local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop
-
local GetTimeLeftString = function(timeLeft)
local days = floor(timeLeft/(24*3600))
local hours = floor(mod(timeLeft, (24*3600)) / 3600)
@@ -65,260 +35,113 @@
end
+ClassOrderPlanCore = {
+ events = {},
+ freeBlocks = {},
+ blocks = {},
+ sortedItems = {},
+ timers = {},
+ shipments = {},
+ playerFirst = false,
+ prototypes = {},
+ Queued = {}
+}
+local MissionList = {
+ templateName = 'ClassPlanMissionEntry',
+ listKey = {'missions', 'available'},
+ listTitle = {'In Progress', 'Available'},
-MissionsHandler.GetPlayerData = function(self)
- if not self.profile then
- return
- end
- local items = C_Garrison.GetLandingPageItems(LE_GARRISON_TYPE_7_0)
- wipe(self.profile.missions)
- for index, data in ipairs(items) do
- print(' -',data.name, '|cFF00FF00'.. data.timeLeft .. '|r', date("%A %I:%m %p", data.missionEndTime))
- tinsert(self.profile.missions, data)
- end
- ClassOrderPlan.isStale = true
-end
+ point = 'TOPLEFT',
+ relativePoint ='TOPLEFT',
+ events = {
+ 'GARRISON_MISSION_LIST_UPDATE',
+ 'GARRISON_LANDINGPAGE_SHIPMENTS'},
+}
+local ShipmentList = {
+ templateName = 'ClassPlanShipmentEntry',
+ listKey = {'shipments'},
+ listTitle = {'Work Orders'},
+ events = {
+ 'GARRISON_MISSION_LIST_UPDATE',
+ 'GARRISON_LANDINGPAGE_SHIPMENTS',
+ 'GARRISON_TALENT_UPDATE',
+ "GARRISON_TALENT_COMPLETE",
+ "GARRISON_SHIPMENT_RECEIVED",
+ 'GARRISON_FOLLOWER_LIST_UPDATE',
+ 'GARRISON_SHOW_LANDING_PAGE'},
+}
+local SharedHandlers = {
+ numBlocks = 0,
+ isStale = true,
+}
+local SharedEntry = {}
+local ShipmentEntry = {}
+local MissionEntry = {}
-MissionsHandler.OnGetItem = function(data)
- if data.missionEndTime < GI_currentTime then
- data.isComplete = true
- end
-end
+local ClassPlan = ClassOrderPlanCore
-MissionsHandler.FreeBlock = function(self, block)
-end
-
-MissionsHandler.SortHandler = function (a,b)
- local result = false
- --if not a or not b then
- -- return true
- --else
- --if (a.isMine ~= b.isMine) then
- -- result = a.isMine
- --else
- --if (not b.missionEndTime) or (not a.missionEndTime) then
- -- print('missing article', b.missionEndTime, a.missionEndTime)
- --end
- return ( b.missionEndTime > a.missionEndTime)
- --end
- --end
-end
-
-ShipmentsHandler.OnGetItem = function(data)
- if data.shipmentsTotal then
- local timeLeft = data.creationTime + data.duration - GI_currentTime
- if (timeLeft <= 0) and (data.shipmentsReady < data.shipmentsTotal) then
- local numOrders = min(-1*floor(timeLeft/data.duration), (data.shipmentsTotal - data.shipmentsReady))
-
- if not data.originalCreationTime then
- data.originalCreationTime = data.creationTime
- data.originalShipmentsReady = data.shipmentsReady
- end
-
- data.creationTime = data.creationTime + numOrders*data.duration
- data.shipmentsReady = data.shipmentsReady + numOrders
- print(data.profileKey, 'shipment "'.. data.name..'" reconciling', numOrders, 'lapsed orders. -->', data.creationTime, data.shipmentsReady)
- end
- end
-end
-
-ShipmentsHandler.SortHandler = function(a, b)
- if b.isComplete ~= a.isComplete then
- return a.isComplete and true or false
- elseif a.shipmentsReady or b.shipmentsReady then
- return (a.shipmentsReady or 0) > (b.shipmentsReady or 0)
- else
- return (a.creationTime) < (b.creationTime)
- end
-end
-
-local ShipmentsInfo = {}
-local AddShipmentInfo = function(shipmentType, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID, followerID)
- -- early login queries may return empty tables, causing the sorter to compare nil
- if not creationTime then
- return
- end
- --print(shipmentType, name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
- tinsert(ShipmentsInfo,
- {
- shipmentType = shipmentType,
- name = name,
- icon = texture,
- shipmentCapacity = shipmentCapacity,
- shipmentsReady = shipmentsReady,
- shipmentsTotal = shipmentsTotal,
- creationTime = creationTime,
- duration = duration,
- timeleftString = timeleftString,
- itemName = itemName,
- itemIcon = itemIcon,
- itemQuality = itemQuality,
- itemID = itemID,
- followerID = followerID,
- })
-end
-ShipmentsHandler.GetPlayerData = function (self)
- if not self.profile then
- return
- end
- wipe(ShipmentsInfo)
-
- local garrisonType = LE_GARRISON_TYPE_7_0
- local buildings = C_Garrison.GetBuildings(garrisonType);
- local shipmentIndex = 0
- --print('Buildings:')
- for i = 1, #buildings do
- local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = C_Garrison.GetLandingPageShipmentInfo(buildingID);
- AddShipmentInfo('Building', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID)
- end
-
- --print('Follower:')
- local followerShipments = C_Garrison.GetFollowerShipments(garrisonType);
- for i = 1, #followerShipments do
- local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = C_Garrison.GetLandingPageShipmentInfoByContainerID(followerShipments[i]);
- AddShipmentInfo('Follower', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, nil, nil, nil, nil, followerID)
- end
-
- --print('Loose:')
- local looseShipments = C_Garrison.GetLooseShipments(garrisonType)
- for i = 1, #looseShipments do
- local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = C_Garrison.GetLandingPageShipmentInfoByContainerID(looseShipments[i]);
- AddShipmentInfo('Misc', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
- end
-
- local talentTrees = C_Garrison.GetTalentTrees(garrisonType, select(3, UnitClass("player")));
- -- this is a talent that has completed, but has not been seen in the talent UI yet.
- local completeTalentID = C_Garrison.GetCompleteTalent(garrisonType);
- --print('Talents:')
- if (talentTrees) then
- for treeIndex, tree in ipairs(talentTrees) do
- for talentIndex, talent in ipairs(tree) do
- local showTalent = false;
- if (talent.isBeingResearched) or (talent.id == completeTalentID) then
- AddShipmentInfo('Talent', talent.name, talent.icon, 1, (talent.isBeingResearched and 0 or 1), 1, talent.researchStartTime, talent.researchDuration, talent.timeleftString)
- end
- end
- end
- end
-
- self.profile.shipments = self.profile.shipments or {}
- wipe(self.profile.shipments)
- for index, data in ipairs(ShipmentsInfo) do
- --DEFAULT_CHAT_FRAME:AddMessage(data.shipmentType ..' '.. tostring(data.name) ..' '.. tostring(data.creationTime) ..' '.. tostring(data.duration))
- tinsert(self.profile.shipments, data)
- end
- ClassOrderPlan.isStale = true
-end
-
-function core:OnLoad ()
+function ClassPlan:OnLoad ()
self:RegisterEvent('PLAYER_LOGIN')
self:RegisterEvent('ADDON_LOADED')
self:RegisterEvent('PLAYER_REGEN_ENABLED')
self:RegisterEvent('PLAYER_REGEN_DISABLED')
- -- Blizzard_GarrisonUI already fires a shipment data request for GARRISON_SHIPMENT_RECEIVED; this is unlikely to
- self:AddHandler('missions', MissionsHandler)
- self:AddHandler('shipments', ShipmentsHandler)
- self:Reanchor()
- C_Garrison.RequestLandingPageShipmentInfo();
+ self:RegisterForDrag('LeftButton')
+ self:SetMovable(true)
+ self:SetToplevel(true)
+
+
+ SLASH_CLASSPLAN1 = "/classplan"
+ SLASH_CLASSPLAN2 = "/cp"
+ SlashCmdList.CLASSPLAN = function(args)
+ self:Toggle()
+ end
+
end
-local parentFrames = {'VeneerWorldState', 'OrderHallCommandBar'}
-function core:Reanchor()
- self:ClearAllPoints()
- self.anchorParent = UIParent
- local anchorTo = 'TOP'
- for i, name in ipairs(parentFrames) do
- local frame = _G[name]
- if frame then
- if not BOUND_FRAMES[frame] then
- BOUND_FRAMES[frame] = {visible = (frame:IsVisible() and frame:IsShown())}
- hooksecurefunc(frame, 'Show', function()
- BOUND_FRAMES[frame].visible = true
- print(frame:GetName(), 'Show', 'reanchor trigger')
- self:Reanchor()
- end)
- hooksecurefunc(frame, 'Hide', function()
- BOUND_FRAMES[frame].visible = nil
- print(frame:GetName(), 'Hide', 'reanchor trigger')
- self:Reanchor()
- end)
- end
- print('f:', frame:GetName(), BOUND_FRAMES[frame].visible)
- if BOUND_FRAMES[frame].visible then
- self.anchorParent = frame
- anchorTo = 'BOTTOM'
- break
- end
- end
- end
- print('|cFFFF8800Using ' .. tostring(self.anchorParent:GetName()) .. '-'..anchorTo..' as anchor point')
+function ClassPlan:GetCurrentProfile()
+ WorldPlanData.OrderHall = WorldPlanData.OrderHall or {}
+ local db = WorldPlanData.OrderHall
+ self.data = db
- if self:IsShown() then
- ClassPlanButton.Background:Show()
- ClassPlanButton:SetWidth(600)
- else
- ClassPlanButton.Background:Hide()
- ClassPlanButton:SetWidth(200)
- end
+ local characters = db.characters or {}
+ db.characters = characters
- self:SetPoint('TOP', ClassPlanButton, 'BOTTOM', 0, 0)
- ClassPlanButton:ClearAllPoints()
- ClassPlanButton:SetPoint('TOP', self.anchorParent, anchorTo, 0, 0)
+ local name, realm = UnitName('player')
+ realm = realm or GetRealmName()
+ local profileName = name .. '-' .. realm
- print(ClassPlanButton:GetPoint(1))
+ self.profile = characters[profileName] or {}
+ self.characters = characters
+ characters[profileName] = self.profile
+
+
+ local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))]
+ local className = UnitClass('player')
+
+ print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName)
+ self.Background:SetColorTexture(classColor.r, classColor.g, classColor.b, 0.5)
+ self.profile.classColor = classColor
+ self.profile.className = className
+ return self.profile
end
-function core:AddHandler(name, prototype)
- self.prototypes[name] = setmetatable(prototype, {
- __index = blockTemplate,
- __tostring = function() return name end
- })
-
- for i, event in ipairs(prototype.events) do
- if not self.events[event] then
- self:RegisterEvent(event)
- self.events[event] = {}
- print('|cFF00FF00registering', event)
- end
-
- prototype.numBlocks = 0
- if not self.events[event][name] then
- print('adding', name, 'to', event)
- self.events[event][name] = prototype.GetPlayerData
- end
+function ClassPlan:SetupHandler(handler)
+ print('|cFF00FF00'..handler:GetName()..' loaded')
+ for i, event in ipairs(handler.events) do
+ print('|cFF00FF00 event', event)
+ handler:RegisterEvent(event)
end
- self.sortedItems[name] = {}
+ for index, listKey in ipairs(handler.listKey) do
+ self.profile[listKey] = self.profile[listKey] or {}
+ local listTitle = handler.listTitle[index]
+ setmetatable(self.profile[listKey], { __tostring = listTitle })
+ end
+ handler:SetList(1)
+ handler.sortedItems = {}
end
-function core:Setup()
- if IsLoggedIn() then
- WorldPlanData.OrderHall = WorldPlanData.OrderHall or {}
- self.data = WorldPlanData.OrderHall
- self.data.characters = self.data.characters or {}
-
- local name, realm = UnitName('player')
- realm = realm or GetRealmName()
- self.profileKey = name .. '-' .. realm
- if not self.data.characters[self.profileKey] then
- self.data.characters[self.profileKey] = {}
- end
- self.profile = self.data.characters[self.profileKey]
-
- self.profile.shipments = self.profile.shipments or {}
- self.profile.missions = self.profile.missions or {}
- self.profile.classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))]
-
- if self.data.IsShown then
- self:Show()
- end
- self.initialized = true
- self.isStale = true
- end
-end
-
-local last_invoc = {}
-function core:OnEvent (event, ...)
- print(event)
+function ClassPlan:OnEvent (event, arg)
+ print(event, arg)
if event == 'PLAYER_REGEN_DISABLED' then
if self:IsVisible() then
self.combatHide = true
@@ -330,149 +153,82 @@
self.combatHide = nil
self:SetShown(true)
end
+ elseif event == 'ADDON_LOADED' then
+ if arg == 'Blizzard_GarrisonUI' then
+ self:Reanchor()
+ end
elseif event == 'PLAYER_LOGIN' then
if not self.initialized then
self:Setup()
end
- elseif self.initialized and self.events[event] then
- self.isStale = true
- if self:IsVisible() then
-
- else
- for handler, func in pairs(self.events[event]) do
- if not self.Queued[handler] then
- print('scheduling update for handler', handler)
- self.Queued[handler] = C_Timer.NewTimer(0.25, function()
- func(handler)
- self.Queued[handler] = nil
- end)
- end
- end
- end
end
end
-function core:UpdateNotifications()
+function ClassPlan:Setup()
+ if IsLoggedIn() then
+ print('|cFFFFFF00'..self:GetName()..':Setup()|r')
+
+ self:GetCurrentProfile()
+ for _, handler in ipairs(self.Handlers) do
+ self:SetupHandler(handler)
+ end
+ self.initialized = true
+ self:SetShown(self.data.IsShown)
+ end
end
-local SetOwnerData = function(self, data)
- local name, realm = string.match(data.profileKey, "(.+)%-(.+)")
- local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r'
- --if realm ~= GI_currentRealm then
- --ownerText = ownerText .. ' (' .. realm .. ')'
- --end
- self.Owner:SetText(ownerText)
- self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b)
-end
+--- Update space
-function core:RefreshItems(configKey, prototype)
- local sortedItems = self.sortedItems[configKey]
+ local max = math.max
+ function ClassPlan:Update()
+ print('|cFF00FFFFRefresh()|r')
+ self.currentHeight = 0
+ for index, handler in pairs(self.Handlers) do
+ if handler.isStale then
+ print(' |cFF00FF00'..index..' '..handler:GetName()..'|r')
+ local sortedItems = handler.sortedItems
+ local activeKey = handler.activeKey
+ handler.profile = self.profile[handler.activeKey]
- self.blocks[configKey] = self.blocks[configKey] or {}
- local blocks = self.blocks[configKey]
+ wipe(sortedItems)
+ handler:GetPlayerData(self.profile)
+ for key, profile in pairs(self.data.characters) do
+ print('profile', key, activeKey)
+ local profileList = profile[activeKey]
+ if profileList and #profileList >= 1 then
+ local classColor = profile.classColor or defaultClassColor
+ local isMine = (profile == self.profile)
+ for index, data in ipairs(profileList) do
+ data.classColor = classColor
+ data.profileKey = key
+ data.isMine = isMine
+ if handler.OnGetItem then
+ handler.OnGetItem(data)
+ end
+ tinsert(sortedItems, data)
+ end
+ end
+ end
- local lastProfile
- local numItems = #sortedItems
- local totalHeight = 0
- for i, data in ipairs(sortedItems) do
- local block = blocks[i]
-
- if not block then
- block = CreateFrame('Button', nil, self, prototype.templateName)
- block:SetID(i)
- block.handler = prototype
- prototype.numBlocks = prototype.numBlocks + 1
-
- if prototype.lastBlock then
- block:SetPoint('TOPLEFT', prototype.lastBlock, 'BOTTOMLEFT', 0, 0)
- else
- block:SetPoint(prototype.point, self[prototype.parent] or self, prototype.relativePoint, 0, 0)
- end
- prototype.lastBlock = block
- blocks[i] = block
- end
-
- totalHeight = totalHeight + block:GetHeight()
- block.lastProfile = lastProfile
- for k,v in pairs(data) do
- if type(block[k]) ~= 'function' then
- block[k] = v
- end
- end
- block:Refresh(data)
- print(block.isComplete, block.missionEndTime, block.name)
- SetOwnerData(block, data)
-
- block:Show()
- lastProfile = data.profileKey
- end
-
- for i = numItems + 1, prototype.numBlocks do
- if blocks[i] then
- blocks[i]:Hide()
- end
- end
-
- return totalHeight
-end
-
-
-local GI_profileKey, GI_profile, GI_isMine
-local defaultClassColor = {r = 0.7, g = 0.7, b =0.7, colorStr = "ffffffff"}
-local DoItemList = function (source, dest, onGetItem)
- local numItems = 0
- for index, data in ipairs(source) do
- data.classColor = GI_profile.classColor or defaultClassColor
- data.profileKey = GI_profileKey
- data.isMine = GI_isMine
- if onGetItem then
- onGetItem(data)
- end
- numItems = numItems + 1
- tinsert(dest, data)
- end
- return numItems
-end
-
-local max = math.max
-function core:Refresh()
- print('|cFF00FFFFRefresh()|r')
- self.currentHeight = 0
- for name, ptype in pairs(self.prototypes) do
- print(' |cFF00FF00'..name..'|r')
- if self.isStale then
- ptype.GetPlayerData(self)
- self.sortedItems[name] = self.sortedItems[name] or {}
-
- wipe(self.sortedItems[name])
- --print( 'object:', ptype)
- for key, profile in pairs(self.data.characters) do
- if profile[name] and #profile[name] >= 1 then
- print(' ', #profile[name], key)
- GI_profileKey = key
- GI_profile = profile
- GI_isMine = (profile == self.profile)
- local results = DoItemList(profile[name], self.sortedItems[name], ptype.OnGetItem)
+ if handler.SortHandler then
+ sort(sortedItems, handler.SortHandler)
end
end
+ handler.isStale = nil
+ local itemsHeight = handler:UpdateItems()
+ self.currentHeight = max(itemsHeight, self.currentHeight)
- if ptype.SortHandler then
- sort(self.sortedItems[name], ptype.SortHandler)
- end
end
- local itemsHeight = self:RefreshItems(name, ptype)
- self.currentHeight = max(itemsHeight, self.currentHeight)
+ self.isStale = nil
+ self:Reanchor()
+ self:SetHeight(self.currentHeight + CP_HEADER_SIZE)
end
- self:Reanchor()
- self:SetHeight(self.currentHeight)
- self.isStale = nil
-end
-function core:Toggle()
+function ClassPlan:Toggle()
if self:IsShown() then
self:Hide()
else
@@ -484,52 +240,416 @@
end
end
-function core:OnUpdate()
+function ClassPlan:OnUpdate()
if self.isStale then
- print('update requested internally')
- self:Refresh()
+ print('|cFFFF4400An illusion! What are you hiding?|r')
+ self:Update()
end
end
-function core:OnShow()
+function ClassPlan:OnShow()
print('|cFF00FFFFShow()')
if self.isStale then
- print('on-show update')
- self:Refresh()
+ self:Update()
end
- ClassPlanButton.Background:Show()
- ClassPlanButton.Grip:SetShown(true)
-end
-function core:OnHide()
- print('|cFF00FFFFHide()')
- ClassPlanButton.Background:Hide()
- ClassPlanButton.Grip:SetShown(false)
+ self:Reanchor()
end
-
-function core:SortItems(ptype)
- print('|cFF0088FFSortItems('..tostring(ptype)..')|r')
- GI_currentTime = time()
-
+function ClassPlan:OnHide()
+ print('|cFF00FFFFHide()')
end
-function MissionsHandler:OnComplete()
- print('flagging complete', self.name)
- self:Refresh()
+function ClassPlan:Reanchor()
+ self:ClearAllPoints()
+ self:SetPoint('CENTER', self.data.positionX, self.data.positionY)
+
+ for index, frame in ipairs(self.Handlers) do
+ frame:Reanchor()
+ end
end
-function MissionsHandler:OnUpdate(sinceLast)
- if self.isComplete then
+function ClassPlan:OnDragStart()
+ self:StartMoving()
+end
+function ClassPlan:OnDragStop()
+
+ self:StopMovingOrSizing()
+ local x,y = self:GetCenter()
+ if x and y then
+ x = (x - GetScreenWidth()/2)
+ y = (y - GetScreenHeight()/2) * -1
+ self.data.positionX, self.data.positionY = x,y
+ print('saving positions:', x, y)
+ end
+end
+
+function SharedHandlers:SetList(index)
+ if not index then
+ if self.currentListIndex == #self.listKey then
+ index = 1
+ else
+ index = self.currentListIndex + 1
+ end
+ end
+
+ print('|cFF0088FF'..self:GetName()..'|r:SetList()', index)
+ self.currentListIndex = index
+ self.activeKey = self.listKey[index]
+ self.activeTitle = self.listTitle[index]
+
+ self.isStale = true
+end
+
+function SharedHandlers:RequestData()
+ print('|cFF0088FF'..self:GetName()..':RequestData()')
+ self.isStale = true
+end
+
+function SharedHandlers:OnEvent(event, arg)
+ if (event == 'GARRISON_MISSION_LIST_UPDATE') and (arg ~= LE_FOLLOWER_TYPE_GARRISON_7_0) then
+ -- ignore non-OrderHall updates
return
end
- self.throttle = (self.throttle or .5) + sinceLast
- if self.throttle >= .5 then
- self.throttle = self.throttle - .5
+ print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, arg)
+ if self:IsVisible() then
+ print('|cFF88FF00 frame visible; get busy')
+ self:RequestData()
else
- return
+ if not self.NextData then
+ print('|cFF88FF00 setting timer')
+ self.NextData = C_Timer.NewTimer(0.25, function()
+ if self.initialized then
+ self:RequestData()
+ self.NextData:Cancel()
+ self.NextData = nil
+ print('|cFF88FF00'..self:GetName()..' clearing timer')
+ end
+
+ end)
+ end
+ end
+end
+function SharedHandlers:OnUpdate()
+ if self.isStale then
+ self:GetParent():Update()
+ end
+end
+
+
+-- Stuff set on every list item
+function SharedHandlers:SetOwnerData (self, data)
+ local name, realm = string.match(data.profileKey, "(.+)%-(.+)")
+ local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r'
+ self.Owner:SetText(ownerText)
+ self.Name:SetText(self.name)
+ self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b)
+end
+
+function SharedHandlers:UpdateItems()
+ local sortedItems = self.sortedItems
+
+ self.blocks = self.blocks or {}
+ local blocks = self.blocks
+
+ local lastProfile
+ local numItems = #sortedItems
+ local totalHeight = 0
+ self.lastBlock = nil
+ self.numActive = 0
+ for i, data in ipairs(sortedItems) do
+ local block = blocks[i]
+ if not block then
+ block = CreateFrame('Button', nil, self, self.templateName)
+ block:SetID(i)
+ block.listType = self.activeKey
+ block.handler = self
+ self.numBlocks = self.numBlocks + 1
+ blocks[i] = block
+ end
+
+ print('RefreshItem', block)
+ self.numActive = self.numActive + 1
+
+ if self.lastBlock then
+ block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0)
+ print('--', i, data.isComplete, data.missionEndTime, data.name)
+ else
+ block:SetPoint('TOPLEFT', 0, 0)
+ print('--top')
+ end
+ self.lastBlock = block
+
+ totalHeight = totalHeight + block:GetHeight()
+ block.lastProfile = lastProfile
+ -- blot out arbitrary flags
+ block.offerEndTime = nil
+ block.missionEndTime = nil
+ block.creationTime = nil
+ block.duration = nil
+ block.throttle = 5
+
+ for k,v in pairs(data) do
+ if type(block[k]) ~= 'function' then
+ block[k] = v
+ end
+ end
+
+ block:Update()
+ self:SetOwnerData(block, data)
+
+ block:Show()
+ lastProfile = data.profileKey
end
- if self.missionEndTime then
+ for i = numItems + 1, self.numBlocks do
+ if blocks[i] then
+ blocks[i]:Hide()
+ end
+ end
+
+ self:Reanchor()
+
+ return totalHeight
+end
+
+
+function ShipmentList:Reanchor()
+ print('|cFF00FFFF'..self:GetName()..':Reanchor|r')
+ self:SetPoint('TOPLEFT', 0, -24)
+ self:SetPoint('BOTTOMRIGHT', -ClassOrderPlan:GetWidth()/2, 0)
+end
+
+function MissionList:Reanchor()
+ self:SetPoint('TOPRIGHT', 0, -24)
+ self:SetPoint('BOTTOMLEFT', ClassOrderPlan:GetWidth()/2, 0)
+
+ self.ListTab:ClearAllPoints()
+ self.ListTab:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, CP_HEADER_SIZE)
+ self.ListTab:SetPoint('BOTTOMRIGHT', self, 'TOPRIGHT', 0, 0)
+ self.ListTab.Label:SetText(self.listTitle[self.currentListIndex])
+ self.ListTab:Show()
+ print(self.ListTab:GetSize())
+end
+
+function MissionList:GetPlayerData (profile)
+ wipe(profile.missions)
+ wipe(profile.available)
+
+ local items = C_Garrison.GetAvailableMissions(GetPrimaryGarrisonFollowerType(LE_GARRISON_TYPE_7_0));
+ for i = 1, #items do
+ if (not items[i].isBuilding and items[i].isZoneSupport) then
+ else
+
+ tinsert(profile.available, items[i])
+ end
+ end
+
+ local items = C_Garrison.GetLandingPageItems(LE_GARRISON_TYPE_7_0)
+ for index, data in ipairs(items) do
+ print(' -',data.name, '|cFF00FF00'.. data.timeLeft .. '|r', date("%A %I:%m %p", data.missionEndTime))
+ tinsert(profile.missions, data)
+ end
+ return true
+end
+
+do
+ local ShipmentsInfo = {}
+ local AddShipmentInfo = function(shipmentType, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID, followerID)
+ -- early login queries may return empty tables, causing the sorter to compare nil
+ if not creationTime then
+ return
+ end
+ --print(shipmentType, name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
+ tinsert(ShipmentsInfo,
+ {
+ shipmentType = shipmentType,
+ name = name,
+ icon = texture,
+ shipmentCapacity = shipmentCapacity,
+ shipmentsReady = shipmentsReady,
+ shipmentsTotal = shipmentsTotal,
+ creationTime = creationTime,
+ duration = duration,
+ timeleftString = timeleftString,
+ itemName = itemName,
+ itemIcon = itemIcon,
+ itemQuality = itemQuality,
+ itemID = itemID,
+ followerID = followerID,
+ })
+ end
+ function ShipmentList:GetPlayerData (profile)
+ if not profile then
+ return false
+ end
+ local profileList = profile.shipments
+ wipe(ShipmentsInfo)
+
+ local garrisonType = LE_GARRISON_TYPE_7_0
+ local buildings = CG_GetBuildings(garrisonType);
+ local shipmentIndex = 0
+ --print('Buildings:')
+ for i = 1, #buildings do
+ local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = CG_GetLandingPageShipmentInfo(buildingID);
+ AddShipmentInfo('Building', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID)
+ end
+
+ --print('Follower:')
+ local followerShipments = CG_GetFollowerShipments(garrisonType);
+ for i = 1, #followerShipments do
+ local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = CG_GetLandingPageShipmentInfoByContainerID(followerShipments[i]);
+ AddShipmentInfo('Follower', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, nil, nil, nil, nil, followerID)
+ end
+
+ --print('Loose:')
+ local looseShipments = CG_GetLooseShipments(garrisonType)
+ for i = 1, #looseShipments do
+ local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = CG_GetLandingPageShipmentInfoByContainerID(looseShipments[i]);
+ AddShipmentInfo('Misc', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
+ end
+
+ local talentTrees = CG_GetTalentTrees(garrisonType, select(3, UnitClass("player")));
+ -- this is a talent that has completed, but has not been seen in the talent UI yet.
+ local completeTalentID = CG_GetCompleteTalent(garrisonType);
+ --print('Talents:')
+ if (talentTrees) then
+ for treeIndex, tree in ipairs(talentTrees) do
+ for talentIndex, talent in ipairs(tree) do
+ local showTalent = false;
+ if (talent.isBeingResearched) or (talent.id == completeTalentID) then
+ AddShipmentInfo('Talent', talent.name, talent.icon, 1, (talent.isBeingResearched and 0 or 1), 1, talent.researchStartTime, talent.researchDuration, talent.timeleftString)
+ end
+ end
+ end
+ end
+
+ wipe(profileList)
+ for index, data in ipairs(ShipmentsInfo) do
+ --DEFAULT_CHAT_FRAME:AddMessage(data.shipmentType ..' '.. tostring(data.name) ..' '.. tostring(data.creationTime) ..' '.. tostring(data.duration))
+ tinsert(profileList, data)
+ end
+ self.isStale = true
+ return true
+ end
+end
+MissionList.OnGetItem = function(data)
+ if data.missionEndTime and (data.missionEndTime < GI_currentTime) then
+ data.isComplete = true
+ end
+end
+
+MissionList.FreeBlock = function(self, block)
+end
+
+MissionList.SortHandler = function (a,b)
+ local result = false
+ --if not a or not b then
+ -- return true
+ --else
+ --if (a.isMine ~= b.isMine) then
+ -- result = a.isMine
+ --else
+ --if (not b.missionEndTime) or (not a.missionEndTime) then
+ -- print('missing article', b.missionEndTime, a.missionEndTime)
+ --end
+ if b.isComplete ~= a.isComplete then
+ return a.isComplete
+ elseif b.isMine ~= a.isMine then
+ return a.isMine
+ elseif b.missionEndTime then
+ return ( b.missionEndTime > a.missionEndTime)
+ else
+ return ( b.offerEndTime > a.offerEndTime)
+ end
+
+ --end
+ --end
+end
+
+
+function MissionList:OnShow()
+ print('|cFF00FF88'..self:GetName()..':OnShow()|r')
+end
+
+function ShipmentList:OnLoad()
+ C_Garrison.RequestLandingPageShipmentInfo();
+end
+function ShipmentList:OnShow()
+ print('|cFF00FF88'..self:GetName()..':OnShow()|r')
+ C_Garrison.RequestLandingPageShipmentInfo()
+end
+
+-- Update shipment flags data
+local SetActualShipmentTime = function(self)
+
+ if self.isComplete then
+ print('|cFF00FF88isComplete '..self.name..'|r')
+ return true
+ end
+
+ local timestamp = time()
+ local timeLeft = self.creationTime + self.duration - timestamp
+ local justFinished = false
+ while (self.shipmentsReady < self.shipmentsTotal) and (timeLeft <= 0) do
+ if not self.originalReady then
+ self.originalReady = self.shipmentsReady
+ self.originalCreationTime = self.creationTime
+ end
+
+
+ self.shipmentsReady = self.shipmentsReady + 1
+ self.creationTime = self.creationTime + self.duration
+ timeLeft = timeLeft + self.duration
+ print('|cFF00FF88udpating '..self.name..'|r', 'timeLeft:', timeLeft, 'shipments:', self.shipmentsReady, self.shipmentsTotal)
+ end
+
+ if (timeLeft <= 0) and (not self.isBeingResearched) then
+ self.isComplete = true
+ self.isStale = true
+ end
+
+ return timeLeft
+end
+
+ShipmentList.OnGetItem = function(data)
+ print('OnGetItem()')
+ if data.shipmentsTotal then
+ SetActualShipmentTime(data)
+ end
+end
+
+ShipmentList.SortHandler = function(a, b)
+ if b.isComplete ~= a.isComplete then
+ return a.isComplete and true or false
+ elseif a.shipmentsReady or b.shipmentsReady then
+ return (a.shipmentsReady or 0) > (b.shipmentsReady or 0)
+ else
+ return (a.creationTime) < (b.creationTime)
+ end
+end
+
+
+function MissionEntry:OnComplete()
+ print('flagging complete', self.name)
+ self:Update()
+end
+
+function MissionEntry:OnUpdate(sinceLast)
+ self.throttle = (self.throttle or .5) + sinceLast
+ if self.throttle < .5 then
+ return
+ else
+ self.throttle = self.throttle - .5
+ end
+ if self.offerEndTime then
+ local timeLeft = self.offerEndTime
+ self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
+ self.TimeLeft:SetTextColor(1,1,1)
+ elseif self.missionEndTime then
+
+ if self.isComplete then
+ return
+ end
local timeLeft = self.missionEndTime - time()
if timeLeft < 0 then
self:OnComplete()
@@ -557,7 +677,7 @@
g = min(progress * 2, 1)
r = 1
end
- self.ProgressBar:SetColorTexture(r,g,0,1)
+ self.ProgressBar:SetColorTexture(r,g,0,.4)
self.ProgressBG:SetColorTexture(r,g,0,0.125)
end
self.ProgressBG:Show()
@@ -571,7 +691,18 @@
end
end
-function MissionsHandler:Refresh()
+function MissionEntry:OnLoad()
+ print('|cFFFF4400',self:GetName() or tostring(self), 'onload')
+ self.Count = self.Overlay.Count
+ self.Name = self.Overlay.Name
+ self.TimeLeft = self.Overlay.TimeLeft
+ self.Owner = self.Overlay.Owner
+
+ self.Icon:SetDesaturated(false)
+ self.Done:Hide()
+end
+
+function MissionEntry:Update()
local r,g,b = 1, 1, 1
if self.isRare then
r,g,b = 0.1, 0.4, 1
@@ -587,11 +718,7 @@
self.Icon:SetAtlas(self.typeAtlas, false)
end
- if self.isComplete then
- self.Done:Show()
- else
- self.Done:Hide()
- end
+
if self.isComplete then
self.TimeLeft:SetText('Complete!')
@@ -601,7 +728,7 @@
end
end
-function MissionsHandler:OnEnter()
+function MissionEntry:OnEnter()
if self.rewardInfo and self.rewardInfo.itemID then
GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
GameTooltip:SetItemByID(self.rewardInfo.itemID)
@@ -609,61 +736,46 @@
end
end
-function MissionsHandler:OnLeave()
+function MissionEntry:OnLeave()
if GameTooltip:IsOwned(self) then
GameTooltip:Hide()
end
end
-function ShipmentsHandler:Refresh()
- --[[
- self.icon = data.icon
- self.shipmentCapacity = data.shipmentCapacity
- self.shipmentsReady = data.shipmentsReady
- self.shipmentsTotal = data.shipmentsTotal
- self.creationTime = data.creationTime
- self.duration = data.duration
- self.itemID = data.itemID
- self.itemQuality = data.itemQuality
- icon = texture,
- shipmentCapacity = shipmentCapacity,
- shipmentsReady = shipmentsReady,
- shipmentsTotal = shipmentsTotal,
- creationTime = creationTime,
- duration = duration,
- timeleftString = timeleftString,
- itemName = itemName,
- itemIcon = itemIcon,
- itemQuality = itemQuality,
- itemID = itemID
+function ShipmentEntry:OnLoad()
+ MissionEntry.OnLoad(self)
+end
- --]]
+
+function ShipmentEntry:Update()
+ print('|cFF0088FF'.. self.name..'|r:Update()')
self.Icon:SetTexture(self.icon)
- self.Name:SetText(self.name)
self.Count:SetText(self.shipmentsReady)
self.Done:SetShown(self.shipmentsReady and (self.shipmentsReady >= 1))
-- flag as complete
+
+ local bgColor = CP_BACKGROUND_COLOR.inProgress
if ( self.shipmentsReady >= self.shipmentsTotal ) and (not self.isBeingResearched) then
self.Swipe:SetCooldownUNIX(0, 0);
self.Done:Show();
- self.isComplete = true
+ bgColor = CP_BACKGROUND_COLOR.complete
else
+ if (self.shipmentsReady >= 1) and (self.shipmentsReady < self.shipmentsTotal) then
+ bgColor = CP_BACKGROUND_COLOR.shipmentsReady
+ end
self.Swipe:SetCooldownUNIX(self.creationTime or 0 , self.duration or 0);
end
+ self.Background:SetColorTexture(unpack(bgColor))
- if self.isComplete then
- self.TimeLeft:SetText('Complete!')
- self.Background:SetColorTexture(0.5,0.5,0.5)
- elseif (self.shipmentsReady and (self.shipmentsReady > 0)) then
- self.Background:SetColorTexture(0.5,0.5,0.5,.5)
- else
- self.Background:SetColorTexture(0,0,0,0.5)
+ SetActualShipmentTime(self)
+
+ if self.originalReady then
+ print('|cFF00FF88'..self.name..'|r', 'starting ready:', self.originalReady, 'starting time:', self.originalCreationTime)
end
end
-local time = time
-function ShipmentsHandler:OnUpdate(sinceLast)
+function ShipmentEntry:OnUpdate(sinceLast)
self.throttle = (self.throttle or 1) + sinceLast
if self.throttle >= 1 then
self.throttle = self.throttle - 1
@@ -671,22 +783,21 @@
return
end
+
if (self.shipmentsReady and self.shipmentsTotal) and (self.shipmentsReady < self.shipmentsTotal) then
- local timeLeft = self.creationTime + self.duration - time()
- if self.shipmentsReady >= 1 then
+ local timeLeft = SetActualShipmentTime(self)
+
+ if self.isComplete then
+ self.TimeLeft:SetText('Complete!')
+ self.TimeLeft:SetTextColor(0,0.5,1)
+ elseif self.shipmentsReady >= 1 then
self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
self.TimeLeft:SetTextColor(0,1,0)
else
self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
self.TimeLeft:SetTextColor(1,1,1)
end
- if (timeLeft < 0) then
- if self.shipmentsReady < self.shipmentsTotal then
- self.shipmentsReady = self.shipmentsReady + 1
- self.creationTime = self.creationTime + self.duration
- -- text will be set on next update
- end
- end
+
elseif self.isBeingResearched then
self.TimeLeft:SetText(GetTimeLeftString(self.researchStartTime + self.researchDuration - time()))
self.TimeLeft:SetTextColor(1,1,0)
@@ -712,7 +823,7 @@
g = min(progress * 2, 1)
r = 1
end
- self.ProgressBar:SetColorTexture(r, g, 0, 1)
+ self.ProgressBar:SetColorTexture(r, g, 0, .4)
self.ProgressBG:SetColorTexture(r, g, 0, .125)
self.ProgressBG:Show()
self.ProgressBar:Show()
@@ -722,7 +833,7 @@
end
end
-function ShipmentsHandler:OnEnter()
+function ShipmentEntry:OnEnter()
if ( self.shipmentsReady and self.shipmentsTotal ) then
GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
GameTooltip:AddLine(self.Owner:GetText(), self.Owner:GetTextColor())
@@ -732,14 +843,27 @@
end
end
-function ShipmentsHandler:OnLeave()
+function ShipmentEntry:OnLeave()
if GameTooltip:IsOwned(self) then
GameTooltip:Hide()
end
end
-function ShipmentsHandler:OnClick(button)
+function ShipmentEntry:OnClick(button)
if button == 'RightButton' then
self.handler:FreeBlock(self)
end
-end
\ No newline at end of file
+end
+
+ClassPlanMissionHandler = Mixin(MissionList, SharedHandlers)
+ClassPlanShipmentHandler = Mixin(ShipmentList, SharedHandlers)
+ClassPlanMissionEntryMixin = Mixin(MissionEntry, SharedEntry)
+ClassPlanShipmentEntryMixin = Mixin(ShipmentEntry,SharedEntry)
+
+ClassPlanHeaderMixin = {
+ OnClick = function(self)
+ self:GetParent():SetList()
+ self:GetParent().isStale = true
+ ClassOrderPlan:Update()
+ end
+}
\ No newline at end of file
diff -r d0114b51cdea -r e8679ecb48d8 ClassPlan.xml
--- a/ClassPlan.xml Fri Oct 28 19:54:00 2016 -0400
+++ b/ClassPlan.xml Tue Nov 01 10:48:50 2016 -0400
@@ -6,47 +6,6 @@
-
@@ -76,16 +35,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-