view ObjectiveTracker/Layout.lua @ 51:4586229986e6

disambiguate local module names
author Nenue
date Fri, 29 Apr 2016 10:52:57 -0400
parents dd1ae565f559
children ed74c5cabe98
line wrap: on
line source
--- ${PACKAGE_NAME}
-- @file-author@
-- @project-revision@ @project-hash@
-- @file-revision@ @file-hash@
-- Created: 3/30/2016 12:49 AM
--- Everything that involves directly placing elements on the screen goes here. Sizing, spacing, tiling, etc.
local B = select(2,...).frame
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 = 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 band, bor = bit.band, bit.bor
local print = B.print('Layout')
local oprint = B.print('Objectives')
local bprint = B.print('Block')
local tprint = B.print('Tracker')
local lprint = B.print('Layout')
local unitLevel = 1

local REWARD_POPUP = _G.VeneerRewardsPopOut
local ANIM_STATE = 'Animation: %04X'
local INIT_STATE = 'Init: %04X'

--- Bitfields of import
--- control value for everything
local OBJECTIVE_TRACKER_UPDATE_REASON = _G.OBJECTIVE_TRACKER_UPDATE_REASON
--- flags reason categories where frame layout requires initializing (starts high)
local initReason = 0xFFFF
--- flags reason categories where frame anchor updates must be delayed because of an ongoing animation (starts low)
local animateReason = 0x0000

--- FRAMES
local Wrapper = _G.VeneerObjectiveWrapper
local Scroller = Wrapper.scrollArea
local Scroll = _G.VeneerObjectiveScroll
local orderedHandlers = T.orderedHandlers
local orderedNames = T.orderedNames

--- FRAME TEMP VARIABLES
local wrapperWidth, wrapperHeight = 0, 0
local scrollWidth, scrollHeight

--- 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 titleFont, titleSize, titleOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'OUTLINE'
local titleColor = {0,.7,1,1 }
local titleBlend = 'BLEND'

local textbg =  {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 }
local textFont, textSize, textOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]], 16, 'OUTLINE'
local textColor = {1,1,1,1 }
local textBlend = 'BLEND'

local widgetTextFont, widgetTextSize, widgetTextOutline = [[Interface\Addons\SharedMedia_MyMedia\font\XOIREQE.TTF]], 11, 'OUTLINE'
local widgetTextColor = {1,1,1,1 }
local widgetHeight, widgetBorder = 17, 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
local blockPosition


local SetAnimate = function(reason, animate)
  print('comparing', animateReason, reason)
  if animate then
    if band(animateReason, reason) == 0 then
      animateReason = animateReason + reason
    end
  else
    if band(animateReason, reason) > 0 then
      animateReason = animateReason - reason
    end
  end
  Wrapper.AnimState:SetFormattedText(ANIM_STATE, animateReason)
end


