diff ObjectiveTracker/Frame.lua @ 35:69d03f8e293e

- separated layout and data logic between Frame.lua and Update.lua - solved disappearing tracker mystery
author Nenue
date Sun, 17 Apr 2016 11:07:48 -0400
parents 9856ebc63fa4
children a487841050be
line wrap: on
line diff
--- a/ObjectiveTracker/Frame.lua	Sun Apr 17 00:21:45 2016 -0400
+++ b/ObjectiveTracker/Frame.lua	Sun Apr 17 11:07:48 2016 -0400
@@ -4,20 +4,20 @@
 -- @file-revision@ @file-hash@
 -- Created: 3/30/2016 12:49 AM
 local B = select(2,...).frame
-local Module = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
+local T = 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, 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
-local Default, AutoQuest, Quest, Bonus, Cheevs = Module.DefaultHandler, Module.AutoQuest, Module.Quest, Module.Bonus, Module.Cheevs
+local Default, AutoQuest, Quest, Bonus, Cheevs = T.DefaultHandler, T.AutoQuest, T.Quest, T.Bonus, T.Cheevs
 local InCombatLockdown, format, lshift, CreateFrame = InCombatLockdown, format, bit.lshift, CreateFrame
 local IsModifiedClick, ChatEdit_GetActiveWindow = IsModifiedClick, ChatEdit_GetActiveWindow
-local print = B.print('Tracker')
+local print = B.print('Layout')
 local oprint = B.print('Objectives')
 local bprint = B.print('Block')
 local tprint = B.print('Tracker')
-local lprint = B.print('Line')
+local lprint = B.print('Layout')
 local unitLevel = 1
 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_REASON
 local debug = false
@@ -26,8 +26,8 @@
 local Wrapper = _G.VeneerObjectiveWrapper
 local Scroller = Wrapper.scrollArea
 local Scroll = _G.VeneerObjectiveScroll
-local orderedHandlers = Module.orderedHandlers
-local orderedNames = Module.orderedNames
+local orderedHandlers = T.orderedHandlers
+local orderedNames = T.orderedNames
 
 --- FRAME TEMP VARIABLES
 local wrapperWidth, wrapperHeight
@@ -63,16 +63,18 @@
 local titleSpacing, textSpacing, blockSpacing = 3, 3, 1
 local titleIndent, textIndent,selectionIndent = 2, 5, 50
 --- END SCHEMA
+local blockPosition
+
 --- schema swapper
