diff ObjectiveUI.lua @ 7:5301c68f28d8

TrackerBlock - use IsModifiedClick function to determine appropriate OnClick actions - handle 'CHATLINK' modifier - handle 'TOGGLEQUESTWATCH' modifier TrackerBlockObjectives - use a generic framework to manage frame creation for various criteria tracker types: - ProgressBar when Blizzard flag data indicates so - skip when Blizzard flag data indicates so - DynamicText otherwise - events related to the criteria are registered in the criteria frame, and unregistered when the frame is hidden, either by destruction of its parent or completion
author Nenue
date Fri, 01 Apr 2016 12:27:05 -0400
parents 589de8ea05b9
children 7923243ae972
line wrap: on
line diff
--- a/ObjectiveUI.lua	Fri Apr 01 01:30:42 2016 -0400
+++ b/ObjectiveUI.lua	Fri Apr 01 12:27:05 2016 -0400
@@ -8,6 +8,7 @@
 local print = B.print('Objectives')
 local Tracker, AutoQuest, Quest, Cheevs = mod.Tracker, mod.AutoQuest, mod.Quest, mod.Cheevs
 local itemButtonSize, itemButtonSpacing =  36, 1
+local tremove, tremovebyval = table.remove, table.removebyval
 
 --------------------------------------------------------------------
 --- Tracker-specific widgets and their handlers
@@ -21,27 +22,28 @@
 end
 
 Tracker.OnMouseUp = function(self, button)
-
   if self.initialButton == 'LeftButton' then
-    self:Select()
-    mod.UpdateWrapper()
-    if self.modShift then
+    if self.modChatLink and ChatEdit_GetActiveWindow() then
+      self:Link()
+    elseif self.modQuestWatch then
       self:Remove()
+    else
+      self:Select()
     end
   elseif button == 'RightButton' then
     self:Open()
   end
   self.initialButton = nil
-  self.modShift = nil
+  self.modChatLink = nil
+  self.modQuestWatch = nil
   print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r ->',self.info.trackingID)
 end
 
 Tracker.OnMouseDown = function(self, button)
   self.initialButton = button
-  self.modShift = IsShiftKeyDown()
-  if button == 'LeftButton' then
-    self:SetStyle('Active')
-  end
+  self.modChatLink = IsModifiedClick("CHATLINK")
+  self.modQuestWatch = IsModifiedClick("QUESTWATCHTOGGLE")
+  self:SetStyle('Active')
   print(self.info.title)
 end
 
@@ -55,6 +57,13 @@
 Quest.name = "Quests"
 Quest.Select = function(self)
   SetSuperTrackedQuestID(self.info.questID)
+  mod.UpdateWrapper()
+end
+Quest.Link = function(self)
+  local questLink = GetQuestLink(block.questLogIndex);
+  if ( questLink ) then
+    ChatEdit_InsertLink(questLink);
+  end
 end
 Quest.Open = function(self)
   QuestMapFrame_OpenToQuestDetails(self.info.questID)
@@ -75,6 +84,13 @@
 --- CHEEVS
 Cheevs.Select = function(self)
 end
+Cheevs.Link = function(self)
+    local achievementLink = GetAchievementLink(self.info.cheevID);
+    if ( achievementLink ) then
+      ChatEdit_InsertLink(achievementLink);
+    end
+  self:SetStyle('CheevNormal')
+end
 
 Cheevs.Open = function(self)
   if ( not AchievementFrame ) then
@@ -212,33 +228,129 @@
 end
 
 -----------------------------------------
--- Progress slider for achievements, and area objecitves
--- Stored by criteria ID to account for multiple bars in one cheev
-Tracker.SetProgress = function(criteria, info)
+-- Criteria frames
+
+--[[
+      text = description,
+      type = type,
+      finished = completed,
+      quantity = quantity,
+      requiredQuantity = requiredQuantity,
+      characterName = characterName,
+      flags = flags,
+      assetID = assetID,
+      quantityString = quantityString,
+      criteriaID = criteriaID,
+]]
+local newWidgetID = 0
+mod.WidgetRegistry = {}
+local wr = mod.WidgetRegistry
+
+--- Get a usable widget for the given achievement criteria set.
+ -- Returns a frame object with dimensioning parameters needed to size the receiving tracker block
+mod.SetWidget = function(obj, info)
+  local widgetType = obj.type
+  local widget
+
+  if not wr[widgetType] or #wr[widgetType].free == 0 then
+    print('VeneerObjectiveCriteria' .. widgetType)
+    widget = CreateFrame('Frame', nil, VeneerObjectiveScroll, 'VeneerObjectiveCriteria' .. widgetType)
+  end
+  local free = wr[widgetType].free
+  local used = wr[widgetType].used
+
+  widget = tremove(free)
+  local index = #used+1
+  used[index] = widget
+  wr[widgetType].usedIndex[widget] = index
+  widget.info = obj
+  widget.parentInfo = info
+  mod.InitializeWidget(widget)
+
+  return widget
 end
 
