changeset 13:9455693fc290

Init - recall XML display state on reload ObjectiveFrame - quest coloring by relative level - quest coloring by daily/weekly/complete status - remember starting scroll value between reload - limit anchor points to edges for regions affected by style attributes ObjectiveInfo - AutoQuest outline definitions - Pull Quest title and tag data in addition to WatchInfo ObjectiveStyle - ensure consistent style table - hardcode certain attributes for sanity XML - ensure consistent naming conventions for heading and content elements - ensure hardcore anchors are based on edges - expansion of file structure to deal with complexities of dynamic widgets and style caching ObjectiveUI - determine primary style by block handler when restoring original style - moved framescript to 'ObjectiveWidgets' lua
author Nenue
date Sat, 02 Apr 2016 17:46:52 -0400
parents 8238cddaddb1
children ed642234f017
files Init.lua ObjectiveCore.lua ObjectiveFrame.lua ObjectiveInfo.lua ObjectiveStyle.lua ObjectiveTracker.xml ObjectiveUI.lua ObjectiveWidgets.lua ObjectiveWidgets.xml
diffstat 9 files changed, 465 insertions(+), 362 deletions(-) [+]
line wrap: on
line diff
--- a/Init.lua	Sat Apr 02 05:01:54 2016 -0400
+++ b/Init.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -386,6 +386,17 @@
 --- Generic handlers for keeping track of XML-defined frames
 B.OnLoad = function(self)
   tinsert(checkForConfig, self)
+  self.Minimize = function(self, forceDown)
+    if not self:IsVisible() then
+       return
+    end
+    local state = (forceDown and 1 or (B.Conf.FrameState[self:GetName()] == 1 and 2 or 1))
+    local stateFunc = (state  == 1) and 'Hide' or 'Show'
+    for i, region in pairs(self.minimizeFrames) do
+      region[stateFunc](region)
+    end
+    B.Conf.FrameState[self:GetName()] = state
+  end
 end
 
 B.InitXMLFrame = function(self)
@@ -395,12 +406,25 @@
   if not B.Conf.FramePosition then
     B.Conf.FramePosition = {}
   end
+  if not B.Conf.FrameState then
+    B.Conf.FrameState = {}
+  end
+
   if B.Conf.FramePosition[self:GetName()] then
     print('restoring frame position', unpack(B.Conf.FramePosition[self:GetName()]))
     self:ClearAllPoints()
     local anchorTo, relativePoint, x, y = unpack(B.Conf.FramePosition[self:GetName()])
     self:SetPoint(anchorTo, UIParent, relativePoint, x, y)
   end
+  local state = B.Conf.FrameState[self:GetName()] and B.Conf.FrameState[self:GetName()] or 2
+  if state == 0 then
+    self:Hide()
+  elseif state == 1 then
+    self.Minimize(self, true)
+  elseif state == 2 then
+    self:Show()
+  end
+  B.Conf.FrameState[self:GetName()] = state
 end
 
 B.OnDragStart = function(self)
--- a/ObjectiveCore.lua	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveCore.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -184,6 +184,7 @@
   mod.SetEvents()
   ObjectiveTrackerFrame:UnregisterAllEvents()
   ObjectiveTrackerFrame:Hide()
+
 end
 
 --[[
--- a/ObjectiveFrame.lua	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveFrame.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -10,6 +10,7 @@
 local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent
 local CreateFrame = CreateFrame
 local print = B.print('Objectives')
+local unitLevel = 1
 --------------------------------------------------------------------
 --- Global frame layout
 --------------------------------------------------------------------
@@ -77,12 +78,17 @@
 end
 
 local WrapperCloseButton_OnClick = function(self)
-  if Scroller:IsVisible() then
-    Scroller:Hide()
+  Wrapper:Minimize()
+  if B.Conf.FrameState[Wrapper:GetName()] == 1 then
+    self:GetNormalTexture():SetTexture([[Interface\PaperDollInfoFrame\UI-Character-SkillsPageDown-Up]])
+    self:GetPushedTexture():SetTexture([[Interface\PaperDollInfoFrame\UI-Character-SkillsPageDown-Down]])
   else
-    Scroller:Show()
+    self:GetNormalTexture():SetTexture([[Interface\PaperDollInfoFrame\UI-Character-SkillsPageUp-Up]])
+    self:GetPushedTexture():SetTexture([[Interface\PaperDollInfoFrame\UI-Character-SkillsPageUp-Down]])
   end
 end
+local WrapperCloseButton_OnMouseWheel = function(self, delta)
+end
 
 mod.InitializeTrackers = function()
 
@@ -112,9 +118,11 @@
   Scroller:SetScript('OnShow', Scroller_OnShow)
   Scroller:SetScript('OnHide', Scroller_OnHide)
   Wrapper.close:SetScript('OnClick', WrapperCloseButton_OnClick)
+  Wrapper.close:SetScript('OnMouseWheel', WrapperCloseButton_OnMouseWheel)
   Wrapper:SetPoint(unpack(wrapperPosition))
-  Scroller_OnShow(Scroller)
-
+  if B.Conf.ObjectiveTrackerMinimized then
+    Scroller_OnShow(Scroller)
+  end
   mod.UpdateWrapperStyle()
 end
 
@@ -287,6 +295,8 @@
   end
   if info.superTracked then
     subStyle = 'Super'
+  elseif info.isDaily then
+    subStyle = 'Daily'
   end
 
   if info.specialItem and not info.itemButton then
@@ -296,9 +306,25 @@
     --info.itemButton = nil
   end
 
+  if info.level then
+    local levelDiff = unitLevel - info.level
+    if  levelDiff > 9 then
+      t.title:SetTextColor(0.7, 0.7, 0.7, 1)
+    elseif levelDiff > 1 then
+      t.title:SetTextColor(0.5, 1, 0.5, 1)
+    elseif levelDiff < -1 then
+      t.title:SetTextColor(1, 0.4, 0.25, 1)
+    elseif levelDiff < -4 then
+      t.title:SetTextColor(1, 0, 0, 1)
+    else
+      t.title:SetTextColor(1,1,1,1)
+    end
+  end
+
+
   if Devian and Devian.InWorkspace() then
     t.debugText:Show()
-    t.debugText:SetText(tostring(blockIndex) .. '\n' .. tostring(info.itemButton and info.itemButton:GetName()))
+    t.debugText:SetText(tostring(blockIndex) .. '\n' .. tostring(info.itemButton and info.itemButton:GetName()) .. "\n" .. (info.level and info.level or '-'))
   end
 
   --- metrics are calculated in SetStyle
@@ -440,6 +466,7 @@
 local usedButtons = mod.Quest.itemButtons
 local freeButtons = mod.Quest.freeButtons
 mod.UpdateWrapper = function()
+  unitLevel = UnitLevel('player')
   wrapperWidth = wrapperMaxWidth
   scrollWidth = wrapperWidth
   local wrapperBlocks = 0
@@ -498,7 +525,7 @@
   mod.SetBlockStyle(Wrapper, 'Wrapper', 'Normal')
 
   Scroller:SetSize(wrapperWidth, wrapperHeight)
-  Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, -headerHeight)
+  Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, 0)
   Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT')
 
 