-Module.UpdateSchema = function(layer, newSchema)
-  if not (Module.Conf.Schema[layer] and Module.Conf.Schema[layer][newSchema]) then
+T.UpdateSchema = function(layer, newSchema)
+  if not (T.Conf.Schema[layer] and T.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 c = T.Conf.Schema[layer][newSchema]
 
   if layer == 'tracker' then
     headerHeight, headerSpacing = c.headerHeight, c.headerSpacing
@@ -99,6 +101,79 @@
   end
   print('|cFFFF0088UpdateSchema:|r', layer, lastSchema[layer], '->', newSchema)
 end
+-- todo: figure out why objectives go invisible
+local anchorPoint, anchorFrame
+local abs, GetTime = math.abs, GetTime
+Default.AddTracker = function(handler, frame, index)
+  if index == 1 then
+    print('|cFF00FF00### beginning wrapper layout -----------------')
+    anchorPoint, anchorFrame = 'TOP', Scroll
+    wrapperHeight = 0
+  end
+
+  frame.destinationOffset = -wrapperHeight
+  print(frame.destinationOffset, frame.previousOffset)
+  if  handler.initialized and (abs(frame.previousOffset - frame.destinationOffset) > 0.9) and frame:IsVisible() then
+    if frame.wasEmpty then
+      frame.previousOffset = -Wrapper:GetHeight()
+    end
+
+    local postFrame, postPoint = anchorFrame, anchorPoint
+    local delta = frame.destinationOffset - frame.previousOffset
+    local _, _, _, _, offset = frame:GetPoint(1)
+    print('  |cFF00FFBBpushing', frame:GetName(), delta, 'pixels, from', frame.previousOffset, '(', offset, ')')
+    frame.SlideIn.translation:SetTarget(frame)
+    frame.SlideIn.translation:SetOffset(0, delta)
+    frame.SlideIn:Play()
+    --for i, b in ipairs(handler.usedBlocks) do
+      --b.SlideIn.translation:SetOffset(0, delta)
+     -- b.SlideIn:Play()
+    --end
+    local start = GetTime()
+    frame.SlideIn:SetScript('OnFinished', function()
+      print('  |cFF00BBFF'..frame:GetName(), 'moved', delta, 'over duration of ', GetTime()-start)
+      frame:SetParent(Scroll)
+      frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset)
+      frame.previousOffset = frame.destinationOffset
+      frame.SlideIn:SetScript('OnFinished', nil)
+      if Wrapper.destinationHeight then
+        Wrapper:SetHeight(Wrapper.destinationHeight)
+        Scroller:SetHeight(Wrapper.destinationHeight)
+        Scroll:SetHeight(Wrapper.destinationHeight)
+        Wrapper.previousHeight = Wrapper.destinationHeight
+        Wrapper.destinationHeight = nil
+      end
+
+    end)
+  else
+    print('  |cFF00BBFFpinning to', anchorFrame:GetName(), anchorPoint, '|rcurrent frame height:', frame.height)
+    print('  |cFFFF0088total height:', wrapperHeight)
+    frame:ClearAllPoints()
+    frame:SetParent(Scroll)
+    frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset)
+    frame.previousOffset = frame.destinationOffset
+    handler.initialized = true
+  end
+
+  frame.title:SetFont(headerFont, headerSize, headerOutline)
+  frame.titlebg:SetHeight(headerHeight)
+  frame.title:SetTextColor(unpack(headerColor))
+
+  if frame.height ~= frame.previousHeight then
+    frame:SetHeight(frame.height)
+  end
+
+  frame:Show()
+  if frame.wasEmpty then
+    frame.headerFade:Play()
+    frame.wasEmpty = nil
+  end
+
+  wrapperHeight = wrapperHeight + frame.height
+  anchorFrame = handler.frame
+  anchorPoint = 'BOTTOM'
+
+end
 
 Default.AddBlock = function(self, block, blockIndex)
   local blockIndex = blockIndex or (self.currentBlock + 1)
@@ -106,10 +181,12 @@
   local tracker = self.frame
   local info = block.info
 
+  block.index = blockIndex
+
   if blockSchema ~= block.schema then
     print('new schema detected, applicating...')
     block.schema = blockSchema
-    block:SetWidth(Module.Conf.Wrapper.Width)
+    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)
@@ -139,6 +216,24 @@
     end
   end
 
+
+  local titleHeight = floor(block.title:GetHeight()+.5)
+  local titlebgHeight = titleHeight + titleSpacing*2
+  block.titlebg:SetHeight(titlebgHeight)
+
+  local statusHeight = floor(block.status:GetHeight()+.5)
+  local statusbgHeight = statusHeight + textSpacing*2
+  local attachmentHeight =floor(block.attachmentHeight + .5)
+
+  print('    |cFF0088FFanchor to', self.currentAnchor:GetName())
+  print('    |cFF00FF00attachment:|r', attachmentHeight, '|cFF00FF00title:|r', titlebgHeight, '('.. titleHeight..')')
+  if attachmentHeight > 0 then
+    attachmentHeight = attachmentHeight + textSpacing
+  end
+
+  block.height = titlebgHeight + attachmentHeight
+  block:SetHeight(block.height)
+
   if block.debug then
     local func = (B.Conf.GuidesMode == true) and 'Show' or 'Hide'
     for _, region in ipairs(block.debug) do
@@ -146,15 +241,25 @@
     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)
+  --- Handler vars
+  if blockIndex == 1 then
+    tracker.previousHeight = tracker.height
+    tracker.height = headerHeight
+    blockPosition = -headerHeight
+    tprint('    |cFF88FF00AddBlock:|r new layout: headerHeight =', headerHeight, 'previousHeight =', tracker.previousHeight)
+  else
+    blockPosition = blockPosition
+    tprint('    |cFF8888FFAddBlock:|r advancing: height =', tracker.height)
+  end
   self.currentBlock = blockIndex
   self.currentAnchor = block
