Nenue@40: local _, db = ... Nenue@4: local wipe, tinsert, sort = table.wipe, tinsert, table.sort Nenue@2: local pairs, ipairs = pairs, ipairs Nenue@4: local floor, mod, time = floor, mod, time Nenue@32: local max, min = math.max, math.min Nenue@2: local GetTime = GetTime Nenue@3: local GI_currentTime = time() Nenue@32: local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop Nenue@3: Nenue@32: local CP_REPLACE_LANDINGPAGE = true Nenue@32: local CP_HEADER_SIZE = 24 Nenue@40: db.ClassPlanDefaultType = { Nenue@40: Nenue@40: backgroundColor = {0, 0, 0, 0.5}, Nenue@40: textColor = {1,1,1,1} Nenue@40: } Nenue@40: db.ClassPlanTypes = setmetatable({}, {__index = db.ClassPlanDefaultType}) Nenue@40: db.ClassPlanTypes.inProgress = { Nenue@40: backgroundColor = {0, 0, 0, 0.5}, Nenue@40: textColor = {1,1,1} Nenue@40: } Nenue@40: db.ClassPlanTypes.shipmentsReady = { Nenue@40: backgroundColor = {1, 1, 0, 0.25 }, Nenue@40: textColor = {1, 1, 0} Nenue@40: } Nenue@40: db.ClassPlanTypes.complete = { Nenue@40: backgroundColor = {0, 1, 0, 0.25 }, Nenue@40: textColor = {0, 1, 0} Nenue@2: } Nenue@2: Nenue@4: local GetTimeLeftString = function(timeLeft) Nenue@4: local days = floor(timeLeft/(24*3600)) Nenue@4: local hours = floor(mod(timeLeft, (24*3600)) / 3600) Nenue@4: local minutes = floor(mod(timeLeft, 3600) / 60) Nenue@4: local seconds = mod(timeLeft, 60) Nenue@4: if days >= 1 then Nenue@6: return (days .. 'd' .. ' ') .. ((hours > 0) and (hours .. 'h') or '') Nenue@95: elseif timeLeft < 60 then Nenue@95: return (seconds .. ' sec') Nenue@4: else Nenue@6: return ((hours > 0) and (hours .. 'h') or '') .. ((minutes > 0) and (' ' ..minutes .. ' min') or '') Nenue@4: end Nenue@4: end Nenue@3: Nenue@32: ClassOrderPlanCore = { Nenue@32: events = {}, Nenue@32: freeBlocks = {}, Nenue@35: characterButtons = {}, Nenue@32: blocks = {}, Nenue@32: sortedItems = {}, Nenue@32: timers = {}, Nenue@32: shipments = {}, Nenue@32: playerFirst = false, Nenue@32: prototypes = {}, Nenue@40: Queued = {}, Nenue@40: Timers = {}, Nenue@40: ReportChunks = {}, Nenue@32: } Nenue@40: ClassPlanHandlerBase = { Nenue@32: numBlocks = 0, Nenue@32: isStale = true, Nenue@35: maxItems = 10 Nenue@32: } Nenue@40: ClassPlanEntryBase = {} Nenue@1: Nenue@32: local ClassPlan = ClassOrderPlanCore Nenue@40: local Embed = function(object, ...) Nenue@40: for i = 1, select('#', ...) do Nenue@40: local src = select(i, ...) Nenue@40: for k,v in pairs(src) do Nenue@40: if not object[k] then Nenue@40: object[k] = v Nenue@40: end Nenue@40: end Nenue@40: end Nenue@40: return object Nenue@40: end Nenue@5: Nenue@32: function ClassPlan:OnLoad () Nenue@3: self:RegisterEvent('PLAYER_LOGIN') Nenue@3: self:RegisterEvent('ADDON_LOADED') Nenue@3: self:RegisterEvent('PLAYER_REGEN_ENABLED') Nenue@5: self:RegisterEvent('PLAYER_REGEN_DISABLED') Nenue@40: self:RegisterEvent('GARRISON_SHOW_LANDING_PAGE') Nenue@32: self:RegisterForDrag('LeftButton') Nenue@95: self:EnableMouse(true) Nenue@32: self:SetMovable(true) Nenue@32: self:SetToplevel(true) Nenue@32: Nenue@32: SLASH_CLASSPLAN1 = "/classplan" Nenue@32: SLASH_CLASSPLAN2 = "/cp" Nenue@32: SlashCmdList.CLASSPLAN = function(args) Nenue@32: self:Toggle() Nenue@32: end Nenue@32: Nenue@40: local originalScript = GarrisonLandingPageMinimapButton:GetScript('OnClick') Nenue@40: GarrisonLandingPageMinimapButton:SetScript("OnClick", function(minimap, button) Nenue@40: if button == 'LeftButton' and (not IsShiftKeyDown()) then Nenue@40: self:Toggle() Nenue@40: else Nenue@40: originalScript(minimap, button) Nenue@40: end Nenue@40: end) Nenue@102: local OnStopped = function() Nenue@102: print('Fade.OnStop()') Nenue@102: self.isAnimating = nil Nenue@102: self:SetShown(self.data.IsShown) Nenue@102: end Nenue@102: Nenue@102: self.FadeOut:SetScript('OnStop', OnStopped) Nenue@40: self.FadeOut:SetScript('OnFinished', function() Nenue@102: print('FadeOut.OnFinished()') Nenue@40: self.isAnimating = nil Nenue@102: self:SetShown(false) Nenue@40: end) Nenue@40: self.FadeIn:SetScript('OnPlay', function() Nenue@102: print('FadeIn.OnPlay()') Nenue@40: self.isAnimating = true Nenue@102: self.data.IsShown = true Nenue@40: end) Nenue@102: self.FadeIn:SetScript('OnStop', OnStopped) Nenue@40: Nenue@40: --hooksecurefunc(C_Garrison, 'RequestLandingPageShipmentInfo', function() Nenue@40: -- WorldPlan:print("Requesting shipments data.") Nenue@40: --end) Nenue@40: C_Garrison.RequestLandingPageShipmentInfo(); Nenue@40: self.isStale = true Nenue@95: UIPanelWindows[self:GetName()] = { area = "right", pushable = 3, whileDead = 1 }; Nenue@95: tinsert(UISpecialFrames, self:GetName()) Nenue@4: end Nenue@19: Nenue@40: Nenue@32: function ClassPlan:GetCurrentProfile() Nenue@32: WorldPlanData.OrderHall = WorldPlanData.OrderHall or {} Nenue@32: local db = WorldPlanData.OrderHall Nenue@32: self.data = db Nenue@4: Nenue@32: local characters = db.characters or {} Nenue@32: db.characters = characters Nenue@4: Nenue@32: local name, realm = UnitName('player') Nenue@32: realm = realm or GetRealmName() Nenue@40: Nenue@32: local profileName = name .. '-' .. realm Nenue@40: self.profile = characters[profileName] or { Nenue@40: showItems = true Nenue@40: } Nenue@117: self.profileName = profileName Nenue@32: self.characters = characters Nenue@32: characters[profileName] = self.profile Nenue@32: Nenue@32: local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))] Nenue@32: local className = UnitClass('player') Nenue@32: print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName) Nenue@32: self.profile.classColor = classColor Nenue@32: self.profile.className = className Nenue@35: self.profile.characterName = name Nenue@35: self.profile.characterRealm = realm Nenue@40: -- flip it on Nenue@40: self.profile.showItems = true Nenue@40: Nenue@40: self.HeaderInset:SetHeight(CP_HEADER_SIZE) Nenue@40: self.ClassStripe:SetColorTexture(classColor.r, classColor.g, classColor.b, 1) Nenue@40: self.ClassStripe:SetPoint('TOPLEFT', self.HeaderInset, 'BOTTOMLEFT') Nenue@40: Nenue@95: self.maxItems = db.maxItems or self.maxItems Nenue@95: Nenue@32: return self.profile Nenue@3: end Nenue@3: Nenue@40: function ClassPlan:AddHandler(frame) Nenue@40: print('|cFF00FF00'..frame:GetName()..' loaded') Nenue@40: for i, event in ipairs(frame.events) do Nenue@32: print('|cFF00FF00 event', event) Nenue@40: frame:RegisterEvent(event) Nenue@1: end Nenue@40: frame.sortedItems = {} Nenue@40: for index, listKey in ipairs(frame.listKey) do Nenue@117: self.profile[listKey] = self.profile[listKey] or {} Nenue@40: frame.profile = self.profile Nenue@40: frame.data = self.data Nenue@40: local listTitle = frame.listTitle[index] Nenue@40: setmetatable(self.profile[listKey], { __tostring = function() return listTitle end }) Nenue@40: frame.sortedItems[listKey] = {} Nenue@95: frame.maxItems = self.maxItems Nenue@32: end Nenue@40: frame.owningFrame = self Nenue@40: frame:SetList(1) Nenue@3: end Nenue@1: Nenue@32: function ClassPlan:OnEvent (event, arg) Nenue@32: print(event, arg) Nenue@5: if event == 'PLAYER_REGEN_DISABLED' then Nenue@6: if self:IsVisible() then Nenue@6: self.combatHide = true Nenue@6: self:SetShown(false) Nenue@6: end Nenue@6: Nenue@5: elseif event == 'PLAYER_REGEN_ENABLED' then Nenue@6: if self.combatHide == true then Nenue@6: self.combatHide = nil Nenue@6: self:SetShown(true) Nenue@6: end Nenue@32: elseif event == 'ADDON_LOADED' then Nenue@32: if arg == 'Blizzard_GarrisonUI' then Nenue@32: self:Reanchor() Nenue@32: end Nenue@3: elseif event == 'PLAYER_LOGIN' then Nenue@3: if not self.initialized then Nenue@4: self:Setup() Nenue@1: end Nenue@40: elseif event == 'GARRISON_SHOW_LANDING_PAGE' then Nenue@40: self:RefreshData() Nenue@2: end Nenue@2: end Nenue@2: Nenue@32: function ClassPlan:Setup() Nenue@32: if IsLoggedIn() then Nenue@32: print('|cFFFFFF00'..self:GetName()..':Setup()|r') Nenue@32: Nenue@32: self:GetCurrentProfile() Nenue@32: for _, handler in ipairs(self.Handlers) do Nenue@40: self:AddHandler(handler) Nenue@40: handler.initialized = true Nenue@32: end Nenue@32: self.initialized = true Nenue@32: self:SetShown(self.data.IsShown) Nenue@40: Nenue@41: GarrisonMinimap_HidePulse(GarrisonLandingPageMinimapButton, 1) -- buildings Nenue@41: GarrisonMinimap_HidePulse(GarrisonLandingPageMinimapButton, 5) -- missions Nenue@32: end Nenue@3: end Nenue@3: Nenue@4: Nenue@32: --- Update space Nenue@4: Nenue@40: local max = math.max Nenue@40: function ClassPlan:RefreshData() Nenue@40: for index, handler in pairs(self.Handlers) do Nenue@40: print(' |cFF00FF00'..handler:GetName()..' data update|r') Nenue@40: handler:RefreshData() Nenue@40: end Nenue@40: self.requestingData = nil Nenue@40: end Nenue@35: Nenue@40: function ClassPlan:Update() Nenue@40: print('|cFF00FFFF'..self:GetName()..'Refresh()|r') Nenue@3: Nenue@40: self.currentHeight = 0 Nenue@40: for index, handler in ipairs(self.Handlers) do Nenue@40: local itemsHeight = handler:UpdateItems() Nenue@40: if itemsHeight then Nenue@117: Nenue@40: self.currentHeight = max(itemsHeight, self.currentHeight) Nenue@117: print('calc height', handler, self.currentHeight) Nenue@40: end Nenue@40: end Nenue@23: Nenue@40: local index = 1 Nenue@40: for key, info in pairs(self.data.characters) do Nenue@40: print('cbutton', key) Nenue@40: if self.data[key] then Nenue@40: print('|cFFFF4400remove legacy value', key) Nenue@40: self.data[key] = nil Nenue@23: end Nenue@23: Nenue@35: Nenue@40: local button = self.characterButtons[index] Nenue@40: if not button then Nenue@40: button = CreateFrame('Button', nil, self, 'ClassOrderPlanCharacterButton') Nenue@40: button:SetID(index) Nenue@40: self.characterButtons[index] = button Nenue@40: Nenue@40: if not self.lastButton then Nenue@40: button:SetPoint('TOPLEFT', self.HeaderInset, 'TOPLEFT', 0, 0) Nenue@40: else Nenue@40: button:SetPoint('TOPLEFT', self.lastButton, 'TOPRIGHT', 2, 0) Nenue@35: end Nenue@40: self.lastButton = button Nenue@40: end Nenue@40: if not info.characterName then Nenue@40: info.characterName, info.characterRealm = key:match("%(.+)%-(.+)^") Nenue@35: end Nenue@35: Nenue@40: print(info.characterName) Nenue@35: Nenue@40: button:SetSize(CP_HEADER_SIZE, CP_HEADER_SIZE) Nenue@40: button.profileKey = key Nenue@40: button.className = info.className Nenue@40: button.classColor = info.classColor Nenue@40: button.characterName = info.characterName Nenue@40: button.characterRealm = info.characterRealm Nenue@40: button.showItems = info.showItems Nenue@40: button.isMine = (info == self.profile) Nenue@40: button:Update() Nenue@40: button:Show() Nenue@40: index = index + 1 Nenue@3: end Nenue@3: Nenue@117: for i = index, #self.characterButtons do Nenue@117: self.characterButtons[i]:Hide() Nenue@117: end Nenue@117: Nenue@117: Nenue@40: self.HeaderInset:SetHeight(CP_HEADER_SIZE) Nenue@40: self.HeaderInset:ClearAllPoints() Nenue@40: self.HeaderInset:SetPoint('TOPLEFT' ,self, 'TOPLEFT') Nenue@40: self.HeaderInset:SetPoint('RIGHT' ,self, 'RIGHT') Nenue@40: self.ClassStripe:ClearAllPoints() Nenue@40: self.ClassStripe:SetPoint('TOPLEFT', self.HeaderInset, 'BOTTOMLEFT', 0, 0) Nenue@40: self.ClassStripe:SetPoint('RIGHT') Nenue@40: self:Reanchor() Nenue@40: self.isStale = nil Nenue@40: end Nenue@40: Nenue@3: Nenue@32: function ClassPlan:Toggle() Nenue@102: print('Toggle()', self:IsVisible(), self:IsShown()) Nenue@102: if self:IsVisible() then Nenue@102: print('fade out') Nenue@102: self.data.IsShown = false Nenue@40: self.FadeOut:Play() Nenue@3: else Nenue@102: print('fade in') Nenue@40: self.data.IsShown = true Nenue@107: self:SetShown(true) Nenue@40: self.FadeIn:Play() Nenue@3: end Nenue@3: end Nenue@3: Nenue@40: Nenue@95: function ClassPlan:OnMouseDown(button) Nenue@95: print(button) Nenue@95: if button == 'RightButton' then Nenue@95: self:Toggle() Nenue@95: end Nenue@95: Nenue@95: end Nenue@95: Nenue@32: function ClassPlan:OnUpdate() Nenue@40: if self.requestingData then Nenue@40: self:RefreshData() Nenue@40: elseif self.isStale then Nenue@40: -- shouldn't happen, usually Nenue@32: self:Update() Nenue@18: end Nenue@40: if #self.ReportChunks >= 1 then Nenue@40: db.print(table.concat(self.ReportChunks, ', ')) Nenue@40: wipe(self.ReportChunks) Nenue@40: end Nenue@40: Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:OnShow() Nenue@23: print('|cFF00FFFFShow()') Nenue@40: self.isStale = true Nenue@32: self:Reanchor() Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:OnHide() Nenue@32: print('|cFF00FFFFHide()') Nenue@102: self.isAnimating = nil Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:Reanchor() Nenue@40: if not (self.data.positionX and self.data.positionY) then Nenue@40: self.data.positionX = 0 Nenue@40: self.data.positionY = -148 Nenue@40: end Nenue@32: self:ClearAllPoints() Nenue@40: self:SetPoint('TOP', self.data.positionX, self.data.positionY) Nenue@40: self.currentHeight = 0 Nenue@32: for index, frame in ipairs(self.Handlers) do Nenue@32: frame:Reanchor() Nenue@35: local ListTab = frame.ListTab Nenue@35: if ListTab then Nenue@35: ListTab:ClearAllPoints() Nenue@40: ListTab:SetPoint('TOPLEFT', frame, 'TOPLEFT', 0, 0) Nenue@40: ListTab:SetPoint('BOTTOMRIGHT', frame, 'TOPRIGHT', 0, -CP_HEADER_SIZE) Nenue@35: ListTab.Label:SetText(frame.listTitle[frame.currentListIndex]) Nenue@35: ListTab:Show() Nenue@117: print(ListTab:GetName(), ListTab:GetSize()) Nenue@35: end Nenue@40: self.currentHeight = max(self.currentHeight, frame.currentHeight or 0) Nenue@40: end Nenue@40: self:SetHeight(self.currentHeight + self.HeaderInset:GetHeight() + self.ClassStripe:GetHeight()) Nenue@35: Nenue@2: end Nenue@2: Nenue@32: function ClassPlan:OnDragStart() Nenue@32: self:StartMoving() Nenue@32: end Nenue@32: function ClassPlan:OnDragStop() Nenue@32: self:StopMovingOrSizing() Nenue@32: local x,y = self:GetCenter() Nenue@32: if x and y then Nenue@32: x = (x - GetScreenWidth()/2) Nenue@32: y = (y - GetScreenHeight()/2) * -1 Nenue@32: self.data.positionX, self.data.positionY = x,y Nenue@32: print('saving positions:', x, y) Nenue@32: end Nenue@32: end Nenue@32: Nenue@40: function ClassPlanHandlerBase:ScheduleUpdate(expires) Nenue@40: -- value will occasionally lag so check here Nenue@40: local duration = expires - time() Nenue@40: self.Timers = self.Timers or {} Nenue@40: if (duration > 0) and (not self.Timers[expires]) then Nenue@40: print(' adding timer at', expires, 'c', duration) Nenue@40: self.Timers[expires] = true Nenue@40: C_Timer.After(duration, function() Nenue@40: self.isStale = true Nenue@40: self:UpdateItems() Nenue@40: self.Timers[expires] = nil Nenue@40: end) Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: function ClassPlanHandlerBase:SetList(index) Nenue@40: local prevIndex = self.currentListIndex Nenue@32: if not index then Nenue@32: if self.currentListIndex == #self.listKey then Nenue@32: index = 1 Nenue@32: else Nenue@32: index = self.currentListIndex + 1 Nenue@32: end Nenue@32: end Nenue@32: Nenue@40: print('|cFF0088FF'..self:GetName()..'|r:SetList()', index, self.listKey[index]) Nenue@32: self.currentListIndex = index Nenue@32: self.activeKey = self.listKey[index] Nenue@32: self.activeTitle = self.listTitle[index] Nenue@32: Nenue@40: self.ListTab.Label:SetText(self.listTitle[index]) Nenue@32: self.isStale = true Nenue@40: Nenue@40: if self.OnSetList then Nenue@40: self:OnSetList(self.currentListIndex, prevIndex) Nenue@40: end Nenue@32: end Nenue@32: Nenue@95: function ClassPlanHandlerBase:OnLoad(...) Nenue@95: print(self:GetName()..':OnLoad()', ...) Nenue@95: self:EnableMouse(true) Nenue@95: end Nenue@95: Nenue@95: function ClassPlanHandlerBase:OnMouseDown(button, down) Nenue@95: print(self:GetName().. ':OnMouseDown()', button) Nenue@95: ClassOrderPlan:OnMouseDown(button) Nenue@95: end Nenue@95: Nenue@40: function ClassPlanHandlerBase:OnMouseWheel(delta) Nenue@95: if IsControlKeyDown() then Nenue@95: if delta > 0 then Nenue@95: if self.maxItems < 30 then Nenue@95: self.maxItems = self.maxItems + 1 Nenue@95: end Nenue@95: Nenue@95: else Nenue@95: if self.maxItems >= 2 then Nenue@95: self.maxItems = self.maxItems - 1 Nenue@95: end Nenue@95: end Nenue@95: if WorldPlanData.OrderHall then Nenue@95: WorldPlanData.OrderHall.maxItems = self.maxItems Nenue@95: end Nenue@95: else Nenue@95: self.scrollOffset = (self.scrollOffset or 0) - ((delta > 0) and 1 or -1) Nenue@95: end Nenue@35: self:UpdateItems() Nenue@35: end Nenue@35: Nenue@40: function ClassPlanHandlerBase:RefreshData() Nenue@40: print('|cFF0088FF'..self:GetName()..':RefreshData()') Nenue@40: local activeKey = self.activeKey Nenue@40: self.truncatedItems = 0 Nenue@40: self.currentTime = time() Nenue@40: if self:GetParent().profile then Nenue@40: self:GetPlayerData() Nenue@40: end Nenue@40: for _, listKey in ipairs(self.listKey) do Nenue@40: local sortedItems = self.sortedItems[listKey] Nenue@40: wipe(sortedItems) Nenue@40: for key, profile in pairs(self.data.characters) do Nenue@40: local isMine = (profile == self.profile) Nenue@40: print(key, listKey, isMine, profile.showItems) Nenue@40: local profileList = profile[listKey] Nenue@40: if profileList and #profileList >= 1 then Nenue@40: local classColor = profile.classColor or RAID_CLASS_COLORS['HUNTER'] Nenue@40: if profile.showItems then Nenue@40: for index, data in ipairs(profileList) do Nenue@40: data.classColor = classColor Nenue@40: data.profileKey = key Nenue@40: data.isMine = isMine Nenue@40: if self.OnGetItem then Nenue@40: self:OnGetItem(data) Nenue@40: end Nenue@40: tinsert(sortedItems, data) Nenue@40: end Nenue@40: else Nenue@40: self.truncatedItems = self.truncatedItems + 1 Nenue@40: end Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: if self.SortHandler then Nenue@40: sort(sortedItems, self.SortHandler) Nenue@40: end Nenue@40: end Nenue@40: Nenue@40: for k,v in pairs(self.sortedItems) do Nenue@40: print(' ', k) Nenue@40: end Nenue@40: Nenue@32: self.isStale = true Nenue@32: end Nenue@32: Nenue@40: function ClassPlanHandlerBase:OnEvent(event, id) Nenue@40: if (event == 'GARRISON_MISSION_LIST_UPDATE') then Nenue@40: if (id == LE_FOLLOWER_TYPE_GARRISON_7_0) then Nenue@40: print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, id) Nenue@40: self:RefreshData() Nenue@40: end Nenue@6: else Nenue@40: print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, id) Nenue@32: end Nenue@32: end Nenue@32: Nenue@40: function ClassPlanHandlerBase:OnUpdate() Nenue@40: if self.isStale then Nenue@40: print('|cFF00FF00'..self:GetName()..':OnUpdate()|r') Nenue@40: Nenue@40: self:UpdateItems() Nenue@40: end Nenue@40: end Nenue@32: Nenue@32: -- Stuff set on every list item Nenue@40: function ClassPlanHandlerBase:SetOwnerData (self, data) Nenue@32: local name, realm = string.match(data.profileKey, "(.+)%-(.+)") Nenue@32: local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r' Nenue@32: self.Owner:SetText(ownerText) Nenue@32: self.Name:SetText(self.name) Nenue@32: self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b) Nenue@32: end Nenue@32: Nenue@117: function ClassPlanHandlerBase:Reanchor() end Nenue@35: Nenue@40: function ClassPlanHandlerBase:UpdateItems() Nenue@40: print('|cFF0088FF '..self:GetName()..':UpdateItems()|r', self.activeKey) Nenue@35: self.MoreItemsUp:Hide() Nenue@35: self.MoreItemsDown:Hide() Nenue@40: local sortedItems = self.sortedItems[self.activeKey] Nenue@35: local scrollOffset = self.scrollOffset or 0 Nenue@35: local numItems = #sortedItems Nenue@35: if (not sortedItems[scrollOffset+1]) or (numItems <= self.maxItems) then Nenue@35: scrollOffset = 0 Nenue@35: elseif (numItems > self.maxItems) and (scrollOffset > (numItems - self.maxItems)) then Nenue@35: scrollOffset = (numItems - self.maxItems) Nenue@35: end Nenue@35: Nenue@117: if self.OnUpdateRequested then Nenue@117: local overrideHeight = self:OnUpdateRequested() Nenue@117: if overrideHeight then Nenue@117: return overrideHeight Nenue@117: end Nenue@117: Nenue@117: Nenue@117: end Nenue@117: Nenue@117: Nenue@40: self.ListTab.Count:SetText(numItems) Nenue@32: self.blocks = self.blocks or {} Nenue@32: local blocks = self.blocks Nenue@32: local lastProfile Nenue@40: local totalHeight = (self.ListTab:GetHeight() or 0) Nenue@32: self.lastBlock = nil Nenue@32: self.numActive = 0 Nenue@35: for i = 1, self.maxItems do Nenue@35: local index = scrollOffset + i Nenue@35: local data = sortedItems[index] Nenue@35: if not data then Nenue@40: print('|cFFFF4400end of data') Nenue@35: break Nenue@35: end Nenue@35: Nenue@32: local block = blocks[i] Nenue@32: if not block then Nenue@40: block = CreateFrame('Button', self:GetName()..'ListItem'..i , self, self.templateName) Nenue@32: block.listType = self.activeKey Nenue@40: Nenue@40: block.doAnimation = true Nenue@40: Nenue@32: block.handler = self Nenue@32: self.numBlocks = self.numBlocks + 1 Nenue@32: blocks[i] = block Nenue@32: end Nenue@35: block:SetID(index) Nenue@32: self.numActive = self.numActive + 1 Nenue@32: Nenue@32: if self.lastBlock then Nenue@32: block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0) Nenue@40: --print('--', index, data.isComplete, data.missionEndTime, data.name) Nenue@32: else Nenue@40: block:SetPoint('TOPLEFT', self.ListTab, 'BOTTOMLEFT', 0, 0) Nenue@40: --print('--top') Nenue@32: end Nenue@32: self.lastBlock = block Nenue@32: Nenue@32: totalHeight = totalHeight + block:GetHeight() Nenue@32: block.lastProfile = lastProfile Nenue@32: -- blot out arbitrary flags Nenue@32: block.offerEndTime = nil Nenue@95: block.isComplete = data.isComplete Nenue@32: block.missionEndTime = nil Nenue@32: block.creationTime = nil Nenue@32: block.duration = nil Nenue@32: block.throttle = 5 Nenue@32: Nenue@32: for k,v in pairs(data) do Nenue@32: if type(block[k]) ~= 'function' then Nenue@32: block[k] = v Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: block:Update() Nenue@32: self:SetOwnerData(block, data) Nenue@32: Nenue@32: block:Show() Nenue@32: lastProfile = data.profileKey Nenue@6: end Nenue@6: Nenue@35: if self.numActive < numItems then Nenue@35: if scrollOffset < (numItems - self.maxItems) then Nenue@35: self.MoreItemsDown:Show() Nenue@35: end Nenue@35: if scrollOffset > 0 then Nenue@35: self.MoreItemsUp:Show() Nenue@35: end Nenue@35: end Nenue@35: Nenue@35: for i = self.numActive + 1, self.numBlocks do Nenue@32: if blocks[i] then Nenue@32: blocks[i]:Hide() Nenue@32: end Nenue@32: end Nenue@32: Nenue@40: self:Reanchor() Nenue@40: if totalHeight ~= self.currentHeight then Nenue@40: self.currentHeight = totalHeight Nenue@40: self:SetHeight(self.currentHeight) Nenue@40: self:GetParent():Reanchor() Nenue@40: end Nenue@40: Nenue@40: Nenue@35: self.scrollOffset = scrollOffset Nenue@40: self.isStale = nil Nenue@117: Nenue@117: Nenue@117: if self.OnItemsUpdated then Nenue@117: return self:OnItemsUpdated() Nenue@117: end Nenue@117: Nenue@32: return totalHeight Nenue@32: end Nenue@32: Nenue@40: function ClassPlanEntryBase:OnAnimFinished() Nenue@40: end Nenue@40: function ClassPlanEntryBase:OnShow() Nenue@32: Nenue@40: print('|cFF44FF00'..self:GetName()..':OnShow()') Nenue@40: if self.doAnimation then Nenue@40: self.doAnimation = nil Nenue@40: if not ClassOrderPlan.isAnimating then Nenue@40: self.NewBlockFade:Play() Nenue@32: end Nenue@32: end Nenue@32: end Nenue@35: Nenue@40: function ClassPlanEntryBase:SetTimeLeft(expires, duration) Nenue@35: if not expires then Nenue@35: return Nenue@32: end Nenue@32: Nenue@35: -- calculate here since time isn't available Nenue@40: local timeLeft = expires - time() Nenue@95: --print(self:GetName(), timeLeft) Nenue@35: if timeLeft < 0 then Nenue@35: -- handle being complete Nenue@40: if self.shipmentsReady and (self.shipmentsReady < self.shipmentsTotal) then Nenue@40: self.TimeLeft:SetText('Ready') Nenue@40: else Nenue@40: self.TimeLeft:SetText('Complete!') Nenue@40: end Nenue@35: else Nenue@35: self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) Nenue@95: if duration then Nenue@95: local progress = (duration - timeLeft) / duration Nenue@95: local r = ((progress >= .5) and (progress/2)) or 1 Nenue@95: local g = ((progress <= .5) and (progress*2)) or 1 Nenue@95: self.ProgressBG:Show() Nenue@95: self.ProgressBar:Show() Nenue@95: self.ProgressBG:SetColorTexture(r,g,0,0.25) Nenue@95: self.ProgressBar:SetColorTexture(r,g,0,0.5) Nenue@95: self.ProgressBar:SetWidth(self.ProgressBG:GetWidth() * progress) Nenue@95: else Nenue@32: Nenue@95: self.ProgressBG:Hide() Nenue@95: self.ProgressBar:Hide() Nenue@95: end Nenue@35: end Nenue@32: end Nenue@32: Nenue@32: Nenue@40: Nenue@40: ClassPlanHeaderMixin = {} Nenue@40: function ClassPlanHeaderMixin:OnLoad() Nenue@40: self:EnableMouse((#self:GetParent().listKey > 1)) Nenue@40: self:RegisterForClicks('AnyUp') Nenue@32: end Nenue@40: function ClassPlanHeaderMixin:OnClick () Nenue@40: local frame = self:GetParent() Nenue@40: frame:SetList() Nenue@40: if frame.OnHeaderClick then Nenue@117: frame:OnHeaderClick() Nenue@32: end Nenue@32: end Nenue@32: Nenue@40: ClassPlanCharacterButtonMixin = { Nenue@40: } Nenue@40: function ClassPlanCharacterButtonMixin:Update () Nenue@40: --print(CLASS_ICON_TCOORDS[self.className:upper()]) Nenue@40: if self.className and CLASS_ICON_TCOORDS[self.className:upper()] then Nenue@40: self.Icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[self.className:upper()])) Nenue@32: end Nenue@40: self.Icon:SetDesaturated((not self.showItems)) Nenue@40: self.SelectGlow:SetShown(self.isMine) Nenue@32: end Nenue@32: Nenue@117: function ClassPlanCharacterButtonMixin:OnLoad() Nenue@117: self:RegisterForClicks('AnyDown') Nenue@117: end Nenue@117: Nenue@40: function ClassPlanCharacterButtonMixin:OnEnter() Nenue@40: if not self.profileKey then Nenue@18: return Nenue@18: end Nenue@2: Nenue@40: GameTooltip:SetOwner(self, 'ANCHOR_RIGHT') Nenue@40: local info = ClassOrderPlan.data.characters[self.profileKey] Nenue@117: GameTooltip:AddLine(self.characterName .. ' - ' .. self.characterRealm, self.classColor.r, self.classColor.g, self.classColor.b) Nenue@40: local numItems = 0 Nenue@40: if info.missions then Nenue@40: GameTooltip:AddLine(#info.missions .. ' mission'..((#info.missions == 1) and '' or 's')..' in progress') Nenue@2: end Nenue@40: if info.shipments then Nenue@40: GameTooltip:AddLine(#info.shipments .. ' work order' .. ((#info.shipments == 1) and '' or 's')) Nenue@40: end Nenue@40: if info.available then Nenue@40: GameTooltip:AddLine(#info.available .. ' mission'..((#info.available == 1) and '' or 's')..' available') Nenue@40: end Nenue@40: GameTooltip:Show() Nenue@2: end Nenue@2: Nenue@40: function ClassPlanCharacterButtonMixin:OnLeave() Nenue@2: if GameTooltip:IsOwned(self) then Nenue@2: GameTooltip:Hide() Nenue@2: end Nenue@2: end Nenue@2: Nenue@40: function ClassPlanCharacterButtonMixin:OnClick(button, down) Nenue@40: local clist = ClassOrderPlan.data.characters Nenue@40: Nenue@3: if button == 'RightButton' then Nenue@117: Nenue@117: if IsShiftKeyDown() then Nenue@117: print('delete profile', self.profileKey) Nenue@117: clist[self.profileKey] = nil Nenue@117: else Nenue@117: Nenue@117: for _, profile in pairs(clist) do Nenue@117: profile.showItems = true Nenue@117: end Nenue@40: end Nenue@117: Nenue@117: Nenue@117: Nenue@40: else Nenue@40: if clist[self.profileKey].showItems then Nenue@40: clist[self.profileKey].showItems = nil Nenue@40: else Nenue@40: clist[self.profileKey].showItems = true Nenue@40: end Nenue@3: end Nenue@40: for i, handler in ipairs(ClassOrderPlan.Handlers) do Nenue@40: handler.isStale = true Nenue@40: end Nenue@40: Nenue@117: Nenue@117: Nenue@40: ClassOrderPlan:RefreshData() Nenue@40: ClassOrderPlan:Update() Nenue@117: print('OnClick', self.profileKey) Nenue@117: print( clist[self.profileKey] and clist[self.profileKey].showItems) Nenue@32: end