@@ -507,7 +534,7 @@
   Scroll:SetPoint('RIGHT', Scroller, 'RIGHT')
 
   --Scroller:UpdateScrollChildRect()
-  Wrapper:SetSize(wrapperWidth, wrapperHeight + headerHeight)
+  Wrapper:SetSize(wrapperWidth, wrapperHeight)
 
   -- update action buttons
   print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(),
--- a/ObjectiveInfo.lua	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveInfo.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -9,6 +9,19 @@
 --------------------------------------------------------------------
 --- Tracker-specific data retrieval functions
 --------------------------------------------------------------------
+
+
+-----------------------------
+--- AUTO_QUEST
+AutoQuest.name = "Remote Quests"
+AutoQuest.GetNumWatched = GetNumAutoQuestPopUps
+AutoQuest.GetInfo = function(watchIndex)
+  return Quest.GetInfo(watchIndex)
+end
+
+-----------------------------
+--- QUEST
+Quest.name = "Quests"
 Quest.itemButtons = {}
 Quest.freeButtons = {}
 Quest.POI = {}
@@ -20,6 +33,10 @@
   print('|cFF00DDFFQuest|r.|cFF0088FFGetInfo(|r'.. tostring(watchIndex)..'|r)')
   local questID, title, questIndex, numObjectives, requiredMoney, isComplete,
   startEvent, isAutoComplete, failureTime, timeElapsed, questType, isTask, isStory, isOnMap, hasLocalPOI = GetQuestWatchInfo(watchIndex)
+
+  local _, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(questIndex)
+  local questTagID, tagName = GetQuestTagInfo(questID);
+
   if not questID then
     return
   end
@@ -30,6 +47,7 @@
   q.type = 'Quest'
   q.questID = questID
   q.title = title
+  q.level = level
   q.questLogIndex = questIndex
   q.numObjectives = numObjectives
   q.requiredMoney = requiredMoney
@@ -44,21 +62,16 @@
   q.isOnMap = isOnMap
   q.hasLocalPOI = hasLocalPOI
 
-  --- Start QuestLogEntry calls
-  -----------------------------------------
-  SelectQuestLogEntry(questIndex)
-  q.greenRange = GetQuestGreenRange()
-  q.isDaily = QuestIsDaily()
-  q.isWeekly = QuestIsWeekly()
-  -----------------------------------------
-  --- End QuestLogEntry calls
-
-  q.isComplete = IsQuestComplete(questID)
-  q.isBreadCrumb = IsBreadcrumbQuest(questID)
-  q.isStoryQuest = IsStoryQuest(questID)
+  q.isDaily = ( frequency == LE_QUEST_FREQUENCY_DAILY and (not isComplete or isComplete == 0) )
+  q.isWeekly = ( frequency == LE_QUEST_FREQUENCY_WEEKLY and (not isComplete or isComplete == 0) )
+  q.isComplete = isComplete
+  q.isStory = isStory
+  q.isTask = isTask
+  --q.isBreadCrumb = isBreadCrumb
   q.completionText= GetQuestLogCompletionText(questIndex)
   q.numObjectives = GetNumQuestLeaderBoards(questIndex)
   q.isWatched = IsQuestWatched(questIndex)
+  q.isHardWatched = IsQuestHardWatched(questIndex)
   q.objectives = {}
   for i = 1, q.numObjectives do
     local text, type, finished = GetQuestLogLeaderBoard(i, questIndex)
@@ -121,10 +134,6 @@
   end
 end
 
-AutoQuest.GetInfo = function(watchIndex)
-  return Quest.GetInfo(watchIndex)
-end
-
 
 Cheevs.GetNumWatched = function(self)
   Cheevs.trackedCheevs = {GetTrackedAchievements()}
