diff ObjectiveTracker/Frame.lua @ 34:9856ebc63fa4

- half solution to Update being fired multiple times during load - change securefunc handlers to dispense a reason code; catch that reason code in the enclosure passed to hooksecurefunc, and decide whether to update or not from there.
author Nenue
date Sun, 17 Apr 2016 00:21:45 -0400
parents 64f2a9bbea79
children 69d03f8e293e
line wrap: on
line diff
--- a/ObjectiveTracker/Frame.lua	Fri Apr 15 17:01:06 2016 -0400
+++ b/ObjectiveTracker/Frame.lua	Sun Apr 17 00:21:45 2016 -0400
@@ -6,7 +6,7 @@
 local B = select(2,...).frame
 local Module = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
 local _G, ipairs, max, min, unpack, floor, pairs, tostring, type, band = _G, ipairs, max, min, unpack, floor, pairs, tostring, type, bit.band
-local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion
+local IsResting, UnitXP, UnitXPMax, GetXPExhaustion, tinsert, tremove = IsResting, UnitXP, UnitXPMax, GetXPExhaustion, table.insert, table.remove
 local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent
 local GetAutoQuestPopUp, GetQuestLogCompletionText = GetAutoQuestPopUp, GetQuestLogCompletionText
 local PERCENTAGE_STRING, GetQuestProgressBarPercent = PERCENTAGE_STRING, GetQuestProgressBarPercent
@@ -14,76 +14,91 @@
 local InCombatLockdown, format, lshift, CreateFrame = InCombatLockdown, format, bit.lshift, CreateFrame
 local IsModifiedClick, ChatEdit_GetActiveWindow = IsModifiedClick, ChatEdit_GetActiveWindow
 local print = B.print('Tracker')
+local oprint = B.print('Objectives')
+local bprint = B.print('Block')
+local tprint = B.print('Tracker')
+local lprint = B.print('Line')
 local unitLevel = 1
 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_REASON
 local debug = false
 
---- Upvalues
+--- FRAMES
 local Wrapper = _G.VeneerObjectiveWrapper
 local Scroller = Wrapper.scrollArea
 local Scroll = _G.VeneerObjectiveScroll
 local orderedHandlers = Module.orderedHandlers
 local orderedNames = Module.orderedNames
 
---- Temp values set during updates
+--- FRAME TEMP VARIABLES
 local wrapperWidth, wrapperHeight
 local scrollWidth, scrollHeight
-local previousBlock
-local currentBlock
---- todo: source these from config
+
+--- SCHEMA VARIABLES
+local schemaName, lastSchema = {
+  tracker = '',
+  block = '',
+  line = ''
+}, {}
+local trackerSchema, blockSchema, lineSchema
+
 local itemButtonSize, itemButtonSpacing =  36, 1
+local wrapperMaxWidth, wrapperMaxHeight = 270, 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 wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0 }
+local rewardSize = 24
 
 local headerHeight, headerColor, headerSpacing = 16, {1,.75,0,1}, 2
 local headerbg = {'VERTICAL', 1, 1, 0.5, 0.5, 1, 1, 0.5, 0}
 local headerFont, headerSize, headerOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 14, 'OUTLINE'
 
 local titlebg = {'HORIZONTAL', 1, 0, .7, 0, 1, 0, .7, .2}
-local titlebg_daily = {'HORIZONTAL', 0, .7, 1, 0, 0, 1, .7, .2 }
-local titlebg_account = {'HORIZONTAL', 0, .45, 1, 0, 0,  .45, 1, .2}
 local titleFont, titleSize, titleOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE'
+local titleColor = {0,.7,1,1}
 
 local textbg =  {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 }
-local textbg_daily = {'HORIZONTAL', 0, .7, 1, .1, 0, 1, .7, .075 }
-local textbg_account = {'HORIZONTAL', 0, .45, 1, 0.4, 0,  .41, 1, .085 }
 local textFont, textSize, textOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE'
-
+local textColor = {1,1,1,1}
 
 local selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225}
 local titleSpacing, textSpacing, blockSpacing = 3, 3, 1
 local titleIndent, textIndent,selectionIndent = 2, 5, 50
+--- END SCHEMA
+--- schema swapper
+Module.UpdateSchema = function(layer, newSchema)
+  if not (Module.Conf.Schema[layer] and Module.Conf.Schema[layer][newSchema]) then
+    return
+  elseif schemaName[layer] == newSchema then
+    return
+  end
+  lastSchema[layer] = schemaName[layer]
+  schemaName[layer] = newSchema
+  local c = Module.Conf.Schema[layer][newSchema]
 