+
+  block:SetPoint('TOPLEFT', self.frame, 'TOPLEFT', 0, blockPosition)
+  block:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
+  self.numBlocks = self.numBlocks + 1
   print('    |cFFFFFF00'..tracker.height..'|r', '|cFF00FF00'..block:GetName()..'|r', block.height, tracker.height)
   tracker.height = tracker.height + block.height
-  self.actualBlocks = self.actualBlocks + 1
+  blockPosition = blockPosition - block.height
 end
 
 --- Used as an iterator of sorts for cascaded tag icon placements (the daily/faction/account icons)
@@ -182,22 +287,24 @@
   local lineIndex = block.currentLine + 1
   local line = handler:GetLine(block, lineIndex)
   line.index = lineIndex
-  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)
+  if template then
+    if line.schema ~= template then
+      print('      |cFF00FF00change schema', template)
+      T.UpdateSchema('line', template)
+      line.status:SetSpacing(textSpacing)
+      line.status:SetPoint('LEFT', line, 'LEFT', textIndent, 0)
+      line.status:SetPoint('RIGHT', line, 'RIGHT',0, 0)
+      line.status:SetTextColor(unpack(textColor))
+      line.schema = template
+    else
+      print('      |cFFFFFF00keep schema', line.schema)
+    end
   end
   line:SetPoint('TOP', block.endPoint, 'BOTTOM', 0, -textSpacing)
   line:Show()
 
 
-  print(' |cFF0088FFAddLine >>|r', block, '::',  block.endPoint:GetName(),'"'.. text .. '"', attachment, template)
+  tprint('      |cFF0088FFAddLine|r (|cFF00FFFF'..tostring(line.schema)..'|r):', line:GetName())
 
 
   -- fill in the text, then derive pixel-rounded height
@@ -206,7 +313,7 @@
 
   -- For progressbar and timer lines, status text may be used as the title heading
   if attachment then
-    print('  |cFFFF0088doing things with a widget', attachment:GetSize())
+    print('      |cFFFF0088doing things with a widget', attachment:GetSize())
     line.height = attachment:GetHeight()
     if text then
       line.height = max(line.height, line.status:GetStringHeight())
@@ -219,8 +326,15 @@
 
   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'))
+
+  local debug_points = ''
+  for i = 1, line:GetNumPoints() do
+    local point, parent, anchor = line:GetPoint(i)
+    debug_points = debug_points .. tostring(parent:GetName()) .. ', ' .. anchor ..  ' '
+  end
+
+  print('      |cFF0088FFsetting line #'..lineIndex..' for|r', block.info.title, "\n     |cFF0088FFsize:|r", line.height,
+    "|cFF0088FFpoint:|r", debug_points, "|cFF0088FFwidget:|r", (line.widget and 'Y' or 'N'))
   block.currentLine = lineIndex
   block.endPoint = line.statusbg -- edge used for the next block
 
@@ -245,6 +359,7 @@
     local line = lines[lineIndex]
     line.index = lineIndex
     line.height = 0
+    line.schema = 'default'
     B.SetConfigLayers(line)
 
     if debug then
@@ -263,21 +378,26 @@
 --- todo: make it use data index to avoid re-coloring every block
 Default.GetBlock = function(handler, logIndex)
   local print = bprint