--- a/ObjectiveStyle.lua	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveStyle.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -11,12 +11,13 @@
 local titleSize, textSize = 15, 15
 local titleOutline, textOutline = "OUTLINE", "OUTLINE"
 local titleSpacing, textSpacing = 4, 3
-local textIndent = 5
+local unpack, type, pairs, tconcat = unpack, type, pairs, table.concat
 local wrapperMaxWidth, wrapperMaxHeight = 280, 490 -- these are the hard bounds, actual *Height variables are changed
 local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE'
 local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24
 local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2
 
+
 mod.defaults.ObjectiveWrapper = {
   ObjectiveTrackerFloat = {'BOTTOM', 'RIGHT'},
   ObjectiveTrackerParent = 'DebuffButton',
@@ -24,7 +25,18 @@
   ObjectiveWrapperParent = '',
 }
 mod.defaults.Style = {
- FontBank = {
+  Format = {
+    Frame = {
+      Width = 270,
+    },
+    title = {
+      Indent = 0
+    },
+    status = {
+      Indent = 5
+    }
+  },
+  FontBank = {
     ['Normal'] = _G.VeneerCriteriaFontNormal,
     ['Progress'] = _G.VeneerCriteriaFontProgress,
     ['Complete'] = _G.VeneerCriteriaFontComplete,
@@ -106,14 +118,12 @@
       },
       titlebg = {
         Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .4},        },
-        BackgroundFullWidth = true,
       },
       status = {
         Font = {textFont, textSize, textOutline},
         Spacing = textSpacing,
       },
       statusbg = {
-        BackgroundFullWidth = true,
         Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .2},        },
       }
     },
@@ -123,16 +133,22 @@
       },
       titlebg = {
         Gradient = {          MinColor = {0, 1, 0, 0.34},          MaxColor = {0, 1, 0, .17},        },
-        BackgroundFullWidth = true
       },
       status = {
         Font = {textFont, textSize, textOutline},        Spacing = textSpacing,
       },
       statusbg = {
         Gradient = {          MinColor = {0, 1, 0, .25},          MaxColor = {0, 1, 0, 0.12},        },
-        BackgroundFullWidth = true
       }
     },