-local lineColors = {
-  normal = {
-    text = {.5,.75,1},
-  },
-  completed = {
-    text = {0, 1, 0}
-  },
-  failed = {
-    text = {1,0,0 }
-  },
-  autocomplete = {
-    text = {0,1,0 }
-  },
-  object = {
-    text = {0,1,1}
-  },
-  monster = {
-    text = {1,1,0}
-  },
-  item = {
-    text = {1,.25,.5}
-  }
-}
-
-local wrapperMaxWidth, wrapperMaxHeight = 270, 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 wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0 }
-local rewardSize = 24
-local oprint = B.print('Objectives')
-local bprint = B.print('Block')
-local tprint = B.print('Tracker')
-local lprint = B.print('Line')
+  if layer == 'tracker' then
+    headerHeight, headerSpacing = c.headerHeight, c.headerSpacing
+    headerColor = c.headerColor
+    headerbg = c.headerbg
+    headerFont, headerSize, headerOutline = c.headerFont, c.headerSize, c.headerOutline
+    trackerSchema = newSchema
+  elseif layer == 'block' then
+    titlebg = c.titlebg
+    titleFont, titleSize, titleOutline = c.titleFont, c.titleSize, c.titleOutline
+    selectionbg = c.selectionbg
+    titleSpacing, textSpacing, blockSpacing = c.titleSpacing, c.textSpacing, c.blockSpacing
+    titleIndent, textIndent,selectionIndent = 2, 5, 50
+    titleColor = c.titleColor
+    rewardSize = 24
+    blockSchema = newSchema
+    textFont, textSize, textOutline = c.textFont, c.textSize, c.textOutline
+    textbg =  c.textbg
+    textIndent = c.textIndent
+    rewardSize = c.rewardSize
+  elseif layer == 'line' then
+    textColor = c.textColor
+    lineSchema = newSchema
+  end
+  print('|cFFFF0088UpdateSchema:|r', layer, lastSchema[layer], '->', newSchema)
+end
 
 Default.AddBlock = function(self, block, blockIndex)
   local blockIndex = blockIndex or (self.currentBlock + 1)
@@ -91,6 +106,47 @@
   local tracker = self.frame
   local info = block.info
 
+  if blockSchema ~= block.schema then
+    print('new schema detected, applicating...')
+    block.schema = blockSchema
+    block:SetWidth(Module.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')
+
+    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
+  end
+
+  if block.debug then
+    local func = (B.Conf.GuidesMode == true) and 'Show' or 'Hide'
+    for _, region in ipairs(block.debug) do
+      region[func]()
+    end
+  end
+
+  -- positioned by offset since they tend to swap contents
   block.index = blockIndex
   block:SetPoint('TOPLEFT', self.frame, 'TOPLEFT', 0, block.offset)
   block:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
@@ -98,7 +154,6 @@
   self.currentAnchor = block
   print('    |cFFFFFF00'..tracker.height..'|r', '|cFF00FF00'..block:GetName()..'|r', block.height, tracker.height)
   tracker.height = tracker.height + block.height
-  self.numBlocks = max(self.numBlocks, blockIndex)
   self.actualBlocks = self.actualBlocks + 1
 end
 
@@ -125,42 +180,46 @@
 Default.AddLine = function(handler, block, text, attachment, template)
   local print = lprint
   local lineIndex = block.currentLine + 1
-  local line = handler:GetLine(block)
+  local line = handler:GetLine(block, lineIndex)
   line.index = lineIndex
-  line:ClearAllPoints()
-  line:SetPoint('LEFT', block, 'LEFT', 0, 0)
-  line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, 0)
-  line:SetPoint('RIGHT', block, 'RIGHT', 0, 0)
+  if line.schema ~= template then
+    print('  |cFF00FF00change schema', template)
+    Module.UpdateSchema('line', template)
+    line.status:SetSpacing(textSpacing)
+    line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0)
+    line.status:SetPoint('RIGHT', line, 'RIGHT', -textIndent, 0)
+    line.status:SetTextColor(unpack(textColor))
+    line.schema = template
+  else
+    print('  |cFFFFFF00keep schema', template)
+  end
+  line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, -textSpacing)
   line:Show()
 