-  print('|cFFFFFF00getting a block for logID', logIndex ..',', #handler.usedBlocks,'used', #handler.freeBlocks, 'free')
+  print('|cFF0088FFgetting a block for logID', logIndex ..',', #handler.usedBlocks,'used', #handler.freeBlocks, 'free')
   local block = handler.LogBlock[logIndex]
+  local used = handler.usedBlocks
 
   if not block then
     if #handler.freeBlocks >= 1 then
       block = tremove(handler.freeBlocks)
-      print('  assigning from free heap|cFF00FFFF', block:GetName())
+      tinsert(handler.usedBlocks, block)
+      block.posIndex = #handler.usedBlocks
+      print(' |cFF00FF00 assigning from free heap', block:GetName())
     else
 
-      local blockIndex = handler.numBlocks + 1
+      local blockIndex = (#handler.usedBlocks + #handler.freeBlocks) + 1
       block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, handler.frame, 'VeneerTrackerBlock')
+      --block:SetParent()
       block.lines = {}
       block.numLines = 0
       block.currentLine = 0
       block.attachmentHeight = 0
+      block.offset = 0
       B.SetConfigLayers(block)
       --- methods for event handlers
 
@@ -289,468 +409,42 @@
       block.clickZone:SetScript('OnMouseDown', function(self, ...) handler.OnMouseDown(block, ...) end)
       block:ClearAllPoints()
       block.index = blockIndex
-      handler.numBlocks = max(handler.numBlocks, blockIndex)
-
-      print('  |cFFFFFF00creating new|r', block:GetName())
+      print('  |cFF00FFBBcreating new|r', block:GetName())
     end
     handler.LogBlock[logIndex] = block
     tinsert(handler.usedBlocks, block)
+    block.posIndex = #handler.usedBlocks
   else
     print('  |cFFFFFF00use existing block|r', block:GetName())
+    local found = false
+    for i, entry in ipairs(used) do
+      if entry == block then
+        found = true
+        break
+      end
+    end
+    if not found then
+      tinsert(used, block)
+      block.posIndex = #used
+    end
   end
   return block
 end
 
-local currentPosition, anchorFrame, anchorPoint
---- Positioning and stuff
-local tick = 0
-local firstUpdate = true
-function Module:Update (reason, ...)
-  if not B.Conf.VeneerObjectiveWrapper.enabled then
-    return
-  end
 
-  tick = tick + 1
-  if firstUpdate or not reason then
-    reason = _G.OBJECTIVE_TRACKER_UPDATE_ALL
-  end
 
-  local print = tprint
-  local updateWrapper = 0
-  local hasStuff
-  local insertingStuff
 
-  print(format('|cFFBB0066Update:|r |cFFFF%04X%d|r  ', tick, lshift(reason, 4)), reason, ...)
-  currentPosition = 0
-  anchorPoint = 'TOP'
-  anchorFrame = Scroll
-
-  local wrapperHeight = 0
-  for id, handler in pairs(Module.orderedHandlers) do
-    local frame = handler.frame
-
-
-    if band(reason, handler.updateReasonModule + handler.updateReasonEvents) > 0 then
-      handler:UpdateTracker(reason, ...)
-      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 (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
-        local _, _, _, _, offset = frame:GetPoint(1)
-        print('  |cFF00BBFFstart slide for', delta, 'pixels, from', frame.previousOffset, '(', offset, ')')
-        frame.SlideIn.translation:SetTarget(frame)
-        frame.SlideIn.translation:SetOffset(0, delta)
-        frame.SlideIn:Play()
-        for i, b in ipairs(handler.usedBlocks) do
-          b.SlideIn.translation:SetOffset(0, delta)
-          b.SlideIn:Play()
-        end
-        local start = GetTime()
-        frame.SlideIn:SetScript('OnFinished', function()
-          print('  |cFF00BBFFsliding finished:', delta, 'pixels covered; duration:', GetTime()-start)
-          frame:SetParent(Scroll)
-          frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset)
-          frame.previousOffset = frame.destinationOffset
-          frame.SlideIn:SetScript('OnFinished', nil)
-          if Wrapper.destinationHeight then
-            Wrapper:SetHeight(Wrapper.destinationHeight)
-            Scroller:SetHeight(Wrapper.destinationHeight)
-            Scroll:SetHeight(Wrapper.destinationHeight)
-            Wrapper.previousHeight = Wrapper.destinationHeight
-            Wrapper.destinationHeight = nil
-          end
-
-        end)
-      else
-        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
-
-      frame:Show()
-      anchorFrame = handler.frame
-      anchorPoint = 'BOTTOM'
-
-      wrapperHeight = wrapperHeight + frame.height
-    else
-
-      print('  |cFFFF4400GetNumWatched:|r',handler.name, '0')
-      frame:SetPoint('TOP', Scroll, 'TOP', 0, 0)
-      frame.destinationOffset = 0
-      frame.previousOffset = 0
-      handler.frame:Hide()
-    end
-  end
-
-
-  if  hasStuff or insertingStuff then
-    print('updating height to', wrapperHeight)
-    if wrapperHeight > Wrapper.previousHeight then
-      Wrapper:SetHeight(wrapperHeight)
-      Scroller:SetHeight(wrapperHeight)
-      Scroll:SetHeight(wrapperHeight)
-      Wrapper.previousHeight = wrapperHeight
-      Wrapper.destinationHeight = wrapperHeight
-    end
-    Scroller:SetVerticalScroll(B.Conf.ObjectiveScroll or 0)
-    print('|cFFFF8800Wrapper:', Wrapper:GetSize())
-    for i = 1, Wrapper:GetNumPoints() do
-      print(' ', Wrapper:GetPoint(i))
-    end
-    print('  |cFF00FFFFScroller:', Scroller:GetSize())
-    for i = 1, Scroller:GetNumPoints() do
-      print(' ', Scroller:GetPoint(i))
-    end
-    print('  |cFF00FFFFScroll:', Scroll:GetSize())
-    for i = 1, Scroll:GetNumPoints() do
-      print(' ', Scroll:GetPoint(i))
-    end
-
-    Wrapper:Show()
-    Scroller:Show()
-    Scroll:Show()
-  end
-  Quest.GetClosest()
-  --Module.UpdateActionButtons(reason)
-  if firstUpdate then
-    firstUpdate = nil
-  end
-end
-
---- Content generator base
-Default.UpdateTracker = function (handler, reason, id, isNew)
-  local print = tprint
-  local tracker = handler.frame
-  local blockIndex = 0
-  tracker.previousHeight = tracker.height
-  tracker.height = 0
-
-  tracker.title:SetFont(headerFont, headerSize, headerOutline)
-  tracker.titlebg:SetHeight(headerHeight)
-  tracker.title:SetTextColor(unpack(headerColor))
-
-  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
-  for blockIndex = 1, handler.numWatched do
-    local currentBlock = handler:UpdateBlock(blockIndex, id, isNew)
-    if currentBlock then
-      currentBlock.offset = blockPosition
-      handler:AddBlock(currentBlock)
-      blockPosition = blockPosition - currentBlock.height
-    else
-      print('  |cFFFF9900END|r @', blockIndex)
-      break -- done with quest stuff
-    end
-  end
-
-
-  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
-    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
-
-
-  if handler.currentBlock >= 1 then
-    tracker.height = tracker.height + headerHeight
-    tracker:Show()
-
-    if tracker.wasEmpty then
-      tracker.headerFade:Play()
-      tracker.wasEmpty = nil
-    end
-    if tracker.height ~= tracker.previousHeight then
-      tracker:SetHeight(tracker.height)
-    end
-    print('    |cFFFFFF00', tracker.height, tracker:GetWidth())
-  else
-    tracker:Hide()
-    tracker.wasEmpty = true
-  end
-
-  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
--- @param info the reference returned by the GetXInfo functions
--- REMEMBER: t.info and questData[questID] are the same table
-Default.UpdateBlock = function (handler, blockIndex, id, added)
-  local print = bprint
-  if not blockIndex then
-    return
-  end
-  local info = handler:GetInfo(blockIndex) -- 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')
-  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
-    Module.UpdateSchema('block', newSchema)
-  end
-
-  block.title:SetText(info.title)
-  local titleHeight = floor(block.title:GetHeight()+.5)
-  local titlebgHeight = titleHeight + titleSpacing*2
-  block.titlebg:SetHeight(titlebgHeight)
-
-  local statusHeight = floor(block.status:GetHeight()+.5)
-  local statusbgHeight = statusHeight + textSpacing*2
-  local attachmentHeight =floor(block.attachmentHeight + .5)
-
-  print('    |cFF0088FFanchor to', handler.currentAnchor:GetName())
-  print('    |cFF00FF00attachment:|r', attachmentHeight, '|cFF00FF00title:|r', titlebgHeight, '('.. titleHeight..')')
-  if attachmentHeight > 0 then
-    attachmentHeight = attachmentHeight + textSpacing
-  end
-
-  block.height = titlebgHeight + attachmentHeight
-
-  block:SetHeight(block.height)
-
-  print('           |cFFFFFF00height|r:', block.height)
-  print('  |cFF00FFFF)|r -> ', block, block:GetHeight())
-
-  block:Show()
-
-  if info.specialItem and not info.itemButton then
-    print('    - |cFF00FFFFgenerating item button for info set')
-    info.itemButton = Module.SetItemButton(block, info)
-  else
-    --info.itemButton = nil
-  end
-
-  local tagPoint, tagAnchor, tagRelative, x, y = 'TOPRIGHT', block, 'TOPRIGHT', -2, -2
-
-  local numCurrency = 0
-  for i, rewardTile in ipairs(block.rewardTile) do
-    if info.rewardInfo and info.rewardInfo[i] then
-      local reward = info.rewardInfo[i]
-        --rewardTile:SetPoint(tagPoint, tagAnchor, tagRelative, -2, -2)
-      rewardTile:SetTexture(reward.texture)
-      rewardTile:Show()
-
-      print('updating reward tile #'.. i, reward.type, reward.count, reward.text, reward.texture)
-      if reward.count and reward.count > 1 then
-        block.rewardLabel[i]:SetText(reward.count)
-        block.rewardLabel[i]:Show()
-      end
-
-      rewardTile:ClearAllPoints()
-      rewardTile:SetPoint(tagPoint, tagAnchor, tagRelative, x, y)
-      tagPoint, tagAnchor, tagRelative, x, y = 'TOPRIGHT', rewardTile, 'TOPLEFT', -2, 0
-    else
-      rewardTile:Hide()
-      block.rewardLabel[i]:Hide()
-    end
-  end
-
-  if info.selected then
-    block.SelectionOverlay:Show()
-  else
-    block.SelectionOverlay:Hide()
-  end
-  -- workaround for scrollchild issue where layers fall out of sync: in this case, it's by 1 vertical pixel
-  --block.highlight:SetPoint('TOPLEFT', block, 'TOPLEFT', 0, 1)
-  --block.lowlight:SetPoint('BOTTOMLEFT', block, 'BOTTOMLEFT', 0, 1)
-
-  if info.tagInfo then
-    tagPoint, tagAnchor, tagRelative = handler:AddTag(block, 'frequencyTag', tagPoint, tagAnchor, tagRelative)
-    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
-
-
-
-
---- 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, block_schema)
-  local print = lprint
-  local info = block.info
-  print('|cFF00FF00default.objectives', block:GetName())
-  -- reset the starting positions
-  block.endPoint = block.titlebg
-  block.attachmentHeight = 0
-  block.currentLine = 0
-
-  local displayObjectiveHeader = false
-
-  block.attachmentHeight = 0
-  local text, attachment, template
-
-
-  if info.description and #info.description >= 1 then
-    print('   |cFF00FFFF  header line:|r', info.description)
-    text = info.description
-    handler:AddLine(block, text, nil)
-  end
-
-  if (info.isComplete or info.numObjectives == 0) and info.completionText then
-    print('     overriding line #1 for completion text:', info.completionText)
-    text = info.completionText
-    handler:AddLine(block, text, nil, 'completed')
-  else
-    if info.objectives then
-      for i, data in ipairs(info.objectives) do
-        local line = handler:GetLine(block)
-        displayObjectiveHeader = true
-        line.height = 0
-        text, attachment, template = handler:UpdateLine(block, line, data)
-        print('   |cFF88FF00#', i, data.type, text, attachment)
-        handler:AddLine(block, text, attachment, template)
-
-      end
-    end
-  end
-
-
-  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)
-  end
-  return block_schema
-end
-
-
---- Module-specific display variables
--- * height   - height of whatever display widget is involved in conveying the task
--- * money    - boolean that determines listening for money events or not
--- * progress - number ranging 0 to 2 indicating none/partial/full completion respectively
-
-
-Default.UpdateLine = function(handler, block, line, data)
-  if line.finished then
-    line.progress = 2
-  elseif line.quantity > 0 then
-    line.progress  = 1
-  else
-    line.progress = 0
-  end
-  return data.text, line.widget, 'normal'
-end
 ----------
 --- Top level methods
 