--- schema swapper
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 = T.Conf.Schema[layer][newSchema]

  if layer == 'tracker' then
    headerHeight, headerSpacing = c.headerHeight, c.headerSpacing
    headerColor = c.headerColor
    headerbg = c.headerbg
    headerFont, headerSize, headerOutline = unpack(c.headerFont)
    trackerSchema = newSchema
  elseif layer == 'block' then
    titlebg = c.titlebg
    titleFont, titleSize, titleOutline = unpack(c.titleFont)
    selectionbg = c.selectionbg
    titleSpacing, textSpacing, blockSpacing = c.titleSpacing, c.textSpacing, c.blockSpacing
    titleIndent, textIndent,selectionIndent = c.titleIndex, c.textIndex, c.selectionIndent
    titleColor = c.titleColor
    titleBlend = c.titlebg[10] or 'BLEND'
    textBlend = c.textbg[10] or 'BLEND'
    print(unpack(c.titleColor))
    rewardSize = 24
    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
  elseif layer == 'widget' then
    widgetTextColor = c.textSpacing
    widgetTextFont, widgetTextSize, widgetTextOutline = unpack(c.textFont)
  end
  tprint('|cFFFF0088       Schema:|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)
  local isInitialized = true
  if initReason and (band(initReason, handler.updateReason) > 0 ) then
    isInitialized = false
    initReason = initReason - handler.updateReason
    print('|cFF00FF00%%% initialization status update:', format('%04X', initReason))

    frame.SlideIn:SetScript('OnPlay', function()
      SetAnimate(handler.updateReasonModule, true)
    end)

    frame.SlideIn:SetScript('OnFinished',  function()
      SetAnimate(handler.updateReasonModule, false)
    end)

    if initReason == 0 then
      initReason = nil
    end
  end

  if index == 1 then
    print('|cFF00FF00### beginning wrapper layout -----------------')
    anchorPoint, anchorFrame = 'TOP', Scroll
    wrapperHeight = 18
  end

  frame.destinationOffset = -wrapperHeight
  print(frame.destinationOffset, frame.previousOffset)
  if isInitialized 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 '..handler.name..' to', anchorFrame:GetName(), anchorPoint, '|rcurrent frame height:', frame.height)
    print('  |cFFFF0088total height:', wrapperHeight)
    frame:ClearAllPoints()
    frame:Show()
    frame:SetParent(Scroll)
    frame:SetPoint('TOP', Scroll, 'TOP', 0, frame.destinationOffset)
    frame:SetPoint('LEFT', Scroll, 'LEFT')
    frame:SetPoint('RIGHT', Scroll, 'RIGHT')
    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

  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)
  local print = bprint
  local tracker = self.frame
  local info = block.info

  block.index = blockIndex
  print('blockschema', blockSchema, block.schema)
  if blockSchema ~= block.schema then
    T.UpdateSchema('block', block.schema)
    print('  ### activating block schema:|cFF0088FF', block.schema)
  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.titlebg:SetBlendMode(titleBlend)
  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.statusbg:SetBlendMode(textBlend)
  block.SelectionOverlay:SetGradientAlpha(unpack(selectionbg))
  block.SelectionOverlay:SetPoint('TOPLEFT', selectionIndent, 0)
  block.SelectionOverlay:SetPoint('BOTTOMRIGHT')


  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)

  if attachmentHeight > 0 then
    attachmentHeight = attachmentHeight + textSpacing
  end

  block.height = titlebgHeight + attachmentHeight
  block:SetHeight(block.height)

  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

  self.print('AddBlock', 'anchor to|cFF0088FF', self.currentAnchor:GetName())
  self.print('AddBlock', 'attachment:|cFF00FF00', attachmentHeight, '|rtitle:|cFF00FF00', titlebgHeight, '|r('.. titleHeight..')')
  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

  --- Handler vars
  if blockIndex == 1 then
    tracker.previousHeight = tracker.height
    tracker.height = headerHeight
    blockPosition = -headerHeight
    self.print('AddBlock', 'new layout: headerHeight:|cFF00FF00', headerHeight, '|rpreviousHeight:|cFF00FF00', tracker.previousHeight)
  else
    blockPosition = blockPosition
    self.print('AddBlock', 'advancing: height:|cFF8888FF', 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
  blockPosition = blockPosition - block.height

  block:Show()


  if Devian and Devian.InWorkspace() then
    block.DebugTab:SetParent(UIParent)
    block.DebugTab:SetPoint('RIGHT', block.titlebg, 'LEFT', 0, 0)
    block.DebugTab.status:SetText(tostring(block.schema) .. ' @|cFF00FF00' .. tostring(block.posIndex) .. '|r #|cFFFFFF00'.. tostring(info.logIndex or info.id) .. '|r'..
        ' H|cFFFFFF00' .. tostring(block.height) .. ' L|cFF00FFFF' .. tostring(block.numLines) ..'|r ' .. (info.statusKey or ''))
    block.DebugTab:Show()
  end
end


local tagOrder = {'completion', 'frequency', 'type'}
--- Used as an iterator of sorts for cascaded tag icon placements (the daily/faction/account icons)
Default.AddTags = function (handler, block, tagInfo, tagCoords)
  local print = bprint

  local tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', block, 'TOPRIGHT'
  handler.print('AddTag', block:GetName(), tagInfo, tagCoords)
  for order, key in ipairs(tagOrder) do
    local tag = block[key .. 'Tag']
    if tag and tagInfo[key] then
      tag:SetTexCoord(unpack(tagInfo[key]))
      tag:Show()
      tag:SetPoint(tagPoint, tagAnchor, tagRelative, 0, 0)
      tagPoint, tagAnchor, tagRelative = 'TOPRIGHT', tag, 'TOPLEFT'
    else
      block[key .. 'Tag']:Hide()
    end
  end

  return tagPoint, tagAnchor, tagRelative
end


--- Adds the given line to the current content and advances the anchor pointer to that new line for the following call.
Default.AddLine = function(handler, block, text, attachment, template)
  local print = lprint
  local lineIndex = block.currentLine + 1
  local line = handler:GetLine(block, lineIndex)

  line.index = lineIndex
  template = template or 'default'
  if template and lineSchema ~= template then
      print('      |cFF00FF00change schema', template)
      T.UpdateSchema('line', template)
  end
  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: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()
  line:SetScript('OnMouseUp', function(self, button)
    handler.OnMouseUp(block, button)
  end)


  handler.print('AddLine', '|cFF00FFFF'..tostring(line.schema)..'|r', line:GetName())
  --[[
  for i = 1, line:GetNumPoints() do
    tprint('      - ', line:GetPoint(i))
  end
  tprint('      - ', line:GetSize())
  tprint('      - ', line:GetParent(), line:GetParent():IsVisible())
  tprint('      - ', line:IsVisible())
  --]]




  -- fill in the text, then derive pixel-rounded height
  line.status:SetText(text)
  line.height = floor(line.status:GetStringHeight()+.5)

  -- For progressbar and timer lines, status text may be used as the title heading
  if attachment then
    attachment:SetPoint('TOP', line, 'TOP')
    attachment:SetPoint('LEFT', line, 'LEFT', textIndent, 0)
    attachment:SetPoint('RIGHT', line, 'RIGHT')
    print('      |cFFFF0088doing things with a widget', attachment:GetSize())
    line.height = attachment:GetHeight()
    if text then
      line.height = max(line.height, line.status:GetStringHeight())
    end
    if attachment.status:GetText() then
      line.height = max(line.height, attachment.status:GetStringHeight())
    end
    attachment:Show()
  end

  line:SetHeight(line.height)
  block.attachmentHeight = block.attachmentHeight + line.height + textSpacing

  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 -- edge used for the next block

  return lineIndex
end



----------
--- Top level methods


T.UpdateItemButtonAnchor = 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 T.UpdateActionButtons()
  end

  local previousItem = itemButton.previousItem
  local upper_bound = Scroller:GetTop() + Scroller.snap_upper
  local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize
  local point, anchor, relative

  if block:GetBottom() < lower_bound then
    print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5))
    if previousItem then
      print('adjusting', previousItem:GetName())
      previousItem:ClearAllPoints()
      previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing)
    end
    itemButton:ClearAllPoints()
    itemButton.x = Wrapper:GetLeft() -4
    itemButton.y = Wrapper:GetBottom()
    point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT'
    Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing

  elseif block:GetTop() > upper_bound then
    print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5))
    itemButton:ClearAllPoints()
    if previousItem then
      print('latch onto another piece')
      point, anchor, relative ='TOP', previousItem, 'BOTTOM'
      itemButton.x = 0
      itemButton.y = -itemButtonSpacing
    else
      print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop())
      point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
      itemButton.x = Scroller:GetLeft() -4
      itemButton.y = Scroller:GetTop()
    end
    itemButton:Show()
    Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing)
  else
    print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5))
    itemButton:ClearAllPoints()
    itemButton.x = block:GetLeft() - itemButtonSpacing
    itemButton.y = block:GetTop()
    point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
  end

  itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y)
  itemButton:Show()