-  print('     |cFF0088FFAddLine >>|r', block, '::',  block.endPoint:GetName(),'"'.. text .. '"', attachment, template)
+
+  print(' |cFF0088FFAddLine >>|r', block, '::',  block.endPoint:GetName(),'"'.. text .. '"', attachment, template)
+
+
+  -- fill in the text, then derive pixel-rounded height
   line.status:SetText(text)
-  line.height = floor(line.status:GetStringHeight()+.5) + textSpacing
-  line:SetHeight(line.height)
-
-  local r, g, b, a = 1, 1, 1, 1
-  if lineColors[template] then
-    r, g, b = unpack(lineColors[template].text)
-  end
-  line.status:SetTextColor(r, g, b, a)
+  line.height = floor(line.status:GetStringHeight()+.5)
 
   -- For progressbar and timer lines, status text may be used as the title heading
   if attachment then
-    local widgetOffset = 0
-    line.height = attachment:GetHeight() + textSpacing
-    if text and #text >= 1 then
-      widgetOffset = line.status:GetHeight() + textSpacing
-      line.height = line.height + floor(line.status:GetStringHeight()+.5) + textSpacing
-      print('     |cFFFF0088doing things with captioned widget')
-    else
-      print('     |cFFFF0088doing things with a widget')
+    print('  |cFFFF0088doing things with a widget', attachment:GetSize())
+    line.height = attachment:GetHeight()
+    if text then
+      line.height = max(line.height, line.status:GetStringHeight())
     end
-    attachment:SetPoint('TOP', line, 'TOP', 0, -widgetOffset)
+    if attachment.status:GetText() then
+      line.height = max(line.height, attachment.status:GetStringHeight())
+    end
     attachment:Show()
   end
 
-  block.attachmentHeight = block.attachmentHeight + line.height
-  print('     |cFF0088FFsetting line #'..lineIndex..' for|r', block.info.title, "\n            |cFF0088FFsize:|r", line.height,
+  line:SetHeight(line.height)
+  block.attachmentHeight = block.attachmentHeight + line.height + textSpacing
+  print('  |cFF0088FFsetting line #'..lineIndex..' for|r', block.info.title, "\n     |cFF0088FFsize:|r", line.height,
     "|cFF0088FFpoint:|r", line:GetPoint(1), "|cFF0088FFwidget:|r", (line.widget and 'Y' or 'N'))
   block.currentLine = lineIndex
   block.endPoint = line.statusbg -- edge used for the next block
@@ -175,13 +234,10 @@
   local lines = block.lines
   if not lineIndex then
     lineIndex = block.currentLine + 1
-    print('        fetching the "next" line:', lineIndex)
-  else
-    print('        fetching explicit offset:', lineIndex)
+    print('        |cFFFFFF00generating a frame')
   end
 
   block.numLines = max(block.numLines, lineIndex)
-  print('        |cFF00FFFFposition|r', block.currentLine, '|cFF00FFFFof|r|cFFFFFF00' , block.numLines)
 
   if not lines[lineIndex] then
     print('     |cFF00FF88created line #'..lineIndex..' from for '..handler.name..' block #'..blockIndex)
@@ -189,14 +245,8 @@
     local line = lines[lineIndex]
     line.index = lineIndex
     line.height = 0
-    line.status:SetSpacing(textSpacing)
-    line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0)
     B.SetConfigLayers(line)
 
-    if lines[lineIndex+1] then
-      lines[lineIndex+1]:ClearAllPoints()
-    end
-
     if debug then
       for _, region in ipairs(lines[lineIndex].debug) do
         region:Show()
@@ -210,59 +260,25 @@
 
 
 --- Creates or retrieves a complete block frame object
-Default.GetBlock = function(handler, blockIndex)
+--- todo: make it use data index to avoid re-coloring every block
+Default.GetBlock = function(handler, logIndex)
   local print = bprint