---- Queue any active item buttons for update for that frame
-local iprint = B.print('ItemButton')
-Module.UpdateActionButtons = function(updateReason)
-  local print = iprint
-  Scroller.snap_upper = 0
-  Scroller.snap_lower = 0
-  local print = B.print('ItemButton')
-  if updateReason then
-    print = B.print('IB_'..updateReason)
-  end
 
-  local previousItem
-  for questID, itemButton in pairs(Quest.itemButtons) do
-    local info= Module.Quest.Info[questID]
-
-    print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName())
-    local block = Module.Quest.QuestBlock[questID]
-    if block then
-        -- Dispatch the probe
-      if IsQuestWatched(info.logIndex) then
-        itemButton.previousItem = previousItem
-        print('  |cFFFFFF00probing', block:GetName())
-        block:SetScript('OnUpdate', function()
-          if block:GetBottom() and not InCombatLockdown() then
-            print('  '..block:GetName()..' |cFF00FF00probe hit!')
-            Module.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope
-            block:SetScript('OnUpdate', nil)
-
-          end
-        end)
-        previousItem = itemButton
-      else
-        print('hidden block or unwatched quest')
-        itemButton.previousItem = nil
-        itemButton:Hide()
-      end
-    elseif itemButton:IsVisible() then
-      print('  |cFFFF0088hiding unwatched quest button', itemButton:GetName())
-      itemButton.previousItem = nil
-      itemButton:Hide()
-    else
-      print('  |cFFBBBBBBignoring hidden log quest button', itemButton:GetName())
-    end
-  end
-end
-
-Module.UpdateBlockAction = function (block, itemButton)
-  local print = iprint
+T.UpdateBlockAction = function (block, itemButton)
+  local print = bprint
   print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()')
   if itemButton.questID ~= block.info.questID then
     print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID)
     -- something happened between this and last frame, go back and set new probes
