annotate Init.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 3397aae1f44d
children 9455693fc290
rev   line source
Nenue@0 1 --- Modulizer framework
Nenue@0 2 -- OnInitialize
Nenue@0 3 -- OnUpdate
Nenue@0 4 -- OnEnable -- run when GetSpecialization() returns true
Nenue@0 5
Nenue@0 6 local ADDON, A = ...
Nenue@0 7 Veneer = Veneer or CreateFrame('Frame', 'Veneer', UIParent)
Nenue@0 8 local B = Veneer
Nenue@3 9 local wipe, min, max, random, tinsert, tremove = table.wipe, math.min, math.max, math.random, table.insert, table.remove
Nenue@0 10 local pairs, ipairs, select, unpack, _G = pairs, ipairs, select, unpack, _G
Nenue@0 11 local type, tostring, format = type, tostring, string.format
Nenue@0 12 A.frame = B
Nenue@0 13
Nenue@0 14 --- Cache tables
Nenue@0 15 local initOnced
Nenue@0 16 local modules = {}
Nenue@0 17 local queuedModules = {}
Nenue@3 18 local checkForConfig = {}
Nenue@0 19 local moduleStack = {
Nenue@0 20 }
Nenue@0 21
Nenue@0 22 --- Various region categories
Nenue@0 23 B.displays = {}
Nenue@0 24 B.configLayers = {}
Nenue@0 25 B.configLayersRef = {}
Nenue@0 26
Nenue@0 27 --@debug@
Nenue@0 28 --- Generates a print handler pointing to a static channel signature
Nenue@0 29 -- @usage func = B.print(sig)
Nenue@0 30 -- @param sig channel name or number
Nenue@0 31 local printfuncs = {}
Nenue@0 32 B.print = function(pref, ...)
Nenue@0 33 if Devian and Devian.InWorkspace() then
Nenue@0 34 printfuncs[pref] = printfuncs[pref] or function(...) print(pref, ...) end
Nenue@0 35
Nenue@0 36 return printfuncs[pref]
Nenue@0 37 else
Nenue@0 38 return function () end
Nenue@0 39 end
Nenue@0 40 end
Nenue@0 41
Nenue@0 42 local rgb = {}
Nenue@0 43 local getcolor = function()
Nenue@0 44 local n, p = 0, 4
Nenue@0 45 for i = 1, 3 do
Nenue@0 46 rgb[i] = min(random(n,p) * 64, 255)
Nenue@0 47 if rgb[i] == 255 then
Nenue@0 48 p = 4
Nenue@0 49 elseif rgb[i] > 0 then
Nenue@0 50 n = 2
Nenue@0 51 end
Nenue@0 52 end
Nenue@0 53 return unpack(rgb)
Nenue@0 54 end
Nenue@0 55
Nenue@0 56 local color = {}
Nenue@0 57 local fprints = {}
Nenue@0 58 B.fprint = function()
Nenue@0 59 if not (Devian and Devian.InWorkspace()) then
Nenue@0 60 return function() end
Nenue@0 61 end
Nenue@0 62
Nenue@0 63
Nenue@0 64 local sig = debugstack(2,1)
Nenue@0 65 if fprints[sig] then
Nenue@0 66 return fprints[sig]
Nenue@0 67 end
Nenue@0 68
Nenue@0 69 local func = sig:match("%`(%a+)%'")
Nenue@0 70 if not func then
Nenue@0 71 func = sig:match("<(.-)>")
Nenue@0 72 end
Nenue@0 73 func = func:gsub('(%l+)(%u)', function(a, b) return a:sub(0,2) .. b end, 1)
Nenue@0 74 func = func:gsub('^.+%\\', '')
Nenue@0 75 if not func then
Nenue@0 76 func = 'noname'
Nenue@0 77 end
Nenue@0 78
Nenue@0 79 local r, g, b = getcolor()
Nenue@0 80 color[sig] = color[sig] or format('|cFF%02X%02X%02X%s|r', r, g, b, func)
Nenue@0 81
Nenue@0 82 --print(color[func] .. ' ( ' .. table.concat(args, ', ')..' )' )
Nenue@0 83 func = B.print(func)
Nenue@0 84 fprints[sig] = func
Nenue@0 85 return func
Nenue@0 86 end
Nenue@0 87
Nenue@0 88 --@end-debug@
Nenue@0 89 --[=[@non-debug@
Nenue@0 90 B.print = function() end
Nenue@0 91 --@end-non-debug@]=]
Nenue@0 92
Nenue@0 93 -- for the Mikk script
Nenue@0 94 -- GLOBALS: NUM_LE_RAID_BUFF_TYPES
Nenue@0 95 -- GLOBALS: BUFF_FLASH_TIME_ON, BUFF_FLASH_TIME_OFF, BUFF_MIN_ALPHA, BUFF_WARNING_TIME, BUFF_DURATION_WARNING_TIME
Nenue@0 96 -- GLOBALS: BUFFS_PER_ROW, BUFF_MAX_DISPLAY, BUFF_ACTUAL_DISPLAY, DEBUFF_MAX_DISPLAY, DEBUFF_ACTUAL_DISPLAY, BUFF_ROW_SPACING
Nenue@0 97 -- GLOBALS: CONSOLIDATED_BUFFS_PER_ROW, CONSOLIDATED_BUFF_ROW_HEIGHT, NUM_TEMP_ENCHANT_FRAMES
Nenue@0 98 -- GLOBALS: BUFF_BUTTON_HEIGHT, BUFF_FRAME_BASE_EXTENT, BUFF_HORIZ_SPACING
Nenue@0 99
Nenue@0 100 local print = B.print('Bfl')
Nenue@0 101
Nenue@0 102 --- Template for making perpendicular traversals of the displays structure; also makes sure the table is there
Nenue@0 103 B.Abstract = function(dest, key, table)
Nenue@0 104 if table then
Nenue@0 105 for _, v in pairs(dest) do
Nenue@0 106 v[key] = {}
Nenue@0 107 end
Nenue@0 108 end
Nenue@0 109 B[key] = setmetatable({}, {
Nenue@0 110 __index = function(t, k)
Nenue@0 111 return dest[k][key]
Nenue@0 112 end,
Nenue@0 113 __newindex = function(_, k, v)
Nenue@0 114 print('abstract write ('..key..'):', k)
Nenue@0 115 dest[k][key] = v
Nenue@0 116 end,
Nenue@0 117 __tostring = function() return 'Abstract:'..key..'' end
Nenue@0 118 })
Nenue@0 119
Nenue@0 120
Nenue@0 121 return B[key]
Nenue@0 122 end
Nenue@0 123
Nenue@0 124
Nenue@0 125 --- localize for speed
Nenue@0 126 local layers, refs, displays = B.configLayers, B.configLayersRef, B.displays
Nenue@0 127
Nenue@0 128 local ModulesCall = function(func)
Nenue@0 129
Nenue@0 130 local n = 0
Nenue@0 131 for i = 1, #moduleStack do
Nenue@0 132 print('calling level '..i)
Nenue@0 133 local stackset = moduleStack[i]
Nenue@0 134
Nenue@0 135 for name, module in pairs(stackset) do
Nenue@0 136 n = n + 1
Nenue@0 137 print(n..' '..name..'.'..func..'()')
Nenue@0 138
Nenue@0 139
Nenue@0 140 if module[func] then
Nenue@0 141 module[func](module)
Nenue@0 142 end
Nenue@0 143 end
Nenue@0 144 end
Nenue@0 145 end
Nenue@0 146
Nenue@0 147
Nenue@0 148 local Enable = function()
Nenue@0 149 end
Nenue@0 150
Nenue@0 151 --- The things that happen repeatedly
Nenue@0 152 local Init = function ()
Nenue@0 153 end
Nenue@0 154
Nenue@0 155
Nenue@0 156 --- Things that happen immediately upon entering world
Nenue@0 157 local InitOnce = function()
Nenue@0 158 print('entering world first time')
Nenue@0 159 local defaults = B.ConfDefaults
Nenue@0 160 print('|cFFFFFF00Veneer|r')
Nenue@0 161 if not VeneerData then
Nenue@0 162 VeneerData = {}
Nenue@0 163 for k,v in pairs(defaults) do
Nenue@0 164 VeneerData[k] = v
Nenue@0 165 end
Nenue@0 166 print('Veneer defaults being used.')
Nenue@0 167 end
Nenue@0 168
Nenue@0 169 B.Conf = setmetatable(VeneerData, {__index = function(_, k) return defaults[k] end})
Nenue@0 170
Nenue@0 171 -- suffix tables
Nenue@0 172 for name, display in pairs(displays) do
Nenue@0 173 display.conf = setmetatable({}, {
Nenue@0 174 __index = function(_, k)
Nenue@0 175 --print('config check '.. name .. k)
Nenue@0 176 return B.Conf[name .. k] or B.Conf['BuffButton' .. k]
Nenue@0 177 end,
Nenue@0 178 __newindex = function(_, k , v)
Nenue@0 179 B.Conf[name..k] = v
Nenue@0 180 end,
Nenue@0 181 })
Nenue@0 182 end
Nenue@0 183
Nenue@0 184 -- To ensure that modules are run in controlled order, walk the dependency list; if the dep shows up
Nenue@0 185 -- in the loaded manifest, remove the value. If the dep list isn't empty, move that module to the next
Nenue@0 186 -- layer.
Nenue@0 187 local loaded = {}
Nenue@0 188 local stackLevels = #moduleStack
Nenue@0 189 local i = 1
Nenue@0 190 moduleStack[1] = modules
Nenue@0 191 repeat
Nenue@0 192 print('setting init level '.. i)
Nenue@0 193 local queue = moduleStack[i]
Nenue@0 194 for name, module in pairs(queue) do
Nenue@0 195
Nenue@0 196 if queuedModules[name] and #queuedModules[name] > 0 then
Nenue@0 197 local p = #queuedModules[name]
Nenue@0 198 for j = 1, p do
Nenue@0 199 local dep = queuedModules[name][j]
Nenue@0 200
Nenue@0 201 if loaded[dep] then
Nenue@0 202 print( ' ' .. dep .. ' OK')
Nenue@0 203 queuedModules[name][j] = nil
Nenue@0 204 for k = j, p do
Nenue@0 205 print(' shift ' .. (k+1) .. ' ('..tostring(queuedModules[name][k+1])..') to ' .. k ..'')
Nenue@0 206 queuedModules[name][k] = queuedModules[name][k+1]
Nenue@0 207 end
Nenue@0 208 end
Nenue@0 209 end
Nenue@0 210
Nenue@0 211 if #queuedModules[name] == 0 then
Nenue@0 212 queuedModules[name] = nil
Nenue@0 213 print(' |cFF00FFFF'.. name ..'|r deps OK')
Nenue@0 214 loaded[name] = true
Nenue@0 215 else
Nenue@0 216
Nenue@0 217 print(' |cFFFF8800' .. name ..'|r pending')
Nenue@0 218 local next = i+1
Nenue@0 219 if not moduleStack[next] then
Nenue@0 220 moduleStack[next] = {}
Nenue@0 221 end
Nenue@0 222 stackLevels = next
Nenue@0 223 moduleStack[next][name] = module
Nenue@0 224 queue[name] = nil
Nenue@0 225 end
Nenue@0 226
Nenue@0 227 else
Nenue@0 228 print(' |cFF00FF00'.. name ..'|r no deps')
Nenue@0 229 loaded[name] = true
Nenue@0 230 end
Nenue@0 231 end
Nenue@0 232 i = i + 1
Nenue@0 233 until i > stackLevels
Nenue@0 234
Nenue@0 235
Nenue@0 236 for level, batch in ipairs(moduleStack) do
Nenue@0 237 print('config level', level)
Nenue@0 238 for name, module in pairs(batch) do
Nenue@0 239 print('integrity check', name)
Nenue@0 240
Nenue@0 241 --[===[@non-debug@
Nenue@0 242 if module.defaults and not VeneerData[name] then
Nenue@0 243 --@end-non-debug@]===]
Nenue@0 244 print('Adding defaults from module ', name)
Nenue@0 245 VeneerData[name] = module.default
Nenue@0 246 --[===[@non-debug@
Nenue@0 247 end
Nenue@0 248 --@end-non-debug@]===]
Nenue@0 249 end
Nenue@0 250 end
Nenue@3 251
Nenue@3 252
Nenue@3 253 if #checkForConfig >= 1 then
Nenue@3 254 local queuedFrame = tremove(checkForConfig)
Nenue@3 255 while queuedFrame do
Nenue@3 256 B.SetConfigLayers(queuedFrame)
Nenue@3 257 B.InitXMLFrame(queuedFrame)
Nenue@3 258 queuedFrame = tremove(checkForConfig)
Nenue@3 259 end
Nenue@3 260 end
Nenue@0 261 -- remove from existing
Nenue@0 262 end
Nenue@0 263
Nenue@0 264 --- Fires an update to all modules
Nenue@0 265 local lastUpdate
Nenue@0 266 function B.UpdateAll(...)
Nenue@0 267 lastUpdate = GetTime()
Nenue@0 268 ModulesCall('OnUpdate', lastUpdate)
Nenue@0 269 end
Nenue@0 270
Nenue@0 271 B:RegisterEvent('PLAYER_ENTERING_WORLD')
Nenue@0 272 B:SetScript('OnEvent', function(self, event)
Nenue@0 273 if event == 'PLAYER_ENTERING_WORLD' then
Nenue@0 274 if not initOnced then
Nenue@0 275 InitOnce()
Nenue@0 276 ModulesCall('OnInitialize')
Nenue@0 277 initOnced = true
Nenue@0 278 C_Timer.After(1, function()
Nenue@0 279 if GetSpecialization() then
Nenue@0 280 print(GetSpecialization(), 'enabling')
Nenue@0 281 ModulesCall('OnEnable')
Nenue@0 282 B:SetScript('OnUpdate', nil)
Nenue@0 283 end
Nenue@0 284
Nenue@0 285 end)
Nenue@0 286 end
Nenue@0 287
Nenue@0 288 end
Nenue@0 289
Nenue@0 290 B.UpdateAll()
Nenue@0 291 end)
Nenue@0 292
Nenue@0 293 --- Modulizer method
Nenue@0 294 --
Nenue@0 295 function B:RegisterModule (name, module, ...)
Nenue@0 296 if modules[name] then
Nenue@0 297 print('pulling modules[|cFFFF8800'.. tostring(name) ..'|r]')
Nenue@0 298 return modules[name]
Nenue@0 299 end
Nenue@0 300
Nenue@0 301 print('new module |cFF00BBFF'.. tostring(name) ..'|r')
Nenue@0 302 if module then
Nenue@0 303 if modules[name] then
Nenue@0 304 error("Module table for '"..tostring(name).."' already exists.")
Nenue@0 305 end
Nenue@0 306 else
Nenue@0 307 module = CreateFrame('Frame', 'Veneer' .. tostring(name) .. 'Handler', B, 'VeneerHandlerTemplate')
Nenue@0 308 end
Nenue@0 309 modules[name] = module
Nenue@3 310 B[name] = module
Nenue@0 311 if select('#', ...) >= 1 then
Nenue@0 312 local numDeps = select('#', ...)
Nenue@0 313 print(' '..numDeps..' deps detected')
Nenue@0 314 for i = 1, numDeps do
Nenue@0 315 local dep = select(i, ...)
Nenue@0 316 -- means that init/enable funcs are ordered to run after deps do their things
Nenue@0 317 queuedModules[name] = queuedModules[name] or {}
Nenue@0 318 tinsert(queuedModules[name], dep)
Nenue@0 319 print(' needs '..dep)
Nenue@0 320 end
Nenue@0 321 end
Nenue@0 322 return module
Nenue@0 323 end
Nenue@0 324
Nenue@0 325
Nenue@0 326 B.SetConfigLayers = function(frame)
Nenue@0 327 local print = B.fprint()
Nenue@0 328 if not frame.config then
Nenue@0 329 print(frame:GetName(), 'has no config layers')
Nenue@0 330 return
Nenue@0 331 end
Nenue@0 332 print('Registering config layers from', frame:GetName())
Nenue@0 333
Nenue@0 334 for i, subframe in ipairs(frame.config) do
Nenue@0 335 -- make sure there are no duplicates
Nenue@0 336 if not refs[subframe] then
Nenue@0 337 local key = #layers+1
Nenue@0 338 layers[key] = subframe
Nenue@0 339 refs[subframe] = key
Nenue@0 340 end
Nenue@0 341 print(' ', i, subframe:GetName())
Nenue@0 342 end
Nenue@0 343 end
Nenue@0 344
Nenue@0 345 B.RemoveConfigLayers = function(frame)
Nenue@3 346
Nenue@0 347 local print = B.fprint()
Nenue@0 348 print('|cFFFF0000RemoveConfigLayers', frame:GetName())
Nenue@0 349 for i, subframe in pairs(layers) do
Nenue@0 350 if subframe:GetParent() == frame then
Nenue@0 351 print('|cFFFF8800 ', subframe:GetParent():GetName(), '|cFFFFFF00', subframe:GetName())
Nenue@0 352 layers[i]:Hide()
Nenue@0 353 layers[i] = nil
Nenue@0 354 refs[subframe] = nil
Nenue@0 355 end
Nenue@0 356 end
Nenue@0 357 end
Nenue@0 358
Nenue@0 359 B.UpdateConfigLayers = function()
Nenue@0 360 local print = B.fprint()
Nenue@0 361 local func = B.Conf.GuidesMode and 'Show' or 'Hide'
Nenue@0 362 local numAnchors = 0
Nenue@0 363 for name, display in pairs(displays) do
Nenue@0 364 numAnchors = numAnchors + 1
Nenue@0 365 display.anchor:EnableMouse(B.Conf.GuidesMode)
Nenue@0 366 if B.Conf.GuidesMode then
Nenue@0 367 display.anchor:SetScript('OnUpdate', display.anchor.OnUpdate)
Nenue@0 368 else
Nenue@0 369 display.anchor:SetScript('OnUpdate', nil)
Nenue@0 370
Nenue@0 371 for i, anchorButton in ipairs(display.anchor.anchorButton) do
Nenue@0 372 anchorButton:Hide()
Nenue@0 373 end
Nenue@0 374
Nenue@0 375 end
Nenue@0 376
Nenue@0 377 end
Nenue@0 378 for id, region in pairs(layers) do
Nenue@0 379 print(id, region:GetName(), func)
Nenue@0 380 region[func](region)
Nenue@0 381 end
Nenue@0 382
Nenue@0 383 print('['..func..'] updated', #layers, 'regions,', numAnchors, 'frames')
Nenue@3 384 end
Nenue@3 385
Nenue@3 386 --- Generic handlers for keeping track of XML-defined frames
Nenue@3 387 B.OnLoad = function(self)
Nenue@3 388 tinsert(checkForConfig, self)
Nenue@3 389 end
Nenue@3 390
Nenue@3 391 B.InitXMLFrame = function(self)
Nenue@3 392 print('|cFF00FF00hello from '..self:GetName())
Nenue@3 393
Nenue@3 394 self:RegisterForDrag('LeftButton')
Nenue@3 395 if not B.Conf.FramePosition then
Nenue@3 396 B.Conf.FramePosition = {}
Nenue@3 397 end
Nenue@3 398 if B.Conf.FramePosition[self:GetName()] then
Nenue@3 399 print('restoring frame position', unpack(B.Conf.FramePosition[self:GetName()]))
Nenue@3 400 self:ClearAllPoints()
Nenue@3 401 local anchorTo, relativePoint, x, y = unpack(B.Conf.FramePosition[self:GetName()])
Nenue@3 402 self:SetPoint(anchorTo, UIParent, relativePoint, x, y)
Nenue@3 403 end
Nenue@3 404 end
Nenue@3 405
Nenue@3 406 B.OnDragStart = function(self)
Nenue@3 407 self.xA = self:GetLeft()
Nenue@3 408 self.yA = self:GetBottom()
Nenue@3 409 self.anchorTo, self.relativeTo, self.relativePoint, self.x, self.y = self:GetPoint(1)
Nenue@3 410 print('acquire anchor', self:GetPoint(1))
Nenue@3 411 print(self:GetName(), 'start moving ('..self.x..', '..self.y..')')
Nenue@3 412 self:StartMoving()
Nenue@3 413 end
Nenue@3 414
Nenue@3 415 B.OnDragStop = function(self)
Nenue@3 416 print(self:GetName(), 'stop moving ('..self:GetLeft()..', '..self:GetBottom()..')')
Nenue@3 417 local xB = self:GetLeft() - self.xA
Nenue@3 418 local yB = self:GetBottom() - self.yA
Nenue@3 419 print('storing anchor point', self.anchorTo, self.relativePoint, self.x + xB, self.y + yB)
Nenue@3 420
Nenue@3 421 self:StopMovingOrSizing()
Nenue@3 422 B.Conf.FramePosition[self:GetName()] = {self.anchorTo, self.relativePoint, self.x + xB, self.y + yB}
Nenue@3 423 B.InitXMLFrame(self)
Nenue@3 424
Nenue@0 425 end