changeset 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
files BuffButton.lua ObjectiveFrame.lua ObjectiveUI.lua ObjectiveWidgets.xml
diffstat 4 files changed, 228 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/BuffButton.lua	Fri Apr 01 01:30:42 2016 -0400
+++ b/BuffButton.lua	Fri Apr 01 12:27:05 2016 -0400
@@ -159,7 +159,8 @@
     -- Background decorations layer
     if not d[i] then
       d[i] = CreateFrame('Frame', buffName..i..'Decor', _G.UIParent, 'VeneerDecorTemplate')
-      --RegisterStateDriver(d[i], "visibility", "[petbattle] [vehicleui] hide")
+      -- todo: sort out a way to fix this without creating taint issues
+      RegisterStateDriver(d[i], "visibility", "[petbattle] [vehicleui] hide")
     end
 
     d[i]:SetPoint('BOTTOMLEFT', guide.icon, 'BOTTOMLEFT', -buffBorder, -buffBorder)
--- a/ObjectiveFrame.lua	Fri Apr 01 01:30:42 2016 -0400
+++ b/ObjectiveFrame.lua	Fri Apr 01 12:27:05 2016 -0400
@@ -83,13 +83,13 @@
     },
     Active = {
       Title = {
-        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, 1},        },
+        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .4},        },
         Font = {titleFont, titleSize, titleOutline},
         Spacing = titleSpacing,
         BackgroundFullWidth = true
       },
       Text = {
-        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, 1},        },
+        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .2},        },
         Font = {textFont, textSize, textOutline},
         Spacing = textSpacing,
         BackgroundFullWidth = true
@@ -107,6 +107,28 @@
         BackgroundFullWidth = true
       }
     },
+    CheevNormal = {
+
+      Title = {
+        Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
+        Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
+      },
+      Text = {
+        Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
+        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
+      },
+    },
+    CheevComplete = {
+
+      Title = {
+        Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
+        Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
+      },
+      Text = {
+        Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
+        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
+      },
+    }
   }
 }
 
@@ -137,7 +159,8 @@
 
 local Scroller_OnMouseWheel = function(self, delta)
   local r = Scroll:GetHeight() - Scroller:GetHeight()
-  local s = self:GetVerticalScroll() - delta * floor(r/5+.5)
+  local s = B.Conf.ObjectiveScroll - delta * floor(r/5+.5)
+  local from = self:GetVerticalScroll()
   if r == 0 then return end
   if s >= r then
     s = r
@@ -145,7 +168,8 @@
     s = 0
   end
   self:SetVerticalScroll(s)
-  print(s, r, self:GetVerticalScroll())
+  B.Conf.ObjectiveScroll = s
+  print('|cFF00FF00OnMouseWheel', 'from = ', from, 'scroll =', s, ' range =', r, 'current =', self:GetVerticalScroll())
 
   mod.UpdateActionButtons('SCROLLING')
 end
@@ -322,7 +346,7 @@
   block.objectives:SetSpacing(textSpacing)
   block.objectives:SetWordWrap(true)
 
-  local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight()
+  local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight() + block.attachmentHeight
   local blockHeight = titleHeight + titleSpacing2 + textHeight + textSpacing2
   local blockWidth = wrapperMaxWidth
 
@@ -387,6 +411,7 @@
 
   info.blockIndex = blockIndex
   handler.BlockInfo[blockIndex] = info
+
   t.Select = handler.Select
   t.Open = handler.Open
   t.Remove = handler.Remove
@@ -395,18 +420,16 @@
   t:SetScript('OnMouseDown', handler.OnMouseDown)
   t.title:SetText(info.title)
 
+  t.attachmentHeight = 0
   if info.isComplete then
     t.objectives:Show()
     t.objectives:SetText(info.completionText)
   elseif info.numObjectives >= 1 then
