changeset 37:e84d645c8ab8

- revised the tracker update function to build its complete data list up front and use the values as points of comparison for determining possible out of place blocks, which will be iterated over afterward to remove what wasn't re-used - also entailed revising the exact role of global event handlers and function hooks, limiting their directions of communication so one doesn't end up calling the other multiple or inifinity times - schema handling polish
author Nenue
date Mon, 18 Apr 2016 07:56:23 -0400
parents a487841050be
children 1f8f9cc3d956
files Core.xml Init.lua ObjectiveTracker/Achievements.lua ObjectiveTracker/AutoQuestPopups.lua ObjectiveTracker/BonusObjectives.lua ObjectiveTracker/DefaultTracker.lua ObjectiveTracker/Events.lua ObjectiveTracker/Frame.lua ObjectiveTracker/ObjectiveTracker.lua ObjectiveTracker/ObjectiveTracker.xml ObjectiveTracker/Quests.lua ObjectiveTracker/Scenarios.lua ObjectiveTracker/Schema.lua ObjectiveTracker/Widgets.lua ObjectiveTracker/Widgets.xml
diffstat 15 files changed, 516 insertions(+), 271 deletions(-) [+]
line wrap: on
line diff
--- a/Core.xml	Sun Apr 17 13:00:31 2016 -0400
+++ b/Core.xml	Mon Apr 18 07:56:23 2016 -0400
@@ -30,7 +30,7 @@
   <Font name="VeneerNumberFont" virtual="true" font="Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf" outline="NORMAL" height="13" >
     <Color r="1" g="1" b="1" a="1" />
   </Font>
-  <Font name="VeneerNumberFontSmall" virtual="true" font="Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf" outline="NORMAL" height="11" >
+  <Font name="VeneerNumberFontSmall" virtual="true" font="Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf" outline="NORMAL" height="12" >
     <Color r="1" g="1" b="1" a="1" />
   </Font>
   <Font name="VeneerTitleFont" virtual="true" font="Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf" outline="NORMAL" height="15" >
--- a/Init.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/Init.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -19,11 +19,19 @@
 local moduleStack = {
 }
 
+--- Utilities
+B.wipeall = function (...)
+  for i = 1, select('#', ...) do
+    wipe(select(i, ...))
+  end
+end
+
 --- Various region categories
 B.displays = {}
 B.configLayers = {}
 B.configLayersRef = {}
 
+
 --@debug@
 --- Generates a print handler pointing to a static channel signature
 -- @usage func = B.print(sig)
--- a/ObjectiveTracker/Achievements.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Achievements.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -11,53 +11,66 @@
 local GetTime, GetAchievementNumCriteria, GetAchievementCriteriaInfo = GetTime, GetAchievementNumCriteria, GetAchievementCriteriaInfo
 local GetNumTrackedAchievements, GetTrackedAchievements, GetAchievementInfo = GetNumTrackedAchievements, GetTrackedAchievements, GetAchievementInfo
 local Default, Cheevs = T.DefaultHandler, T.Cheevs
-local print = B.print('Tracker')
-local lprint = B.print('Line')
-local iprint = B.print('Info')
+local wipe = table.wipe
+local print, bprint, lprint, iprint = B.print('Tracker'), B.print('Block'), B.print('Line'), B.print('iprint')
 
 --- Data retrieval