end

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

  if Devian and Devian.InWorkspace() then
    Wrapper.AnimState:SetFormattedText(ANIM_STATE, animateReason)
    Wrapper.AnimState:Show()
  end

  Wrapper:Show()
  Scroller:Show()
  Scroll:Show()
end


-----------------------------------------
-- Criteria frames

--[[
      text = description,
      type = type,
      finished = completed,
      quantity = quantity,
      requiredQuantity = requiredQuantity,
      characterName = characterName,
      flags = flags,
      assetID = assetID,
      quantityString = quantityString,
      criteriaID = criteriaID,
]]
T.WidgetRegistry = {}
local wr = T.WidgetRegistry

--- WidgetTemplate 'OnShow'
local wrapperWidth, textIndent
T.InitializeWidget = setmetatable({}, {
  __call = function(t, frame, isNew, ...)
    -- todo: config pull
    if not wrapperWidth then
      wrapperWidth = T.Conf.Wrapper.Width
      textIndent = T.Conf.Wrapper.TextIndent
    end

    tprint('Initialize', frame:GetName(), isNew, ...)
    frame:SetWidth(wrapperWidth - textIndent * 2)
    frame:SetScript('OnEvent', T.UpdateWidget[frame.widgetType])
    frame:RegisterEvent('QUEST_LOG_UPDATE')
    frame:RegisterEvent('TRACKED_ACHIEVEMENT_UPDATE')
    frame:RegisterEvent('TRACKED_ACHIEVEMENT_LIST_CHANGED')
    frame:RegisterEvent('CRITERIA_UPDATE')
    frame:RegisterEvent('CRITERIA_COMPLETE')
    frame:RegisterEvent('CRITERIA_EARNED')
    t[frame.widgetType](frame, isNew)
    T.UpdateWidget[frame.widgetType](frame, isNew)
  end,
})

