diff Config.lua @ 0:3dbcad2b387d

initial push
author Nenue
date Wed, 30 Mar 2016 02:24:56 -0400
parents
children 66b927b46776
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Config.lua	Wed Mar 30 02:24:56 2016 -0400
@@ -0,0 +1,388 @@
+--- All the control GUI stuff, including chat command functions
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 3/12/2016 12:49 AM
+local B, _G = select(2,...).frame, _G
+local M = B:RegisterModule("Options")
+local tostring, tonumber, floor, format = tostring, tonumber, floor, string.format
+local unpack, select, pairs, ipairs, type, wipe = unpack, select, pairs, ipairs, type, table.wipe
+local CreateFrame, IsControlKeyDown = _G.CreateFrame, _G.IsControlKeyDown
+local max = math.max
+local OpacitySliderFrame, ColorPickerFrame = _G.OpacitySliderFrame, _G.ColorPickerFrame
+local print = B.print('Cfgl')
+local function round(number, decimals)
+  if floor(number) == number then
+    return ('%d'):format(number)
+  end
+
+  return (("%%.%df"):format(decimals)):format(number)
+end
+
+--- STATE VARIABLES
+local configInit
+--- Dummies for addon table upvalues
+local configFrames = {} -- actual frame objects
+local displays = B.displays     -- anchor objects dummy
+
+
+--- Returns a value retreival function and the current value stored in config
+-- @paramsig value, previousValue = configInteger(key)
+-- @param key Name of the config field being represented.
+local defaultGroup = 'BuffButton'
+local configInteger = function(group, key)
+  return function(self ,display)
+    return floor(tonumber(self:GetValue()) + 0.5)
+  end, (B.Conf[group ..key] or B.Conf[defaultGroup..key])
+end
+local configPercent = function(group, key)
+  return function(self, display)
+    local value = self:GetValue()
+    if display then
+      return tostring(floor(value*100+0.5))..' %'
+    else
+      return floor((value*100+0.5))/100
+    end
+  end, (B.Conf[group ..key] or B.Conf[defaultGroup..key])
+end
+local configColor = function(group, key)
+  -- table for config, color value list for text
+  return function(self, display)
+    if display then
+      return "|cFFFF4444" .. round(self.rgba[1], 1) .. "|r, |cFF44FF44" .. round(self.rgba[2], 1) .. "|r, |cFF4488FF" ..
+          round(self.rgba[3], 1) .. "|r, " .. round(self.rgba[4], 1)
+    else
+      return self.rgba
+    end
+  end, (B.Conf[group ..key] or B.Conf[defaultGroup..key])
+end
+local configCheck = function(group, key)
+  return function(self) return self:GetChecked() end, B.Conf[group ..key] or B.Conf[defaultGroup..key]
+end
+-- initializes the corresponding type of config field
+local frameTypeConv = {
+  Color = 'Button',
+  Font = 'Frame',
+}
+local configTypeParams = {
+  Slider = function(frame, optionInfo)
+    frame:SetMinMaxValues(optionInfo[5], optionInfo[6])
+    frame:SetValueStep(optionInfo[7])
+    frame:SetStepsPerPage(optionInfo[8])
+    print(frame.OptName, '\n  {', optionInfo[5], optionInfo[6], optionInfo[7], optionInfo[8], '}')
+  end,
+  CheckButton = function(frame, optionInfo)
+    frame.SetValue = function(self, ...)
+      self:SetChecked(...)
+      B.Conf[self.OptName] = self:GetChecked()
+      print(self.OptTab)
+      B.UpdateAll()
+    end
+    frame:SetScript("OnClick",function(self)
+      B.Conf[self.OptName] = self:GetChecked()
+      print(B.Conf[self.OptName], self:GetChecked())
+      B.UpdateAll()
+    end)
+  end,
+  Color = function(frame, optionInfo)
+    frame.rgba = { frame.current:GetVertexColor() }
+    local colorPickerCallback = function(restore)
+      local newR, newG, newB, newA
+      if restore then
+        newR, newG, newB, newA = unpack(restore)
+      else
+        newA, newR, newG, newB = OpacitySliderFrame:GetValue(), ColorPickerFrame:GetColorRGB()
+        print('not cancel', newA, newR, newB, newG)
+      end
+      frame:SetValue({newR, newG, newB, newA})
+      B.UpdateBuffs(frame.OptTab)
+    end
+    frame:SetScript("OnClick", function(self)
+      print('got a click')
+      local r, g, b, a = frame.current:GetVertexColor()
+      ColorPickerFrame:SetColorRGB(r, g, b)
+      ColorPickerFrame.hasOpacity =  (a ~= nil)
+      ColorPickerFrame.opacity = a
+      ColorPickerFrame.previousValues = {r,g,b,a}
+      ColorPickerFrame.func, ColorPickerFrame.opacityFunc, ColorPickerFrame.cancelFunc =
+      colorPickerCallback, colorPickerCallback,colorPickerCallback
+      ColorPickerFrame:Hide()
+      ColorPickerFrame:Show()
+    end)
+    frame.SetValue = function(self, rgba)
+      print(rgba)
+      frame.rgba = rgba
+      B.Conf[self.OptName] = rgba
+      frame.current:SetVertexColor(unpack(rgba))
+      frame.fieldvalue:SetText(frame.OptValue(frame, true))
+    end
+  end
+}
+--- configDialog
+-- @usage tinsert(configDialog, {prefix, row, [...] })
+-- Each top level member defines a group of config value handlers, structured as an iterative table where the
+-- first member is a key prefix, the second member is an integer row value, and all following members are treated
+-- as a widget resource, defined initially as a complete sub-table, which can be re-used further down by passing
+-- the string literal widget suffix.
+-- widget table: ... {'suffix', 'description', valueCallback, 'template', [widget parameters]}
+-- widget copy: ... 'suffix', ...
+local configDialog = {
+  {'BuffButton', 1,
+
+    {'Max', 'Max', configInteger, 'Slider',
+      1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage
+    {'PerRow', 'Per Row', configInteger, 'Slider',
+      1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage,
+    {'Size', 'Icon Size', configInteger, 'Slider',
+      1, 256, 1, 1},
+    {'Spacing', 'Icon Spacing', configInteger, 'Slider',
+      1, 50, 1, 1},
+    {'DurationSize', 'Duration Text Height', configInteger, 'Slider',
+      1, 72, 1, 1},
+    {'Zoom', 'Icon Zoom', configInteger, 'Slider',
+      0, 100, 1, 1},
+    {'Border', 'Border', configInteger, 'Slider',
+      1, 16, 1, 1},
+    {'Color', 'Default Border', configColor, 'Color'},
+    {'RaidColor', 'RaidBuff Border', configColor, 'Color'},
+    {'PlayerColor', 'Player Buffs', configColor, 'Color'},
+    {'BossColor', 'Encounter Buffs', configColor, 'Color'},
+    {'ShowSelfCast', 'Show name for self-casts', configCheck, 'CheckButton'}
+  },
+  { 'DebuffButton', 1,
+    {'Max', 'Max', configInteger, 'Slider',
+      1, _G.DEBUFF_MAX_DISPLAY, 1, 1 }
+    ,
+    {'PerRow', 'Per Row', configInteger, 'Slider',
+      1, _G.DEBUFF_MAX_DISPLAY, 1, 1 },
+    'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border',
+    'Color', 'RaidColor', 'PlayerColor', 'BossColor',
+  },
+  { 'TempEnchant', 1,
+    {'Max', 'Max', configInteger, 'Slider',
+      1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1 },
+    {'PerRow', 'Per Row', configInteger, 'Slider',
+      1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1},
+    'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border',
+    'Color', 'RaidColor', 'PlayerColor', 'BossColor',
+  },
+  { 'ConsolidatedBuff', 2,
+    {'Position', 'Slot Position', configInteger, 'Slider',
+    1, _G.BUFF_MAX_DISPLAY, 1, 1 }
+
+  },
+  { 'ConsolidatedBuff', 2,
+    'Size'
+  },
+  { 'Raid', 3,
+    {'ShowMissing', 'Verbose missing raid buffs', configCheck, 'CheckButton'}
+  }
+}
+
+
+
+
+local configFrame
+local optionTemplates = {}
+local configPadding, configSpacing = 3, 3
+
+--- Walks the structure table to generate a pretty config panel
+local InitConfig = function()
+  configInit = true
+  local configWidth = B:GetWidth()
+  local optionWidth = (configWidth - configPadding) / 3 - configSpacing
+  local configHeight = 0
+  local bottom_extent = 0
+  local clusterHeight = 0
+  local clusterOffset = 0
+  local lastCluster
+  local cluster = 1
+  local col = 0
+  for t, taboptions in ipairs(configDialog) do
+    local group = taboptions[1]
+    cluster = taboptions[2]
+    col = col + 1
+
+
+    if not configFrames[t] then
+      configFrames[t] = {}
+    end
+
+
+    if cluster ~= lastCluster then
+      configHeight = configHeight + clusterHeight
+      print('|cFFFF8800## new cluster|r, advancing offset from', clusterOffset, 'to', clusterOffset + clusterHeight)
+      clusterOffset = clusterOffset + clusterHeight
+      col = 1
+      clusterHeight = 0
+      lastCluster = cluster
+    end
+
+    print('processing tab', group)
+    local row = 0
+    for i = 3, #taboptions do
+      row = row + 1
+      local optionInfo = taboptions[i]
+      if type(optionInfo) == 'string' then
+        optionInfo = optionTemplates[optionInfo]
+      end
+      local key, fieldname, valueFuncGenerator, configType = unpack(optionInfo)
+
+      if not optionTemplates[key] then
+        optionTemplates[key] = optionInfo
+      end
+
+      local fullkey = group .. key
+      print(fullkey, fieldname)
+
+      if not configFrames[t][row] then
+        print('building frame', t, group, row)
+        local frameTemplate =  'VeneerConfig'..configType
+        local frameType = frameTypeConv[configType] or configType
+        configFrames[t][row] = CreateFrame(frameType, fullkey, B, frameTemplate)
+        local f = configFrames[t][row]
+        f.OptKey = key
+        f.OptTab = group
+        f.OptName = fullkey
+        local valueFunc, initialValue = valueFuncGenerator(group, key)
+        print('  value getter', fullkey,'->', valueFunc,initialValue)
+        configTypeParams[configType](f, optionInfo)
+        f.OptValue = valueFunc
+
+        --- Enclosing these to
+        -- a) make the panel easy to bring up externally
+        -- b) limit gameplay risk from config frame errors
+        -- c) milk the iterator scope for all its worth
+        f.OnChange = function(self)
+
+          -- holding control; mirror this setting in other categories
+          if IsControlKeyDown() and not (configInit) then
+            configInit = true
+            for optTab, opts in pairs(configFrames) do
+              for _, opt in ipairs(opts) do
+                if opt.OptKey == key then
+                  if optTab ~= group then
+                    print('mapping to', optTab, opt.OptKey)
+                    opt:SetValue(self:GetValue())
+                  end
+
+                end
+              end
+            end
+            configInit = nil
+          end
+          local newValue = valueFunc(self)
+          if newValue ~= B.Conf[fullkey] then
+            print(newValue, fullkey)
+            f.fieldvalue:SetText(valueFunc(self, true))
+            B.Conf[fullkey] = valueFunc(self)
+            -- prepare to update
+            wipe(B.drawn[f.OptTab])
+            B.UpdateBuffs(self.OptTab)
+            B.UpdateConfigLayers()
+          end
+
+        end
+
+        f:SetValue(initialValue)
+        local yBuffer = configPadding
+        if f.fieldname then
+          f.fieldname:SetText(fieldname)
+          yBuffer = yBuffer + f.fieldname:GetHeight()
+        end
+        if f.fieldvalue then
+          f.fieldvalue:SetText(f:OptValue(true))
+        end
+
+        local point, relative, x, y = 'TOPLEFT', 'BOTTOMLEFT', 0, -3
+
+        local base
+        if (row == 1) then
+          bottom_extent = 0
+          base = B.header
+          x = (col-1) * (optionWidth+configSpacing)
+          y = -configPadding
+        else
+          base = configFrames[t][row-1]
+        end
+
+        print('|cFFFF0088'..cluster..'|r |cFF00FF00'.. row..'|r', col, base:GetName(), x, y - clusterOffset)
+
+        if frameType ~= 'CheckButton' then
+          f:SetWidth(optionWidth)
+        end
+
+        f:SetPoint(point, base, relative, x, y-yBuffer-clusterOffset)
+        --print('creating', frameType, fieldname)
+        f:Show()
+
+        bottom_extent = bottom_extent + f:GetHeight() + yBuffer + configSpacing
+
+
+
+        clusterHeight = max(clusterHeight, bottom_extent)
+        --print('y', floor(yBuffer+0.5), 'f:H', floor(f:GetHeight()+0.5), 'hTally', floor(bottom_extent+0.5), 'hMax', floor(configHeight+0.5))
+      end
+    end
+  end
+
+  -- grab the last cluster
+  if lastCluster == cluster then
+    print('|cFF00FF00##scooping up last cluster info')
+    configHeight = configHeight + clusterHeight
+  end
+
+  if not B.configFramesCreated then
+    B.configFramesCreated = true
+    B:SetHeight(B.header:GetStringHeight() + configSpacing*3 + configHeight)
+  end
+  if configInit then configInit = nil end
+end
+
+M.Command = function(enable, editbox)
+  displays = B.displays
+  if type(enable) == 'boolean' then
+    B.Conf.ConfigMode = enable
+  else
+    B.Conf.ConfigMode = (B.Conf.ConfigMode == false) and true or false
+  end
+
+  print('/BUFF', B.Conf.ConfigMode, type(B.Conf.ConfigMode))
+  if B.Conf.ConfigMode  then
+    if not B.configFramesCreated then
+      InitConfig()
+    end
+    print('Veneer config')
+    B:Show()
+  else
+    B:Hide()
+  end
+  B.UpdateAll()
+  B.UpdateConfigLayers()
+end
+
+B.Close = function ()
+  M.Command()
+end
+
+B.ToggleGuides = function(_, self)
+  B.Conf.GuidesMode = (not B.Conf.GuidesMode)
+  if B.Conf.GuidesMode then
+    self:GetNormalTexture():SetTexture(0.94, 0.21, 0.21, 1)
+  else
+    self:GetNormalTexture():SetTexture(0, 0, 0, 1)
+  end
+
+  B.UpdateConfigLayers()
+end
+
+M.OnEnable = function()
+  M.Command(B.Conf.ConfigMode)
+end
+
+M.OnInitialize = function()
+  DEFAULT_CHAT_FRAME:AddMessage("|cFF22D822Veneer|r")
+  SLASH_BUFFALO1, SLASH_BUFFALO2 = "/buffalo", "/buff"
+  SlashCmdList.BUFFALO = M.Command
+
+end
\ No newline at end of file