-Cheevs.GetNumWatched = function(self)
-  print('|cFF00FF00' .. GetTime())
-  Cheevs.trackedCheevs = {GetTrackedAchievements()}
-  return GetNumTrackedAchievements()
-end
-Cheevs.GetInfo = function(self, watchIndex)
-  --- step 1: confirm primary data and begin an entry if needed
-  local cheevID = Cheevs.trackedCheevs[watchIndex]
-  local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy = GetAchievementInfo(cheevID)
-  if not id then return false end
+Cheevs.GetNumWatched = function(self, targetID, isNew)
+  local trackedList = {GetTrackedAchievements() }
+  local numWatched, numAll = #trackedList, #self.WatchList
+  print('    |cFF00FF88GetNumWatched:|r',self.name, numWatched, ' ('..numAll..' recorded)')
+  local start = 1
+  local limit = max(numAll, #trackedList)
+  if targetID then
+    if not isNew and self.Info[targetID] then
+      -- if it's only an update, we can limit the scope
+      start = self.Info[targetID].watchIndex
+      print('    |cFF0088FFGetNumWatched: limit selection to['..start..'-'..limit..']')
+      if self.InfoBlock[targetID] then
+        self.InfoBlock[targetID]:Hide()
+      end
 
-  if not self.Info[cheevID] then self.Info[cheevID] = {} end
-  local c = self.Info[cheevID]
-  local numObjectives = GetAchievementNumCriteria(cheevID)
-
-  local tagInfo = {}
-  local objectives = c.objectives or {}
-  for i = 1, numObjectives do
-    local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(cheevID, i)
-    local line = objectives[i] or {}
-    line.objectiveIndex = i
-    line.cheevID = cheevID
-    line.text = description
-    line.type = type
-    line.finished = completed
-    line.value = quantity
-    line.maxValue = requiredQuantity
-    line.characterName = characterName
-    line.flags = flags
-    line.assetID = assetID
-    line.quantityString = quantityString
-    line.criteriaID = criteriaID
-    objectives[i] = line
+    end
   end
 
+  for index = start, limit do
+    if index > numWatched then
+      self.WatchList[index] = nil
+      print('      % dropping watch entry #'..index)
+    else
+      local cheevID = trackedList[index]
+      if not self.Info[cheevID] then
+        self.Info[cheevID] = self:GetInfo(cheevID, index)
+      else
+        print('    |cFF00FFBBGetInfo:', cheevID, 'already pulled')
+      end
+      self:GetObjectives(cheevID)
 
+      local info = self.Info[cheevID]
+      local watchBlock = self.WatchBlock[cheevID]
+
+      self.Info[cheevID].watchIndex = index
+      self.WatchList[index] = info
+    end
+  end
+
+  numAll = #self.WatchList
+  return numWatched, numAll, self.WatchList
+end
+Cheevs.GetInfo = function(self, cheevID, watchIndex)
+  --- step 1: confirm primary data and begin an entry if needed
+  local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy = GetAchievementInfo(cheevID)
+  if not id then return nil end
+
+  print('      |cFF44AAFFGetInfo: pulling', id..',', name, earnedBy)
+
+
+  self.Info[cheevID] = self.Info[cheevID] or {}
+  local c = self.Info[cheevID]
   local rewards = {}
-  print('      |cFF0088FFGetInfo|r:', watchIndex, '|cFF00FFFF', name)
 
+  c.schema = 'achievement'
   c.rewardInfo = rewards
-  c.numObjectives = numObjectives
-  c.objectives = objectives
   c.type = 'Cheevs'
   c.title = name
   c.points = points
@@ -73,44 +86,84 @@
   c.wasEarnedByMe = wasEarnedByMe
   c.earnedBy = earnedBy
 
+  local tagInfo = {}
   c.tagInfo = tagInfo
   c.watchIndex = watchIndex
   c.id = cheevID
   c.cheevID = cheevID
+
+  self.Info[cheevID] = c
   self.WatchInfo[watchIndex] = c
-  return self.Info[cheevID]
+  return c
+end
+
+Cheevs.GetObjectives = function(self, cheevID)
+  local c = self.Info[cheevID]
+  c.numObjectives = GetAchievementNumCriteria(cheevID)
+  c.objectives = c.objectives or {}
+  for i = 1, c.numObjectives do
+    local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(cheevID, i)
+    local line = c.objectives[i] or {}
+    line.objectiveIndex = i
+    line.cheevID = cheevID
+    line.text = description
+    line.type = type
+    line.finished = completed
+    line.value = quantity
+    line.maxValue = requiredQuantity
+    line.characterName = characterName
+    line.flags = flags
+    line.assetID = assetID
+    line.quantityString = quantityString
+    line.criteriaID = criteriaID
+    c.objectives[i] = line
+
+    print('        |cFF44FFDDGetObjectives:|r', i, type, description, quantityString)
+  end
 end
 
 --- Content handlers
 Cheevs.UpdateLine = function(handler, block, line, data)
   local print = B.print('CheevsLine')
   local attachment
+  local text
   line.progress = 0
   print('  ', data.objectiveIndex,'|cFF0088FF-|r', data.objectiveType, data.text)
   if data.flags then
     if band(data.flags, 0x00000001) > 0 then
       line.format = "%d/%d"
-      line.widget = T.SetWidget(line, data, 'ProgressBar', data.criteriaID)
-      line.height = line.widget.height
+      attachment = T.SetWidget(line, data, 'ProgressBar', data.criteriaID)
+      attachment.value = data.value
+      attachment.maxValue = data.maxValue
+      attachment:SetParent(handler.frame)
+
+      print(attachment:GetNumPoints())
+      for i = 1, attachment:GetNumPoints() do
+        print('  ',attachment:GetPoint(i))
+      end
+      attachment.status:SetFormattedText("%d/%d", data.value, data.maxValue)
+      attachment:SetPoint('TOP', line, 'TOP')
+      line.height = attachment.height
     elseif band(data.flags, 0x00000002) then
       line.widget = nil
+      text = line.text
     else
       line.widget = nil
       line.displayColor = 'FFFFFF'
-      line.displayText = line.text
+      text = line.text
 
     end
   else
 
     line.displayText = data.text
   end
-  print('line.type =', data.type)
-  print('  ** qtyStr:', data.quantityString, 'qty:', data.quantity, 'assetID:', data.assetID)
-  return line.displayText, line.widget
+  print('  |cFF00DD22UpdateLine:|r', data.type, data.quantityString, 'qty:', data.quantity, 'assetID:', data.assetID)
+  return text, attachment, 'default'
 end
 
 Cheevs.Select = function(self, block)
   Cheevs.Link(self, block)
+  T:Update(self.updateReasonModule, block.info.cheevID)
 end
 
 Cheevs.Remove = function(self, block)
--- a/ObjectiveTracker/AutoQuestPopups.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/AutoQuestPopups.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -12,6 +12,7 @@
 local GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetQuestLogIndexByID, GetQuestLogTitle = GetNumAutoQuestPopUps, GetAutoQuestPopUp, GetQuestLogIndexByID, GetQuestLogTitle
 --- Data retrieval
 function AutoQuest:GetNumWatched ()
+  if true then return 0, 0, nil end
   print(self.name, self)
   --Quest:GetNumWatched()
   self.numWatched = GetNumAutoQuestPopUps()
--- a/ObjectiveTracker/BonusObjectives.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/BonusObjectives.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -86,6 +86,7 @@
 Bonus.QuestBlock = {}
 Bonus.WatchInfo = {}
 function Bonus:GetNumWatched ()
+  if true then return 0, 0, nil end
   local print = iprint
   print(self.name, self)
 
@@ -257,6 +258,7 @@
     attachment.maxValue = 100
     attachment:SetPoint('TOP', line, 'TOP', 0, 0)
     attachment.status:SetFormattedText(PERCENTAGE_STRING, percent)
+    attachment:SetParent(handler.frame)
     print(attachment.status:GetText())
     print('    |cFFFF0022** text:|r', data.text, '|cFFFF0022value:|r', data.value, '|cFFFF0022max:|r', data.maxValue)
   end
--- a/ObjectiveTracker/DefaultTracker.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/DefaultTracker.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -89,20 +89,28 @@
 
 Default.UpdateTracker = function (handler, reason, id, isNew)
   local print = tprint
-  local tracker = handler.frame
+  local frame = handler.frame
   local blockIndex = 0
 
+  print(format('  |cFFFF8800UpdateTracker|r(%s): %s', handler.name, reason))
   handler.updateReason = reason
-  handler.numWatched = handler:GetNumWatched()
-  if handler.numWatched >= 1 then
+  local numWatched, numAll, watchTable = handler:GetNumWatched(id, isNew)
 
-    print('    |cFF00FF88GetNumWatched:|r',handler.name, handler.numWatched, 'of', handler.numAll)
+  if numWatched >= 1 then
+    if watchTable then
+      print('|cFF00FF00      n     ID    Obj wID Log Blk')
+      for i, w in ipairs(watchTable) do
+        print(format('     %2d => %6d %3d %3d %3s %s', i, w.id, w.numObjectives, w.watchIndex, (w.logIndex or ''), (handler.InfoBlock[w.id] and handler.InfoBlock[w.id]:GetName() or '')))
+      end
+    end
   end
 
+  handler.numWatched = numWatched
+  handler.numAll = numAll
   handler.numBlocks = 0
   handler.currentBlock = 0
-  handler.currentAnchor = tracker.titlebg
-  for blockIndex = 1, handler.numWatched do
+  handler.currentAnchor = frame.titlebg
+  for blockIndex = 1, numWatched do
     local currentBlock = handler:UpdateBlock(blockIndex, id, isNew)
     if currentBlock then
       handler:AddBlock(currentBlock)
@@ -116,39 +124,41 @@
   local numBlocks = handler.numBlocks
   local used = handler.usedBlocks
   local free = handler.freeBlocks
-  print(format('  |cFFFF8800UpdateTracker|r(%s): |cFFFF8800%04X|r --- blocks |cFFFF8800%d|r, (used/free: |cFFFF8800%d|r/|cFFFF8800%d|r)', handler.name, band(reason, handler.updateReasonModule + handler.updateReasonEvents, reason), numBlocks, #used, #free))
-  return tracker.numWatched, tracker.numAll
+  print(format('    (%s): |cFFFF8800%04X|r --- blocks |cFFFF8800%d|r, (used/free: |cFFFF8800%d|r/|cFFFF8800%d|r)', handler.name, band(reason, handler.updateReasonModule + handler.updateReasonEvents, reason), numBlocks, #used, #free))
+  return numWatched, numAll
 end
 
-Default.UpdateBlock = function (handler, blockIndex, id, added)
+Default.UpdateBlock = function (handler, index)
   local print = bprint
-  if not blockIndex then
+  if not index then
     return
   end
-  local info = handler:GetInfo(blockIndex) -- should match up with whatever the internal watch list has
+  local info = handler.WatchList[index] -- should match up with whatever the internal watch list has
   if not info then
     return
   end
-  print('  Updating |cFF00FF00'..handler.displayName..'|r|cFF00FFFF'..blockIndex..'|r|cFF0099FF', info.id ,'|r')
+  print('  Updating |cFF00FF00'..handler.displayName..'|r|cFF00FFFF'..index..'|r|cFF0099FF', info.id ,'|r')
   local frame = handler.frame
   local block = handler:GetBlock(info.id)
 
-  if added then
-    -- do something if the block is being assigned a new thing
-  end
-
   block.handler = handler
   block.info = info
 
-  info.blockIndex = blockIndex
-  if info.questID then handler.QuestBlock[info.questID] = block end
-  if info.logIndex then handler.LogBlock[info.logIndex] = block end
-  if info.watchIndex then handler.WatchBlock[info.watchIndex] = block end
-  handler.BlockInfo[blockIndex] = info
-  local newSchema = handler:UpdateObjectives(block)
-  if newSchema and newSchema ~= blockSchema then
-    T.UpdateSchema('block', newSchema)
+  info.blockIndex = index
+  if info.id then
+    print('  storing id', info.id, 'for', block:GetName())
+    handler.InfoBlock[info.id] = block
   end
+  if info.logIndex then
+    print('  storing logIndex', info.logIndex, 'for', block:GetName())
+    handler.LogBlock[info.logIndex] = block
+  end
+  if info.watchIndex then
+    print('  storing watchIndex', info.watchIndex, 'for', block:GetName())
+    handler.WatchBlock[info.watchIndex] = block
+  end
+  handler.BlockInfo[index] = info
+  handler:UpdateObjectives(block)
 
   block.title:SetText(info.title)
 
@@ -201,15 +211,20 @@
     tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'completionTag', tagPoint, tagAnchor, tagRelative)
   end
 
+  if info.schema then
+    block.schema = info.schema
+  end
+
   if info.statusKey and (Devian and Devian.InWorkspace()) then
-    block.debugText:SetText(info.statusKey)
+    block.debugText:SetText(tostring(info.statusKey) .. ' ' .. tostring(block.posIndex) .. ' '.. tostring(info.logIndex))
     block.debugText:Show()
   end
   return block
 end
 
-Default.UpdateObjectives = function(handler, block, block_schema)
+Default.UpdateObjectives = function(handler, block)
   local print = lprint
+  local block_schema = block.schema
   local info = block.info
   print('  |cFF00FF00default.objectives', block:GetName())
   -- reset the starting positions
@@ -271,10 +286,10 @@
   T:Update()
 end
 Default.Open = function(handler, block)
-  T:Update(handler.watchReasonModule)
+  T:Update(handler.updateReasonModule)
 end
 Default.Remove = function(handler, block)
-  T:Update(handler.watchReasonModule)
+  T:Update(handler.updateReasonModule)
 end
 Default.Report = function(handler, block)
   print('Stats:', handler.numWatched,'items tracked,', handler.numBlocks,'blocks assigned.')
@@ -296,7 +311,7 @@
   self.initialButton = nil
   self.modChatLink = nil
   self.modQuestWatch = nil
-  T:Update(self.handler.updateReasonModule)
+  --T:Update(self.handler.updateReasonModule)
   print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r')
 end
 Default.OnMouseDown = function(self, button)
--- a/ObjectiveTracker/Events.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Events.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -26,22 +26,19 @@
 local Quest = T.Quest
 T.RemoveQuestWatch = function(questIndex, ...)
   print('|cFFFF8800RemoveQuestWatch', questIndex, ...)
-  local block = T.Quest.LogBlock[questIndex]
-  if block then
-    block:Hide()
-  end
-  return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST
+
+  --return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST
 end
 
 T.AddTrackedAchievement = function(cheevID)
   T.CleanWidgets()
-  return OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT
+  --return OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT
 end
 
 
 T.RemoveTrackedAchievement = function(cheevID)
   T.CleanWidgets()
-  return OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT
+  --return OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT
 end
 
 T.AcceptQuest = function()
@@ -57,7 +54,7 @@
     local q = T.Quest.Info[questID]
     if q.logIndex then
       local block = T.Quest.LogBlock[q.logIndex]
-      if block and block.id == questID then
+      if block then
         block:Hide()
       end
     end
--- a/ObjectiveTracker/Frame.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Frame.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -30,7 +30,7 @@
 local orderedNames = T.orderedNames
 
 --- FRAME TEMP VARIABLES
-local wrapperWidth, wrapperHeight
+local wrapperWidth, wrapperHeight = 0, 0
 local scrollWidth, scrollHeight
 
 --- SCHEMA VARIABLES
@@ -80,26 +80,27 @@
     headerHeight, headerSpacing = c.headerHeight, c.headerSpacing
     headerColor = c.headerColor
     headerbg = c.headerbg
-    headerFont, headerSize, headerOutline = c.headerFont, c.headerSize, c.headerOutline
+    headerFont, headerSize, headerOutline = unpack(c.headerFont)
     trackerSchema = newSchema
   elseif layer == 'block' then
     titlebg = c.titlebg
-    titleFont, titleSize, titleOutline = c.titleFont, c.titleSize, c.titleOutline
+    titleFont, titleSize, titleOutline = unpack(c.titleFont)
     selectionbg = c.selectionbg
     titleSpacing, textSpacing, blockSpacing = c.titleSpacing, c.textSpacing, c.blockSpacing
-    titleIndent, textIndent,selectionIndent = 2, 5, 50
+    titleIndent, textIndent,selectionIndent = c.titleIndex, c.textIndex, c.selectionIndent
     titleColor = c.titleColor
+    print(unpack(c.titleColor))
     rewardSize = 24
-    blockSchema = newSchema
-    textFont, textSize, textOutline = c.textFont, c.textSize, c.textOutline
+    textFont, textSize, textOutline = unpack(c.textFont)
     textbg =  c.textbg
     textIndent = c.textIndent
     rewardSize = c.rewardSize
+    blockSchema = newSchema
   elseif layer == 'line' then
     textColor = c.textColor
     lineSchema = newSchema
   end
-  print('|cFFFF0088UpdateSchema:|r', layer, lastSchema[layer], '->', newSchema)
+  tprint('|cFFFF0088UpdateSchema:|r', layer, lastSchema[layer], '->', newSchema)
 end
 -- todo: figure out why objectives go invisible
 local anchorPoint, anchorFrame
@@ -146,7 +147,7 @@
 
     end)
   else
-    print('  |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint, '|rcurrent frame height:', frame.height)
+    print('  |cFF00BBFFpinning '..handler.name..' to', anchorFrame:GetName(), anchorPoint, '|rcurrent frame height:', frame.height)
     print('  |cFFFF0088total height:', wrapperHeight)
     frame:ClearAllPoints()
     frame:SetParent(Scroll)
@@ -183,37 +184,40 @@
 
   block.index = blockIndex
 
+  print('blockschema', blockSchema, block.schema)
   if blockSchema ~= block.schema then
+    T.UpdateSchema('block', block.schema)
     print('new schema detected, applicating...')
-    block.schema = blockSchema
-    block:SetWidth(T.Conf.Wrapper.Width)
-    block.title:SetSpacing(titleSpacing)
-    block.title:SetPoint('TOP', block, 'TOP', 0, -titleSpacing)
-    block.title:SetPoint('LEFT', block, 'LEFT', titleIndent, 0)
-    block.titlebg:SetTexture(1,1,1,1)
-    block.titlebg:SetGradientAlpha(unpack(titlebg))
-    block.titlebg:SetPoint('TOP', block, 'TOP', 0, 0)
-    block.titlebg:SetPoint('BOTTOM', block.title, 'BOTTOM', 0, -titleSpacing)
-    block.status:SetSpacing(textSpacing)
-    block.status:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, -textSpacing)
-    block.status:SetPoint('LEFT', block.titlebg, 'LEFT', textIndent, 0)
-    block.statusbg:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, 0)
-    block.statusbg:SetPoint('BOTTOM', block, 'BOTTOM', 0, 0)
-    block.statusbg:SetTexture(1,1,1,1)
-    block.statusbg:SetGradientAlpha(unpack(textbg))
-    block.SelectionOverlay:SetGradientAlpha(unpack(selectionbg))
-    block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0)
-    block.SelectionOverlay:SetPoint('BOTTOMRIGHT')
+  end
 
-    local anchor, target, point, x, y = 'TOPRIGHT', block, 'TOPRIGHT', -2, -2
-    for i, tile in ipairs(block.rewardTile)  do
-      print(rewardSize)
-      tile:SetSize(rewardSize, rewardSize)
-      tile:ClearAllPoints()
-      tile:SetPoint(anchor, target, point, x, y)
-      block.rewardLabel[i]:SetPoint('TOP', tile, 'TOP', 0, 0)
-      anchor, target, point, x, y = 'TOPRIGHT', tile, 'TOPLEFT', -2, 0
-    end
+  block:SetWidth(T.Conf.Wrapper.Width)
+  block.title:SetSpacing(titleSpacing)
+  block.title:SetPoint('TOP', block, 'TOP', 0, -titleSpacing)
+  block.title:SetPoint('LEFT', block, 'LEFT', titleIndent, 0)
+  block.title:SetTextColor(unpack(titleColor))
+  block.titlebg:SetTexture(1,1,1,1)
+  block.titlebg:SetGradientAlpha(unpack(titlebg))
+  block.titlebg:SetPoint('TOP', block, 'TOP', 0, 0)
+  block.titlebg:SetPoint('BOTTOM', block.title, 'BOTTOM', 0, -titleSpacing)
+  block.status:SetSpacing(textSpacing)
+  block.status:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, -textSpacing)
+  block.status:SetPoint('LEFT', block.titlebg, 'LEFT', textIndent, 0)
+  block.statusbg:SetPoint('TOP', block.titlebg, 'BOTTOM', 0, 0)
+  block.statusbg:SetPoint('BOTTOM', block, 'BOTTOM', 0, 0)
+  block.statusbg:SetTexture(1,1,1,1)
+  block.statusbg:SetGradientAlpha(unpack(textbg))
+  block.SelectionOverlay:SetGradientAlpha(unpack(selectionbg))
+  block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0)
+  block.SelectionOverlay:SetPoint('BOTTOMRIGHT')
+
+  local anchor, target, point, x, y = 'TOPRIGHT', block, 'TOPRIGHT', -2, -2
+  for i, tile in ipairs(block.rewardTile)  do
+    --print(rewardSize)
+    tile:SetSize(rewardSize, rewardSize)
+    tile:ClearAllPoints()
+    tile:SetPoint(anchor, target, point, x, y)
+    block.rewardLabel[i]:SetPoint('TOP', tile, 'TOP', 0, 0)
+    anchor, target, point, x, y = 'TOPRIGHT', tile, 'TOPLEFT', -2, 0
   end
 
 