+    Daily = {
+      titlebg = {
+        Gradient = {          MinColor = {0, .4, 1, 0.34},          MaxColor = {0, 0.4, 1, .17},        },
+      },
+      statusbg = {
+        Gradient = {          MinColor = {0, .4, 1, 0.25},          MaxColor = {0, 0.4, 1, .12},        },
+      },
+    },
     Cheev =  {
       Normal = {
 
@@ -303,27 +319,18 @@
   end
   style_cache_func[styleName](frame)
 
-
-  --print("Generated func = function()\n",code, "\nend")
-  --local cache_func[styleName] = loadstring(code)
-
-  -- todo: remove hardcode and rely on attribute handler
-  if frame.status then
-    frame.status:SetWidth(270)
-  end
-  if frame.title then
-    frame.title:SetWidth(270)
-  end
-
-
+  --- Hardcoding the sizing vars for sanity
+  local normalSettings = mod.defaults.Style.Format
   frame.titleHeight = frame.title and (frame.title:GetStringHeight() + frame.title.spacing*2) or 0
   frame.statusHeight = frame.status and (frame.status:GetStringHeight() + frame.status.spacing*2 + frame.attachmentHeight) or 0
   frame.height = frame.titleHeight + frame.statusHeight
-  frame.width = 270
-
+  frame.width = normalSettings.Frame.Width
+  frame.statusWidth = frame.width - normalSettings.status.Indent
+  frame.titleWidth = frame.width - normalSettings.title.Indent
 
   if frame.status then
-    print('status  ', frame.statusHeight)
+    print('status  ', frame.statusHeight, normalSettings.status.Indent, 0)
+    frame.status:SetPoint('LEFT', frame, 'LEFT', normalSettings.status.Indent, 0)
     frame.status:SetHeight(frame.statusHeight)
     if frame.statusbg then
 
@@ -333,7 +340,8 @@
     end
   end
   if frame.title then
-    print('title  ',frame.titleHeight)
+    print('title  ',frame.titleHeight, normalSettings.title.Indent)
+    frame.title:SetPoint('LEFT', frame, 'LEFT', normalSettings.title.Indent)
     frame.title:SetHeight(frame.titleHeight)
     if frame.titlebg then
       print('titlebg',frame.titleHeight)
--- a/ObjectiveTracker.xml	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveTracker.xml	Sat Apr 02 17:46:52 2016 -0400
@@ -5,6 +5,10 @@
     <Color r="1" g="1" b="0" a="1" />
   </Texture>
 
+  <Font name="VeneerTitleFont" virtual="true" font="Fonts\FRIZQT__.TTF" outline="NORMAL" height="16" >
+    <Color r="1" g=".80" b=".25" a="1" />
+  </Font>
+
   <Font name="VeneerCriteriaFontNormal" virtual="true" font="Fonts\FRIZQT__.TTF" outline="NORMAL" height="16">
     <Color r="1" g="1" b="1" a="1" />
   </Font>
@@ -93,6 +97,16 @@
             <Anchor point="LEFT" />
           </Anchors>
         </FontString>
+
+        <!--<Texture name="$parentTCR" parentKey="outlineClosed" file="Interface\FrameGeneral\UI-Frame">
+          <Size x="40" y="30" />
+          <Color r="1" g="1" b="1" a="1" />
+          <TexCoords top=".0156" bottom=".0265" left=".625" right=".875" />
+          <Anchors>
+            <Anchor point="TOPRIGHT" relativePoint="TOPRIGHT" x="2" y="2" />
+          </Anchors>
+        </Texture>-->
+
       </Layer>
     </Layers>
     <Frames>
@@ -131,14 +145,18 @@
         </Layers>
       </Frame>
 
-      <Button name="$parentClose" parentKey="close" inherits="UIPanelCloseButtonNoScripts">
-        <Size x="25" y="20" />
+      <Button name="$parentClose" parentKey="close" inherits="UIPanelCloseButtonNoScripts" enableMouseWheel="true" enableMouse="true">
+
+        <NormalTexture file="Interface\PaperDollInfoFrame\UI-Character-SkillsPageDown-Up" />
+        <PushedTexture file="Interface\PaperDollInfoFrame\UI-Character-SkillsPageDown-Down" />
         <Anchors>
-          <Anchor point="TOPRIGHT" x="-4" y="-2" />
+          <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" x="-2" y="2" />
         </Anchors>
+        <Layers>
+        </Layers>
       </Button>
 
-      <ScrollFrame name="$parentScrollFrame" enableMouseWheel="true" parentKey="scrollArea">
+      <ScrollFrame name="$parentScrollFrame" enableMouseWheel="true" parentKey="scrollArea" parentArray="minimizeFrames">
         <Layers>
           <Layer level="BACKGROUND">
             <Texture setAllPoints="true" parentKey="bg">
@@ -268,18 +286,23 @@
         </Texture>
       </Layer>
       <Layer level="OVERLAY">
-        <FontString name="$parentTitle" parentKey="title" inherits="VeneerFontHighlight" justifyH="LEFT" justifyV="MIDDLE">
+        <FontString name="$parentTitle" parentKey="title" inherits="VeneerTitleFont" justifyH="LEFT" justifyV="MIDDLE">
           <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.titlebg" />
-          </Anchors>
-        </FontString>
-        <FontString name="$parentStatus" parentKey="status" inherits="VeneerFontNormal" justifyH="LEFT" justifyV="MIDDLE" wordwrap="true">
-          <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.statusbg" x="5" y="0" />
+            <Anchor point="TOP" relativeKey="$parent.titlebg" />
+            <Anchor point="BOTTOM" relativeKey="$parent.titlebg"  />
+            <Anchor point="LEFT" relativeKey="$parent.titlebg" />
             <Anchor point="RIGHT" relativeKey="$parent" />
           </Anchors>
         </FontString>
-        <FontString name="$parentDebugText" parentKey="debugText" inherits="VeneerCriteriaFontNormal">
+        <FontString name="$parentStatus" parentKey="status" inherits="VeneerCriteriaFontNormal" justifyH="LEFT" justifyV="MIDDLE" wordwrap="true">
+          <Anchors>
+            <Anchor point="TOP" relativeKey="$parent.statusbg" />
+            <Anchor point="BOTTOM" relativeKey="$parent.statusbg"  />
+            <Anchor point="LEFT"  relativeKey="$parent.statusbg" />
+            <Anchor point="RIGHT" relativeKey="$parent.statusbg" />
+          </Anchors>
+        </FontString>
+        <FontString name="$parentDebugText" parentKey="debugText" inherits="VeneerCriteriaFontNormal" justifyH="RIGHT">
           <Anchors>
             <Anchor point="TOPRIGHT" relativePoint="TOPRIGHT" />
           </Anchors>
@@ -297,4 +320,5 @@
   <Script file="ObjectiveStyle.lua" />
   <Script file="ObjectiveFrame.lua" />
   <Script file="ObjectiveEvents.lua" />
+  <Script file="ObjectiveWidgets.lua" />
 </Ui>
\ No newline at end of file
--- a/ObjectiveUI.lua	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveUI.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -11,7 +11,9 @@
 local tremove, tremovebyval = table.remove, table.removebyval
 
 --------------------------------------------------------------------
---- Tracker-specific widgets and their handlers
+--- Functions responsible for:
+--- - UI interactions that propagate to the BlizzardUI (sending RemoveQuestWatch() on remove quest action)
+--- -
 --------------------------------------------------------------------
 
 Tracker.Select = function(self) end
@@ -25,6 +27,7 @@
   if button == 'LeftButton' then
     if IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() then
       self:Link()
+      self:SetStyle('TrackerBlock',  self.info.type, 'Normal')
     elseif IsModifiedClick("QUESTWATCHTOGGLE") then
       self:Remove()
     else
@@ -32,6 +35,7 @@
     end
   elseif button == 'RightButton' then
     self:Open()
+    self:SetStyle('TrackerBlock',  self.info.type, 'Normal')
   end
   self.initialButton = nil
   self.modChatLink = nil
@@ -40,19 +44,11 @@
 end
 
 Tracker.OnMouseDown = function(self, button)
-  self:SetStyle('TrackeBlock','MouseDown')
+  self:SetStyle('TrackerBlock', 'MouseDown')
   print(IsModifiedClick("CHATLINK"), IsModifiedClick("QUESTWATCHTOGGLE"))
   print(self.info.title)
 end
 
------------------------------
---- AUTO_QUEST
-AutoQuest.name = "Remote Quests"
-AutoQuest.GetNumWatched = GetNumAutoQuestPopUps
-
------------------------------
---- QUEST
-Quest.name = "Quests"
 Quest.Select = function(self)
   SetSuperTrackedQuestID(self.info.questID)
   mod.UpdateWrapper()
@@ -76,13 +72,13 @@
 -----------------------------
 --- CHEEVS
 Cheevs.Select = function(self)
+  self:SetStyle('TrackerBlock',  self.info.type, 'Normal')
 end
 Cheevs.Remove = function(self)
   RemoveTrackedAchievement(self.info.cheevID)
 end
 Cheevs.OnMouseUp = function(self, button)
   Tracker.OnMouseUp(self, button)
-  self:SetStyle('TrackerBlock', 'Cheev', 'CheevNormal')
 end
 Cheevs.Link = function(self)
   local achievementLink = GetAchievementLink(self.info.cheevID);
@@ -101,294 +97,3 @@
   AchievementFrame_SelectAchievement(self.info.cheevID);
 end
 
-----------------------------------------------------------------------------------------
---- frame template and scripts lifted from "QuestKing 2" by Barjack
---- url: http://mods.curse.com/addons/wow/questking
-----------------------------------------------------------------------------------------
-local usedButtons = mod.Quest.itemButtons
-local freeButtons = mod.Quest.freeButtons
-mod.SetItemButton = function(block, info)
-  local itemInfo = info.specialItem
-  if not itemInfo then
-    return
-  end
-  --- .specialItem :: {link = link, charges = charges, icon = icon, start = start, duration = duration, enable = enable}
-
-
-  local itemButton
-  if not info.itemButton then
-    if #freeButtons >= 1 then
-      print('    |cFF00FFFFfound a free button')
-      itemButton = freeButtons[#freeButtons]
-      freeButtons[#freeButtons] = nil
-      if itemButton.block then
-        itemButton.block.itemButton = nil
-        itemButton.block = nil
-      end
-    else
-      local buttonIndex = mod.Quest.numButtons + #freeButtons + 1
-      itemButton = CreateFrame('Button', 'VeneerQuestItemButton' .. buttonIndex, UIParent, 'VeneerItemButtonTemplate')
-      itemButton.buttonIndex = buttonIndex
-      itemButton:SetSize(itemButtonSize, itemButtonSize)
-      itemButton:GetNormalTexture():SetSize(itemButtonSize * (5/3), itemButtonSize * (5/3))
-      print('    |cFFFF4400starting new button', itemButton:GetName())
-    end
-    mod.Quest.numButtons = mod.Quest.numButtons + 1
-  else
-    itemButton = info.itemButton
-    print('    |cFF00FF00found assigned button', itemButton:GetName())
-
-  end
-  -- set values
-
-  info.itemButton = itemButton
-  usedButtons[info.questID] = itemButton
-  print('      |cFF8800FFassigning|r', itemButton:GetName(), 'to quest|cFF00FF00', info.questID, '|rat|cFFFFFF00', block:GetName(),'|r')
-
-  for k,v in pairs(usedButtons) do
-    print('|cFFFF44DD'..k..'|r', v:GetName())
-    end
-
-  itemButton:SetAttribute("type", "item")
-  itemButton:SetAttribute("item", itemInfo.link)
-
-  itemButton.questID = info.questID
-  itemButton.questLogIndex = info.questLogIndex
-  itemButton.charges = itemInfo.charges
-  itemButton.rangeTimer = -1
-  itemButton.block = block
-
-  SetItemButtonTexture(itemButton, itemInfo.icon)
-  SetItemButtonCount(itemButton, itemInfo.charges)
-  Veneer_QuestObjectiveItem_UpdateCooldown(itemButton);
-
-  return itemButton
-end
---- Clear an itemButton from the given block
-mod.FreeItemButtons = function(block)
-
-  if block.itemButton then
-    local itemButton = block.itemButton
-    if itemButton.questID ~= block.info.questID then
-      block.itemButton = nil
-      itemButton.block = mod.Quest.InfoBlock[itemButton.questID]
-    else
-      itemButton.block = nil
-      itemButton:Hide()
-
-      usedButtons[itemButton.questID] = nil
-      freeButtons[#freeButtons + 1] = itemButton
-      mod.Quest.numButtons = mod.Quest.numButtons - 1
-      print('|cFFFF0088released', itemButton:GetName(),'and', block:GetName())
-    end
-  end
-end
-
-function Veneer_QuestObjectiveItem_OnUpdate (self, elapsed)
-  -- Handle range indicator
-  local rangeTimer = self.rangeTimer
-  if (rangeTimer) then
-    rangeTimer = rangeTimer - elapsed
-    if (rangeTimer <= 0) then
-      local link, item, charges, showItemWhenComplete = GetQuestLogSpecialItemInfo(self.questLogIndex)
-      if ((not charges) or (charges ~= self.charges)) then
-        mod.UpdateWrapper()
-        return
-      end
-
-      local count = self.HotKey
-      local valid = IsQuestLogSpecialItemInRange(self.questLogIndex)
-      if (valid == 0) then
-        count:Show()
-        count:SetVertexColor(1.0, 0.1, 0.1)
-      elseif (valid == 1) then
-        count:Show()
-        count:SetVertexColor(0.6, 0.6, 0.6)
-      else
-        count:Hide()
-      end
-      rangeTimer = TOOLTIP_UPDATE_TIME
-    end
-
-    self.rangeTimer = rangeTimer
-  end
-end
-
-function Veneer_QuestObjectiveItem_UpdateCooldown (itemButton)
-  local start, duration, enable = GetQuestLogSpecialItemCooldown(itemButton.questLogIndex)
-  if (start) then
-    CooldownFrame_SetTimer(itemButton.Cooldown, start, duration, enable)
-    if (duration > 0 and enable == 0) then
-      SetItemButtonTextureVertexColor(itemButton, 0.4, 0.4, 0.4)
-    else
-      SetItemButtonTextureVertexColor(itemButton, 1, 1, 1)
-    end
-  end
-end
-
------------------------------------------
--- 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 print = B.print('ObjectiveWidgets')
-  local widgetType = obj.type
-  local widget
-  if wr[widgetType] and wr[widgetType].used[obj.criteriaID] then
-    widget = wr[widgetType].used[obj.criteriaID]
-    print('|cFF00FF00Updating ('..obj.criteriaID..')', widget)
-  elseif not wr[widgetType] or #wr[widgetType].free == 0 then
-    widget = CreateFrame('Frame', 'VeneerObjective' .. widgetType .. (wr[widgetType] and (wr[widgetType].lastn+1) or (1)), VeneerObjectiveScroll, 'VeneerObjectiveCriteria' .. widgetType)
-
-    print('|cFFFF0088Creating `'..widget:GetName()..'` id', wr[widgetType].lastn)
-  else
-    widget = tremove(wr[widgetType].free)
-    print('|cFFFFFF00Acquiring released widget', widget:GetName())
-  end
-
-  wr[widgetType].used[obj.criteriaID] = widget
-  widget.info = obj
-  widget.parentInfo = info
-  mod.InitializeWidget(widget)
-  return widget
-end
-
---- WidgetTemplate 'OnLoad'
-mod.RegisterWidget = function(frame)
-  local print = B.print('ObjectiveWidgets')
-  local widgetType = frame.widgetType
-  if not wr[frame.widgetType] then
-    print('|cFFFF4400[[WidgetTemplate]]|r', widgetType)
-    wr[widgetType] = { lastn = 1, free = {}, used = {}, usedIndex = {}, freeIndex = {} }
-  else
-    print('|cFF0088FF+ [[WidgetTemplate]]r', widgetType, wr[widgetType].lastn)
-    wr[widgetType].lastn = wr[widgetType].lastn + 1
-  end
-end
-
---- WidgetTemplate 'OnShow'
-mod.InitializeWidget = setmetatable({}, {
-  __call = function(t, frame)
-    -- todo: config pull
-    local maxWidth = 250
-
-    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,
-})
-
---- WidgetTemplate 'OnEvent'
-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
-})
-
---- WidgetTemplate 'OnHide'
-mod.ReleaseWidget = function(frame)
-  local print = B.print('ObjectiveWidgets')
-  local reg = wr[frame.widgetType]
-  if reg and reg.used[frame.info.criteriaID] then
-    reg.used[frame.info.criteriaID] = nil
-    frame.info = nil
-    frame.parentInfo = nil
-    frame:UnregisterAllEvents()
-    tinsert(reg.free, frame)
-    print('|cFFBBBBBBreleased from service', frame:GetName())
-  end
-end
-
---- RemoveTrackedAchievement post-hook
-mod.CleanWidgets = function()
-  local print = B.print('ObjectiveWidgets')
-  local tracked = {GetTrackedAchievements() }
-  for type, reg in pairs(mod.WidgetRegistry) do
-    print('collecting', type)
-    for criteriaID, frame in pairs(reg.used) do
-      local id = frame.info.cheevID
-
-      if id and not tContains(tracked, id) then
-
-        print('  untracked achievement', id, 'associated with', criteriaID, frame:GetName())
-        frame:Hide()
-      end
-    end
-  end
-end
-
-mod.WidgetParams = {
-  ['ProgressBar'] = {
-    height = 20,
-    caption = {},
-    quantityString = {SetFontObject = _G.VeneerFontNormal}
-  }
-}
-
-mod.InitializeWidget.ProgressBar = function(self)
-  local print = B.print('ObjectiveWidgets')
-  local params = mod.WidgetParams[self.widgetType]
-  self.height = params.height
-  self:SetHeight(20)
-  self.bg:SetHeight(20)
-  self.fg:ClearAllPoints()
-  self.fg:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', 2, 2)
-  self.fg:SetHeight(16)
-  self.quantityString:SetFontObject(params.quantityString.SetFontObject)
-  self.quantityString:SetText(self.info.quantityString)
-end
-
-mod.UpdateWidget.ProgressBar = function (self)
-  local print = B.print('ObjectiveWidgets')
-  local quantity, requiredQuantity = self.info.quantity, self.info.requiredQuantity
-
-  if self.info.finished then
-    self.fg:SetWidth(self.bg:GetWidth() - 4)
-  elseif quantity == 0 then
-    self.fg:Hide()
-  else
-    self.fg:Show()
-    self.fg:SetWidth((self.bg:GetWidth()-4) * (quantity / requiredQuantity))
-  end
-end
-
-
-mod.InitializeWidget.Hidden = function (self)
-  self.height = 0
-end
-mod.UpdateWidget.Hidden = function (self)
-  self.height=  0
-end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ObjectiveWidgets.lua	Sat Apr 02 17:46:52 2016 -0400
@@ -0,0 +1,304 @@
+local B = select(2,...).frame
+local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
+local print = B.print('WidgetFactory')
+local UIParent = UIParent
+local GetQuestLogSpecialItemInfo, IsQuestLogSpecialItemInRange, GetQuestLogSpecialItemCooldown = GetQuestLogSpecialItemInfo, IsQuestLogSpecialItemInRange, GetQuestLogSpecialItemCooldown
+local CooldownFrame_SetTimer, SetItemButtonTextureVertexColor, CreateFrame, VeneerObjectiveScroll = CooldownFrame_SetTimer, SetItemButtonTextureVertexColor, CreateFrame, VeneerObjectiveScroll
+local tremove, tinsert, tContains, pairs, setmetatable = tremove, tinsert, tContains, pairs, setmetatable
+----------------------------------------------------------------------------------------
+--- XML and script code lifted from "QuestKing 2" by Barjack,
+---   found at http://mods.curse.com/addons/wow/questking
+----------------------------------------------------------------------------------------
+local usedButtons = mod.Quest.itemButtons
+local freeButtons = mod.Quest.freeButtons
+mod.SetItemButton = function(block, info)
+  local itemInfo = info.specialItem
+  if not itemInfo then
+    return
+  end
+
+  --- Quest.GetInfo().specialItem :: {link = link, charges = charges, icon = icon, start = start, duration = duration, enable = enable}
+
+
+  local itemButton
+  if not info.itemButton then
+    if #freeButtons >= 1 then
+      print('    |cFF00FFFFfound a free button')
+      itemButton = freeButtons[#freeButtons]
+      freeButtons[#freeButtons] = nil
+      if itemButton.block then
+        itemButton.block.itemButton = nil
+        itemButton.block = nil
+      end
+    else
+      local buttonIndex = mod.Quest.numButtons + #freeButtons + 1
+      itemButton = CreateFrame('Button', 'VeneerQuestItemButton' .. buttonIndex, UIParent, 'VeneerItemButtonTemplate')
+      itemButton.buttonIndex = buttonIndex
+      itemButton:SetSize(36, 36)
+      itemButton:GetNormalTexture():SetSize(36 * (5/3), 36 * (5/3))
+      print('    |cFFFF4400starting new button', itemButton:GetName())
+    end
+    mod.Quest.numButtons = mod.Quest.numButtons + 1
+  else
+    itemButton = info.itemButton
+    print('    |cFF00FF00found assigned button', itemButton:GetName())
+
+  end
+  -- set values
+
+  info.itemButton = itemButton
+  usedButtons[info.questID] = itemButton
+  print('      |cFF8800FFassigning|r', itemButton:GetName(), 'to quest|cFF00FF00', info.questID, '|rat|cFFFFFF00', block:GetName(),'|r')
+
+  for k,v in pairs(usedButtons) do
+    print('|cFFFF44DD'..k..'|r', v:GetName())
+  end
+
+  itemButton:SetAttribute("type", "item")
+  itemButton:SetAttribute("item", itemInfo.link)
+
+  itemButton.questID = info.questID
+  itemButton.questLogIndex = info.questLogIndex
+  itemButton.charges = itemInfo.charges
+  itemButton.rangeTimer = -1
+  itemButton.block = block
+
+  SetItemButtonTexture(itemButton, itemInfo.icon)
+  SetItemButtonCount(itemButton, itemInfo.charges)
+  Veneer_QuestObjectiveItem_UpdateCooldown(itemButton);
+
+  return itemButton
+end
+--- Clear an itemButton from the given block
+mod.FreeItemButtons = function(block)
+
+  if block.itemButton then
+    local itemButton = block.itemButton
+    if itemButton.questID ~= block.info.questID then
+      block.itemButton = nil
+      itemButton.block = mod.Quest.InfoBlock[itemButton.questID]
+    else
+      itemButton.block = nil
+      itemButton:Hide()
+
+      usedButtons[itemButton.questID] = nil
+      freeButtons[#freeButtons + 1] = itemButton
+      mod.Quest.numButtons = mod.Quest.numButtons - 1
+      print('|cFFFF0088released', itemButton:GetName(),'and', block:GetName())
+    end
+  end
+end
+
+function Veneer_QuestObjectiveItem_OnUpdate (self, elapsed)
+  -- Handle range indicator
+  local rangeTimer = self.rangeTimer
+  if (rangeTimer) then
+    rangeTimer = rangeTimer - elapsed
+    if (rangeTimer <= 0) then
+      local link, item, charges, showItemWhenComplete = GetQuestLogSpecialItemInfo(self.questLogIndex)
+      if ((not charges) or (charges ~= self.charges)) then
+        mod.UpdateWrapper()
+        return
+      end
+
+      local count = self.HotKey
+      local valid = IsQuestLogSpecialItemInRange(self.questLogIndex)
+      if (valid == 0) then
+        count:Show()
+        count:SetVertexColor(1.0, 0.1, 0.1)
+      elseif (valid == 1) then
+        count:Show()
+        count:SetVertexColor(0.6, 0.6, 0.6)
+      else
+        count:Hide()
+      end
+      rangeTimer = TOOLTIP_UPDATE_TIME
+    end
+
+    self.rangeTimer = rangeTimer
+  end
+end
+
+function Veneer_QuestObjectiveItem_UpdateCooldown (itemButton)
+  local start, duration, enable = GetQuestLogSpecialItemCooldown(itemButton.questLogIndex)
+  if (start) then
+    CooldownFrame_SetTimer(itemButton.Cooldown, start, duration, enable)
+    if (duration > 0 and enable == 0) then
+      SetItemButtonTextureVertexColor(itemButton, 0.4, 0.4, 0.4)
+    else
+      SetItemButtonTextureVertexColor(itemButton, 1, 1, 1)
+    end
+  end
+end
+
+-----------------------------------------
+-- 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 print = B.print('ObjectiveWidgets')
+  local widgetType = obj.type
+  local widget
+  if wr[widgetType] and wr[widgetType].used[obj.criteriaID] then
+    widget = wr[widgetType].used[obj.criteriaID]
+    print('|cFF00FF00Updating ('..obj.criteriaID..')', widget)
+  elseif not wr[widgetType] or #wr[widgetType].free == 0 then
+    widget = CreateFrame('Frame', 'VeneerObjective' .. widgetType .. (wr[widgetType] and (wr[widgetType].lastn+1) or (1)), VeneerObjectiveScroll, 'VeneerObjectiveCriteria' .. widgetType)
+
+    print('|cFFFF0088Creating `'..widget:GetName()..'` id', wr[widgetType].lastn)
+  else
+    widget = tremove(wr[widgetType].free)
+    print('|cFFFFFF00Acquiring released widget', widget:GetName())
+  end
+
+  wr[widgetType].used[obj.criteriaID] = widget
+  widget.info = obj
+  widget.parentInfo = info
+  mod.InitializeWidget(widget)
+  return widget
+end
+
+--- WidgetTemplate 'OnLoad'
+mod.RegisterWidget = function(frame)
+  local print = B.print('ObjectiveWidgets')
+  local widgetType = frame.widgetType
+  if not wr[frame.widgetType] then
+    print('|cFFFF4400[[WidgetTemplate]]|r', widgetType)
+    wr[widgetType] = { lastn = 1, free = {}, used = {}, usedIndex = {}, freeIndex = {} }
+  else
+    print('|cFF0088FF+ [[WidgetTemplate]]r', widgetType, wr[widgetType].lastn)
+    wr[widgetType].lastn = wr[widgetType].lastn + 1
+  end
+end
+
+--- WidgetTemplate 'OnShow'
+mod.InitializeWidget = setmetatable({}, {
+  __call = function(t, frame)
+    -- todo: config pull
+    local maxWidth = 250
+
+    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,
+})
+
+--- WidgetTemplate 'OnEvent'
+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
+})
+
+--- WidgetTemplate 'OnHide'
+mod.ReleaseWidget = function(frame)
+  local print = B.print('ObjectiveWidgets')
+  local reg = wr[frame.widgetType]
+  if reg and reg.used[frame.info.criteriaID] then
+    reg.used[frame.info.criteriaID] = nil
+    frame.info = nil
+    frame.parentInfo = nil
+    frame:UnregisterAllEvents()
+    tinsert(reg.free, frame)
+    print('|cFFBBBBBBreleased from service', frame:GetName())
+  end
+end
+
+--- RemoveTrackedAchievement post-hook
+mod.CleanWidgets = function()
+  local print = B.print('ObjectiveWidgets')
+  local tracked = {GetTrackedAchievements() }
+  for type, reg in pairs(mod.WidgetRegistry) do
+    print('collecting', type)
+    for criteriaID, frame in pairs(reg.used) do
+      local id = frame.info.cheevID
+
+      if id and not tContains(tracked, id) then
+
+        print('  untracked achievement', id, 'associated with', criteriaID, frame:GetName())
+        frame:Hide()
+      end
+    end
+  end
+end
+
+
+mod.defaults.WidgetVars = {
+  ProgressBar = {
+    bg = {
+      Height = 20,
+    },
+    fg = {
+      Height = 16,
+    },
+    status = {
+      FontObject = _G.VeneerFontNormal
+    }
+  }
+}
+mod.InitializeWidget.ProgressBar = function(self)
+  local c = mod.defaults.WidgetVars.ProgressBar
+  local params = mod.WidgetParams[self.widgetType]
+  self.height = params.height
+  self:SetHeight(c.bg.Height)
+  self.bg:SetHeight(c.bg.Height)
+  self.fg:ClearAllPoints()
+  self.fg:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', 2, 2)
+  self.fg:SetHeight(c.fg.Height)
+  self.status:SetFontObject(c.status.FontObject)
+  self.status:SetText(self.info.quantityString)
+end
+
+mod.UpdateWidget.ProgressBar = function (self)
+  local quantity, requiredQuantity = self.info.quantity, self.info.requiredQuantity
+
+  if self.info.finished then
+    self.fg:SetWidth(self.bg:GetWidth() - 4)
+  elseif quantity == 0 then
+    self.fg:Hide()
+  else
+    self.fg:Show()
+    self.fg:SetWidth((self.bg:GetWidth()-4) * (quantity / requiredQuantity))
+  end
+end
+
+
+mod.InitializeWidget.Hidden = function (self)
+  self.height = 0
+end
+mod.UpdateWidget.Hidden = function (self)
+  self.height=  0
+end
\ No newline at end of file
--- a/ObjectiveWidgets.xml	Sat Apr 02 05:01:54 2016 -0400
+++ b/ObjectiveWidgets.xml	Sat Apr 02 17:46:52 2016 -0400
@@ -61,7 +61,7 @@
     </Scripts>
     <Layers>
       <Layer level="OVERLAY">
-        <FontString name="$parentQuantityString" parentKey="quantityString" inherits="VeneerCriteriaFont">
+        <FontString name="$parentStatusText" parentKey="status" inherits="VeneerCriteriaFont">
 
         </FontString>
       </Layer>
@@ -85,7 +85,7 @@
     </Scripts>
     <Layers>
       <Layer level="OVERLAY">
-        <FontString name="$parentQuantityString" parentKey="quantityString" inherits="VeneerCriteriaFont">
+        <FontString name="$parentStatusText" parentKey="status" inherits="VeneerCriteriaFont">
 
         </FontString>
       </Layer>