-    return Module.UpdateActionButtons()
+    return T.UpdateActionButtons()
   end
 
   local previousItem = itemButton.previousItem
@@ -799,43 +493,34 @@
   itemButton:Show()
 end
 
-Module.UpdateItemButtonCooldown = function(button)
+T.UpdateItemButtonCooldown = function(button)
 
 end
 
+function T:FinishWrapper ()
+  if wrapperHeight > Wrapper.previousHeight then
+    Wrapper:SetHeight(wrapperHeight)
+    Scroller:SetHeight(wrapperHeight*3)
+    Scroll:SetHeight(wrapperHeight)
+    Wrapper.previousHeight = wrapperHeight
+    Wrapper.destinationHeight = wrapperHeight
+  end
+  Scroller:SetVerticalScroll(B.Conf.ObjectiveScroll or 0)
+  print('|cFF00FF00### end of wrapper layout', Wrapper:GetSize())
+  print('  |cFF00FF00Scroller:', Scroller:GetSize())
+  print('  |cFF00FF00Scroll:', Scroll:GetSize())
+  for i = 1, Wrapper:GetNumPoints() do
+    print('|cFF00FF00 ', Wrapper:GetPoint(i))
+  end
+  for i = 1, Scroller:GetNumPoints() do
+    print('|cFF00FF00 ', Scroller:GetPoint(i))
+  end
+  for i = 1, Scroll:GetNumPoints() do
+    print('|cFF00FF00 ', Scroll:GetPoint(i))
+  end
 
-Default.Select = function(handler, block)
-  Module:Update(handler.watchReasonModule)
-end
-Default.Open = function(handler, block)
-  Module:Update(handler.watchReasonModule)
-end
-Default.Remove = function(handler, block)
-  Module:Update(handler.watchReasonModule)
-end
-Default.Report = function(handler, block)
-  print('Stats:', handler.numWatched,'items tracked,', handler.numBlocks,'blocks assigned.')
+  Wrapper:Show()
+  Scroller:Show()
+  Scroll:Show()
 end
 
-Default.OnMouseUp = function(self, button)
-  print(self.handler.name, self.mainStyle, self.subStyle)
-  if button == 'LeftButton' then
-    if IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() then
-      self.Link(self.handler, self)
-    elseif IsModifiedClick("QUESTWATCHTOGGLE") then
-      self.Remove(self.handler, self)
-    else
-      self.Select(self.handler, self)
-    end
-  elseif button == 'RightButton' then
-    self.Open(self.handler, self)
-  end
-  self.initialButton = nil
-  self.modChatLink = nil
-  self.modQuestWatch = nil
-  Module:Update(self.handler.updateReasonModule)
-  print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r')
-end
-Default.OnMouseDown = function(self, button)
-  print(self.info.title)
-end