annotate Devian.lua @ 13:080dfa4990fb

necessary abstractions for running multiple console buffers in place message prefix can act as a channel selector when tagged in savedvars more frame vars defined in the XML XML parentKey names organized
author Nenue
date Sat, 19 Dec 2015 07:59:12 -0500
parents 65fcb81f4e0a
children 5254d1ba6013
rev   line source
Nenue@0 1 -- User: Krakyn
Nenue@0 2 -- Created: 11/30/2015 7:46 AM
Nenue@0 3 if not LibStub then
Nenue@0 4 print('Something has happened...')
Nenue@0 5 end
Nenue@0 6 Devian = LibStub("AceAddon-3.0"):NewAddon("Devian", "AceConsole-3.0", "AceEvent-3.0")
Nenue@13 7 local MAJOR, MINOR = 'Devian-1.3', 'r@project-revision@'
Nenue@0 8 local D = _G.Devian
Nenue@0 9 local STATE_LOW, STATE_HIGH = 1, 2
Nenue@0 10 local PLAYER_REALM = UnitName("player") .. '-' .. GetRealmName()
Nenue@13 11 local DEVIAN_FRAME = 'DevianConsole'
Nenue@7 12 local print = function(...)
Nenue@13 13 _G.print('Dvn', ...)
Nenue@7 14 end
Nenue@9 15 local db
Nenue@13 16 local defaults = {
Nenue@13 17 ['global'] = {[STATE_LOW] = {}, [STATE_HIGH] = {}},
Nenue@13 18 ['tags'] = {},
Nenue@13 19 ['channels'] = {[1] = {signature = 'Dvn', name = 'Main', header = "%n [%t]", x = 100, y = 800, height = 500, width = 600, enabled = true}},
Nenue@13 20 current_channel = 1,
Nenue@13 21 console = true,
Nenue@13 22 dnd_status = true,
Nenue@13 23 dnd_message = "Debugging. Your messages may get eaten.",
Nenue@13 24 font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]],
Nenue@13 25 fontsize = 13,
Nenue@13 26 fontoutline = 'NONE',
Nenue@13 27 }
Nenue@9 28
Nenue@4 29
Nenue@13 30 local function ScanAddOnList(cmd, ...)
Nenue@0 31 local list_state
Nenue@0 32
Nenue@13 33 local mode = tonumber(cmd:match("%d"))
Nenue@0 34
Nenue@13 35
Nenue@13 36 print('Starting Addons scan. arg=', mode)
Nenue@0 37 if mode == nil then
Nenue@0 38 list_state = db.enabled and STATE_LOW or STATE_HIGH
Nenue@0 39 db.enabled = (db.enabled == false) and true or false
Nenue@0 40 print(list_state, db.enabled)
Nenue@0 41
Nenue@0 42 if list_state == STATE_LOW then
Nenue@0 43 end
Nenue@0 44
Nenue@0 45 else
Nenue@0 46 if mode > 2 then
Nenue@13 47 print('Something has happened.')
Nenue@0 48 return
Nenue@0 49 end
Nenue@0 50 list_state = mode == STATE_LOW and STATE_LOW or STATE_HIGH
Nenue@0 51
Nenue@0 52
Nenue@0 53 end
Nenue@0 54 local char_list, global_list = db[PLAYER_REALM][list_state], db.global[list_state]
Nenue@0 55
Nenue@0 56 local playername = UnitName("player")
Nenue@0 57
Nenue@0 58 for i = 1, GetNumAddOns() do
Nenue@0 59 local name = GetAddOnInfo(i)
Nenue@0 60 local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i)
Nenue@0 61
Nenue@0 62 if mode == STATE_LOW or mode == STATE_HIGH then
Nenue@0 63 char_list[name] = enableState
Nenue@0 64 global_list[name] = globalState
Nenue@0 65 else
Nenue@13 66 if char_list[name] or global_list[name] then
Nenue@0 67
Nenue@0 68 if char_list[name] ~= 0 and global_list[name] ~= 0 then
Nenue@0 69 local value = false
Nenue@0 70 if char_list[name] == 2 and global_list[name] == 1 then
Nenue@0 71 value = UnitName("player")
Nenue@0 72 elseif global_list[name] == 2 then
Nenue@0 73 value = true
Nenue@0 74 end
Nenue@0 75 print('EnableAddOn(', i, ',', value,')')
Nenue@0 76 EnableAddOn(i, value)
Nenue@0 77 else
Nenue@0 78 local value = true
Nenue@0 79 if char_list[name] == 2 and global_list[name] == 1 then
Nenue@0 80 value = UnitName("player")
Nenue@0 81 end
Nenue@0 82 print('DisableAddOn(', i, ',', value,')')
Nenue@0 83 DisableAddOn(i,value)
Nenue@0 84 end
Nenue@13 85 end
Nenue@0 86
Nenue@0 87 end
Nenue@0 88 end
Nenue@0 89
Nenue@0 90 if mode == nil then
Nenue@0 91 ReloadUI()
Nenue@0 92 end
Nenue@0 93 if mode == STATE_LOW then
Nenue@0 94 D:Print('Developement AddOn list saved.')
Nenue@0 95 else
Nenue@0 96 D:Print('Standard AddOn list saved.')
Nenue@0 97 end
Nenue@0 98 end
Nenue@0 99
Nenue@0 100
Nenue@13 101 local function Console_MinMax(self)
Nenue@13 102 if self.minimized then
Nenue@7 103 self:Maximize()
Nenue@7 104 else
Nenue@7 105 self:Minimize()
Nenue@7 106 end
Nenue@7 107 end
Nenue@13 108
Nenue@13 109 local function Console_Minimize(self)
Nenue@13 110 self:SetHeight(20)
Nenue@13 111 self:SetMaxResize(GetScreenWidth(),20)
Nenue@13 112 self.minimized = true
Nenue@13 113 return self.out:Hide()
Nenue@7 114 end
Nenue@0 115
Nenue@13 116 local function Console_Maximize(self)
Nenue@13 117 local db = db.channels[self.index]
Nenue@13 118 self:SetHeight(db.height)
Nenue@13 119 self:SetMaxResize(GetScreenWidth(),GetScreenHeight())
Nenue@13 120 self.minimized = nil
Nenue@13 121 self.grip:SetTexture(0.5,0.5,0.5)
Nenue@13 122 return self.out:Show()
Nenue@13 123 end
Nenue@13 124
Nenue@13 125
Nenue@13 126 local function Console_Save(self)
Nenue@13 127 local db = db.channels[self.index]
Nenue@13 128 db.y = (self:GetTop() - GetScreenHeight())
Nenue@13 129 db.x = self:GetLeft()
Nenue@13 130 db.width = self:GetWidth()
Nenue@13 131 if not self.minimized then
Nenue@13 132 db.height = self:GetHeight()
Nenue@13 133 db.minimized = nil
Nenue@13 134 else
Nenue@13 135 db.minimized = true
Nenue@13 136 end
Nenue@13 137 if self:IsVisible() then
Nenue@13 138 db.enabled = true
Nenue@13 139 else
Nenue@13 140 db.enabled = nil
Nenue@13 141 end
Nenue@13 142 self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y)
Nenue@13 143 end
Nenue@13 144
Nenue@13 145
Nenue@13 146 local function Console_Toggle(input)
Nenue@13 147 local key = input:gmatch("[%a%d]")
Nenue@13 148 local search
Nenue@13 149 if key and D.sig[key] then
Nenue@13 150 search = {D.sig[key]}
Nenue@13 151 elseif D.console[key] then
Nenue@13 152 search = {D.console[key]}
Nenue@13 153 else
Nenue@13 154 search = D.console
Nenue@13 155 end
Nenue@13 156
Nenue@13 157 for _, c in ipairs(search) do
Nenue@13 158 if c:IsVisible() then
Nenue@13 159 c:Hide()
Nenue@13 160 else
Nenue@13 161 c:Show()
Nenue@13 162 c:Maximize()
Nenue@13 163 end
Nenue@13 164 c:Save()
Nenue@13 165 end
Nenue@13 166 end
Nenue@13 167
Nenue@13 168 --
Nenue@13 169 --
Nenue@13 170 -- Construct a console frame
Nenue@13 171 local function CreateConsole(i, vars)
Nenue@13 172 local f = CreateFrame('Frame', 'DevianChannelFrame' .. tostring(i), UIParent, DEVIAN_FRAME)
Nenue@13 173 f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.channels[i].x, db.channels[i].y)
Nenue@13 174 f:SetSize(vars.width, vars.height)
Nenue@13 175 f:Lower()
Nenue@13 176 f.out:SetFont(db.font, db.fontsize, db.fontoutline)
Nenue@13 177 f.Save = Console_Save
Nenue@13 178 f.Minimize = Console_Minimize
Nenue@13 179 f.Maximize = Console_Maximize
Nenue@13 180 f.MinMax = Console_MinMax
Nenue@13 181 f.Toggle = D.Console_Toggle
Nenue@13 182 f.name = vars.name
Nenue@13 183 f.index = i
Nenue@13 184
Nenue@13 185 if db.channels[i].enabled then
Nenue@13 186 f:Show()
Nenue@13 187 end
Nenue@13 188 if db.channels[i].minimized then
Nenue@13 189 f:Minimize()
Nenue@13 190 end
Nenue@13 191
Nenue@13 192 return f
Nenue@13 193 end
Nenue@13 194
Nenue@13 195 --
Nenue@13 196 --
Nenue@13 197 -- Send a message somewhere
Nenue@0 198 local function Message(prefix, ...)
Nenue@1 199 if prefix == nil then
Nenue@13 200 prefix = 1
Nenue@1 201 end
Nenue@9 202
Nenue@13 203 local channel
Nenue@13 204 local byName = true
Nenue@13 205 if D.sig[prefix] then
Nenue@13 206 channel = D.sig[prefix]
Nenue@13 207 elseif D.console[prefix] then
Nenue@13 208 channel = D.console[prefix]
Nenue@13 209 byName = nil
Nenue@13 210 else
Nenue@13 211 channel = D.console[1]
Nenue@13 212 end
Nenue@13 213
Nenue@13 214
Nenue@13 215
Nenue@9 216 -- color me timbers
Nenue@9 217 local pcolor
Nenue@13 218 if D.tags[prefix] then
Nenue@9 219 pcolor = db.tags[prefix]
Nenue@13 220 elseif byName then
Nenue@0 221 local c = {0, 0, 0 }
Nenue@0 222 local max = string.len(prefix)
Nenue@0 223 for i = 1, max, 3 do
Nenue@0 224 for k, v in ipairs(c) do
Nenue@0 225 local j = i + (k - 1)
Nenue@0 226 c[k] = c[k] + (j <= max and string.byte(prefix,j) or 0)
Nenue@0 227 end
Nenue@0 228 end
Nenue@0 229 for k,v in ipairs(c) do
Nenue@0 230 c[k] = c[k] % 255
Nenue@0 231 if c[k] < 64 then
Nenue@0 232 c[k] = 0
Nenue@0 233 elseif c[k] > 127 then
Nenue@0 234 c[k] = 255
Nenue@0 235 end
Nenue@0 236 end
Nenue@13 237 D.tags[prefix] = string.format('%02X%02X%02X', unpack(c))
Nenue@0 238 end
Nenue@0 239
Nenue@13 240 local buffer = {'|cFF'.. D.tags[prefix]..prefix ..'|r'}
Nenue@0 241 for i = 1, select('#',...) do
Nenue@0 242 local var = select(i, ...)
Nenue@0 243
Nenue@0 244 if type(var) == 'table' then
Nenue@0 245 var = '<table>'
Nenue@0 246 elseif type(var) == 'boolean' then
Nenue@0 247 var = var and 'true' or 'false'
Nenue@0 248 elseif type(var) == 'function' then
Nenue@0 249 var = '<funcref>'
Nenue@0 250 elseif type(var) == 'nil' then
Nenue@0 251 var = 'nil'
Nenue@0 252 end
Nenue@0 253
Nenue@0 254 table.insert(buffer, var)
Nenue@0 255 end
Nenue@13 256 channel.out:AddMessage(table.concat(buffer, ' '))
Nenue@0 257 table.wipe(buffer)
Nenue@0 258 end
Nenue@0 259
Nenue@0 260 function D:OnEnable()
Nenue@13 261 -- commands
Nenue@13 262 local cmdlist = {
Nenue@13 263 ['dvn'] = ScanAddOnList,
Nenue@13 264 ['devian'] = ScanAddOnList,
Nenue@13 265 ['dvc'] = Console_Toggle,
Nenue@13 266 }
Nenue@13 267 for cmd, func in pairs(cmdlist) do
Nenue@13 268 self:RegisterChatCommand(cmd, func, true)
Nenue@13 269 end
Nenue@13 270
Nenue@11 271 if db.enabled == true then
Nenue@0 272 D:Print('Standard AddOn list active. Type /dvn to switch to development mode.')
Nenue@0 273 else
Nenue@0 274 D:Print('Development AddOn list active. Type /dvn to revert to regular operation.')
Nenue@0 275 end
Nenue@13 276
Nenue@0 277 end
Nenue@0 278
Nenue@5 279
Nenue@0 280 function D:OnInitialize()
Nenue@13 281 -- emergency button
Nenue@13 282 self:RegisterChatCommand("cleandvn", function(args)
Nenue@13 283 DevianDB = nil
Nenue@13 284 ReloadUI()
Nenue@13 285 end)
Nenue@13 286
Nenue@13 287 -- savedvars
Nenue@13 288 local cherry = false
Nenue@9 289 if not _G.DevianDB then
Nenue@13 290 _G.DevianDB = defaults
Nenue@13 291 cherry = "Type /dvnsave to snapshot your current UI"
Nenue@9 292 end
Nenue@9 293 db = _G.DevianDB
Nenue@0 294
Nenue@0 295 if not db[PLAYER_REALM] then
Nenue@9 296 db[PLAYER_REALM] = {[STATE_LOW] = {}, [STATE_HIGH] = {}}
Nenue@0 297 if not cherry then
Nenue@0 298 cherry = "This character didn't have an AddOn table."
Nenue@0 299 end
Nenue@0 300 end
Nenue@0 301
Nenue@13 302 -- copy tags
Nenue@13 303 self.tags = {}
Nenue@13 304 for n, c in pairs(db.tags) do
Nenue@13 305 self.tags[n] = c
Nenue@13 306 end
Nenue@0 307 if cherry then
Nenue@0 308 D:Print(cherry)
Nenue@0 309 end
Nenue@0 310 D.oldprint = getprinthandler()
Nenue@0 311 if not _G.oldprint then
Nenue@0 312 _G.oldprint = D.oldprint
Nenue@0 313 end
Nenue@13 314
Nenue@13 315 self.console = {}
Nenue@13 316 self.sig = {}
Nenue@13 317 for i, cinfo in ipairs(db.channels) do
Nenue@13 318 self.console[i] = CreateConsole(i, cinfo)
Nenue@13 319 self.sig[cinfo.signature] = self.console[i]
Nenue@13 320 end
Nenue@0 321 setprinthandler(Message)
Nenue@13 322 print(MAJOR, MINOR)
Nenue@0 323 end