-  local block = handler.usedBlocks[blockIndex]
+  print('|cFFFFFF00getting a block for logID', logIndex ..',', #handler.usedBlocks,'used', #handler.freeBlocks, 'free')
+  local block = handler.LogBlock[logIndex]
 
-  if not handler.usedBlocks[blockIndex] then
+  if not block then
     if #handler.freeBlocks >= 1 then
-      block = handler.freeBlocks[#handler.freeBlocks]
-      handler.freeBlocks[#handler.freeBlocks] = nil
+      block = tremove(handler.freeBlocks)
+      print('  assigning from free heap|cFF00FFFF', block:GetName())
     else
+
+      local blockIndex = handler.numBlocks + 1
       block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, handler.frame, 'VeneerTrackerBlock')
-
-      local c = Module.Conf.Wrapper
-      block.index = blockIndex
       block.lines = {}
       block.numLines = 0
       block.currentLine = 0
-      block:SetWidth(c.Width)
-
-      block.title:SetSpacing(c.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(c.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(Module.colors.default.selectionbg))
-      block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0)
-      block.SelectionOverlay:SetPoint('BOTTOMRIGHT')
-
-      --block.icon:SetSize(rewardSize, rewardSize)
-      --block.icon:SetPoint()
-      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, -2)
-        anchor, target, point, x, y = 'TOPRIGHT', tile, 'TOPLEFT', -2, 0
-      end
-
-
+      block.attachmentHeight = 0
+      B.SetConfigLayers(block)
       --- methods for event handlers
 
       block.Select = handler.Select
@@ -271,33 +287,32 @@
       block.Link = handler.Link
       block.clickZone:SetScript('OnMouseUp', function(self, ...) handler.OnMouseUp(block, ...) end)
       block.clickZone:SetScript('OnMouseDown', function(self, ...) handler.OnMouseDown(block, ...) end)
-      block.attachmentHeight = 0
       block:ClearAllPoints()
+      block.index = blockIndex
+      handler.numBlocks = max(handler.numBlocks, blockIndex)
 
-      B.SetConfigLayers(block)
-
-      if debug then
-        for _, region in ipairs(block.debug) do
-          region:Show()
-        end
-      end
+      print('  |cFFFFFF00creating new|r', block:GetName())
     end
-    handler.usedBlocks[blockIndex] = block
+    handler.LogBlock[logIndex] = block
+    tinsert(handler.usedBlocks, block)
+  else
+    print('  |cFFFFFF00use existing block|r', block:GetName())
   end
-  return handler.usedBlocks[blockIndex]
+  return block
 end
 
 local currentPosition, anchorFrame, anchorPoint
 --- Positioning and stuff
 local tick = 0
-local maxReason = 0
+local firstUpdate = true
 function Module:Update (reason, ...)
+  if not B.Conf.VeneerObjectiveWrapper.enabled then
+    return
+  end
+
   tick = tick + 1
-  -- is this the first time updating?
-  if maxReason == 0 then
-    reason = OBJECTIVE_TRACKER_UPDATE_ALL
-  elseif not reason then
-    reason = OBJECTIVE_TRACKER_UPDATE_REASON
+  if firstUpdate or not reason then
+    reason = _G.OBJECTIVE_TRACKER_UPDATE_ALL
   end
 
   local print = tprint
@@ -305,7 +320,7 @@
   local hasStuff
   local insertingStuff
 
-  print(format('%d |cFFFF%04X Update()', tick, lshift(reason, 4)), reason, ...)
+  print(format('|cFFBB0066Update:|r |cFFFF%04X%d|r  ', tick, lshift(reason, 4)), reason, ...)
   currentPosition = 0
   anchorPoint = 'TOP'
   anchorFrame = Scroll
@@ -314,20 +329,21 @@
   for id, handler in pairs(Module.orderedHandlers) do
     local frame = handler.frame
 
-    print(format('|cFF00FFFF%s and(%04X vs %04x+%04x) = %04X|r', handler.name, reason, handler.updateReasonModule, handler.updateReasonEvents, band(reason, handler.updateReasonModule + handler.updateReasonEvents)))
+
     if band(reason, handler.updateReasonModule + handler.updateReasonEvents) > 0 then
       handler:UpdateTracker(reason, ...)
-      print(' |cFF00FF00'..id..'|r', handler.displayName, 'count:', handler.numWatched)
       insertingStuff = true
     else
       print(' |cFFFF0088'..id..'|r', 'no reason to update')
     end
 
     if handler.numWatched >= 1 then
+
+      print(format('|cFF88FFBB%s and(%04X, %04x+%04x) = %04X|r', handler.name, reason, handler.updateReasonModule, handler.updateReasonEvents, band(reason, handler.updateReasonModule + handler.updateReasonEvents)))
       hasStuff = true
       currentPosition = currentPosition + 1
       frame.destinationOffset = -wrapperHeight
-      if frame.previousOffset ~= wrapperHeight and frame:IsVisible() then
+      if (not firstUpdate) and frame.previousOffset ~= wrapperHeight and frame:IsVisible() then
         print(frame.SlideIn.translation)
         local postFrame, postPoint = anchorFrame, anchorPoint
         local delta = frame.destinationOffset - frame.previousOffset
@@ -340,8 +356,9 @@
           b.SlideIn.translation:SetOffset(0, delta)
           b.SlideIn:Play()
         end
+        local start = GetTime()
         frame.SlideIn:SetScript('OnFinished', function()
-          print('  |cFF00BBFFsliding finished:', delta, 'pixels covered')
+          print('  |cFF00BBFFsliding finished:', delta, 'pixels covered; duration:', GetTime()-start)
           frame:SetParent(Scroll)
           frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset)
           frame.previousOffset = frame.destinationOffset
@@ -356,7 +373,8 @@
 
         end)
       else
