diff Veneer.lua @ 47:1a322b92dbfa

file cleanup
author Nenue
date Thu, 28 Apr 2016 05:54:21 -0400
parents Init.lua@756e8aeb040b
children 9837069e366a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Veneer.lua	Thu Apr 28 05:54:21 2016 -0400
@@ -0,0 +1,569 @@
+--- Modulizer framework
+-- OnInitialize
+-- OnUpdate
+-- OnEnable     -- run when GetSpecialization() returns true
+
+local ADDON, A = ...
+Veneer = Veneer or CreateFrame('Frame', 'Veneer', UIParent)
+local B = Veneer
+local wipe, min, max, random, tinsert, tremove = table.wipe, math.min, math.max, math.random, table.insert, table.remove
+local pairs, ipairs, select, unpack, _G = pairs, ipairs, select, unpack, _G
+local type, tostring, format = type, tostring, string.format
+A.frame = B
+
+--- Cache tables
+local initOnced
+local modules = {}
+local queuedModules = {}
+local checkForConfig = {}
+local moduleStack = {
+}
+
+--- Utilities
+B.wipeall = function (...)
+  for i = 1, select('#', ...) do
+    wipe(select(i, ...))
+  end
+end
+
+--- Various region categories
+B.displays = {}
+B.configLayers = {}
+B.configLayersRef = {}
+
+
+--@debug@
+--- Generates a print handler pointing to a static channel signature
+-- @usage func = B.print(sig)
+-- @param sig channel name or number
+local printfuncs = {}
+B.print = function(pref, ...)
+  if Devian and Devian.InWorkspace() then
+      printfuncs[pref] = printfuncs[pref] or function(...) print(pref,  ...) end
+
+    return printfuncs[pref]
+  else
+   return function () end
+  end
+end
+
+local rgb = {}
+local getcolor = function()
+  local n, p = 0, 4
+  for i = 1, 3 do
+    rgb[i] = min(random(n,p) * 64, 255)
+    if rgb[i] == 255 then
+      p = 4
+    elseif rgb[i] > 0 then
+      n = 2
+    end
+  end
+  return unpack(rgb)
+end
+
+local color = {}
+local fprints = {}
+B.fprint = function()
+  if not (Devian and Devian.InWorkspace()) then
+    return function() end
+  end
+
+
+  local sig = debugstack(2,1)
+  if fprints[sig] then
+    return fprints[sig]
+  end
+
+  local func = sig:match("%`(%a+)%'")
+  if not func then
+    func = sig:match("<(.-)>")
+  end
+  func = func:gsub('(%l+)(%u)', function(a, b) return a:sub(0,2) .. b  end, 1)
+  func = func:gsub('^.+%\\', '')
+  if not func then
+    func = 'noname'
+  end
+
+  local r, g, b = getcolor()
+  color[sig] = color[sig] or format('|cFF%02X%02X%02X%s|r', r, g, b, func)
+
+  --print(color[func] .. ' ( ' .. table.concat(args, ', ')..' )' )
+  func = B.print(func)
+  fprints[sig] = func
+  return func
+end
+
+--@end-debug@
+--[=[@non-debug@
+B.print = function() end
+--@end-non-debug@]=]
+
+-- for the Mikk script
+-- GLOBALS: NUM_LE_RAID_BUFF_TYPES
+-- GLOBALS: BUFF_FLASH_TIME_ON, BUFF_FLASH_TIME_OFF, BUFF_MIN_ALPHA, BUFF_WARNING_TIME, BUFF_DURATION_WARNING_TIME
+-- GLOBALS: BUFFS_PER_ROW, BUFF_MAX_DISPLAY, BUFF_ACTUAL_DISPLAY, DEBUFF_MAX_DISPLAY, DEBUFF_ACTUAL_DISPLAY, BUFF_ROW_SPACING
+-- GLOBALS: CONSOLIDATED_BUFFS_PER_ROW, CONSOLIDATED_BUFF_ROW_HEIGHT, NUM_TEMP_ENCHANT_FRAMES
+-- GLOBALS: BUFF_BUTTON_HEIGHT, BUFF_FRAME_BASE_EXTENT, BUFF_HORIZ_SPACING
+
+local print = B.print('Bfl')
+
+--- Template for making perpendicular traversals of the displays structure; also makes sure the table is there
+B.Abstract = function(dest, key, table)
+  if table then
+    for _, v in pairs(dest) do
+      v[key] = {}
+    end
+  end
+  B[key] = setmetatable({}, {
+    __index = function(t, k)
+      return dest[k][key]
+    end,
+    __newindex = function(_, k, v)
+      print('abstract write ('..key..'):', k)
+      dest[k][key] = v
+    end,
+    __tostring = function() return 'Abstract:'..key..'' end
+  })
+
+
+  return B[key]
+end
+
+
+--- localize for speed
+local layers, refs, displays = B.configLayers, B.configLayersRef, B.displays
+
+local ModulesCall = function(func, flag)
+
+  local n = 0
+  for i = 1, #moduleStack do
+    print('calling level '..i)
+    local stackset = moduleStack[i]
+
+    for name, module in pairs(stackset) do
+      n = n + 1
+
+
+      if module[func] then
+        -- nil = pass
+        if not flag or module.Conf[flag] then
+          if (flag) then
+            print('  check', flag, '=', module.Conf[flag])
+          end
+
+          print(' ',n..'  '..name..'.'..func..'()')
+          module[func](module, module.Conf)
+        end
+
+      end
+    end
+  end
+end
+
+
+local Enable = function()
+end
+
+--- The things that happen repeatedly
+local Init = function ()
+end
+
+
+--- Things that happen immediately upon entering world
+local InitOnce = function()
+  print('entering world first time')
+  local defaults = B.ConfDefaults
+  print('|cFFFFFF00Veneer|r')
+  if not VeneerData then
+    VeneerData = {}
+    for k,v in pairs(defaults) do
+
+
+      VeneerData[k] = v
+    end
+    print('Veneer defaults being used.')
+  end
+
+  B.Conf = setmetatable(VeneerData, {__index = function(_, k) return defaults[k] end})
+
+
+
+  -- suffix tables
+  for name, display in pairs(displays) do
+    display.conf = setmetatable({}, {
+      __index = function(_, k)
+        --print('config check '.. name .. k)
+        return B.Conf[name .. k] or B.Conf['BuffButton' .. k]
+      end,
+      __newindex = function(_, k , v)
+        B.Conf[name..k] = v
+      end,
+    })
+  end
+
+  -- To ensure that modules are run in controlled order, walk the dependency list; if the dep shows up
+  -- in the loaded manifest, remove the value. If the dep list isn't empty, move that module to the next
+  -- layer.
+  local loaded = {}
+  local stackLevels = #moduleStack
+  local i = 1
+  moduleStack[1] = modules
+  repeat
+    print('setting init level '.. i)
+    local queue = moduleStack[i]
+    for name, module in pairs(queue) do
+
+      if queuedModules[name] and #queuedModules[name] > 0 then
+        local p = #queuedModules[name]
+        for j = 1, p do
+          local dep = queuedModules[name][j]
+
+          if loaded[dep] then
+            print( '    ' .. dep .. ' OK')
+            queuedModules[name][j] = nil
+            for k = j, p do
+              print('   shift ' .. (k+1)  .. ' ('..tostring(queuedModules[name][k+1])..') to ' .. k ..'')
+              queuedModules[name][k] = queuedModules[name][k+1]
+            end
+          end
+        end
+
+        if #queuedModules[name] == 0 then
+          queuedModules[name] = nil
+          print('  |cFF00FFFF'.. name ..'|r deps OK')
+          loaded[name] = true
+        else
+
+          print('  |cFFFF8800' .. name ..'|r pending')
+          local next = i+1
+          if not  moduleStack[next] then
+            moduleStack[next] = {}
+          end
+          stackLevels = next
+          moduleStack[next][name] = module
+          queue[name] = nil
+        end
+
+      else
+        print('  |cFF00FF00'.. name ..'|r no deps')
+        loaded[name] = true
+      end
+   end
+    i = i + 1
+  until i > stackLevels
+
+
+  for level, batch in ipairs(moduleStack) do
+    print('config level', level)
+    for name, module in pairs(batch) do
+      if not VeneerData[name] then
+        VeneerData[name] = {}
+      end
+
+      if module.defaults then
+        print('setting defaults for module', name)
+        --[===[@non-debug@
+        if not VeneerData[name] then
+        --@end-non-debug@]===]
+          VeneerData[name] = {}
+        --[===[@non-debug@
+        end
+        --@end-non-debug@]===]
+        for k,v in pairs(module.defaults) do
+          VeneerData[name][k] = v
+        end
+        module.Conf = VeneerData[name]
+      end
+
+      if VeneerData[name].enabled == nil then
+        VeneerData[name].enabled = true
+      end
+
+    end
+  end
+
+
+  if #checkForConfig >= 1 then
+    local queuedFrame = tremove(checkForConfig)
+    while queuedFrame do
+      B.SetConfigLayers(queuedFrame)
+      B.UpdateXMLFrame(queuedFrame)
+      queuedFrame = tremove(checkForConfig)
+    end
+  end
+  -- remove from existing
+end
+
+--- Fires an update to all modules
+local lastUpdate
+function B.UpdateAll(...)
+  lastUpdate = GetTime()
+  ModulesCall('OnUpdate')
+end
+
+B:RegisterEvent('PLAYER_ENTERING_WORLD')
+B:SetScript('OnEvent', function(self, event)
+  if event == 'PLAYER_ENTERING_WORLD' then
+    if not initOnced then
+      InitOnce()
+      ModulesCall('OnInitialize')
+      initOnced = true
+      C_Timer.After(1, function()
+        if GetSpecialization() then
+          print(GetSpecialization(), 'enabling')
+
+          ModulesCall('OnEnable', 'enabled')
+          B:SetScript('OnUpdate', nil)
+        end
+      end)
+    end
+  end
+
+  B.UpdateAll()
+
+  if event == 'PLAYER_ENTERING_WORLD' then
+    B.UpdateConfigLayers()
+  end
+
+end)
+
+--- Modulizer method
+--
+function B:RegisterModule (name, module, ...)
+  if modules[name] then
+    print('pulling modules[|cFFFF8800'.. tostring(name) ..'|r]')
+    return modules[name]
+  end
+
+  print('new module |cFF00BBFF'.. tostring(name) ..'|r')
+  if module then
+    if modules[name] then
+      error("Module table for '"..tostring(name).."' already exists.")
+    end
+  else
+    module = CreateFrame('Frame', 'Veneer' .. tostring(name) .. 'Handler', B, 'VeneerHandlerTemplate')
+  end
+  modules[name] = module
+  B[name] = module
+  if select('#', ...) >= 1 then
+    local numDeps = select('#', ...)
+    print('  '..numDeps..' deps detected')
+    for i = 1, numDeps do
+      local dep = select(i, ...)
+        -- means that init/enable funcs are ordered to run after deps do their things
+      queuedModules[name] = queuedModules[name]  or {}
+      tinsert(queuedModules[name], dep)
+      print('  needs '..dep)
+    end
+  end
+  return module
+end
+
+
+B.SetConfigLayers =  function(frame)
+  local print = B.fprint()
+  if not frame.config then
+    --print(frame:GetName(), 'has no config layers')
+    return
+  end
+  --print('Registering config layers from', frame:GetName())
+
+  for i, subframe in ipairs(frame.config) do
+    -- make sure there are no duplicates
+    if not refs[subframe] then
+      local key = #layers+1
+      layers[key] = subframe
+      refs[subframe] = key
+    end
+    --print(' ', i, subframe:GetName())
+  end
+end
+
+B.RemoveConfigLayers = function(frame)
+
+  local print = B.fprint()
+  print('|cFFFF0000RemoveConfigLayers', frame:GetName())
+  for i, subframe in pairs(layers) do
+    if subframe:GetParent() == frame then
+      print('|cFFFF8800  ', subframe:GetParent():GetName(), '|cFFFFFF00', subframe:GetName())
+      layers[i]:Hide()
+      layers[i] = nil
+      refs[subframe] = nil
+    end
+  end
+end
+
+B.UpdateConfigLayers = function()
+  local print = B.fprint()
+  local func = B.Conf.GuidesMode and 'Show' or 'Hide'
+  local numAnchors = 0
+  for name, display in pairs(displays) do
+    numAnchors = numAnchors + 1
+    display.anchor:EnableMouse(B.Conf.GuidesMode)
+    if B.Conf.GuidesMode then
+      display.anchor:SetScript('OnUpdate', display.anchor.OnUpdate)
+    else
+      display.anchor:SetScript('OnUpdate', nil)
+
+      for i, anchorButton in ipairs(display.anchor.anchorButton) do
+        anchorButton:Hide()
+      end
+
+    end
+    --print(B.Conf.ConfigMode)
+    display.anchor:EnableMouse(B.Conf.ConfigMode)
+  end
+  for id, region in pairs(layers) do
+    --print(id, region:GetName(), func)
+    region[func](region)
+  end
+
+  --print('['..func..'] updated', #layers, 'regions,', numAnchors, 'frames')
+end
+
+local XMLFrame_Enable = function(self, value)
+  local name = self:GetName()
+  local print = B.print('XML')
+
+  if not B.Conf[name] then
+    B.Conf[name] = {
+      enabled = true
+    }
+  end
+
+  print()
+  local enabled
+  if value == nil then
+    if B.Conf[name].enabled == nil then
+      print('toggle based on visibility')
+      enabled = (not self:IsVisible()) and true or false
+    else
+      print('toggle a config value =', B.Conf[name].enabled)
+      enabled = B.Conf[name].enabled
+    end
+
+    enabled = (enabled ~= true) and true or false
+  else
+      print('use argument value', value)
+      enabled = value
+  end
+
+  print('arg =', value, 'conf =', B.Conf[name].enabled, 'result=', enabled)
+
+  B.Conf[name].enabled = enabled
+
+  local stateFunc = enabled and 'Show' or 'Hide'
+  local eventFunc = enabled and 'OnToggle' or 'OnToggle'
+  --- taggled layers
+  if self.toggled then
+    for i, region in pairs(self.toggled) do
+      region[stateFunc](region)
+    end
+  end
+  --- toggle action
+  if self.OnToggle then
+    self:OnToggle(B.Conf[name].enabled)
+  end
+  --- do enable
+  if B.Conf[name].enabled then
+    if self.OnEnable then
+      self:OnEnable()
+    end
+  else
+    if self.OnDisable then
+      self:OnDisable()
+    end
+  end
+end
+--- Generic handlers for keeping track of XML-defined frames
+local print = B.print('XML')
+B.prototypes = {}
+B.prototypes.OnDragStart = function(self)
+  local print = B.print('XML')
+  self.xA = self:GetLeft()
+  self.yA = self:GetBottom()
+  self.anchorTo, self.relativeTo, self.relativePoint, self.x, self.y = self:GetPoint(1)
+  print('acquire anchor', self:GetPoint(1))
+  print(self:GetName(), 'start moving ('..self.x..', '..self.y..')')
+  self:StartMoving()
+end
+
+B.prototypes.OnDragStop = function(self)
+  local print = B.print('XML')
+  local name = self:GetName()
+  print(name, 'stop moving ('..self:GetLeft()..', '..self:GetBottom()..')')
+  local xB = self:GetLeft() - self.xA
+  local yB = self:GetBottom() - self.yA
+  print('storing anchor point', self.anchorTo, self.relativePoint, self.x + xB, self.y + yB)
+
+  self:StopMovingOrSizing()
+  B.Conf[name].position = {self.anchorTo, self.relativePoint, self.x + xB, self.y + yB}
+  B.UpdateXMLFrame(self)
+end
+
+
+B.RegisterModuleFrame = function(self, moduleName)
+  local print = B.print('XML')
+  local name = self:GetName()
+  tinsert(checkForConfig, self)
+  self.Enable = XMLFrame_Enable
+  self.moduleName = moduleName
+  print('|cFF00FF00XML stuff related to '.. tostring(moduleName) .. ':', self:GetName())
+  ------------------------------------------------------------------------------------------
+  if not B[name] then
+    return
+  end
+
+  local scriptTypes = {'OnUpdate', 'OnEvent', 'OnDragStart', 'OnDragStop'}
+  for script in next(scriptTypes) do
+    if B[name][script] then
+      self:SetScript(script, B[name][script])
+    end
+  end
+
+end
+
+B.UpdateXMLFrame = function(self)
+  local print = B.print('XML')
+
+  local name = self:GetName()
+
+
+  if self.drag then
+    self:RegisterForDrag('LeftButton')
+    self:SetScript('OnDragStart', XMLFrame_OnDragStart)
+    if self.OnDragStop then
+      self:SetScript('OnDragStop', function(self, ...)
+        print('|cFFFF0088end of dragging')
+        self:OnDragStop(self, ...)
+        XMLFrame_OnDragStop(self, ...)
+      end)
+    else
+      self:SetScript('OnDragStop', XMLFrame_OnDragStop)
+    end
+  else
+    self:EnableMouse(false)
+  end
+
+  if not B.Conf[name] then
+    B.Conf[name] = {
+      enabled = self.enabled,
+    }
+  end
+  local c = B.Conf[name]
+
+  if not c.position then
+    local anchor, _, point, x, y = self:GetPoint(1)
+    print('seeding default position', anchor, point, x, y)
+    c.position = {anchor, point, x, y}
+  else
+
+    print('restoring frame position', unpack(c.position))
+    self:ClearAllPoints()
+    local anchorTo, relativePoint, x, y = unpack(c.position)
+    self:SetPoint(anchorTo, UIParent, relativePoint, x, y)
+  end
+  self:Enable(c.enabled)
+
+
+end