annotate Devian.lua @ 35:3304455a3f45

code organizing; UI stuff is in the UI script, Devian prime just deals with config and print corner menu elements placed and hooked, still needs follow-up code
author Nenue
date Sun, 27 Dec 2015 03:51:17 -0500
parents 7441f3bce940
children bec37163b7fe
rev   line source
Nenue@32 1 --- ${PACKAGE_NAME}
Nenue@32 2 -- @file-author@
Nenue@32 3 -- @project-revision@ @project-hash@
Nenue@32 4 -- @file-revision@ @file-hash@
Nenue@0 5 if not LibStub then
Nenue@0 6 print('Something has happened...')
Nenue@0 7 end
Nenue@0 8 Devian = LibStub("AceAddon-3.0"):NewAddon("Devian", "AceConsole-3.0", "AceEvent-3.0")
Nenue@13 9 local MAJOR, MINOR = 'Devian-1.3', 'r@project-revision@'
Nenue@0 10 local D = _G.Devian
Nenue@32 11 local WORKSPACE_ON, WORKSPACE_OFF = 1, 2
Nenue@0 12 local PLAYER_REALM = UnitName("player") .. '-' .. GetRealmName()
Nenue@18 13 local print = _G.print
Nenue@9 14 local db
Nenue@13 15 local defaults = {
Nenue@32 16 ['global'] = {{}, {}},
Nenue@13 17 ['tags'] = {},
Nenue@32 18 ['channels'] = {[1] = {signature = 'Main', index = 1, x = 100, y = 800, height = 500, width = 600, enabled = true}},
Nenue@33 19 primary_channel = 1, -- the channel to which default output is sent
Nenue@33 20 current_channel = 1, -- the front channel
Nenue@33 21 max_channel = 1, -- the highest created channel id
Nenue@33 22 enable = true, -- allow enabled consoles to appear
Nenue@33 23 load_message = "Defaults loaded.", -- messages to be displayed after reload
Nenue@33 24 font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]], -- font info
Nenue@13 25 fontsize = 13,
Nenue@13 26 fontoutline = 'NONE',
Nenue@33 27 headergrad = {'VERTICAL', 0, 0, 0, 0.5, 0.1, 0.1, 0.1, 0.3}, -- header info
Nenue@33 28 headerdrop = {1,1,1,1},
Nenue@33 29 headeralpha = 1,
Nenue@33 30 backdrop = {0,0,0,1}, -- background frame info
Nenue@14 31 backgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.3, 0, 0, 0, 0.5},
Nenue@33 32 backblend = 'MOD',
Nenue@33 33 backalpha = 0.7,
Nenue@33 34 backborder = {0,0,1,0.75},
Nenue@33 35 frontdrop = {0,0,0,1}, -- foreground frame info
Nenue@14 36 frontgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.9, 0, 0, 0, 0.9},
Nenue@33 37 frontblend = 'MOD',
Nenue@28 38 frontalpha = 1,
Nenue@22 39 frontborder = {1,0,0,1},
Nenue@33 40 tagcolor = {}, -- tag color repository
Nenue@33 41 workspace = 1, -- current profile
Nenue@33 42 last_workspace = 2 -- default workspace to alternate with when just "/dvn" is issued
Nenue@13 43 }
Nenue@9 44
Nenue@13 45 local function ScanAddOnList(cmd, ...)
Nenue@0 46 local list_state
Nenue@0 47
Nenue@14 48 local args = {}
Nenue@14 49 local arg, n = D:GetArgs(cmd, 1)
Nenue@14 50 while arg do
Nenue@14 51 table.insert(args, arg)
Nenue@14 52 arg, n = D:GetArgs(cmd,1,n)
Nenue@14 53 end
Nenue@14 54 local mode, tag, dest = unpack(args)
Nenue@0 55
Nenue@13 56
Nenue@14 57 -- no args, toggle ui
Nenue@32 58 if mode == 'dock' then
Nenue@33 59 if db.workspace == 1 then
Nenue@33 60 D:Print('Must be in dev mode to use this.')
Nenue@33 61 return
Nenue@33 62 end
Nenue@32 63 if #args <= 2 then
Nenue@32 64 D:Print("Not enough arguments for dock command.")
Nenue@32 65 return
Nenue@32 66 end
Nenue@0 67
Nenue@32 68 local target
Nenue@32 69 local worklist = {}
Nenue@32 70 for i = 2, #args do
Nenue@32 71 local ch
Nenue@32 72 local k = tostring(args[i])
Nenue@32 73 local j = tonumber(args[i])
Nenue@32 74 if db.channels[j] then
Nenue@32 75 ch = db.channels[j]
Nenue@32 76 elseif D.sig[k] then
Nenue@32 77 ch = D.sig[k]
Nenue@32 78 elseif D.sigID[k] then
Nenue@32 79 ch = db.channels[D.sigID[k]]
Nenue@32 80 elseif db.tags[k] and db.tags[k][1] then
Nenue@32 81 ch = db.channels[db.tags[j][1]]
Nenue@32 82 -- last resort
Nenue@32 83 else
Nenue@32 84 D:Print('No entry for argument #'..i..': '..tostring(args[i]))
Nenue@32 85 return
Nenue@32 86 end
Nenue@35 87 --@debug@
Nenue@35 88 --print(i, '->', ch.index, '-', ch.signature)--@end-debug@
Nenue@32 89 if i > 2 then
Nenue@32 90 table.insert(worklist, ch.index)
Nenue@32 91 else
Nenue@32 92 target = ch
Nenue@32 93
Nenue@35 94 --@debug@
Nenue@35 95 --print('arg1', args[2], target)--@end-debug@
Nenue@32 96 end
Nenue@0 97 end
Nenue@32 98 D:Print("Docking |cFF88FFFF"..table.concat(worklist, "|r, |cFF88FFFF").."|r with |cFFFFFF00"..target.index..', '..target.signature.."|r.")
Nenue@32 99 return D:DockFrame(target.index, unpack(worklist))
Nenue@32 100
Nenue@32 101
Nenue@14 102 elseif mode == 'stack' then
Nenue@33 103 if db.workspace == 1 then
Nenue@33 104 return D:Print(MSG_NEED_DEV_MODE)
Nenue@33 105 end
Nenue@14 106 return D:StackFrames()
Nenue@14 107 elseif mode == 'grid' then
Nenue@33 108 if db.workspace == 1 then
Nenue@33 109 return D:Print(MSG_NEED_DEV_MODE)
Nenue@33 110 end
Nenue@14 111 return D:DistributeFrames()
Nenue@14 112 elseif mode == 'tag' then -- tagging
Nenue@33 113 if db.workspace == 1 then
Nenue@33 114 return D:Print(MSG_NEED_DEV_MODE)
Nenue@33 115 end
Nenue@32 116
Nenue@14 117 if tag ~= nil and dest ~= nil then
Nenue@32 118 -- convert to ID
Nenue@32 119 if tonumber(dest) == nil and D.sigID[dest] then
Nenue@32 120 dest = db.channels[D.sigID[dest]].index
Nenue@18 121 end
Nenue@18 122
Nenue@32 123 -- make a new channel?
Nenue@32 124 if not db.channels[dest] then
Nenue@32 125 dest = db.max_channel + 1
Nenue@32 126 D:Print('Creating a new channel for '.. tag)
Nenue@32 127 D:SetChannel(tag, dest)
Nenue@32 128 end
Nenue@32 129
Nenue@32 130 if db.tags[tag] and db.tags[tag][dest] then
Nenue@32 131 db.tags[tag][dest] = nil
Nenue@34 132 D:Print('Hiding |cFF88FFFF'..tag..'|r messages in |cFFFFFF00'..db.channels[dest].index ..':'.. db.channels[dest].signature)
Nenue@32 133 else
Nenue@32 134 if not db.tags[tag] then
Nenue@32 135 db.tags[tag] = {}
Nenue@32 136 end
Nenue@32 137 db.tags[tag][dest] = dest
Nenue@34 138 D:Print('Showing |cFF88FFFF'..tag..'|r messages in |cFFFFFF00'..db.channels[dest].index ..':'.. db.channels[dest].signature)
Nenue@32 139 end
Nenue@14 140 else
Nenue@14 141 D:Print('Usage: /dvn tag <prefix> <console name or number>')
Nenue@14 142 end
Nenue@14 143 return
Nenue@32 144 elseif tonumber(mode) ~= nil or mode == 'save' then
Nenue@32 145 -- iterating for something
Nenue@32 146 if mode == 'save' then
Nenue@32 147 if tonumber(tag) == nil then
Nenue@32 148 T:Print('Save ID is invalid:', tag)
Nenue@32 149 end
Nenue@32 150 list_state = tonumber(tag)
Nenue@32 151 else
Nenue@32 152 list_state = tonumber(mode)
Nenue@32 153 db.workspace = list_state
Nenue@33 154 if list_state ~= 1 then
Nenue@33 155 db.last_workspace = list_state
Nenue@33 156 end
Nenue@33 157
Nenue@0 158 end
Nenue@32 159 elseif mode == nil then
Nenue@33 160 list_state = (db.workspace == 1) and db.last_workspace or 1
Nenue@33 161 db.workspace = list_state
Nenue@33 162 db.load_message = "quick swapped workspace #"..list_state
Nenue@32 163 else
Nenue@32 164 return D:PrintHelp()
Nenue@0 165 end
Nenue@32 166
Nenue@32 167 -- start the iterating
Nenue@0 168 local char_list, global_list = db[PLAYER_REALM][list_state], db.global[list_state]
Nenue@0 169 local playername = UnitName("player")
Nenue@0 170
Nenue@0 171 for i = 1, GetNumAddOns() do
Nenue@0 172 local name = GetAddOnInfo(i)
Nenue@0 173 local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i)
Nenue@0 174
Nenue@32 175 if mode == 'save' then
Nenue@0 176 char_list[name] = enableState
Nenue@0 177 global_list[name] = globalState
Nenue@0 178 else
Nenue@13 179 if char_list[name] or global_list[name] then
Nenue@32 180 if char_list[name] ~= 0 and global_list[name] ~= 0 then
Nenue@32 181 local value = false
Nenue@32 182 if char_list[name] == 2 and global_list[name] == 1 then
Nenue@32 183 value = UnitName("player")
Nenue@32 184 elseif global_list[name] == 2 then
Nenue@32 185 value = true
Nenue@32 186 end
Nenue@32 187 --print('EnableAddOn(', i, ',', value,')')
Nenue@32 188 EnableAddOn(i, value)
Nenue@32 189 else
Nenue@32 190 local value = true
Nenue@32 191 if char_list[name] == 2 and global_list[name] == 1 then
Nenue@32 192 value = UnitName("player")
Nenue@32 193 end
Nenue@32 194 --print('DisableAddOn(', i, ',', value,')')
Nenue@32 195 DisableAddOn(i,value)
Nenue@0 196 end
Nenue@33 197 elseif mode ~= 'save' then
Nenue@32 198 if type(db.unlisted) ~= 'table' then
Nenue@32 199 db.unlisted = {}
Nenue@0 200 end
Nenue@32 201 table.insert(db.unlisted, name)
Nenue@13 202 end
Nenue@0 203
Nenue@0 204 end
Nenue@0 205 end
Nenue@0 206
Nenue@32 207 if mode ~= 'save' then
Nenue@33 208 --db.load_message = "AddOn profile ".. list_state .." was loaded."
Nenue@0 209 ReloadUI()
Nenue@0 210 else
Nenue@32 211 D:Print('Profile #'.. (list_state)..' saved.')
Nenue@32 212 if list_state == 1 then
Nenue@32 213 D:Print('This will be your main AddOn list.')
Nenue@32 214 elseif list_state == db.default_list then
Nenue@32 215 db.last_workspace = list_state
Nenue@32 216 D:Print('This will be your default workspace')
Nenue@32 217 end
Nenue@0 218 end
Nenue@0 219 end
Nenue@0 220
Nenue@0 221
Nenue@13 222
Nenue@18 223 --- Creates a Devian-style output.
Nenue@18 224 -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print()
Nenue@18 225 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint().
Nenue@18 226 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel.
Nenue@18 227 -- @param ... Output contents.
Nenue@0 228 local function Message(prefix, ...)
Nenue@33 229 if not db.enabled then
Nenue@23 230 return D.oldprint(prefix, ...)
Nenue@23 231 end
Nenue@23 232
Nenue@1 233 if prefix == nil then
Nenue@13 234 prefix = 1
Nenue@1 235 end
Nenue@9 236
Nenue@18 237 local sendq = {}
Nenue@30 238 local tag, id, tagged
Nenue@13 239 local byName = true
Nenue@18 240 if D.tags[prefix] then
Nenue@18 241 for _, id in pairs(D.tags[prefix]) do
Nenue@18 242 if D.console[id] then
Nenue@18 243 sendq[id] = D.console[id]
Nenue@30 244 tagged = true
Nenue@18 245 end
Nenue@18 246 end
Nenue@18 247 end
Nenue@18 248
Nenue@13 249 if D.sig[prefix] then
Nenue@18 250 sendq[D.sig[prefix].index] = D.sig[prefix]
Nenue@13 251 elseif D.console[prefix] then
Nenue@18 252 sendq[D.console[prefix]] = D.console[prefix]
Nenue@30 253 elseif not tagged then
Nenue@18 254 sendq[D.primary_channel] = D.console[D.primary_channel]
Nenue@13 255 end
Nenue@18 256
Nenue@9 257 -- color me timbers
Nenue@9 258 local pcolor
Nenue@18 259 if (not db.tagcolor[prefix]) and byName then
Nenue@30 260 local c = {
Nenue@30 261 math.random(64,255), math.random(64,255), math.random(64,255)
Nenue@30 262 }
Nenue@30 263 if c[1] > 223 and c[2] > 223 and c[3] > 223 then
Nenue@30 264 c[math.random(1,3)] = math.random(64,223)
Nenue@0 265 end
Nenue@30 266
Nenue@18 267 db.tagcolor[prefix] = string.format('%02X%02X%02X', unpack(c))
Nenue@0 268 end
Nenue@18 269 pcolor = db.tagcolor[prefix]
Nenue@0 270
Nenue@18 271 local buffer = {'|cFF'.. pcolor..prefix ..'|r'}
Nenue@0 272 for i = 1, select('#',...) do
Nenue@0 273 local var = select(i, ...)
Nenue@0 274
Nenue@0 275 if type(var) == 'table' then
Nenue@20 276 if type(var.GetName) == 'function' then
Nenue@32 277 var = '<table:'..var:GetName()..'>'
Nenue@20 278 else
Nenue@32 279 var = '<'..tostring(var)..'>'
Nenue@20 280 end
Nenue@20 281
Nenue@0 282 elseif type(var) == 'boolean' then
Nenue@0 283 var = var and 'true' or 'false'
Nenue@0 284 elseif type(var) == 'function' then
Nenue@0 285 var = '<funcref>'
Nenue@0 286 elseif type(var) == 'nil' then
Nenue@0 287 var = 'nil'
Nenue@0 288 end
Nenue@0 289
Nenue@0 290 table.insert(buffer, var)
Nenue@0 291 end
Nenue@18 292 local message = table.concat(buffer, ' ')
Nenue@18 293 for id, channel in pairs(sendq) do
Nenue@18 294 channel.out:AddMessage(message)
Nenue@18 295 end
Nenue@0 296 table.wipe(buffer)
Nenue@0 297 end
Nenue@0 298
Nenue@14 299
Nenue@32 300
Nenue@14 301
Nenue@32 302 function D:PrintHelp()
Nenue@32 303 D:Print("|cFFFFFF00/dvn|r",
Nenue@32 304 "\n |cFFFFFF00<number>|r - Loads a saved addon list. List 1 is treated as a gameplay profile and consoles will be disabled by default.")
Nenue@32 305
Nenue@32 306 D:Print("|cFFFFFF00/resetdvn|r", "- Resets all but profile data SavedVariables.")
Nenue@32 307 D:Print("|cFFFFFF00/cleandvn|r", "- Fully resets SavedVariables, profiles and all.")
Nenue@32 308 end
Nenue@32 309
Nenue@0 310 function D:OnEnable()
Nenue@33 311 print(MAJOR, MINOR)
Nenue@33 312
Nenue@33 313 if db.unlisted and #db.unlisted > 0 then
Nenue@33 314 D:Print('New AddOns have been found since the last profile update: '.. table.concat(db.unlisted, ', '))
Nenue@33 315 table.wipe(db.unlisted)
Nenue@33 316 end
Nenue@33 317
Nenue@33 318 if db.workspace == 1 then
Nenue@33 319 D:Print('Gameplay mode active (list #'..db.workspace..'). Print handling turned |cFFFFFF00OFF|r.')
Nenue@33 320 else
Nenue@33 321 D:Print('Development mode active (list #'..db.workspace..'). Print handling |cFF00FF00ON|r.')
Nenue@33 322 end
Nenue@33 323
Nenue@33 324 end
Nenue@33 325
Nenue@33 326 function D:OnInitialize()
Nenue@13 327 -- commands
Nenue@33 328 self:RegisterChatCommand("cleandvn", function(args)
Nenue@33 329 DevianDB = nil
Nenue@33 330 DevianDB = {
Nenue@33 331 load_message = "All SavedVars wiped."
Nenue@33 332 }
Nenue@33 333 ReloadUI()
Nenue@33 334 end)
Nenue@33 335 self:RegisterChatCommand("resetdvn", function(args)
Nenue@33 336 for k,v in pairs(DevianDB) do
Nenue@33 337 if k ~= 'global' then
Nenue@33 338 DevianDB[k] = nil
Nenue@33 339 end
Nenue@33 340 end
Nenue@33 341
Nenue@33 342 DevianDB.load_message = "Non-user SavedVars have been reset."
Nenue@33 343 for k,v in pairs(defaults) do
Nenue@33 344 DevianDB[k] = v
Nenue@33 345 end
Nenue@33 346 ReloadUI()
Nenue@33 347 end)
Nenue@13 348 local cmdlist = {
Nenue@13 349 ['dvn'] = ScanAddOnList,
Nenue@13 350 ['devian'] = ScanAddOnList,
Nenue@13 351 ['dvc'] = Console_Toggle,
Nenue@13 352 }
Nenue@13 353 for cmd, func in pairs(cmdlist) do
Nenue@13 354 self:RegisterChatCommand(cmd, func, true)
Nenue@13 355 end
Nenue@13 356
Nenue@33 357 -- pull defaults
Nenue@9 358 if not _G.DevianDB then
Nenue@13 359 _G.DevianDB = defaults
Nenue@9 360 end
Nenue@9 361 db = _G.DevianDB
Nenue@32 362 self.tags = db.tags
Nenue@32 363 self.channelinfo = db.channels
Nenue@0 364
Nenue@0 365 if not db[PLAYER_REALM] then
Nenue@32 366 db[PLAYER_REALM] = {[WORKSPACE_ON] = {}, [WORKSPACE_OFF] = {}}
Nenue@0 367 end
Nenue@0 368
Nenue@32 369 if db.load_message then
Nenue@32 370 D:Print(db.load_message)
Nenue@32 371 db.load_message = nil
Nenue@0 372 end
Nenue@0 373 D.oldprint = getprinthandler()
Nenue@0 374 if not _G.oldprint then
Nenue@0 375 _G.oldprint = D.oldprint
Nenue@0 376 end
Nenue@13 377
Nenue@33 378 -- Stop here in game mode
Nenue@33 379 if db.workspace == 1 then
Nenue@33 380 return
Nenue@33 381 end
Nenue@35 382 -----------------------------------------------------------------------
Nenue@35 383 self.db = db
Nenue@35 384 self.channels = db.channels
Nenue@32 385 self.max_channel = 0
Nenue@14 386 self.num_channels = 0
Nenue@13 387 self.console = {}
Nenue@13 388 self.sig = {}
Nenue@14 389 self.sigID = {}
Nenue@14 390 self.IDsig = {}
Nenue@14 391 for i, cinfo in pairs(db.channels) do
Nenue@14 392 i = tonumber(i)
Nenue@14 393 if not self.primary_channel then
Nenue@14 394 self.primary_channel = i
Nenue@14 395 end
Nenue@14 396 self:SetChannel(cinfo, i)
Nenue@32 397 self.max_channel = math.max(i, self.max_channel)
Nenue@32 398 self.num_channels = self.num_channels + 1
Nenue@32 399 end
Nenue@32 400
Nenue@32 401 for i, channel in pairs(db.channels) do
Nenue@32 402 if type(channel.docked) == 'table' then
Nenue@32 403 oldprint('docking',i, unpack(channel.docked))
Nenue@32 404 self.DockFrame(i, unpack(channel.docked))
Nenue@14 405 end
Nenue@13 406 end
Nenue@18 407
Nenue@18 408 if self.console[db.current_channel] then
Nenue@18 409 self.console[db.current_channel]:ToFront()
Nenue@28 410 -- bring the current channel to the front
Nenue@18 411 end
Nenue@33 412 setprinthandler(Message)
Nenue@33 413 print = function(...)
Nenue@33 414 _G.print('Dvn', ...)
Nenue@23 415 end
Nenue@0 416 end