-        print('  |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint)
+        print('  |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint, '|rcurrent frame height:', frame.height)
+        print('  |cFFFF0088total height:', wrapperHeight)
         frame:SetParent(Scroll)
         frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset)
       end
@@ -365,10 +383,10 @@
       anchorFrame = handler.frame
       anchorPoint = 'BOTTOM'
 
-      print('current frame height:', frame.height)
       wrapperHeight = wrapperHeight + frame.height
-      print('|cFFFF0088total height:', wrapperHeight)
     else
+
+      print('  |cFFFF4400GetNumWatched:|r',handler.name, '0')
       frame:SetPoint('TOP', Scroll, 'TOP', 0, 0)
       frame.destinationOffset = 0
       frame.previousOffset = 0
@@ -406,6 +424,9 @@
   end
   Quest.GetClosest()
   --Module.UpdateActionButtons(reason)
+  if firstUpdate then
+    firstUpdate = nil
+  end
 end
 
 --- Content generator base
@@ -422,6 +443,11 @@
 
   handler.updateReason = reason
   handler.numWatched = handler:GetNumWatched()
+  if handler.numWatched >= 1 then
+
+    print('  |cFF00FF88GetNumWatched:|r',handler.name, handler.numWatched, 'of', handler.numAll)
+  end
+
   handler.currentBlock = 0
   handler.currentAnchor = tracker.titlebg
   local blockPosition = -headerHeight
@@ -437,15 +463,22 @@
     end
   end
 
-  for i = handler.currentBlock+1, handler.numBlocks do
-    local used = handler.usedBlocks
+
+  local numBlocks = handler.numBlocks
+  local used = handler.usedBlocks
+  if numBlocks < #used then
+    print('  |cFF0088FFcull the dead: showing|r', numBlocks, '|cFF0088FF out of|r', #used)
     local free = handler.freeBlocks
-    print('clean up dead quest block')
-    if used[i] then
-      used[i]:Hide()
-      used[i]:ClearAllPoints()
-      free[#free+1]= used[blockIndex]
-      used[i] = nil
+    local remaining = #used
+    for i = #used, 1, -1 do
+      print('    -', 'i='.. i, 'watchIndex='..used[i].info.watchIndex)
+      if used[i].info.watchIndex > numBlocks then
+        print('    clean up dead quest block')
+        local released = tremove(used, i)
+        released:Hide()
+        released:ClearAllPoints()
+        tinsert(free, used[blockIndex])
+      end
     end
   end
 
@@ -470,6 +503,7 @@
   return tracker.numWatched, tracker.numAll
 end
 
+
 --- Updates the selected block frame to display the given info batch
 -- If `previousBlock` is set, it will attempt to anchor to that
 -- @param blockNum the ordered block to be updated, not a watchIndex value
@@ -477,7 +511,6 @@
 -- REMEMBER: t.info and questData[questID] are the same table
 Default.UpdateBlock = function (handler, blockIndex, id, added)
   local print = bprint
-  print('  Updating |cFF00FF00'..handler.displayName..'|r|cFF00FFFF'..blockIndex..'|r')
   if not blockIndex then
     return
   end
@@ -485,25 +518,26 @@
   if not info then
     return
   end
+  print('  Updating |cFF00FF00'..handler.displayName..'|r|cFF00FFFF'..blockIndex..'|r|cFF0099FF', info.id ,'|r')
   local frame = handler.frame
-  local block = handler:GetBlock(blockIndex)
+  local block = handler:GetBlock(info.id)
 
-  block.questID = info.questID
-  if id == info.questID then
-      --block.questFadeIn:Play()
+  if added then
+    -- do something if the block is being assigned a new thing
   end
 
   block.handler = handler
   block.info = info
-  block.mainStyle = info.mainStyle or 'Normal'
-  block.subStyle = info.subStyle
 
   info.blockIndex = blockIndex
   if info.questID then handler.QuestBlock[info.questID] = block end
-  if info.questLogIndex then handler.LogBlock[info.questLogIndex] = 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
-  handler:UpdateObjectives(block)
+  local newSchema = handler:UpdateObjectives(block)
+  if newSchema and newSchema ~= blockSchema then
+    Module.UpdateSchema('block', newSchema)
+  end
 
   block.title:SetText(info.title)
   local titleHeight = floor(block.title:GetHeight()+.5)
@@ -516,15 +550,12 @@
 
   print('    |cFF0088FFanchor to', handler.currentAnchor:GetName())
   print('    |cFF00FF00attachment:|r', attachmentHeight, '|cFF00FF00title:|r', titlebgHeight, '('.. titleHeight..')')
-  --block.titlebg:SetHeight(block.title:GetHeight() + Module.Conf.Wrapper.TitleSpacing)
+  if attachmentHeight > 0 then
+    attachmentHeight = attachmentHeight + textSpacing
+  end
+
   block.height = titlebgHeight + attachmentHeight
 
-  if statusHeight > 1 then
-    block.height = block.height + statusbgHeight
-    print('           status:', statusbgHeight, '('.. statusHeight..')')
-  else
-    print('      |cFFFF0088             skipped')
-  end
   block:SetHeight(block.height)
 
   print('           |cFFFFFF00height|r:', block.height)
@@ -578,6 +609,11 @@
     tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'typeTag', tagPoint, tagAnchor, tagRelative)
     tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'completionTag', tagPoint, tagAnchor, tagRelative)
   end
+
+  if info.statusKey and (Devian and Devian.InWorkspace()) then
+    block.debugText:SetText(info.statusKey)
+    block.debugText:Show()
+  end
   return block
 end
 
@@ -586,7 +622,7 @@
 
 --- Does the main iterations for populating block content.
 -- Hooked by corresponding handler functions where additional details need to be sorted.
-Default.UpdateObjectives = function(handler, block)
+Default.UpdateObjectives = function(handler, block, block_schema)
   local print = lprint
   local info = block.info
   print('|cFF00FF00default.objectives', block:GetName())
@@ -618,28 +654,28 @@
         displayObjectiveHeader = true
         line.height = 0
         text, attachment, template = handler:UpdateLine(block, line, data)
-        print('     |cFF88FF00#', i, data.type, text)
+        print('   |cFF88FF00#', i, data.type, text, attachment)
         handler:AddLine(block, text, attachment, template)
 
       end
     end
   end
 
-  if info.statusKey and (Devian and Devian.InWorkspace()) then
-    handler:AddLine(block, info.statusKey, nil)
-  end
 
-  for i = block.currentLine + 1, block.numLines do
-    print(i, block.numLines)
-    print('      - hide |cFFFF0088'..i..'|r', block.lines[i])
-    block.lines[i]:ClearAllPoints()
-    block.lines[i]:Hide()
+  if block.currentLine < block.numLines then
+    print('   - cull', block.currentLine, block.numLines)
+    for i = block.currentLine + 1, block.numLines do
+      print('   - hide |cFFFF0088'..i..'|r', block.lines[i])
+      block.lines[i]:ClearAllPoints()
+      block.lines[i]:Hide()
+    end
   end
 
   if block.currentLine > 0 then
     block.attachmentHeight = block.attachmentHeight + textSpacing
-    print('     |cFF00FF00attachment:', block.attachmentHeight)
+    print('   |cFF00FF00attachment:', block.attachmentHeight)
   end
+  return block_schema
 end
 
 
@@ -681,7 +717,7 @@
     local block = Module.Quest.QuestBlock[questID]
     if block then
         -- Dispatch the probe
-      if IsQuestWatched(info.questLogIndex) then
+      if IsQuestWatched(info.logIndex) then
         itemButton.previousItem = previousItem
         print('  |cFFFFFF00probing', block:GetName())
         block:SetScript('OnUpdate', function()
@@ -767,6 +803,7 @@
 
 end
 
+
 Default.Select = function(handler, block)
   Module:Update(handler.watchReasonModule)
 end