changeset 10:f03c75f63566

ObjectiveStyle & ObjectiveFrame - abstract aesthetic details away from ObjectiveFrame - revise SetBlockStyle into a more general algorithm for every frame - implement caching of resolved attribute combinations - use loadstring functions to store resolved attributes and call upon those when, for example, a MouseUp leads a tracker block to restore its original style
author Nenue
date Sat, 02 Apr 2016 03:19:25 -0400
parents 2698173edd40
children fb80e365bab3
files ObjectiveCore.lua ObjectiveFrame.lua ObjectiveStyle.lua ObjectiveTracker.xml ObjectiveUI.lua
diffstat 5 files changed, 541 insertions(+), 231 deletions(-) [+]
line wrap: on
line diff
--- a/ObjectiveCore.lua	Fri Apr 01 14:54:01 2016 -0400
+++ b/ObjectiveCore.lua	Sat Apr 02 03:19:25 2016 -0400
@@ -32,6 +32,11 @@
 local Scroller = Wrapper.scrollArea
 local Scroll = _G.VeneerObjectiveScroll
 
+--- Baseline defaults
+mod.defaults = {
+
+}
+
 --- list used to make things happen
 mod.orderedNames = {[1] = 'AutoQuest',  [2] = 'Quest', [3] = 'Cheevs'}
 
--- a/ObjectiveFrame.lua	Fri Apr 01 14:54:01 2016 -0400
+++ b/ObjectiveFrame.lua	Sat Apr 02 03:19:25 2016 -0400
@@ -4,11 +4,11 @@
 -- @file-revision@ @file-hash@
 -- Created: 3/30/2016 12:49 AM
 local B = select(2,...).frame
+local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
 local ipairs, max, min, unpack, floor, pairs, tostring, type = ipairs, max, min, unpack, floor, pairs, tostring, type
 local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion
 local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent
 local CreateFrame = CreateFrame
-local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
 local print = B.print('Objectives')
 --------------------------------------------------------------------
 --- Global frame layout
@@ -26,7 +26,7 @@
 local scrollWidth, scrollHeight
 local previousBlock
 local currentBlock
---- todo: map these into config table when its sorted out
+--- todo: source these from config
 local itemButtonSize, itemButtonSpacing =  36, 1
 local titleFont, textFont = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]]
 local titleSize, textSize = 15, 15
@@ -40,110 +40,13 @@
 local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0}
 
 --- These are mostly aesthetic choices so it lives here
-mod.defaults = {
-  ObjectiveTrackerAnchor = {'BOTTOM', 'RIGHT'},
-  ObjectiveTrackerParent = 'DebuffButton',
-  ObjectiveTrackerSize = {250, 600},
-  ObjectiveWrapperParent = '',
-  WrapperStyle = {
-    Header = {
-      Background = {Left = '', Right = '', Tile = ''},
-      BackgroundCrop = {Left = {0, 0.4, 0,1}, Right={0.6,1,0,1}, Tile = {0.4,.6,0,1,}},
-      BackgroundScale = {Left = 100, Right = 100},
-      Font = {wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline}
-    }
-  },
-  ObjectiveHeaderStyle = {
-    Normal = {
-      Gradient = {MinColor = {.05,.15,0.5,0.7}, MaxColor = {.05,.15,0.5,.35}},
-      Font = {headerFont, headerSize, headerOutline}, Spacing = headerSpacing,
-    }
-  },
-  ObjectiveTrackerStyle = {
-    Normal = {
-      Title = {
-        Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
-        Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
-      },
-      Text = {
-        Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
-        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
-      },
-    },
-    Super = {
-      Title = {
-        Gradient = { MinColor = {0, .7, .6, .8}, MaxColor = {0, .7, .6, 0.2}},
-        Font = {titleFont, titleSize, titleOutline},
-        Spacing = titleSpacing, BackgroundFullWidth = true
-      },
-      Text = {
-        Gradient = { MinColor = {0, .7, .6, 0.5}, MaxColor = {0, .7, .6, 0.1} },
-        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
-      },
-    },
-    Active = {
-      Title = {
-        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .4},        },
-        Font = {titleFont, titleSize, titleOutline},
-        Spacing = titleSpacing,
-        BackgroundFullWidth = true
-      },
-      Text = {
-        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .2},        },
-        Font = {textFont, textSize, textOutline},
-        Spacing = textSpacing,
-        BackgroundFullWidth = true
-      }
-    },
-    Complete = {
-      Title = {
-        Gradient = {          MinColor = {0, 1, 0, 0.34},          MaxColor = {0, 1, 0, .17},        },
-        Font = {titleFont, titleSize, titleOutline},        Spacing = titleSpacing,
-        BackgroundFullWidth = true
-      },
-      Text = {
-        Gradient = {          MinColor = {0, 1, 0, .25},          MaxColor = {0, 1, 0, 0.12},        },
-        Font = {textFont, textSize, textOutline},        Spacing = textSpacing,
-        BackgroundFullWidth = true
-      }
-    },
-    CheevNormal = {
 
-      Title = {
-        Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
-        Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
-      },
-      Text = {
-        Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
-        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
-      },
-    },
-    CheevComplete = {
-
-      Title = {
-        Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
-        Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
-      },
-      Text = {
-        Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
-        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
-      },
-    }
-  }
-}
-
-local FontBank = {
-  ['Normal'] = VeneerCriteriaFontNormal,
-  ['Progress'] = VeneerCriteriaFontProgress,
-  ['Complete'] = VeneerCriteriaFontComplete,
-  ['Failed'] = VeneerCriteriaFontFailed,
-}
 
 local Scroller_OnShow = function()
   Wrapper.watchMoneyReasons = 0;
   mod.UpdateWrapper()
   mod.SetEvents()