@@ -302,6 +306,9 @@
     end
   end
   line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, -textSpacing)
+  line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0)
+  line:SetPoint('LEFT', block, 'LEFT')
+  line:SetPoint('RIGHT', block, 'RIGHT')
   line:Show()
 
 
@@ -360,7 +367,7 @@
     local line = lines[lineIndex]
     line.index = lineIndex
     line.height = 0
-    line.schema = 'default'
+    line.schema = ''
     B.SetConfigLayers(line)
 
     if debug then
@@ -377,10 +384,10 @@
 
 --- Creates or retrieves a complete block frame object
 --- todo: make it use data index to avoid re-coloring every block
-Default.GetBlock = function(handler, logIndex)
+Default.GetBlock = function(handler, index)
   local print = bprint
-  print('|cFF0088FFgetting a block for logID', logIndex ..',', #handler.usedBlocks,'used', #handler.freeBlocks, 'free')
-  local block = handler.LogBlock[logIndex]
+  print('|cFF0088FFgetting a block for index', index ..',', #handler.usedBlocks,'used', #handler.freeBlocks, 'free')
+  local block = handler.InfoBlock[index]
   local used = handler.usedBlocks
 
   if not block then
@@ -394,6 +401,7 @@
       local blockIndex = (#handler.usedBlocks + #handler.freeBlocks) + 1
       block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, handler.frame, 'VeneerTrackerBlock')
       --block:SetParent()
+      block.schema = ''
       block.lines = {}
       block.numLines = 0
       block.currentLine = 0
@@ -412,7 +420,7 @@
       block.index = blockIndex
       print('  |cFF00FFBBcreating new|r', block:GetName())
     end
-    handler.LogBlock[logIndex] = block
+    handler.InfoBlock[index] = block
     tinsert(handler.usedBlocks, block)
     block.posIndex = #handler.usedBlocks
   else
--- a/ObjectiveTracker/ObjectiveTracker.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/ObjectiveTracker.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -126,8 +126,10 @@
   freeBlocks = {},  --- blocks hidden due to list shrinkage
   usedBlocks = {},  --- block in use
   BlockInfo = {},   --- by block creation offset, used by framescript
+  WatchList = {},   --- ordered manifest of watched items
 
   --- Indexes
+  InfoBlock = {},   --- by unique ID
   LogBlock = {},    --- by API log offset, used by GetBlock if possible
   WatchBlock = {},  --- block by internal offset, used in GetBlock scope
   WatchInfo = {},   --- info by internal offset, used in Update scope
@@ -154,6 +156,7 @@
 T.Cheevs = {
   name = "Cheevs",
   displayName = "Achievements",
+  schema = 'achievement',
   updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT,
   updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT +
       OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED,
@@ -258,12 +261,12 @@
 end
 
 Event.QUEST_WATCH_LIST_CHANGED = function(questID, added)
-  if ( added ) then
+  if ( added == true ) then
     if ( not IsQuestTask(questID) ) then
       return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added
     end
-  else
-    return OBJECTIVE_TRACKER_UPDATE_QUEST, questID, added
+  elseif questID then
+    return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added
   end
 end
 
@@ -274,8 +277,8 @@
   end
   return OBJECTIVE_TRACKER_UPDATE_ALL
 end
-Event.SUPER_TRACKED_QUEST_CHANGED = function()
-  return OBJECTIVE_TRACKER_UPDATE_QUEST
+Event.SUPER_TRACKED_QUEST_CHANGED = function(questID)
+  return OBJECTIVE_TRACKER_UPDATE_QUEST, questID
 end
 Event.ZONE_CHANGED = function()
   local inMicroDungeon = IsPlayerInMicroDungeon();
@@ -306,11 +309,7 @@
   return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT
 end
 Event.TRACKED_ACHIEVEMENT_LIST_CHANGED = function(achievementID, added)
-  if ( added ) then
-    return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, achievementID
-  else
-    return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT
-  end
+  return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, achievementID, added
 end
 Event.ZONE_CHANGED_NEW_AREA = function ()
   if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then
@@ -452,38 +451,26 @@
 
 local Play = function(file) if Devian and Devian.InWorkspace() then PlaySoundFile(file) end end
 
+local tprint = B.print('Tracker')
 T.OnHookedFunc = function(name, ...)
-  print('|cFFFF8800securehook:|r', name, '|cFF00FFFFargs:|r', ...)
-  local updateReason = T[name](...)
+  tprint('|cFFFF8800securehook:|r', name, '|cFF00FFFFargs:|r', ...)
+  local updateReason, arg1, arg2, arg3 = T[name](...)
   if updateReason then
-    print('|cFF00FFFFupdate reason:|r', updateReason)
-    T:Update(updateReason)
+    print('|cFF00FFFFupdate reason:|r', updateReason, arg1, arg2, arg3)
+    T:Update(updateReason, arg1, arg2, arg3)
   end
 end
 
 function T:OnEvent (event, ...)
   local isHandled
-  print('OnEvent(|cFF00FF00'.. event ..'|r):', ...)
+  tprint('OnEvent(|cFF00FF00'.. event ..'|r):', ...)
   local reason, arg1, arg2, arg3
   if Event[event] then
     if type(Event[event]) == 'function' then
       Play([[Interface\Addons\SharedMedia_MyMedia\sound\Info.ogg]])
       reason, arg1, arg2, arg3 = Event[event](...)
-    elseif type(Event[event]) == 'table' then
-      Play([[Interface\Addons\SharedMedia_MyMedia\sound\Link.ogg]])
-      for i, action in ipairs(Event[event]) do
-        if type(action) == 'function' then
-          reason, arg1, arg2, arg3 = action(event, ...)
-        else
-          reason = action
-        end
-
-        if reason then
-          T:Update(reason, arg1, arg2, arg3)
-        end
-      end
     else
-      --Play([[Interface\Addons\SharedMedia_MyMedia\sound\Heart.ogg]])
+      Play([[Interface\Addons\SharedMedia_MyMedia\sound\Heart.ogg]])
       reason = Event[event]
     end
   else
--- a/ObjectiveTracker/ObjectiveTracker.xml	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/ObjectiveTracker.xml	Mon Apr 18 07:56:23 2016 -0400
@@ -103,6 +103,30 @@
         </Layers>
       </Frame>
 
+
+
+      <Frame name="$parentClock" parentKey="Clock" hidden="false">
+        <Anchors>
+          <Anchor point="TOPRIGHT" x="-75" y="0" />
+        </Anchors>
+        <Layers>
+          <Layer level="OVERLAY">
+            <FontString inherits="VeneerNumberFont" parentKey="time" text="GAME_TIME">
+              <Anchors>
+                <Anchor point="TOPRIGHT" />
+              </Anchors>
+              <Color r="1" g="1" b="1" a="1" />
+            </FontString>
+          </Layer>
+        </Layers>
+        <Scripts>
+          <OnUpdate>
+            local hour, min = GetGameTime()
+            self.time:SetFormattedText("%d:%d", hour, min)
+          </OnUpdate>
+        </Scripts>
+      </Frame>
+
       <Button name="$parentCloseButton" parentKey="CloseButton" enableMouse="true" frameStrata="MEDIUM">
         <Size x="16" y="16" />
         <HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
@@ -123,7 +147,6 @@
 
 
 
-
   <Frame name="$parentXP" parent="VeneerObjectiveWrapper" parentKey="XPBar" hidden="true">
     <Size x="250" y="24" />
     <Anchors>
--- a/ObjectiveTracker/Quests.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Quests.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -9,12 +9,10 @@
 local QUEST_TAG_ACCOUNT, LE_QUEST_FACTION_HORDE, LE_QUEST_FREQUENCY_DAILY, LE_QUEST_FREQUENCY_WEEKLY = QUEST_TAG_ACCOUNT, LE_QUEST_FACTION_HORDE, LE_QUEST_FREQUENCY_DAILY, LE_QUEST_FREQUENCY_WEEKLY
 local QUEST_TAG_TCOORDS, IsQuestSequenced = QUEST_TAG_TCOORDS, IsQuestSequenced
 local Default, Quest = T.DefaultHandler, T.Quest
-local format = format
-local print = B.print('Tracker')
-local lprint = B.print('Line')
-local iprint = B.print('Info')
-local colors = T.colors
-local tprint = B.print('Tracker')
+local format, wipe, select = format, table.wipe, select
+local wipeall = B.wipeall
+local lprint, iprint, tprint = B.print('Line'), B.print('Info'), B.print('Tracker')
+local print = tprint
 
 local superTrackQuestID, playerMoney, inScenario, showPOIs
 Quest.Update = function(self, reason, ...)
@@ -79,39 +77,166 @@
 
 -----------------------------
 --- QUEST
+local tremove, tinsert = tremove, tinsert
+local GetQuestLogIndexByID, IsQuestWatched = GetQuestLogIndexByID, IsQuestWatched
 Quest.QuestBlock = {}
 Quest.LogBlock = {}
 Quest.LogInfo = {}
+function Quest:FreeBlock (block)
+  local used = Quest.usedBlocks
+  local free = Quest.freeBlocks
+  local reason = ''
+  local doRelease = false
+  local info = block.info
+  local questID = info.questID
+  local logIndex = info.logIndex
 
-function Quest:GetNumWatched ()
+  if info.posIndex then
+    if used[info.posIndex] == block then
+      doRelease = true
+      reason = 'posIndex mismatch'
+    end
+  elseif logIndex then
+    if not IsQuestWatched(logIndex) then
+      reason = 'not being watched'
+    elseif not self.LogBlock[logIndex] then
+      doRelease = true
+      reason = 'missing logBlock entry'
+    elseif (self.LogBlock[logIndex] ~= block) then
+      doRelease = true
+      reason = 'different block using index'
+    end
+  elseif info.questID then
+    if not GetQuestLogIndexByID(info.questID) then
+      doRelease = true
+      reason = 'no identifiable quest log entry'
+    end
+  end
+
+
+  if doRelease then
+    print('  |cFF00FF00FreeBlock (' .. block:GetName() .. '):', reason)
+    block:Hide()
+    tremove(used, info.posIndex)
+    tinsert(free, block)
+  end
+
+
+end
+local watchesChecked = {}
+local infosChecked = {}
+local blocksChecked = {}
+local GetQuestWatchIndex = GetQuestWatchIndex
+--- Get a total of things to show, and straighten out the index while we're at it
+--- Return the number shown, total in log, and the info table to parse
+Quest.GetNumWatched = function (self, id, added)
   superTrackQuestID = GetSuperTrackedQuestID()
   playerMoney = GetMoney();
   inScenario = C_Scenario.IsInScenario();
   showPOIs = GetCVarBool("questPOI");
-  self.numAll = GetNumQuestLogEntries()
-  self.numWatched = GetNumQuestWatches()
-  return self.numWatched, self.numAll
+  local numAll = GetNumQuestLogEntries()
+  local numWatched = GetNumQuestWatches()
+  local bottomIndex = 1
+  print('    |cFF00FF88GetNumWatched:|r',self.name, numWatched, 'of', numAll)
+  local start, limit = 1, numAll
+
+  --- start a list of blocks affected by this function
+  wipe(blocksChecked)
+  if id and not added then
+    if self.InfoBlock[id] then
+      tinsert(blocksChecked, self.InfoBlock[id])
+    end
+  end
+
+  for logIndex = start, limit do
+    local reason1, reason2 = '', ''
+    local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(logIndex)
+    local watchIndex = GetQuestWatchIndex(logIndex)
+
+    if watchIndex and watchIndex >= bottomIndex then
+      local watchInfo = self.WatchInfo[watchIndex]
+      local watchBlock = self.WatchBlock[watchIndex]
+      if watchInfo and watchInfo.questID ~= questID then
+        print('    |cFFBBFF00GetNumWatched: trimming WatchInfo ['..watchIndex..'] =/=', questID)
+        self.WatchInfo[watchIndex] = nil
+      end
+      if watchBlock and watchBlock.info.questID ~= questID then
+        print('    |cFFBBFF00GetNumWatched: trimming WatchBlock ['..watchIndex..'] =/=', watchBlock:GetName())
+        self.WatchBlock[watchIndex] = nil
+        tinsert(blocksChecked, watchBlock)
+      end
+    end
+
+    local logBlock = self.LogBlock[logIndex]
+    if logBlock and logBlock.info.questID ~= questID then
+      --print('    |cFFBBFF00GetNumWatched: trimming LogBlock ['..logIndex..'] =/=', logBlock:GetName())
+      self.LogBlock[logIndex] = nil
+      tinsert(blocksChecked, logBlock)
+    end
+
+    if questID ~= 0 then
+      self.Info[questID] = self:GetInfo(logIndex, watchIndex)
+      --print('    |cFF44BBFFGetNumWatched:|r map', questID, 'to', logIndex, (watchIndex and ('('..watchIndex..')') or ''))
+    end
+  end
+
+  --- remove any orphaned blocks from view and, if possible, free it for re-use
+  for i, block in ipairs(blocksChecked) do
+    if not GetQuestLogIndexByID(block.info.questID, 'player') then
+      print('    |cFFBBFF00GetNumWatched:|r literating a block without an index |cFFBBFF00'.. block:GetName()..'|r')
+      block:Hide()
+      self:FreeBlock(block)
+    end
+    if not IsQuestWatched(block.info.logIndex) then
+      print('    |cFFBBFF00GetNumWatched:|r hiding untracked quest |cFFBBFF00'.. block:GetName()..'|r')
+      block:Hide()
+    end
+  end
+
+  self.numWatched = numWatched
+  self.numAll = numAll
+
+  return numWatched, numAll, self.WatchList
 end
 
+
 --- Returns an iterable table from which tracker blocks can be filled out. Data includes:
 -- All entry-layer GetXInfo return values
 -- Manifest of line data to be displayed in relation to the tracked object
-Quest.GetInfo = function (self, watchIndex)
+Quest.GetInfo = function (self, logIndex, watchIndex)
   local print = iprint
-
-  local questID, title, questLogIndex, numObjectives, requiredMoney, isComplete, startEvent, isAutoComplete,
-    failureTime, timeElapsed, questType, isTask, isStory, isOnMap, hasLocalPOI = GetQuestWatchInfo(watchIndex)
+  local title, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, questID, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(logIndex)
   if ( not questID ) then
+    tprint('      |cFFFF0088GetInfo:|r', logIndex, watchIndex, '|cFFFF2299no data|r')
     return
   end
 
-  tprint('      |cFFFFBB00GetInfo:|r', watchIndex, '|cFFFF2299'..title..'|r')
-  local _, level, suggestedGroup, isHeader, isCollapsed, isComplete, frequency, _, startEvent, displayQuestID, isOnMap, hasLocalPOI, isTask, isStory = GetQuestLogTitle(questLogIndex)
+  Quest.Info[questID] = Quest.Info[questID] or {}
+  local q = Quest.Info[questID]
+  q.questID = questID
+  q.id = questID
+  q.logIndex = logIndex
+  q.watchIndex = watchIndex
 
-  Quest.Info[questID] = Quest.Info[questID] or {}
+  local numObjectives, requiredMoney, isAutoComplete, failureTime, timeElapsed, questType
+   = 0, 0, nil, false, false, 0
+  if watchIndex then
+    local _
+    _,_,_, numObjectives, requiredMoney, _, _, isAutoComplete,
+    failureTime, timeElapsed, questType = GetQuestWatchInfo(watchIndex)
+    self.WatchList[watchIndex] = q
+    --tprint('      |cFF88FF00GetInfo:|r set watch entry', watchIndex)
+    tprint('      |cFFFFBB00GetInfo:|r', logIndex, watchIndex, '|cFFFF2299'..title..'|r')
+  end
+  self.LogInfo[logIndex] = q
 
+  q.numObjectives = numObjectives
+  q.requiredMoney = requiredMoney
+  q.failureTime = failureTime
+  q.timeElapsed = timeElapsed
 
-  local q = Quest.Info[questID]
+
+
   q.type = 'Quest'
   q.title = title
   q.level = level
@@ -174,7 +299,7 @@
     -- Case 3: quest in progress
     -- * Multiple objective lines
     -- * Possible extra lines for money and timer data respectively
-    objectives = Quest.GetObjectives(questLogIndex, numObjectives, false, isSequenced, isStory)
+    objectives = Quest.GetObjectives(logIndex, numObjectives, false, isSequenced, isStory)
     q.objectives = objectives
 
     --- anything past here gets appended to existing objectives
@@ -208,13 +333,9 @@
       end
     end
   end
-  q.numObjectives = numObjectives
   q.objectives = objectives
-  q.requiredMoney = requiredMoney
   q.moneyInfo = moneyInfo
   q.timerInfo = timerInfo
-  q.failureTime = failureTime
-  q.timeElapsed = timeElapsed
   q.completionText = completionText
 
   -- POI data
@@ -222,7 +343,8 @@
   if ( showPOIs ) then
     POI = {
       questID = questID,
-      questLogIndex = questLogIndex,
+      logIndex = logIndex,
+      watchIndex = watchIndex
     }
     local poiButton;
     if ( hasLocalPOI ) then
@@ -236,7 +358,7 @@
       POI.type = 'remote'
     end
 
-    local distance, onContinent = GetDistanceSqToQuest(questLogIndex)
+    local distance, onContinent = GetDistanceSqToQuest(logIndex)
     if distance ~= nil and distance > 0 then
       POI.distance = distance
       POI.onContinent = onContinent
@@ -248,6 +370,7 @@
   -- completionTag  - in progres, complete, failed, autocomplete
   -- typeTag        - account, faction, pvp, dungeon, group
   -- frequencyTag   - daily/weekly
+  local schema = 'default'
   local questTagID, tagName = GetQuestTagInfo(questID)
   local tagInfo = {}
   local tagCoords = {}
@@ -255,8 +378,10 @@
   if( questTagID and questTagID == QUEST_TAG_ACCOUNT ) then
     if( factionGroup ) then
       tagID = "ALLIANCE"
+      schema = 'alliance'
       if ( factionGroup == LE_QUEST_FACTION_HORDE ) then
         tagID = "HORDE"
+        schema = 'horde'
       end
       isFaction = true
     else
@@ -280,11 +405,13 @@
     tagInfo['frequencyTag'] = tagID
     tagCoords['frequencyTag'] = QUEST_TAG_TCOORDS[tagID]
     isDaily = true
+    schema = 'daily'
   elseif( frequency == LE_QUEST_FREQUENCY_WEEKLY and (not isComplete or isComplete == 0) )then
     tagID = 'WEEKLY'
     tagInfo['frequencyTag'] = tagID
     tagCoords['frequencyTag'] = QUEST_TAG_TCOORDS[tagID]
     isWeekly = true
+    schema = 'weekly'
   elseif( questTagID ) then
     tagID = questTagID
   end
@@ -303,12 +430,12 @@
   q.tagName = tagName
 
   -- action button information
-  local link, icon, charges = GetQuestLogSpecialItemInfo(questLogIndex)
-  local start, duration, enable = GetQuestLogSpecialItemCooldown(questLogIndex)
+  local link, icon, charges = GetQuestLogSpecialItemInfo(logIndex)
+  local start, duration, enable = GetQuestLogSpecialItemCooldown(logIndex)
   if link or icon or charges then
     q.specialItem = {
       questID = questID,
-      questLogIndex = questLogIndex,
+      logIndex = questLogIndex,
       link = link,
       charges = charges,
       icon = icon,
@@ -341,14 +468,13 @@
   T.SetRewards(q, questID)
 
   q.questID = questID
-  q.logIndex = questLogIndex
+  q.logIndex = logIndex
   q.watchIndex = watchIndex
   q.id = questID
-  self.WatchInfo[watchIndex] = q
-  self.LogInfo[questLogIndex] = q
+  q.schema = schema
 
   if Devian and Devian.InWorkspace() then
-    print('|cFF00DDFFstatus:|r', temp_status, '|cFF00FF00questLogIndex|r:', questLogIndex, title)
+    print('|cFF00DDFFstatus:|r', temp_status, '|cFF00FF00questLogIndex|r:', logIndex, title)
     local temp  ={}
     local data_txt = '|cFFFF4400values:|r'
     for k,v in pairs(q) do
@@ -371,10 +497,10 @@
   return q
 end
 
-Quest.GetObjectives = function(questLogIndex, numObjectives, isComplete, isSequenced, isStory)
+Quest.GetObjectives = function(logIndex, numObjectives, isComplete, isSequenced, isStory)
   local objectives = {}
   for i = 1, numObjectives do
-    local text, type, finished = GetQuestLogLeaderBoard(i, questLogIndex)
+    local text, type, finished = GetQuestLogLeaderBoard(i, logIndex)
     print(format('      |cFFFF4400GetObjectives:|r #%d %s %s %s', i, tostring(type), tostring(text), tostring(finished)))
     objectives[i] = {
       index = i,
--- a/ObjectiveTracker/Scenarios.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Scenarios.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -6,8 +6,9 @@
 local B = select(2,...).frame
 local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
 
-local Scenario = Module.Scenario
+local Scenario = T.Scenario
 
 Scenario.GetNumWatched = function()
+  if true then return 0, 0, nil end
 end
 
--- a/ObjectiveTracker/Schema.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Schema.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -7,22 +7,38 @@
 local B = select(2,...).frame
 local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
 local setmetatable, type, rawset = setmetatable, type, rawset
-local print = B.print('Schema')
+local print = B.print('Tracker')
+local lprint = B.print('Layout')
+local oprint = B.print('Objectives')
 T.defaults.Schema = setmetatable({}, {
   __newindex = function(schemas,layerName, layerTable)
     -- tracker/block/line
     if type(layerTable) == 'table' then
+
+      print('adding layer', layerName)
+      for k,v in pairs(layerTable) do
+        print('  incorporated schema', k)
+        if type(v) == 'table' and k ~= 'default' then
+          setmetatable(v, {
+            __index = function(schemaTable, key)
+              print('  substituting default "'..tostring(schemas[layerName].default[key])..'" for |cFF00FFFF', layerName..'|r.|cFF0088FF'..k..'|r.'..key)
+              return schemas[layerName].default[key]
+            end
+          })
+        end
+      end
       rawset(schemas, layerName, setmetatable(layerTable, {
-        __index = function(layerTable, schemaName)
-
-        end,
         __newindex = function(layerTable, schemaName, schemaTable)
           -- schema table
           if type(schemaTable) == 'table' then
+            print('adding schema', schemaName, 'to', layerName, 'layers')
+
+
             rawset(layerTable, schemaName, setmetatable(schemaTable, {
               __index = function(schemaTable, key)
-                print('substituting a default value for |cFF00FFFF', layerName..'|r.|cFF0088FF'..schemaName..'|r.'..key)
-                return layerTable.default[key]
+                print('  substituting default "'..tostring(schemas[layerName].default[key])..'" for |cFF00FFFF', layerName..'|r.|cFF0088FF'..schemaName..'|r.'..key)
+                rawset(schemaTable, key, schemas[layerName].default[key])
+                return schemas[layerName].default[key]
               end
             }))
           end
@@ -32,81 +48,89 @@
   end
 })
 
-T.defaults.Schema = {
-  tracker = {
-    default = {
-      headerbg = {'VERTICAL', 1, 1, 0.5, 0.5, 1, 1, 0.5, 0},
-      headerFont = {[[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 14, 'OUTLINE'},
-      blockSpacing = 1,
-    }
+T.defaults.Schema.tracker = {
+  default = {
+    headerbg = {'VERTICAL', 1, 1, 0.5, 0.5, 1, 1, 0.5, 0},
+    headerFont = {[[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 14, 'OUTLINE'},
+    blockSpacing = 1,
+  }
+}
+T.defaults.Schema.block = {
+  default = {
+    titleColor = {1, 0.7, 0, 1},
+    titlebg = {'HORIZONTAL', 1, 0, .7, 0,    1, 0, .7, .125},
+    textbg = {'HORIZONTAL', 0, 0, 0, 0,      0, 0, 0, 0.4 },
+    selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225},
+    titleFont = {[[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE'},
+    textFont = {[[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE'},
+    titleIndent = 4,
+    titleSpacing = 3,
+    selectionIndent = 5,
+    textIndent = 3,
+    textSpacing = 3,
+    rewardSize = 24,
   },
-  block = {
-    default = {
-      titlebg = {'HORIZONTAL', 1, 0, .7, 0,    1, 0, .7, .125},
-      textbg = {'HORIZONTAL', 0, 0, 0, 0.4,      0, 0, 0, 0 },
-      selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225},
-      titleFont = {[[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE'},
-      textFont = {[[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE'},
-      titleIndent = 4,
-      titleSpacing = 3,
-      textIndent = 3,
-      textSpacing = 3,
-      rewardSize = 24,
-    },
-    daily = {
-      titlebg = {'HORIZONTAL', 0, .7, 1, .25,  0, 1, .7, .125},
-      textbg = {'HORIZONTAL', 0, .7, 1, .1,    0, 1, .7, .075 },
-    },
-    weekly = {
-      titlebg = {'HORIZONTAL', 0, .35, .7, .25,   0, .35, .7, .125},
-      textbg = {'HORIZONTAL', 0, .35, .7, .1,     0, .35, .7, .075 },
-    },
-    account = {
-      titlebg = {'HORIZONTAL', .1, .1, .1, .25, .1, .1, .1, .125},
-      textbg = {'HORIZONTAL', .1, .1, .1, 0.4, .1, .1, .1, .085 },
-    },
-    -- alliance
-    faction_1 = {
-      titlebg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 },
-      textbg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 },
-    },
-    -- horde
-    faction_2 = {
-      titlebg = {'HORIZONTAL', .6, 0, 0.4, 0.4,  .6, 0, 0.4, .085 },
-      textbg = {'HORIZONTAL', .6, 0, 0.4, 0.4,   .6, 0, 0.4, .085 },
-    }
+  achievement = {
+    titleColor = {0, 0.7, 1, 1},
   },
-  line = {
-    default  = {
-      textColor = {.5,.75,1},
-      textSpacing = 3,
-      textIndent = 3,
-    },
-    completed = {
-      textColor = {0, 1, 0}
-    },
-    failed = {
-      textColor = {1,0,0 }
-    },
-    autocomplete = {
-      textColor = {0,1,0 }
-    },
-    objectColor = {
-      textColor = {0,1,1}
-    },
-    monster = {
-      textColor = {1,1,0}
-    },
-    item = {
-      textColor = {1,.25,.5}
-    }
+  achievement_account = {
+    titleColor = {.35, 0.7, 1, 1},
   },
-  widget = {
-    progressbar = {
+  daily = {
+    titleColor = {0, 0.7, 1, 1},
+    titlebg = {'HORIZONTAL', 0, .7, 1, .25,  0, 1, .7, .125},
+    textbg = {'HORIZONTAL', 0, .7, 1, .075,    0, 1, .7, .1},
+  },
+  weekly = {
+    titleColor = {.25, 0.7, 1, 1},
+    titlebg = {'HORIZONTAL', 0, .35, .7, .25,   0, .35, .7, .125},
+    textbg = {'HORIZONTAL', 0, .35, .7, .1,     0, .35, .7, .075 },
+  },
+  account = {
+    titlebg = {'HORIZONTAL', .1, .1, .1, .25, .1, .1, .1, .125},
+    textbg = {'HORIZONTAL', .1, .1, .1, 0.4, .1, .1, .1, .085 },
+  },
+  -- alliance
+  faction_1 = {
+    titlebg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 },
+    textbg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 },
+  },
+  -- horde
+  faction_2 = {
+    titlebg = {'HORIZONTAL', .6, 0, 0.4, 0.4,  .6, 0, 0.4, .085 },
+    textbg = {'HORIZONTAL', .6, 0, 0.4, 0.4,   .6, 0, 0.4, .085 },
+  }
+}
+T.defaults.Schema.line = {
+  default  = {
+    textColor = {.5,.75,1},
+    textSpacing = 3,
+    textIndent = 3,
+  },
+  completed = {
+    textColor = {0, 1, 0}
+  },
+  failed = {
+    textColor = {1,0,0 }
+  },
+  autocomplete = {
+    textColor = {0,1,0 }
+  },
+  objectColor = {
+    textColor = {0,1,1}
+  },
+  monster = {
+    textColor = {1,1,0}
+  },
+  item = {
+    textColor = {1,.25,.5}
+  }
+}
+T.defaults.Schema.widget = {
+  progressbar = {
 
-    },
-    timer = {
+  },
+  timer = {
 
-    }
-  },
+  }
 }
\ No newline at end of file
--- a/ObjectiveTracker/Widgets.lua	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Widgets.lua	Mon Apr 18 07:56:23 2016 -0400
@@ -392,7 +392,7 @@
 
 }
 
-local progressHeight = 8
+local progressHeight = 17
 local progressBorder = 1
 local progressFont = _G.VeneerCriteriaFontNormal
 
@@ -412,7 +412,7 @@
   self.fg:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', progressBorder, progressBorder)
   self.fg:SetHeight(progressHeight - progressBorder *  2)
 
-  self.status:SetFontObject(progressFont)
+  --self.status:SetFontObject(progressFont)
   self.status:SetText(self.objective.quantityString)
 end
 
--- a/ObjectiveTracker/Widgets.xml	Sun Apr 17 13:00:31 2016 -0400
+++ b/ObjectiveTracker/Widgets.xml	Mon Apr 18 07:56:23 2016 -0400
@@ -41,9 +41,9 @@
         </Texture>
       </Layer>
       <Layer level="OVERLAY">
-        <FontString name="$parentStatus" parentKey="status" inherits="VeneerCriteriaFont">
+        <FontString name="$parentStatus" parentKey="status" inherits="VeneerNumberFontSmall">
           <Anchors>
-            <Anchor point="TOPLEFT" />
+            <Anchor point="CENTER" />
           </Anchors>
         </FontString>
       </Layer>