+    t.attachmentHeight = textSpacing
     t.objectives:Show()
     print('  - objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
 
     local text = ''
-    if info.description then
-      print('  -- has description text:', select('#', info.description), info.description)
-      text = info.description
-    end
 
     --- todo: implement objective displays
      -- in an accumulator loop, call upon handler for the appropriate display frame, each defining:
@@ -454,7 +477,11 @@
 end
 
 mod.UpdateObjectives = function(block, info, text)
-  local attachmentHeight = 0
+  local attachmentHeight = block.attachmentHeight
+  if info.description then
+    print('  -- has description text:', select('#', info.description), info.description)
+    text = info.description
+  end
   for o, obj in ipairs(info.objectives) do
     --- achievement criteria
     if obj.flags then
@@ -462,7 +489,6 @@
 
       if bit.band(obj.flags, 0x00000001) > 0 then
         obj.type = 'ProgressBar'
-        obj.widget = mod.SetWidget(obj, info)
       elseif bit.band(obj.flags, 0x00000002) then
         obj.type = 'Hidden'
         obj.widget = nil
@@ -472,7 +498,9 @@
         text = text .. ((text == '') and "" or "\n") .. obj.text
       end
 
-      print(obj.type, obj.text, obj.quantityString)
+      print('obj.type =', obj.type)
+      print('  ** qtyStr:', obj.quantityString, 'qty:', obj.quantity, 'assetID:', obj.assetID)
+      obj.widget = mod.SetWidget(obj, info)
       --- none of the above (most quests)
     else
       local line = obj.text
@@ -490,6 +518,10 @@
     end
 
     if obj.widget then
+
+      obj.widget:Show()
+      obj.widget:SetPoint('TOPLEFT', block.objectives, 'BOTTOMLEFT', 0, -attachmentHeight)
+      print('have a widget, height is', obj.widget.height)
       attachmentHeight = attachmentHeight + obj.widget.height
     end
 
@@ -620,8 +652,9 @@
   Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, -headerHeight)
   Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT')
 
+
   Scroll:SetSize(scrollWidth, scrollHeight)
-  Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, 0)
+  Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0)
   Scroll:SetPoint('RIGHT', Scroller, 'RIGHT')
 
   --Scroller:UpdateScrollChildRect()
--- 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
--- a/ObjectiveWidgets.xml	Fri Apr 01 01:30:42 2016 -0400
+++ b/ObjectiveWidgets.xml	Fri Apr 01 12:27:05 2016 -0400
@@ -1,7 +1,7 @@
 <Ui>
   <!-- houses objective widget templates -->
 
-  <Frame name="VeneerObjectiveCriteriaProgressBar" virtual="true">
+  <Frame name="VeneerObjectiveCriteriaProgressBar" virtual="true" hidden="true">
     <Size x="250" y="30" />
     <Scripts>
       <OnLoad>
@@ -20,15 +20,51 @@
     </Scripts>
     <Layers>
       <Layer level="BACKGROUND">
-        <Texture SetAllPoints="true" name="$parentBackground" parentKey="bg" setAllPoints="true">
+        <Texture SetAllPoints="true" name="$parentBackground" parentKey="bg">
           <Color r="0" g="0" b="0" a="0.25" />
+          <Anchors>
+            <Anchor point="BOTTOMLEFT" />
+            <Anchor point="TOPRIGHT" />
+          </Anchors>
         </Texture>
       </Layer>
       <Layer level="ARTWORK">
 
+        <Texture SetAllPoints="true" name="$parentForeground" parentKey="fg">
+          <Color r="1" g="1" b="1" a="1" />
+          <Anchors>
+            <Anchor point="TOPLEFT" x="1" y="-1" />
+          </Anchors>
+        </Texture>
       </Layer>
       <Layer level="OVERLAY">
         <FontString name="$parentQuantityString" parentKey="quantityString" inherits="VeneerCriteriaFont">
+          <Anchors>
+            <Anchor point="CENTER" />
+          </Anchors>
+        </FontString>
+      </Layer>
+    </Layers>
+  </Frame>
+
+  <Frame name="VeneerObjectiveCriteriaEvent" virtual="true" hidden="true">
+    <Size x="250" y="24" />
+    <Scripts>
+      <OnLoad>
+        self.widgetType = 'Event'
+        self.lines = 1
+        Veneer.ObjectiveTracker.RegisterWidget(self)
+      </OnLoad>
+      <OnShow>
+        Veneer.ObjectiveTracker.InitializeWidget(self)
+      </OnShow>
+      <OnHide>
+        Veneer.ObjectiveTracker.ReleaseWidget(self)
+      </OnHide>
+    </Scripts>
+    <Layers>
+      <Layer level="OVERLAY">
+        <FontString name="$parentQuantityString" parentKey="quantityString" inherits="VeneerCriteriaFont">
 
         </FontString>
       </Layer>