-  for i, region in ipairs(Wrapper.header) do
+  for i, region in ipairs(Wrapper.headerComplex) do
     region:Show()
   end
 end
@@ -152,7 +55,7 @@
   local self = Wrapper
   Wrapper:UnregisterAllEvents()
   Wrapper:SetScript('OnEvent', nil)
-  for i, region in ipairs(Wrapper.header) do
+  for i, region in ipairs(Wrapper.headerComplex) do
     region:Hide()
   end
 end
@@ -183,9 +86,6 @@
 
 mod.InitializeTrackers = function()
 
-  local c = mod.defaults.ObjectiveHeaderStyle.Normal
-  local g1, g2, g3, g4 = unpack(c.Gradient.MinColor)
-  local h1, h2, h3, h4 = unpack(c.Gradient.MaxColor)
 
   for i, name in ipairs(orderedNames) do
     if not mod.orderedHandlers[i] then
@@ -193,19 +93,16 @@
         local handler = mod[name]
 
         local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate')
-        tracker.header:SetText(handler.name)
-        tracker.header:SetHeight(headerHeight)
-        tracker.header:SetFont(unpack(c.Font))
-        tracker.header:SetTextColor(unpack(headerColor))
-
-        tracker.headerbg:SetGradientAlpha('HORIZONTAL', g1, g2 ,g3, g4, h1, h2, h3, h4)
-        tracker.headerbg:SetHeight(headerHeight)
+        tracker.title:SetText(name)
+        mod.SetBlockStyle(tracker, 'Tracker', 'Normal')
 
         handler.Tracker = tracker
         mod.orderedTrackers[i] = tracker
         mod.namedTrackers[name] = tracker
         mod.indexedTrackers[handler] = tracker
         print('created new tracker frames for new handler')
+
+
       end
     end
   end
@@ -301,80 +198,18 @@
   end
 end
 
-mod.UpdateReputation = function(self)
-end
 
