annotate Config.lua @ 7:5301c68f28d8

TrackerBlock - use IsModifiedClick function to determine appropriate OnClick actions - handle 'CHATLINK' modifier - handle 'TOGGLEQUESTWATCH' modifier TrackerBlockObjectives - use a generic framework to manage frame creation for various criteria tracker types: - ProgressBar when Blizzard flag data indicates so - skip when Blizzard flag data indicates so - DynamicText otherwise - events related to the criteria are registered in the criteria frame, and unregistered when the frame is hidden, either by destruction of its parent or completion
author Nenue
date Fri, 01 Apr 2016 12:27:05 -0400
parents 3dbcad2b387d
children 66b927b46776
rev   line source
Nenue@0 1 --- All the control GUI stuff, including chat command functions
Nenue@0 2 -- @file-author@
Nenue@0 3 -- @project-revision@ @project-hash@
Nenue@0 4 -- @file-revision@ @file-hash@
Nenue@0 5 -- Created: 3/12/2016 12:49 AM
Nenue@0 6 local B, _G = select(2,...).frame, _G
Nenue@0 7 local M = B:RegisterModule("Options")
Nenue@0 8 local tostring, tonumber, floor, format = tostring, tonumber, floor, string.format
Nenue@0 9 local unpack, select, pairs, ipairs, type, wipe = unpack, select, pairs, ipairs, type, table.wipe
Nenue@0 10 local CreateFrame, IsControlKeyDown = _G.CreateFrame, _G.IsControlKeyDown
Nenue@0 11 local max = math.max
Nenue@0 12 local OpacitySliderFrame, ColorPickerFrame = _G.OpacitySliderFrame, _G.ColorPickerFrame
Nenue@0 13 local print = B.print('Cfgl')
Nenue@0 14 local function round(number, decimals)
Nenue@0 15 if floor(number) == number then
Nenue@0 16 return ('%d'):format(number)
Nenue@0 17 end
Nenue@0 18
Nenue@0 19 return (("%%.%df"):format(decimals)):format(number)
Nenue@0 20 end
Nenue@0 21
Nenue@0 22 --- STATE VARIABLES
Nenue@0 23 local configInit
Nenue@0 24 --- Dummies for addon table upvalues
Nenue@0 25 local configFrames = {} -- actual frame objects
Nenue@0 26 local displays = B.displays -- anchor objects dummy
Nenue@0 27
Nenue@0 28
Nenue@0 29 --- Returns a value retreival function and the current value stored in config
Nenue@0 30 -- @paramsig value, previousValue = configInteger(key)
Nenue@0 31 -- @param key Name of the config field being represented.
Nenue@0 32 local defaultGroup = 'BuffButton'
Nenue@0 33 local configInteger = function(group, key)
Nenue@0 34 return function(self ,display)
Nenue@0 35 return floor(tonumber(self:GetValue()) + 0.5)
Nenue@0 36 end, (B.Conf[group ..key] or B.Conf[defaultGroup..key])
Nenue@0 37 end
Nenue@0 38 local configPercent = function(group, key)
Nenue@0 39 return function(self, display)
Nenue@0 40 local value = self:GetValue()
Nenue@0 41 if display then
Nenue@0 42 return tostring(floor(value*100+0.5))..' %'
Nenue@0 43 else
Nenue@0 44 return floor((value*100+0.5))/100
Nenue@0 45 end
Nenue@0 46 end, (B.Conf[group ..key] or B.Conf[defaultGroup..key])
Nenue@0 47 end
Nenue@0 48 local configColor = function(group, key)
Nenue@0 49 -- table for config, color value list for text
Nenue@0 50 return function(self, display)
Nenue@0 51 if display then
Nenue@0 52 return "|cFFFF4444" .. round(self.rgba[1], 1) .. "|r, |cFF44FF44" .. round(self.rgba[2], 1) .. "|r, |cFF4488FF" ..
Nenue@0 53 round(self.rgba[3], 1) .. "|r, " .. round(self.rgba[4], 1)
Nenue@0 54 else
Nenue@0 55 return self.rgba
Nenue@0 56 end
Nenue@0 57 end, (B.Conf[group ..key] or B.Conf[defaultGroup..key])
Nenue@0 58 end
Nenue@0 59 local configCheck = function(group, key)
Nenue@0 60 return function(self) return self:GetChecked() end, B.Conf[group ..key] or B.Conf[defaultGroup..key]
Nenue@0 61 end
Nenue@0 62 -- initializes the corresponding type of config field
Nenue@0 63 local frameTypeConv = {
Nenue@0 64 Color = 'Button',
Nenue@0 65 Font = 'Frame',
Nenue@0 66 }
Nenue@0 67 local configTypeParams = {
Nenue@0 68 Slider = function(frame, optionInfo)
Nenue@0 69 frame:SetMinMaxValues(optionInfo[5], optionInfo[6])
Nenue@0 70 frame:SetValueStep(optionInfo[7])
Nenue@0 71 frame:SetStepsPerPage(optionInfo[8])
Nenue@0 72 print(frame.OptName, '\n {', optionInfo[5], optionInfo[6], optionInfo[7], optionInfo[8], '}')
Nenue@0 73 end,
Nenue@0 74 CheckButton = function(frame, optionInfo)
Nenue@0 75 frame.SetValue = function(self, ...)
Nenue@0 76 self:SetChecked(...)
Nenue@0 77 B.Conf[self.OptName] = self:GetChecked()
Nenue@0 78 print(self.OptTab)
Nenue@0 79 B.UpdateAll()
Nenue@0 80 end
Nenue@0 81 frame:SetScript("OnClick",function(self)
Nenue@0 82 B.Conf[self.OptName] = self:GetChecked()
Nenue@0 83 print(B.Conf[self.OptName], self:GetChecked())
Nenue@0 84 B.UpdateAll()
Nenue@0 85 end)
Nenue@0 86 end,
Nenue@0 87 Color = function(frame, optionInfo)
Nenue@0 88 frame.rgba = { frame.current:GetVertexColor() }
Nenue@0 89 local colorPickerCallback = function(restore)
Nenue@0 90 local newR, newG, newB, newA
Nenue@0 91 if restore then
Nenue@0 92 newR, newG, newB, newA = unpack(restore)
Nenue@0 93 else
Nenue@0 94 newA, newR, newG, newB = OpacitySliderFrame:GetValue(), ColorPickerFrame:GetColorRGB()
Nenue@0 95 print('not cancel', newA, newR, newB, newG)
Nenue@0 96 end
Nenue@0 97 frame:SetValue({newR, newG, newB, newA})
Nenue@0 98 B.UpdateBuffs(frame.OptTab)
Nenue@0 99 end
Nenue@0 100 frame:SetScript("OnClick", function(self)
Nenue@0 101 print('got a click')
Nenue@0 102 local r, g, b, a = frame.current:GetVertexColor()
Nenue@0 103 ColorPickerFrame:SetColorRGB(r, g, b)
Nenue@0 104 ColorPickerFrame.hasOpacity = (a ~= nil)
Nenue@0 105 ColorPickerFrame.opacity = a
Nenue@0 106 ColorPickerFrame.previousValues = {r,g,b,a}
Nenue@0 107 ColorPickerFrame.func, ColorPickerFrame.opacityFunc, ColorPickerFrame.cancelFunc =
Nenue@0 108 colorPickerCallback, colorPickerCallback,colorPickerCallback
Nenue@0 109 ColorPickerFrame:Hide()
Nenue@0 110 ColorPickerFrame:Show()
Nenue@0 111 end)
Nenue@0 112 frame.SetValue = function(self, rgba)
Nenue@0 113 print(rgba)
Nenue@0 114 frame.rgba = rgba
Nenue@0 115 B.Conf[self.OptName] = rgba
Nenue@0 116 frame.current:SetVertexColor(unpack(rgba))
Nenue@0 117 frame.fieldvalue:SetText(frame.OptValue(frame, true))
Nenue@0 118 end
Nenue@0 119 end
Nenue@0 120 }
Nenue@0 121 --- configDialog
Nenue@0 122 -- @usage tinsert(configDialog, {prefix, row, [...] })
Nenue@0 123 -- Each top level member defines a group of config value handlers, structured as an iterative table where the
Nenue@0 124 -- first member is a key prefix, the second member is an integer row value, and all following members are treated
Nenue@0 125 -- as a widget resource, defined initially as a complete sub-table, which can be re-used further down by passing
Nenue@0 126 -- the string literal widget suffix.
Nenue@0 127 -- widget table: ... {'suffix', 'description', valueCallback, 'template', [widget parameters]}
Nenue@0 128 -- widget copy: ... 'suffix', ...
Nenue@0 129 local configDialog = {
Nenue@0 130 {'BuffButton', 1,
Nenue@0 131
Nenue@0 132 {'Max', 'Max', configInteger, 'Slider',
Nenue@0 133 1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage
Nenue@0 134 {'PerRow', 'Per Row', configInteger, 'Slider',
Nenue@0 135 1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage,
Nenue@0 136 {'Size', 'Icon Size', configInteger, 'Slider',
Nenue@0 137 1, 256, 1, 1},
Nenue@0 138 {'Spacing', 'Icon Spacing', configInteger, 'Slider',
Nenue@0 139 1, 50, 1, 1},
Nenue@0 140 {'DurationSize', 'Duration Text Height', configInteger, 'Slider',
Nenue@0 141 1, 72, 1, 1},
Nenue@0 142 {'Zoom', 'Icon Zoom', configInteger, 'Slider',
Nenue@0 143 0, 100, 1, 1},
Nenue@0 144 {'Border', 'Border', configInteger, 'Slider',
Nenue@0 145 1, 16, 1, 1},
Nenue@0 146 {'Color', 'Default Border', configColor, 'Color'},
Nenue@0 147 {'RaidColor', 'RaidBuff Border', configColor, 'Color'},
Nenue@0 148 {'PlayerColor', 'Player Buffs', configColor, 'Color'},
Nenue@0 149 {'BossColor', 'Encounter Buffs', configColor, 'Color'},
Nenue@0 150 {'ShowSelfCast', 'Show name for self-casts', configCheck, 'CheckButton'}
Nenue@0 151 },
Nenue@0 152 { 'DebuffButton', 1,
Nenue@0 153 {'Max', 'Max', configInteger, 'Slider',
Nenue@0 154 1, _G.DEBUFF_MAX_DISPLAY, 1, 1 }
Nenue@0 155 ,
Nenue@0 156 {'PerRow', 'Per Row', configInteger, 'Slider',
Nenue@0 157 1, _G.DEBUFF_MAX_DISPLAY, 1, 1 },
Nenue@0 158 'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border',
Nenue@0 159 'Color', 'RaidColor', 'PlayerColor', 'BossColor',
Nenue@0 160 },
Nenue@0 161 { 'TempEnchant', 1,
Nenue@0 162 {'Max', 'Max', configInteger, 'Slider',
Nenue@0 163 1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1 },
Nenue@0 164 {'PerRow', 'Per Row', configInteger, 'Slider',
Nenue@0 165 1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1},
Nenue@0 166 'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border',
Nenue@0 167 'Color', 'RaidColor', 'PlayerColor', 'BossColor',
Nenue@0 168 },
Nenue@0 169 { 'ConsolidatedBuff', 2,
Nenue@0 170 {'Position', 'Slot Position', configInteger, 'Slider',
Nenue@0 171 1, _G.BUFF_MAX_DISPLAY, 1, 1 }
Nenue@0 172
Nenue@0 173 },
Nenue@0 174 { 'ConsolidatedBuff', 2,
Nenue@0 175 'Size'
Nenue@0 176 },
Nenue@0 177 { 'Raid', 3,
Nenue@0 178 {'ShowMissing', 'Verbose missing raid buffs', configCheck, 'CheckButton'}
Nenue@0 179 }
Nenue@0 180 }
Nenue@0 181
Nenue@0 182
Nenue@0 183
Nenue@0 184
Nenue@0 185 local configFrame
Nenue@0 186 local optionTemplates = {}
Nenue@0 187 local configPadding, configSpacing = 3, 3
Nenue@0 188
Nenue@0 189 --- Walks the structure table to generate a pretty config panel
Nenue@0 190 local InitConfig = function()
Nenue@0 191 configInit = true
Nenue@0 192 local configWidth = B:GetWidth()
Nenue@0 193 local optionWidth = (configWidth - configPadding) / 3 - configSpacing
Nenue@0 194 local configHeight = 0
Nenue@0 195 local bottom_extent = 0
Nenue@0 196 local clusterHeight = 0
Nenue@0 197 local clusterOffset = 0
Nenue@0 198 local lastCluster
Nenue@0 199 local cluster = 1
Nenue@0 200 local col = 0
Nenue@0 201 for t, taboptions in ipairs(configDialog) do
Nenue@0 202 local group = taboptions[1]
Nenue@0 203 cluster = taboptions[2]
Nenue@0 204 col = col + 1
Nenue@0 205
Nenue@0 206
Nenue@0 207 if not configFrames[t] then
Nenue@0 208 configFrames[t] = {}
Nenue@0 209 end
Nenue@0 210
Nenue@0 211
Nenue@0 212 if cluster ~= lastCluster then
Nenue@0 213 configHeight = configHeight + clusterHeight
Nenue@0 214 print('|cFFFF8800## new cluster|r, advancing offset from', clusterOffset, 'to', clusterOffset + clusterHeight)
Nenue@0 215 clusterOffset = clusterOffset + clusterHeight
Nenue@0 216 col = 1
Nenue@0 217 clusterHeight = 0
Nenue@0 218 lastCluster = cluster
Nenue@0 219 end
Nenue@0 220
Nenue@0 221 print('processing tab', group)
Nenue@0 222 local row = 0
Nenue@0 223 for i = 3, #taboptions do
Nenue@0 224 row = row + 1
Nenue@0 225 local optionInfo = taboptions[i]
Nenue@0 226 if type(optionInfo) == 'string' then
Nenue@0 227 optionInfo = optionTemplates[optionInfo]
Nenue@0 228 end
Nenue@0 229 local key, fieldname, valueFuncGenerator, configType = unpack(optionInfo)
Nenue@0 230
Nenue@0 231 if not optionTemplates[key] then
Nenue@0 232 optionTemplates[key] = optionInfo
Nenue@0 233 end
Nenue@0 234
Nenue@0 235 local fullkey = group .. key
Nenue@0 236 print(fullkey, fieldname)
Nenue@0 237
Nenue@0 238 if not configFrames[t][row] then
Nenue@0 239 print('building frame', t, group, row)
Nenue@0 240 local frameTemplate = 'VeneerConfig'..configType
Nenue@0 241 local frameType = frameTypeConv[configType] or configType
Nenue@0 242 configFrames[t][row] = CreateFrame(frameType, fullkey, B, frameTemplate)
Nenue@0 243 local f = configFrames[t][row]
Nenue@0 244 f.OptKey = key
Nenue@0 245 f.OptTab = group
Nenue@0 246 f.OptName = fullkey
Nenue@0 247 local valueFunc, initialValue = valueFuncGenerator(group, key)
Nenue@0 248 print(' value getter', fullkey,'->', valueFunc,initialValue)
Nenue@0 249 configTypeParams[configType](f, optionInfo)
Nenue@0 250 f.OptValue = valueFunc
Nenue@0 251
Nenue@0 252 --- Enclosing these to
Nenue@0 253 -- a) make the panel easy to bring up externally
Nenue@0 254 -- b) limit gameplay risk from config frame errors
Nenue@0 255 -- c) milk the iterator scope for all its worth
Nenue@0 256 f.OnChange = function(self)
Nenue@0 257
Nenue@0 258 -- holding control; mirror this setting in other categories
Nenue@0 259 if IsControlKeyDown() and not (configInit) then
Nenue@0 260 configInit = true
Nenue@0 261 for optTab, opts in pairs(configFrames) do
Nenue@0 262 for _, opt in ipairs(opts) do
Nenue@0 263 if opt.OptKey == key then
Nenue@0 264 if optTab ~= group then
Nenue@0 265 print('mapping to', optTab, opt.OptKey)
Nenue@0 266 opt:SetValue(self:GetValue())
Nenue@0 267 end
Nenue@0 268
Nenue@0 269 end
Nenue@0 270 end
Nenue@0 271 end
Nenue@0 272 configInit = nil
Nenue@0 273 end
Nenue@0 274 local newValue = valueFunc(self)
Nenue@0 275 if newValue ~= B.Conf[fullkey] then
Nenue@0 276 print(newValue, fullkey)
Nenue@0 277 f.fieldvalue:SetText(valueFunc(self, true))
Nenue@0 278 B.Conf[fullkey] = valueFunc(self)
Nenue@0 279 -- prepare to update
Nenue@0 280 wipe(B.drawn[f.OptTab])
Nenue@0 281 B.UpdateBuffs(self.OptTab)
Nenue@0 282 B.UpdateConfigLayers()
Nenue@0 283 end
Nenue@0 284
Nenue@0 285 end
Nenue@0 286
Nenue@0 287 f:SetValue(initialValue)
Nenue@0 288 local yBuffer = configPadding
Nenue@0 289 if f.fieldname then
Nenue@0 290 f.fieldname:SetText(fieldname)
Nenue@0 291 yBuffer = yBuffer + f.fieldname:GetHeight()
Nenue@0 292 end
Nenue@0 293 if f.fieldvalue then
Nenue@0 294 f.fieldvalue:SetText(f:OptValue(true))
Nenue@0 295 end
Nenue@0 296
Nenue@0 297 local point, relative, x, y = 'TOPLEFT', 'BOTTOMLEFT', 0, -3
Nenue@0 298
Nenue@0 299 local base
Nenue@0 300 if (row == 1) then
Nenue@0 301 bottom_extent = 0
Nenue@0 302 base = B.header
Nenue@0 303 x = (col-1) * (optionWidth+configSpacing)
Nenue@0 304 y = -configPadding
Nenue@0 305 else
Nenue@0 306 base = configFrames[t][row-1]
Nenue@0 307 end
Nenue@0 308
Nenue@0 309 print('|cFFFF0088'..cluster..'|r |cFF00FF00'.. row..'|r', col, base:GetName(), x, y - clusterOffset)
Nenue@0 310
Nenue@0 311 if frameType ~= 'CheckButton' then
Nenue@0 312 f:SetWidth(optionWidth)
Nenue@0 313 end
Nenue@0 314
Nenue@0 315 f:SetPoint(point, base, relative, x, y-yBuffer-clusterOffset)
Nenue@0 316 --print('creating', frameType, fieldname)
Nenue@0 317 f:Show()
Nenue@0 318
Nenue@0 319 bottom_extent = bottom_extent + f:GetHeight() + yBuffer + configSpacing
Nenue@0 320
Nenue@0 321
Nenue@0 322
Nenue@0 323 clusterHeight = max(clusterHeight, bottom_extent)
Nenue@0 324 --print('y', floor(yBuffer+0.5), 'f:H', floor(f:GetHeight()+0.5), 'hTally', floor(bottom_extent+0.5), 'hMax', floor(configHeight+0.5))
Nenue@0 325 end
Nenue@0 326 end
Nenue@0 327 end
Nenue@0 328
Nenue@0 329 -- grab the last cluster
Nenue@0 330 if lastCluster == cluster then
Nenue@0 331 print('|cFF00FF00##scooping up last cluster info')
Nenue@0 332 configHeight = configHeight + clusterHeight
Nenue@0 333 end
Nenue@0 334
Nenue@0 335 if not B.configFramesCreated then
Nenue@0 336 B.configFramesCreated = true
Nenue@0 337 B:SetHeight(B.header:GetStringHeight() + configSpacing*3 + configHeight)
Nenue@0 338 end
Nenue@0 339 if configInit then configInit = nil end
Nenue@0 340 end
Nenue@0 341
Nenue@0 342 M.Command = function(enable, editbox)
Nenue@0 343 displays = B.displays
Nenue@0 344 if type(enable) == 'boolean' then
Nenue@0 345 B.Conf.ConfigMode = enable
Nenue@0 346 else
Nenue@0 347 B.Conf.ConfigMode = (B.Conf.ConfigMode == false) and true or false
Nenue@0 348 end
Nenue@0 349
Nenue@0 350 print('/BUFF', B.Conf.ConfigMode, type(B.Conf.ConfigMode))
Nenue@0 351 if B.Conf.ConfigMode then
Nenue@0 352 if not B.configFramesCreated then
Nenue@0 353 InitConfig()
Nenue@0 354 end
Nenue@0 355 print('Veneer config')
Nenue@0 356 B:Show()
Nenue@0 357 else
Nenue@0 358 B:Hide()
Nenue@0 359 end
Nenue@0 360 B.UpdateAll()
Nenue@0 361 B.UpdateConfigLayers()
Nenue@0 362 end
Nenue@0 363
Nenue@0 364 B.Close = function ()
Nenue@0 365 M.Command()
Nenue@0 366 end
Nenue@0 367
Nenue@0 368 B.ToggleGuides = function(_, self)
Nenue@0 369 B.Conf.GuidesMode = (not B.Conf.GuidesMode)
Nenue@0 370 if B.Conf.GuidesMode then
Nenue@0 371 self:GetNormalTexture():SetTexture(0.94, 0.21, 0.21, 1)
Nenue@0 372 else
Nenue@0 373 self:GetNormalTexture():SetTexture(0, 0, 0, 1)
Nenue@0 374 end
Nenue@0 375
Nenue@0 376 B.UpdateConfigLayers()
Nenue@0 377 end
Nenue@0 378
Nenue@0 379 M.OnEnable = function()
Nenue@0 380 M.Command(B.Conf.ConfigMode)
Nenue@0 381 end
Nenue@0 382
Nenue@0 383 M.OnInitialize = function()
Nenue@0 384 DEFAULT_CHAT_FRAME:AddMessage("|cFF22D822Veneer|r")
Nenue@0 385 SLASH_BUFFALO1, SLASH_BUFFALO2 = "/buffalo", "/buff"
Nenue@0 386 SlashCmdList.BUFFALO = M.Command
Nenue@0 387
Nenue@0 388 end