--- WidgetTemplate 'OnEvent'
T.UpdateWidget = setmetatable({}, {
  __call = function(t, frame, isNew, ...)
    tprint('Update', frame:GetName(), isNew, ...)
    if not frame.widgetType then
      return
    end

    return t[frame.widgetType](frame, isNew)
  end
})


local progressHeight = 17
local progressBorder = 1
local progressFont = _G.VeneerCriteriaFontNormal

local lprint = B.print('Line')
T.InitializeWidget.StatusBar = function(self, isNew)
  local print = lprint
  local c = T.Conf.Wrapper

  tprint(self:GetName(), isNew)
  if isNew then
    self:SetMinMaxValues(0, self.maxValue)

    self:SetHeight(widgetHeight)
    self.height = widgetHeight

    self.status:SetFont(widgetTextFont, widgetTextSize, widgetTextOutline)
    self.status:SetTextColor(unpack(widgetTextColor))
  end
  self:SetValue(self.value)

  self.status:SetText(self.objective.quantityString)
end

T.UpdateWidget.StatusBar = function (self)
  local value, maxValue = self.value, self.maxValue
  print('update vals:')
  for k,v in pairs(self) do
    print(k, v)
  end
  self.width = self.width or self:GetWidth()
  self:SetValue(self.value)
  local format = self.format or '%d/%d'
  self.status:SetFormattedText(format, value, maxValue)
  local progress = (value / maxValue)
  if progress > 0 then
    print('color:', 1-progress*2 , progress*2 - 1,0,1)
    print('width:', (self.width  -progressBorder * 2) * progress)
    self:SetStatusBarColor(1-progress*2 , progress*2,0,1)
  end
end


T.InitializeWidget.Hidden = function (self)
  self.height = 0
end
T.UpdateWidget.Hidden = function (self)
  self.height=  0
end


--- Queue any active item buttons for update for that frame
local iprint = B.print('ItemButton')
local Quest = T.Quest
local IsQuestWatched, InCombatLockdown = IsQuestWatched, InCombatLockdown
T.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= T.Quest.Info[questID]

    print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName())
    local block = T.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!')
            T.UpdateItemButtonAnchor(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

Default.FadeOutBlock = function (handler, blockIndex)

end