---- Argument containers
-local a1, a2, a3, a4, b1, b2, b3, b4, f1, f2, f3, w1, w2
-mod.SetBlockStyle = function(block, name)
-  -- var names intended to reflect argument order
-  --@debug@
-  local c = mod.defaults.ObjectiveTrackerStyle[name]
-  --@end-debug@
-  --[===[@non-debug
-  local c = mod.Conf
-  --@end-non-debug]===]
-  a1, a2, a3, a4 = unpack(c.Title.Gradient.MinColor)
-  b1, b2, b3, b4 = unpack(c.Title.Gradient.MaxColor)
-  block.titlebg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
-
-  a1, a2, a3, a4 = unpack(c.Text.Gradient.MinColor)
-  b1, b2, b3, b4 = unpack(c.Text.Gradient.MaxColor)
-  block.bg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
-
-  f1, f2, f3 = unpack(c.Title.Font)
-  block.title:SetFont(f1, f2, f3)
-
-  f1, f2 ,f3 = unpack(c.Text.Font)
-  block.objectives:SetFont(f1,f2,f3)
-
-  w1 = Wrapper:GetWidth()
-  w2 = (c.Title.BackgroundFullWidth and w1 or  block.title:GetStringWidth())
-
-  local titleSpacing, titleSpacing2 = c.Title.Spacing, (c.Title.Spacing * 2)
-  local textSpacing, textSpacing2 = c.Text.Spacing, (c.Text.Spacing * 2)
-
-  if block.info.isTrivial then
-    block.title:SetTextColor(0.7, 0.7, 0.7, 1)
-  elseif block.info.isComplete then
-    block.title:SetTextColor(1,1,1,1)
-  else
-    block.title:SetTextColor(0,.7,1,1)
-  end
-  block.title:SetSpacing(titleSpacing)
-  block.objectives:SetSpacing(textSpacing)
-  block.objectives:SetWordWrap(true)
-
-  local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight() + block.attachmentHeight
-  local blockHeight = titleHeight + titleSpacing2 + textHeight + textSpacing2
-  local blockWidth = wrapperMaxWidth
-
-  block.titlebg:SetSize(min(w1, w2), titleHeight + titleSpacing2)
-  block.bg:SetSize(w1, textHeight + textSpacing2)
-  block:SetSize(blockWidth, blockHeight)
-
-  block.title:SetPoint('TOPLEFT', block.titlebg, 'TOPLEFT', 0, -titleSpacing)
-  block.objectives:SetPoint('TOPLEFT', block.titlebg, 'BOTTOMLEFT', textIndent, -textSpacing)
-
-  -- store
-  block.titleHeight = titleHeight
-  block.textHeight = textHeight
-  block.width = blockWidth
-  block.height = blockHeight
-
-  print('    |cFF00FFFF'..block:GetName()..'|r:|cFF0088FFSetStyle|r(', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
-end
 
 local segments = {'Left', 'Right', 'Tile'}
 mod.UpdateWrapperStyle = function()
-  local c = mod.defaults.WrapperStyle
-  for _, segment in ipairs(segments) do
-    Wrapper['Background'..segment]:SetAtlas(c.Header.Background[segment])
-    Wrapper['Background'..segment]:SetTexCoord(unpack(c.Header.BackgroundCrop[segment]))
-    if c.Header.BackgroundScale[segment] then
-    Wrapper['Background'..segment]:SetWidth(c.Header.BackgroundScale[segment])
+  --[[for _, segment in ipairs(segments) do
+    local texture, a1, a2, a3, a4, width = unpack(mod.defaults.Style.Wrapper.BackgroundComplex[segment])
+    Wrapper['Background'..segment]:SetAtlas(texture)
+    Wrapper['Background'..segment]:SetTexCoord(a1, a2, a3, a4)
+    if width then
+      Wrapper['Background'..segment]:SetWidth(width)
     end
-  end
+  end]]
 end
 
 --- Updates the selected block frame to display the given info batch
@@ -383,20 +218,19 @@
 -- @param info the reference returned by the GetXInfo functions
 -- REMEMBER: t.info and questData[questID] are the same table
 mod.UpdateTrackerBlock = function (handler, blockIndex, info)
+  local print = B.print('ObjectiveBlockParse')
   print('  |cFF00FFFFUpdateTrackerBlock('..blockIndex..'|r')
   if not blockIndex or not info then
     return
   end
 
+  local mainStyle = 'Normal'
+  local subStyle
   local tracker = handler.Tracker
 
   local t = handler:GetBlock(blockIndex)
   if previousBlock then
-    if blockIndex == 1 then
-      t:SetPoint('TOPLEFT', previousBlock, 'TOPLEFT', 0, -headerHeight)
-    else
-      t:SetPoint('TOPLEFT', previousBlock, 'BOTTOMLEFT', 0, 0)
-    end
+    t:SetPoint('TOPLEFT', previousBlock, 'BOTTOMLEFT', 0, 0)
     t:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
   end
   --print(t:GetName(), t:GetSize())
@@ -421,38 +255,38 @@
 
   t.attachmentHeight = 0
   if info.isComplete then
-    t.objectives:Show()
-    t.objectives:SetText(info.completionText)
+    t.status:Show()
+    t.status:SetText(info.completionText)
   elseif info.numObjectives >= 1 then
     t.attachmentHeight = textSpacing
-    t.objectives:Show()
-    print('  - objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
+    t.status:Show()
+    print('  - objective lines:', info.numObjectives, 'can wrap:', t.status:CanWordWrap())
 
     local text = ''
 
     --- todo: implement objective displays
      -- in an accumulator loop, call upon handler for the appropriate display frame, each defining:
-      -- * height of whatever display widget is involved in conveying the task
-      -- * number of non-wrapped text lines to account for line space; may be discarded depending on things
-      -- * boolean that determines listening for money events or not
-    t.attachmentHeight, text = mod.UpdateObjectives(t, info, text)
+      -- * height   - height of whatever display widget is involved in conveying the task
+      -- * lines    - number of non-wrapped text lines to account for line space; may be discarded depending on things
+      -- * money    - boolean that determines listening for money events or not
+      -- * progress - number ranging 0 to 2 indicating none/partial/full completion respectively
+    text = mod.UpdateObjectives(t, info, text)
 
-    t.objectives:SetText(text)
-    t.objectives:SetWordWrap(true)
-
-
+    t.status:SetText(text)
+    t.status:SetWordWrap(true)
 
   elseif info.description then
-    t.objectives:SetText(info.description)
-    t.objectives:SetWordWrap(true)
+    t.status:SetText(info.description)
+    t.status:SetWordWrap(true)
   else
-    t.objectives:SetText(nil)
+    t.status:SetText(nil)
   end
-  local style = 'Normal'
+
   if info.isComplete then
-    style = 'Complete'
-  elseif info.superTracked then
-    style = 'Super'
+    mainStyle = 'Complete'
+  end
+  if info.superTracked then
+    subStyle = 'Super'
   end
 
   if info.specialItem and not info.itemButton then
@@ -468,7 +302,7 @@
   end
 
   --- metrics are calculated in SetStyle
-  t:SetStyle(style)
+  t:SetStyle('TrackerBlock', handler.name, mainStyle, subStyle)
   t:Show()
 
   print('  |cFF00FFFF)|r -> ', t, t:GetHeight())
@@ -476,11 +310,14 @@
 end
 
 mod.UpdateObjectives = function(block, info, text)
+  local print = B.print('ObjectiveBlockParse')
+
   local attachmentHeight = block.attachmentHeight
   if info.description then
     print('  -- has description text:', select('#', info.description), info.description)
     text = info.description
   end
+  local completionScore, completionMax = 0, 0
   for o, obj in ipairs(info.objectives) do
     --- achievement criteria
     if obj.flags then
@@ -500,11 +337,21 @@
       print('obj.type =', obj.type)
       print('  ** qtyStr:', obj.quantityString, 'qty:', obj.quantity, 'assetID:', obj.assetID)
       obj.widget = mod.SetWidget(obj, info)
+      if obj.finished then
+        obj.progress = 2
+      elseif obj.quantity > 0 then
+        obj.progress  = 1
+      else
+        obj.progress = 0
+      end
+
+
       --- none of the above (most quests)
     else
       local line = obj.text
       local color = '00FFFF'
       if obj.finished then
+        obj.progress = 2
         color = 'FFFFFF'
       elseif obj.type == 'monster' then
         color = 'FFFF00'
@@ -522,10 +369,16 @@
       obj.widget:SetPoint('TOPLEFT', block.objectives, 'BOTTOMLEFT', 0, -attachmentHeight)
       print('have a widget, height is', obj.widget.height)
       attachmentHeight = attachmentHeight + obj.widget.height
+      completionScore = completionScore + obj.progress
+      completionMax = completionMax + 2
     end
 
   end
-  return attachmentHeight, text
+
+  block.completionScore = completionScore / completionMax
+  block.attachmentHeight = attachmentHeight
+
+  return text
 end
 
 mod.UpdateTracker = function(handler)
@@ -535,7 +388,7 @@
   local trackerHeight = headerHeight
   local w = 300
 
-  previousBlock = handler.Tracker
+  previousBlock = tracker.title
   local numWatched = handler.GetNumWatched()
   local numBlocks = handler.numBlocks
   local actualBlocks = 0
@@ -546,6 +399,7 @@
       if info then
         local currentBlock = mod.UpdateTrackerBlock(handler, blockIndex, info)
         previousBlock = currentBlock
+        print('|cFF00FF00'..currentBlock:GetName()..'|r', currentBlock.height)
         trackerHeight = trackerHeight + currentBlock.height
         numBlocks = max(numBlocks, watchIndex)
         actualBlocks = actualBlocks + 1
@@ -596,7 +450,7 @@
     if handler.actualBlocks >= 1 then
       local tracker = handler.Tracker
       print('setting', handler.Tracker, 'to anchor to offset', -scrollHeight)
-      tracker:SetParent(Scroll) -- this doesn't do anything that relativeTo doesn't
+      tracker:SetParent(Scroll)
       tracker:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight)
       tracker:SetSize(wrapperWidth, tracker.height)
       print('adding ', tracker.height)
@@ -623,11 +477,11 @@
   headerHeight = floor(headerHeight+.5)
 
   if wrapperBlocks >= 1 then
-    for i, region in ipairs(Wrapper.header) do
+    for i, region in ipairs(Wrapper.headerComplex) do
       region:Show()
     end
   else
-    for i, region in ipairs(Wrapper.header) do
+    for i, region in ipairs(Wrapper.headerComplex) do
       region:Hide()
     end
     return
@@ -639,6 +493,10 @@
   print('|cFFFFFF00params:|r wrapper:', wrapperWidth, 'x', wrapperHeight)
   print('|cFFFFFF00params:|r header:', headerHeight)
 
+  mod.SetBlockStyle(Scroller, 'Scroller', 'Normal')
+  mod.SetBlockStyle(Scroller, 'Scroll', 'Normal')
+  mod.SetBlockStyle(Wrapper, 'Wrapper', 'Normal')
+
   Scroller:SetSize(wrapperWidth, wrapperHeight)
   Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, -headerHeight)
   Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ObjectiveStyle.lua	Sat Apr 02 03:19:25 2016 -0400