-mod.WidgetRegistry = {}
-local wr = mod.WidgetRegistry
-mod.SetWidget = function(criteria, info)
-  local widget
-  if not wr[criteria.type] then
-    print('|cFFFF4400[[WidgetTemplate]]|r', criteria.type)
-    wr[criteria.type] = { free = {}, used = {}, }
+--- Fired by OnLoad() when a new frame is spawned
+mod.RegisterWidget = function(frame)
+  local widgetType = frame.widgetType
+  local obj = frame.info
+  if not wr[frame.widgetType] then
+    print('|cFFFF4400[[WidgetTemplate]]|r', widgetType)
+    wr[widgetType] = { lastn = 0, free = {}, used = {}, usedIndex = {}, freeIndex = {} }
   end
-  if #wr[criteria.type].free == 0 then
+  tinsert(wr[frame.widgetType].free, frame)
+end
+mod.InitializeWidget = setmetatable({}, {
+  __call = function(t, frame)
+    -- todo: config pull
+    local maxWidth = 250
 
-    local frameID = #wr[criteria.type].free + #wr[criteria.type].used
-    widget = CreateFrame('Frame', 'VeneerCriteria' .. criteria.type .. frameID, VeneerObjectiveWrapper, 'VeneerObjectiveCriteria' .. criteria.type)
+    frame:SetWidth(maxWidth)
+    mod.UpdateWidget[frame.widgetType](frame)
+    frame:SetScript('OnEvent', mod.UpdateWidget[frame.widgetType])
+    if frame.info.isCurrency then
+      frame:RegisterEvent('CHAT_MSG_CURRENCY')
+      frame:RegisterEvent('CURRENCY_LIST_UPDATE')
+    end
+    frame:RegisterEvent('TRACKED_ACHIEVEMENT_UPDATE')
+    frame:RegisterEvent('TRACKED_ACHIEVEMENT_LIST_CHANGED')
+    frame:RegisterEvent('CRITERIA_UPDATE')
+    frame:RegisterEvent('CRITERIA_COMPLETE')
+    frame:RegisterEvent('CRITERIA_EARNED')
+
+    return t[frame.widgetType](frame)
+  end,
+})
+mod.UpdateWidget = setmetatable({}, {
+  __call = function(t, frame)
+    if not frame.widgetType then
+      error('Invalid widget template, needs .widgetType')
+      return
+    end
+
+    return t[frame.widgetType](frame)
+  end
+})
+
+mod.ReleaseWidget = function(frame)
+  local reg = wr[frame.widgetType]
+  if reg and reg.usedIndex[frame] then
+    tremove(reg.used, reg.usedIndex[frame])
+    reg.usedIndex[frame] = nil
+    frame:UnregisterAllEvents()
+    tinsert(reg.free, frame)
   end
 end
-mod.RegisterWidget = function(frame)
-  tinsert(wr[frame.widgetType].free, frame)
+
+mod.WidgetParams = {
+  ['ProgressBar'] = {
+    height = 20,
+    caption = {},
+    quantityString = {SetFontObject = _G.VeneerFontNormal}
+  }
+}
+
+mod.InitializeWidget.ProgressBar = function(self)
+  local params = mod.WidgetParams[self.widgetType]
+  self.height = params.height
+  self:SetHeight(20)
+  self.bg:SetHeight(20)
+  self.fg:SetHeight(18)
+  self.fg:SetPoint('BOTTOMLEFT', self.bg, 'BOTTOMLEFT', 1, 1)
+  self.quantityString:SetFontObject(params.quantityString.SetFontObject)
+  self.quantityString:SetText(self.info.quantityString)
 end
-mod.InitializeWidget = function(frame)
+
+mod.UpdateWidget.ProgressBar = function (self)
+  local quantity, requiredQuantity = self.info.quantity, self.info.requiredQuantity
+  self.fg:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 0)
+  if self.info.finished then
+    self.fg:SetWidth(self.bg:GetWidth() - 2)
+  elseif quantity == 0 then
+    self.fg:Hide()
+  else
+    self.fg:Show()
+    self.fg:SetWidth(self:GetWidth() * (quantity / requiredQuantity))
+  end
 
 end
-mod.ReleaseWidget = function(frame)
-
-  if tContains(wr[frame.widgetType], frame) then
-  end
-end
\ No newline at end of file