@@ -0,0 +1,440 @@
+local B = select(2,...).frame
+local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
+local print = B.print('SetStyle')
+-------------------------------------------------------------
+--- Deals with swapping between different color palettes
+---
+
+local itemButtonSize, itemButtonSpacing =  36, 1
+local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0}
+local titleFont, textFont = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]]
+local titleSize, textSize = 15, 15
+local titleOutline, textOutline = "OUTLINE", "OUTLINE"
+local titleSpacing, textSpacing = 4, 3
+local textIndent = 5
+local wrapperMaxWidth, wrapperMaxHeight = 280, 490 -- these are the hard bounds, actual *Height variables are changed
+local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE'
+local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24
+local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2
+
+mod.defaults.ObjectiveWrapper = {
+  ObjectiveTrackerFloat = {'BOTTOM', 'RIGHT'},
+  ObjectiveTrackerParent = 'DebuffButton',
+  ObjectiveTrackerSize = {250, 600},
+  ObjectiveWrapperParent = '',
+}
+mod.defaults.Style = {
+ FontBank = {
+    ['Normal'] = _G.VeneerCriteriaFontNormal,
+    ['Progress'] = _G.VeneerCriteriaFontProgress,
+    ['Complete'] = _G.VeneerCriteriaFontComplete,
+    ['Failed'] = _G.VeneerCriteriaFontFailed,
+  },
+  Normal = {
+    title = {
+      TextColor = {1, 1, 1, 1},
+      Width = 270,
+    },
+    titlebg = {
+      Background = {0, 0, 0, 1},
+      Width = 270,
+    },
+    status = {
+      Width = 270,
+    },
+    statusbg = {
+      Width = 270,
+    },
+    Frame = {
+      Width = 270,
+    }
+  },
+  Wrapper = {
+    Frame = {
+    Point = {wrapperPosition},
+    MaxSize = {wrapperMaxWidth, wrapperMaxHeight},
+    BackgroundComplex = {Left = {'', 0, 0.4, 0,1, 100}, Right={'', 0.6,1,0,1}, Tile = {'', 0.4,.6,0,1, 100}}, },
+    title = {
+      Font = {wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline},
+      Spacing = 4,}
+  },
+  Tracker = {
+    Normal = {
+      title = {
+        Font = {headerFont, headerSize, headerOutline}, Spacing = headerSpacing,
+      },
+      titlebg = {
+        Gradient = {MinColor = {0,0,0,0.7}, MaxColor = {0,0,0,.35}},
+      }
+    }
+  },
+  TrackerBlock = {
+    Normal = {
+      titlebg = {
+        Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
+      },
+      title = {
+        Font = {titleFont, titleSize, titleOutline},
+        Spacing = titleSpacing,
+      },
+      status = {
+        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
+      },
+      statusbg = {
+        Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
+      }
+    },
+    Super = {
+      title = {
+        Font = {titleFont, titleSize, titleOutline},
+        Spacing = titleSpacing, BackgroundFullWidth = true
+      },
+      titlebg = {
+        Gradient = { MinColor = {0, .7, .6, .8}, MaxColor = {0, .7, .6, 0.2}},
+      },
+      status = {
+        Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
+      },
+      statusbg = {
+        Gradient = { MinColor = {0, .7, .6, 0.5}, MaxColor = {0, .7, .6, 0.1} },
+      },
+    },
+    MouseDown = {
+      title = {
+        Font = {titleFont, titleSize, titleOutline},
+        Spacing = titleSpacing,
+      },
+      titlebg = {
+        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .4},        },
+        BackgroundFullWidth = true,
+      },
+      status = {
+        Font = {textFont, textSize, textOutline},
+        Spacing = textSpacing,
+      },
+      statusbg = {
+        BackgroundFullWidth = true,
+        Gradient = {          MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .2},        },
+      }
+    },
+    Complete = {
+      title = {
+        Font = {titleFont, titleSize, titleOutline},        Spacing = titleSpacing,
+      },
+      titlebg = {
+        Gradient = {          MinColor = {0, 1, 0, 0.34},          MaxColor = {0, 1, 0, .17},        },
+        BackgroundFullWidth = true
+      },
+      status = {
+        Font = {textFont, textSize, textOutline},        Spacing = textSpacing,
+      },
+      statusbg = {
+        Gradient = {          MinColor = {0, 1, 0, .25},          MaxColor = {0, 1, 0, 0.12},        },
+        BackgroundFullWidth = true
+      }
+    },
+    Cheev =  {
+      Normal = {
+
+        title = {
+          Font = {titleFont, titleSize, titleOutline},
+          Spacing = titleSpacing,
+        },
+        titlebg = {
+          Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
+
+        },
+        status = {
+          Font = {textFont, textSize, textOutline},
+          Spacing = textSpacing,
+        },
+        statusbg = {
+          Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
+        },
+      },
+      Complete = {
+        title = {
+          Font = {titleFont, titleSize, titleOutline},
+          Spacing = titleSpacing,
+        },
+        titlebg = {
+          Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
+        },
+        status = {
+          Font = {textFont, textSize, textOutline},
+          Spacing = textSpacing,
+        },
+        statusbg = {
+          Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
+        },
+      },
+    }
+  }
+}
+
+local style_cache_func = {}
+local block_vars = {
+  ['titleSize'] = {'titleWidth', 'titleHeight'},
+  ['FrameSize'] = {'width', 'height'}
+}
+local attrib_vars = {
+  ['Font'] = {'height'},
+}
+
+mod.BlockStyleCache = {}
+local style_cache = mod.BlockStyleCache
+mod.regions = {}
+mod.regionStyles = {}
+mod.SetBlockStyle = function(frame, frameType, ...)
+  -- var names intended to reflect argument order
+  --@debug@
+  local c = mod.defaults.Normal
+  local style_list = {... }
+  local styleName = frameType .. '-' .. table.concat(style_list,'')
+
+  if not style_cache[styleName] then
+    local style = {}
+
+    if mod.defaults.Style[frameType] then
+      print(' setting style class |cFF00FFFF'..frameType)
+    else
+      print(' resorting to class Normal (missing |cFFFF8800'.. frameType..'|r)')
+    end
+    local normal = mod.defaults.Style.Normal
+    local root =  mod.defaults.Style[frameType] or normal
+    for i, className in ipairs(style_list) do
+      local class = root[className] or normal[className] or root
+      if root[className] then
+
+        print('  SubClass |cFF0088FF'.. className .. '|r')
+      elseif normal[className] then
+        print('  SubClass Normal.|cFFFF0088'..className..'|r')
+      else
+        print('  SubClass Normal')
+      end
+      for elementName, element in pairs(class) do
+        if not elementName:match('^%u') then
+          print('   scanning Element |cFF8800FF'.. elementName ..'|r')
+          if not style[elementName] then
+            style[elementName] = {}
+          end
+          for key, value in pairs(element) do
+            if mod.SetBlockAttribute[key] then
+              print('   |cFF00FF00'..elementName..'|r.|cFF00FFFF'..key..' =', (type(value) == 'table' and ('{'..table.concat(value,', ')..'}') or tostring(value)))
+              style[elementName][key] = value
+            end
+
+          end
+        end
+
+      end
+
+    end
+
+    for k, elements in pairs(mod.defaults.Style.Normal) do
+      if not style[k] and type(elements) ~= 'table' then
+        style[k] = elements
+      end
+    end
+
+
+    print('result for: ', frame:GetName())
+    for k,v in pairs(style) do
+      if type(v) == 'table' and not k:match('^%u') then
+        for kk, vv in pairs(v) do
+        print('  |cFFFFFF00'..k..'|r.|cFF00FF00'..kk..'|r =', tostring(vv))
+        end
+      else
+        print(' |cFFFFFFFF' .. k ..'|r =', tostring(v))
+      end
+    end
+    style_cache[styleName] = style
+  else
+    print('Cache hit: ', styleName)
+  end
+
+  local style = style_cache[styleName]
+
+  if not style_cache_func[styleName] then
+    local code =
+        "return function (frame)\n"..
+        "  local func = Veneer.ObjectiveTracker.SetBlockAttribute\n"..
+        "  local cache = Veneer.ObjectiveTracker.BlockStyleCache" ..
+        "  print('CacheFunc', '|cFFFFFF00SET|r "..styleName.." |cFFFFFF00ON|r', frame:GetName()) "
+
+    for elementName, styleset in pairs(style) do
+        code = code ..
+            "\n if frame['"..elementName.."'] then"
+
+        for attributeName, value in pairs(styleset) do
+          if mod.SetBlockAttribute[attributeName] then
+            print('  '..elementName..':'.. attributeName ..'(', value, ')')
+
+
+            --mod.SetBlockAttribute[attributeName](region, value)
+            code = code .. "\n    print('CacheFunc', '  applying', '|cFF00FFFF" .. attributeName .. "|r to', '|cFF0088FF"..elementName.."|r', cache['"..styleName.."']['"..elementName.."']['".. attributeName .."'])" ..
+                "\n\n    func['" .. attributeName .. "'](frame['"..elementName.."'],"..
+                " cache['"..styleName.."']['"..elementName.."']['".. attributeName .."'])"
+
+            --- Set any frame.blah variables used in Updates
+            if block_vars[elementName .. attributeName] then
+              print('|cFF008800BVar|r', elementName..attributeName)
+              for i, blockKey in ipairs(block_vars[elementName .. attributeName]) do
+                print('  assigning |cFF008800'..blockKey..'|r')
+                frame[blockKey] = (type(value) == 'table') and value[i] or value
+              end
+            end
+
+          end
+        end
+        code = code ..
+            "\n  else"..
+            "\n    print('CacheFunc', '  |cFFFF4400missing', frame:GetName()..'."..elementName.."')"..
+            "\n  end"
+    end
+    code = code .. "\nend"
+    local result = assert(loadstring(code))
+    print('storing style func', styleName, result())
+    style_cache_func[styleName] = result()
+
+  else
+    print('Cache function hit:', styleName)
+  end
+  style_cache_func[styleName](frame)
+
+
+  --print("Generated func = function()\n",code, "\nend")
+  --local cache_func[styleName] = loadstring(code)
+
+  -- todo: remove hardcode and rely on attribute handler
+  if frame.status then
+    frame.status:SetWidth(270)
+  end
+  if frame.title then
+    frame.title:SetWidth(270)
+  end
+
+
+  frame.titleHeight = frame.title and (frame.title:GetStringHeight() + frame.title.spacing*2) or 0
+  frame.statusHeight = frame.status and (frame.status:GetStringHeight() + frame.status.spacing*2 + frame.attachmentHeight) or 0
+  frame.height = frame.titleHeight + frame.statusHeight
+  frame.width = 270
+
+
+  if frame.status then
+    print('status  ', frame.statusHeight)
+    frame.status:SetHeight(frame.statusHeight)
+    if frame.statusbg then
+
+      print('statusbg', frame.statusHeight)
+      frame.statusbg:SetHeight(frame.statusHeight)
+      frame.statusbg:SetWidth(frame.width)
+    end
+  end
+  if frame.title then
+    print('title  ',frame.titleHeight)
+    frame.title:SetHeight(frame.titleHeight)
+    if frame.titlebg then
+      print('titlebg',frame.titleHeight)
+      frame.titlebg:SetHeight(frame.titleHeight)
+      frame.titlebg:SetWidth(frame.width)
+    end
+  end
+  print('sizing frame', frame.width, frame.height)
+  frame:SetSize(frame.width, frame.height)
+  print(frame:GetSize())
+    --[[
+      local titleSpacing, titleSpacing2 = c.Title.Spacing, (c.Title.Spacing * 2)
+      local textSpacing, textSpacing2 = c.Text.Spacing, (c.Text.Spacing * 2)
+
+      block.title:SetSpacing(titleSpacing)
+      block.objectives:SetSpacing(textSpacing)
+      block.objectives:SetWordWrap(true)
+
+      local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight() + block.attachmentHeight
+      local blockHeight = titleHeight + titleSpacing2 + textHeight + textSpacing2
+      local blockWidth = wrapperMaxWidth
+
+      block.titlebg:SetSize(min(w1, w2), titleHeight + titleSpacing2)
+      block.bg:SetSize(w1, textHeight + textSpacing2)
+      block:SetSize(blockWidth, blockHeight)
+
+      block.title:SetPoint('TOPLEFT', block.titlebg, 'TOPLEFT', 0, -titleSpacing)
+      block.objectives:SetPoint('TOPLEFT', block.titlebg, 'BOTTOMLEFT', textIndent, -textSpacing)
+
+      -- store
+      block.titleHeight = titleHeight
+      block.textHeight = textHeight
+      block.width = blockWidth
+      block.height = blockHeight
+    --]]
+  --print('    |cFF00FFFF'..block:GetName()..'|r:|cFF0088FFSetStyle|r(', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
+end
+
+--- Argument containers
+local o = "" -- text flag
+local a1, a2, a3, a4, b1, b2, b3, b4 = 0,0,0,1, 0,0,0,1 -- color1, color2
+local f1, f2, f3 = "", 0, "" -- font
+local w1, w2 = 0, 0 -- size
+local p1, p2, p3, x, y = "", "", "", 0, 0 -- path/point args
+mod.SetBlockAttribute = {}
+local sb = mod.SetBlockAttribute
+local print = B.print('Attribute')
+sb.Gradient = function(region, value)
+  print('|cFF8844FFGradient|r', region:GetName(), unpack(value))
+  o = 'HORIZONTAL'
+  a1, a2, a3, a4 = unpack(value.MinColor)
+  b1, b2, b3, b4 = unpack(value.MaxColor)
+  region:SetVertexColor(1,1,1)
+  region:SetTexture(1,1,1,1)
+  region:SetGradientAlpha(o, a1, a2, a3, a4, b1, b2, b3, b4)
+end
+
+sb.Background = function(region, value)
+  print('|cFF0088FFBackground|r', unpack(value))
+  region:SetVertexColor(1,1,1) -- reset
+  region:SetTexture(unpack(value))
+end
+sb.BackgroundComplex = function (region, value)
+  local left, tile, right = value.Left, value.Tile, value.Right
+
+end
+sb.Font = function(region, value)
+  f1, f2, f3 = unpack(value)
+  print('|cFFFFFF00Font|r', f1, f2, f3)
+  region:SetFont(f1, f2, f3)
+end
+
+sb.Spacing = function(region, value)
+  print('FontSpacing', value)
+  region:SetSpacing(value)
+  region.spacing = value
+end
+
+sb.TextColor = function(region, value)
+  a1, a2, a3, a4 = unpack(value)
+  print('TextColor', a1, a2, a3, a4)
+  region:SetTextColor(a1, a2, a3, a4)
+end
+sb.Texture = function(region, value)
+
+  p1, a1, a2, a3, a4 = unpack(value)
+  print('Texture', p1, a1, a2, a3, a4)
+  region:SetTexture(p1)
+  if a1 then
+    region:SetTexCoord(a1, a2, a3, a4)
+  end
+end
+sb.Width = function(region, value)
+  w1 = value
+  region:SetWidth(w1)
+end
+
+sb.Height = function(region, value)
+  w2 = value
+  region:SetHeight(w2)
+end
+sb.Size = function(region, value)
+  w1, w2 = unpack(value)
+  region:SetSize(w1, w2)
+end
\ No newline at end of file
--- a/ObjectiveTracker.xml	Fri Apr 01 14:54:01 2016 -0400
+++ b/ObjectiveTracker.xml	Sat Apr 02 03:19:25 2016 -0400
@@ -19,6 +19,10 @@
     <Color r="1" g=".4" b="0" a=".75" />
   </Font>
 
+  <Font name="VeneerStatusFont" virtual="true" font="Fonts\FRIZQT__.TTF" outline="NORMAL" height="14">
+    <Color r="1" g="1" b="0" a="1" />
+  </Font>
+
   <Frame name="VeneerObjectiveWrapper" parent="UIParent" movable="true" enableMouse="true">
     <Scripts>
       <OnLoad>
@@ -44,10 +48,10 @@
     <Layers>
 
       <Layer level="ARTWORK">
-        <Texture parentKey="BackgroundLeft" parentArray="header" />
-        <Texture parentKey="BackgroundRight" parentArray="header" />
-        <Texture parentKey="BackgroundTile" parentArray="header" />
-        <Texture parentKey="HeaderBounds" parentArray="config" alphaMode="ADD" hidden="true">
+        <Texture parentKey="BackgroundLeft" parentArray="headerComplex" />
+        <Texture parentKey="BackgroundRight" parentArray="headerComplex" />
+        <Texture parentKey="BackgroundTile" parentArray="headerComplex" />
+        <Texture parentKey="headerComplexBounds" parentArray="config" alphaMode="ADD" hidden="true">
           <Color r="0" g="0" b="1" a="0.5" />
           <Anchors>
             <Anchor point="TOPLEFT" relativeKey="$parent.BackgroundLeft" />
@@ -84,7 +88,11 @@
         </Texture>-->
       </Layer>
       <Layer level="OVERLAY">
-
+        <FontString name="$parentTitle" parentKey="title" inherits="VeneerStatusFont">
+          <Anchors>
+            <Anchor point="LEFT" />
+          </Anchors>
+        </FontString>
       </Layer>
     </Layers>
     <Frames>
@@ -96,11 +104,11 @@
         </Anchors>
         <Layers>
           <Layer level="BACKGROUND">
-            <Texture name="$parentBackground" parentKey="bg" setAllPoints="true"/>
+            <Texture name="$parentBackground" parentKey="background" setAllPoints="true"/>
           </Layer>
           <Layer level="ARTWORK">
 
-            <Texture name="$parentForeground" parentKey="fg">
+            <Texture name="$parentForeground" parentKey="foreground">
               <Anchors>
                 <Anchor point="TOPLEFT" />
                 <Anchor point="BOTTOMLEFT" />
@@ -114,7 +122,7 @@
             </Texture>
           </Layer>
           <Layer level="OVERLAY">
-            <FontString inherits="VeneerFontNormal" parentKey="xpText">
+            <FontString inherits="VeneerFontNormal" parentKey="title">
               <Anchors>
                 <Anchor point="CENTER" />
               </Anchors>
@@ -133,7 +141,7 @@
       <ScrollFrame name="$parentScrollFrame" enableMouseWheel="true" parentKey="scrollArea">
         <Layers>
           <Layer level="BACKGROUND">
-            <Texture setAllPoints="true">
+            <Texture setAllPoints="true" parentKey="bg">
               <Color r="0.15" g=".3" b=".3" a="0" />
             </Texture>
           </Layer>
@@ -167,7 +175,7 @@
     </Anchors>
     <Layers>
       <Layer level="BACKGROUND">
-        <Texture setAllPoints="true">
+        <Texture setAllPoints="true" parentKey="bg">
           <Color r="1" g="1" b="1" a="1" />
           <Gradient orientation="HORIZONTAL">
             <MinColor r="0" g="0.5" b="0.5" a="0" />
@@ -181,7 +189,7 @@
   <Frame name="VeneerTrackerTemplate" parent="UIParent" virtual="true">
     <Layers>
       <Layer level="BACKGROUND">
-        <Texture name="$parentHeaderBG" parentKey="headerbg">
+        <Texture name="$parentTitleBackground" parentKey="titlebg">
           <Anchors>
             <Anchor point="TOPLEFT" relativePoint="TOPLEFT" />
             <Anchor point="RIGHT" relativePoint="RIGHT" />
@@ -194,13 +202,11 @@
         </Texture>
       </Layer>
       <Layer level="OVERLAY">
-        <FontString name="$parentHeader" inherits="VeneerFontHighlight" text="OBJ" parentKey="header">
+        <FontString name="$parentTitle" inherits="VeneerFontHighlight" text="OBJ" parentKey="title">
           <Anchors>
             <Anchor point="TOPLEFT" />
           </Anchors>
         </FontString>
-
-
       </Layer>
     </Layers>
   </Frame>
@@ -217,7 +223,7 @@
             <Anchor point="TOPLEFT" />
           </Anchors>
         </Texture>
-        <Texture name="$parentBackground" parentKey="bg">
+        <Texture name="$parentStatusBackground" parentKey="statusbg">
           <Anchors>
             <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.titlebg" />
           </Anchors>
@@ -250,8 +256,8 @@
         </Texture>
         <Texture name="$parentLowLight" parentKey="highlight2">
           <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bg" x="0" y="14" />
-            <Anchor point="BOTTOM" relativePoint="BOTTOM" relativeKey="$parent.bg" x="0" y="0"/>
+            <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.statusbg" x="0" y="14" />
+            <Anchor point="BOTTOM" relativePoint="BOTTOM" relativeKey="$parent.statusbg" x="0" y="0"/>
             <Anchor point="RIGHT" relativePoint="RIGHT" relativeKey="$parent" />
           </Anchors>
           <Color r="1" g="1" b="1" a="1" />
@@ -267,9 +273,9 @@
             <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.titlebg" />
           </Anchors>
         </FontString>
-        <FontString name="$parentLeaderBoard" parentKey="objectives" inherits="VeneerFontNormal" justifyH="LEFT" justifyV="MIDDLE" wordwrap="true">
+        <FontString name="$parentStatus" parentKey="status" inherits="VeneerFontNormal" justifyH="LEFT" justifyV="MIDDLE" wordwrap="true">
           <Anchors>
-            <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.bg" x="5" y="0" />
+            <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.statusbg" x="5" y="0" />
             <Anchor point="RIGHT" relativeKey="$parent" />
           </Anchors>
         </FontString>
@@ -288,6 +294,7 @@
   <Script file="ObjectiveCore.lua" />
   <Script file="ObjectiveInfo.lua" />
   <Script file="ObjectiveUI.lua" />
+  <Script file="ObjectiveStyle.lua" />
   <Script file="ObjectiveFrame.lua" />
   <Script file="ObjectiveEvents.lua" />
 </Ui>
\ No newline at end of file
--- a/ObjectiveUI.lua	Fri Apr 01 14:54:01 2016 -0400
+++ b/ObjectiveUI.lua	Sat Apr 02 03:19:25 2016 -0400
@@ -40,7 +40,7 @@
 end
 
 Tracker.OnMouseDown = function(self, button)
-  self:SetStyle('Active')
+  self:SetStyle('TrackeBlock','MouseDown')
   print(IsModifiedClick("CHATLINK"), IsModifiedClick("QUESTWATCHTOGGLE"))
   print(self.info.title)
 end
@@ -82,7 +82,7 @@
 end
 Cheevs.OnMouseUp = function(self, button)
   Tracker.OnMouseUp(self, button)
-  self:SetStyle('CheevNormal')
+  self:SetStyle('TrackerBlock', 'Cheev', 'CheevNormal')
 end
 Cheevs.Link = function(self)
   local achievementLink = GetAchievementLink(self.info.cheevID);