Nenue@32: --- ${PACKAGE_NAME} Nenue@32: -- @file-author@ Nenue@32: -- @project-revision@ @project-hash@ Nenue@32: -- @file-revision@ @file-hash@ Nenue@0: if not LibStub then Nenue@0: print('Something has happened...') Nenue@0: end Nenue@0: Devian = LibStub("AceAddon-3.0"):NewAddon("Devian", "AceConsole-3.0", "AceEvent-3.0") Nenue@13: local MAJOR, MINOR = 'Devian-1.3', 'r@project-revision@' Nenue@0: local D = _G.Devian Nenue@32: local WORKSPACE_ON, WORKSPACE_OFF = 1, 2 Nenue@0: local PLAYER_REALM = UnitName("player") .. '-' .. GetRealmName() Nenue@13: local DEVIAN_FRAME = 'DevianConsole' Nenue@33: local DEVIAN_DOCK_FRAME = 'DevianDockFrame' Nenue@33: local MSG_NEED_DEV_MODE = 'Must be in development mode to use this function.' Nenue@18: local print = _G.print Nenue@9: local db Nenue@13: local defaults = { Nenue@32: ['global'] = {{}, {}}, Nenue@13: ['tags'] = {}, Nenue@32: ['channels'] = {[1] = {signature = 'Main', index = 1, x = 100, y = 800, height = 500, width = 600, enabled = true}}, Nenue@33: primary_channel = 1, -- the channel to which default output is sent Nenue@33: current_channel = 1, -- the front channel Nenue@33: max_channel = 1, -- the highest created channel id Nenue@33: enable = true, -- allow enabled consoles to appear Nenue@33: load_message = "Defaults loaded.", -- messages to be displayed after reload Nenue@33: font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]], -- font info Nenue@13: fontsize = 13, Nenue@13: fontoutline = 'NONE', Nenue@33: headergrad = {'VERTICAL', 0, 0, 0, 0.5, 0.1, 0.1, 0.1, 0.3}, -- header info Nenue@33: headerdrop = {1,1,1,1}, Nenue@33: headeralpha = 1, Nenue@33: backdrop = {0,0,0,1}, -- background frame info Nenue@14: backgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.3, 0, 0, 0, 0.5}, Nenue@33: backblend = 'MOD', Nenue@33: backalpha = 0.7, Nenue@33: backborder = {0,0,1,0.75}, Nenue@33: frontdrop = {0,0,0,1}, -- foreground frame info Nenue@14: frontgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.9, 0, 0, 0, 0.9}, Nenue@33: frontblend = 'MOD', Nenue@28: frontalpha = 1, Nenue@22: frontborder = {1,0,0,1}, Nenue@33: tagcolor = {}, -- tag color repository Nenue@33: workspace = 1, -- current profile Nenue@33: last_workspace = 2 -- default workspace to alternate with when just "/dvn" is issued Nenue@13: } Nenue@9: Nenue@4: Nenue@13: local function ScanAddOnList(cmd, ...) Nenue@0: local list_state Nenue@0: Nenue@14: local args = {} Nenue@14: local arg, n = D:GetArgs(cmd, 1) Nenue@14: while arg do Nenue@14: table.insert(args, arg) Nenue@14: arg, n = D:GetArgs(cmd,1,n) Nenue@14: end Nenue@14: local mode, tag, dest = unpack(args) Nenue@0: Nenue@13: Nenue@14: -- no args, toggle ui Nenue@32: if mode == 'dock' then Nenue@33: if db.workspace == 1 then Nenue@33: D:Print('Must be in dev mode to use this.') Nenue@33: return Nenue@33: end Nenue@32: if #args <= 2 then Nenue@32: D:Print("Not enough arguments for dock command.") Nenue@32: return Nenue@32: end Nenue@0: Nenue@32: local target Nenue@32: local worklist = {} Nenue@32: for i = 2, #args do Nenue@32: local ch Nenue@32: local k = tostring(args[i]) Nenue@32: local j = tonumber(args[i]) Nenue@32: if db.channels[j] then Nenue@32: ch = db.channels[j] Nenue@32: elseif D.sig[k] then Nenue@32: ch = D.sig[k] Nenue@32: elseif D.sigID[k] then Nenue@32: ch = db.channels[D.sigID[k]] Nenue@32: elseif db.tags[k] and db.tags[k][1] then Nenue@32: ch = db.channels[db.tags[j][1]] Nenue@32: -- last resort Nenue@32: else Nenue@32: D:Print('No entry for argument #'..i..': '..tostring(args[i])) Nenue@32: return Nenue@32: end Nenue@32: oldprint(i, '->', ch.index, '-', ch.signature) Nenue@32: if i > 2 then Nenue@32: table.insert(worklist, ch.index) Nenue@32: else Nenue@32: target = ch Nenue@32: Nenue@32: oldprint('arg1', args[2], target) Nenue@32: end Nenue@0: end Nenue@32: D:Print("Docking |cFF88FFFF"..table.concat(worklist, "|r, |cFF88FFFF").."|r with |cFFFFFF00"..target.index..', '..target.signature.."|r.") Nenue@32: return D:DockFrame(target.index, unpack(worklist)) Nenue@32: Nenue@32: Nenue@14: elseif mode == 'stack' then Nenue@33: if db.workspace == 1 then Nenue@33: return D:Print(MSG_NEED_DEV_MODE) Nenue@33: end Nenue@14: return D:StackFrames() Nenue@14: elseif mode == 'grid' then Nenue@33: if db.workspace == 1 then Nenue@33: return D:Print(MSG_NEED_DEV_MODE) Nenue@33: end Nenue@14: return D:DistributeFrames() Nenue@14: elseif mode == 'tag' then -- tagging Nenue@33: if db.workspace == 1 then Nenue@33: return D:Print(MSG_NEED_DEV_MODE) Nenue@33: end Nenue@32: Nenue@14: if tag ~= nil and dest ~= nil then Nenue@32: -- convert to ID Nenue@32: if tonumber(dest) == nil and D.sigID[dest] then Nenue@32: dest = db.channels[D.sigID[dest]].index Nenue@18: end Nenue@18: Nenue@32: -- make a new channel? Nenue@32: if not db.channels[dest] then Nenue@32: dest = db.max_channel + 1 Nenue@32: D:Print('Creating a new channel for '.. tag) Nenue@32: D:SetChannel(tag, dest) Nenue@32: end Nenue@32: Nenue@32: if db.tags[tag] and db.tags[tag][dest] then Nenue@32: db.tags[tag][dest] = nil Nenue@34: D:Print('Hiding |cFF88FFFF'..tag..'|r messages in |cFFFFFF00'..db.channels[dest].index ..':'.. db.channels[dest].signature) Nenue@32: else Nenue@32: if not db.tags[tag] then Nenue@32: db.tags[tag] = {} Nenue@32: end Nenue@32: db.tags[tag][dest] = dest Nenue@34: D:Print('Showing |cFF88FFFF'..tag..'|r messages in |cFFFFFF00'..db.channels[dest].index ..':'.. db.channels[dest].signature) Nenue@32: end Nenue@14: else Nenue@14: D:Print('Usage: /dvn tag ') Nenue@14: end Nenue@14: return Nenue@32: elseif tonumber(mode) ~= nil or mode == 'save' then Nenue@32: -- iterating for something Nenue@32: if mode == 'save' then Nenue@32: if tonumber(tag) == nil then Nenue@32: T:Print('Save ID is invalid:', tag) Nenue@32: end Nenue@32: list_state = tonumber(tag) Nenue@32: else Nenue@32: list_state = tonumber(mode) Nenue@32: db.workspace = list_state Nenue@33: if list_state ~= 1 then Nenue@33: db.last_workspace = list_state Nenue@33: end Nenue@33: Nenue@0: end Nenue@32: elseif mode == nil then Nenue@33: list_state = (db.workspace == 1) and db.last_workspace or 1 Nenue@33: db.workspace = list_state Nenue@33: db.load_message = "quick swapped workspace #"..list_state Nenue@32: else Nenue@32: return D:PrintHelp() Nenue@0: end Nenue@32: Nenue@32: -- start the iterating Nenue@0: local char_list, global_list = db[PLAYER_REALM][list_state], db.global[list_state] Nenue@0: local playername = UnitName("player") Nenue@0: Nenue@0: for i = 1, GetNumAddOns() do Nenue@0: local name = GetAddOnInfo(i) Nenue@0: local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i) Nenue@0: Nenue@32: if mode == 'save' then Nenue@0: char_list[name] = enableState Nenue@0: global_list[name] = globalState Nenue@0: else Nenue@13: if char_list[name] or global_list[name] then Nenue@32: if char_list[name] ~= 0 and global_list[name] ~= 0 then Nenue@32: local value = false Nenue@32: if char_list[name] == 2 and global_list[name] == 1 then Nenue@32: value = UnitName("player") Nenue@32: elseif global_list[name] == 2 then Nenue@32: value = true Nenue@32: end Nenue@32: --print('EnableAddOn(', i, ',', value,')') Nenue@32: EnableAddOn(i, value) Nenue@32: else Nenue@32: local value = true Nenue@32: if char_list[name] == 2 and global_list[name] == 1 then Nenue@32: value = UnitName("player") Nenue@32: end Nenue@32: --print('DisableAddOn(', i, ',', value,')') Nenue@32: DisableAddOn(i,value) Nenue@0: end Nenue@33: elseif mode ~= 'save' then Nenue@32: if type(db.unlisted) ~= 'table' then Nenue@32: db.unlisted = {} Nenue@0: end Nenue@32: table.insert(db.unlisted, name) Nenue@13: end Nenue@0: Nenue@0: end Nenue@0: end Nenue@0: Nenue@32: if mode ~= 'save' then Nenue@33: --db.load_message = "AddOn profile ".. list_state .." was loaded." Nenue@0: ReloadUI() Nenue@0: else Nenue@32: D:Print('Profile #'.. (list_state)..' saved.') Nenue@32: if list_state == 1 then Nenue@32: D:Print('This will be your main AddOn list.') Nenue@32: elseif list_state == db.default_list then Nenue@32: db.last_workspace = list_state Nenue@32: D:Print('This will be your default workspace') Nenue@32: end Nenue@0: end Nenue@0: end Nenue@0: Nenue@0: Nenue@13: local function Console_MinMax(self) Nenue@13: if self.minimized then Nenue@7: self:Maximize() Nenue@7: else Nenue@7: self:Minimize() Nenue@7: end Nenue@7: end Nenue@13: Nenue@13: local function Console_Minimize(self) Nenue@13: self:SetHeight(20) Nenue@13: self:SetMaxResize(GetScreenWidth(),20) Nenue@13: self.minimized = true Nenue@14: self.out:Hide() Nenue@14: self:Save() Nenue@7: end Nenue@0: Nenue@13: local function Console_Maximize(self) Nenue@13: local db = db.channels[self.index] Nenue@13: self:SetHeight(db.height) Nenue@13: self:SetMaxResize(GetScreenWidth(),GetScreenHeight()) Nenue@13: self.minimized = nil Nenue@14: self.out:Show() Nenue@14: self:Save() Nenue@13: end Nenue@13: Nenue@13: Nenue@13: local function Console_Save(self) Nenue@13: local db = db.channels[self.index] Nenue@14: if self.x then Nenue@14: db.x = self.x Nenue@14: else Nenue@14: db.x = self:GetLeft() Nenue@14: end Nenue@14: Nenue@14: if self.y then Nenue@14: db.y = self.y Nenue@14: else Nenue@14: db.y = (self:GetTop() - GetScreenHeight()) Nenue@14: end Nenue@14: Nenue@14: if self.width then Nenue@14: db.width = self.width Nenue@14: else Nenue@14: db.width = self:GetWidth() Nenue@14: end Nenue@14: Nenue@13: if not self.minimized then Nenue@14: if self.height then Nenue@14: db.height = self.height Nenue@14: else Nenue@14: db.height = self:GetHeight() Nenue@14: end Nenue@14: self:SetHeight(db.height) Nenue@13: end Nenue@14: Nenue@32: db.dockedTo = self.dockedTo Nenue@32: db.docked = self.docked Nenue@32: Nenue@14: db.minimized = self.minimized and true or nil Nenue@14: db.enabled = self:IsVisible() and true or nil Nenue@14: db.active = self.active and true or nil Nenue@17: --print('save:', db.signature, 'min=', db.minimized, ' enabled=', db.enabled, ' active = ', db.active, 'x=', db.x, 'y=', db.y, 'h=', db.height, 'w=', db.width) Nenue@13: self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y) Nenue@14: self:SetWidth(db.width) Nenue@13: end Nenue@13: Nenue@14: -- Console frame toggler Nenue@14: -- @paramsig [...] Nenue@14: -- @param ... one or more space-seperated channel keys Nenue@13: local function Console_Toggle(input) Nenue@33: if db.workspace == 1 then Nenue@33: return D:Print(MSG_NEED_DEV_MODE) Nenue@33: end Nenue@14: local search = {} Nenue@28: local n = 0 Nenue@28: if D:GetArgs(input,1) then Nenue@14: repeat Nenue@28: key, n = D:GetArgs(input,1,n) Nenue@14: if D.sig[key] then Nenue@14: table.insert(search, D.sig[key]) Nenue@14: elseif D.console[key] then Nenue@14: table.insert(search, D.console[key]) Nenue@14: end Nenue@14: until n == 1e9 Nenue@13: else Nenue@13: search = D.console Nenue@13: end Nenue@13: Nenue@33: db.enabled = (not db.enabled) and true or nil Nenue@28: for i, c in ipairs(search) do Nenue@33: --print(i,c.index) Nenue@33: if db.enabled then Nenue@28: c.enabled = true Nenue@14: c:Show() Nenue@26: if db.current_channel == c.index then Nenue@26: c:ToFront() Nenue@26: end Nenue@33: c:Save() Nenue@14: else Nenue@13: c:Hide() Nenue@13: end Nenue@13: end Nenue@14: Nenue@33: if db.enabled then Nenue@14: D:Print('toggled on?') Nenue@14: else Nenue@14: D:Print('toggled off?') Nenue@14: end Nenue@13: end Nenue@13: Nenue@18: --- Brings the console to the front. Nenue@18: -- Frame method used to bring a console frame to the front of the display stack. Nenue@14: local function Console_ToFront(c) Nenue@14: --print(D.raise_ct, 'Raising', c.signature) Nenue@14: --print(unpack(db.frontdrop)) Nenue@14: --print(unpack(db.frontgrad)) Nenue@14: --print(db.frontblend) Nenue@22: -- D.raise_ct = D.raise_ct + 1 Nenue@14: c:Raise() Nenue@28: c:SetAlpha(db.frontalpha) Nenue@14: c.out.backdrop:SetTexture(unpack(db.frontdrop)) Nenue@14: c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad)) Nenue@14: c.out.backdrop:SetBlendMode(db.frontblend) Nenue@20: db.current_channel = c.index Nenue@18: Nenue@18: for _, part in pairs(c.border) do Nenue@24: part:SetTexture(unpack(db.frontborder)) Nenue@18: end Nenue@14: Nenue@14: for id, bc in pairs(D.console) do Nenue@14: if id ~= c.index then Nenue@14: --print(D.raise_ct, 'Lowering', bc.signature) Nenue@14: --print(unpack(db.backdrop)) Nenue@14: --print(unpack(db.backgrad)) Nenue@14: --print(db.backblend) Nenue@28: bc:SetAlpha(db.backalpha) Nenue@14: bc.out.backdrop:SetTexture(unpack(db.backdrop)) Nenue@14: bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad)) Nenue@14: bc.out.backdrop:SetBlendMode(db.backblend) Nenue@18: Nenue@18: for _, part in pairs(bc.border) do Nenue@24: part:SetTexture(unpack(db.backborder)) Nenue@14: end Nenue@18: end Nenue@18: Nenue@14: end Nenue@14: Nenue@14: end Nenue@14: Nenue@32: local function Console_MouseDown(self, button, up) Nenue@32: if button == 'LeftButton' then Nenue@32: if up then Nenue@32: self:StopMovingOrSizing() Nenue@32: self:ToFront() Nenue@32: self.x = nil Nenue@32: self.y = nil Nenue@32: self.width = nil Nenue@32: self.height = nil Nenue@32: self:Save() Nenue@32: elseif self.out.grip:IsMouseOver() then Nenue@32: self:StartSizing() Nenue@32: else Nenue@32: self:StartMoving() Nenue@32: end Nenue@22: else Nenue@32: if up then Nenue@32: self:MinMax() Nenue@14: end Nenue@13: end Nenue@32: end Nenue@32: local function Console_MouseUp(self, button) Nenue@32: return Console_MouseDown(self, button, true) Nenue@13: end Nenue@13: Nenue@18: --- Creates a Devian-style output. Nenue@18: -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print() Nenue@18: -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint(). Nenue@18: -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel. Nenue@18: -- @param ... Output contents. Nenue@0: local function Message(prefix, ...) Nenue@33: if not db.enabled then Nenue@23: return D.oldprint(prefix, ...) Nenue@23: end Nenue@23: Nenue@1: if prefix == nil then Nenue@13: prefix = 1 Nenue@1: end Nenue@9: Nenue@18: local sendq = {} Nenue@30: local tag, id, tagged Nenue@13: local byName = true Nenue@18: if D.tags[prefix] then Nenue@18: for _, id in pairs(D.tags[prefix]) do Nenue@18: if D.console[id] then Nenue@18: sendq[id] = D.console[id] Nenue@30: tagged = true Nenue@18: end Nenue@18: end Nenue@18: end Nenue@18: Nenue@13: if D.sig[prefix] then Nenue@18: sendq[D.sig[prefix].index] = D.sig[prefix] Nenue@13: elseif D.console[prefix] then Nenue@18: sendq[D.console[prefix]] = D.console[prefix] Nenue@30: elseif not tagged then Nenue@18: sendq[D.primary_channel] = D.console[D.primary_channel] Nenue@13: end Nenue@18: Nenue@9: -- color me timbers Nenue@9: local pcolor Nenue@18: if (not db.tagcolor[prefix]) and byName then Nenue@30: local c = { Nenue@30: math.random(64,255), math.random(64,255), math.random(64,255) Nenue@30: } Nenue@30: if c[1] > 223 and c[2] > 223 and c[3] > 223 then Nenue@30: c[math.random(1,3)] = math.random(64,223) Nenue@0: end Nenue@30: Nenue@18: db.tagcolor[prefix] = string.format('%02X%02X%02X', unpack(c)) Nenue@0: end Nenue@18: pcolor = db.tagcolor[prefix] Nenue@0: Nenue@18: local buffer = {'|cFF'.. pcolor..prefix ..'|r'} Nenue@0: for i = 1, select('#',...) do Nenue@0: local var = select(i, ...) Nenue@0: Nenue@0: if type(var) == 'table' then Nenue@20: if type(var.GetName) == 'function' then Nenue@32: var = '' Nenue@20: else Nenue@32: var = '<'..tostring(var)..'>' Nenue@20: end Nenue@20: Nenue@0: elseif type(var) == 'boolean' then Nenue@0: var = var and 'true' or 'false' Nenue@0: elseif type(var) == 'function' then Nenue@0: var = '' Nenue@0: elseif type(var) == 'nil' then Nenue@0: var = 'nil' Nenue@0: end Nenue@0: Nenue@0: table.insert(buffer, var) Nenue@0: end Nenue@18: local message = table.concat(buffer, ' ') Nenue@18: for id, channel in pairs(sendq) do Nenue@18: channel.out:AddMessage(message) Nenue@18: end Nenue@0: table.wipe(buffer) Nenue@0: end Nenue@0: Nenue@14: Nenue@32: --- Constructs the frame object for a console channel Nenue@32: -- Initializes the console channel at a specified index. Nenue@32: -- Configuration data can be overridden by passing a desired settings table. Nenue@32: -- @param i Numeric index of the channel as it manifests in db.channels Nenue@32: -- @param vars Optional settings table to be used. Nenue@32: local function CreateConsole(i, vars) Nenue@33: if tonumber(i) == nil or math.floor(i) ~= i then Nenue@33: error('Non-integer index value.') Nenue@33: end Nenue@33: if not vars then Nenue@33: vars = db.channels[i] and db.channels[i] or db.channels[db.primary_channel] Nenue@33: end Nenue@33: local f Nenue@33: if vars.docked then Nenue@33: f = CreateFrame('Frame','DevianDockFrame' .. i, DEVIAN_DOCK_FRAME) Nenue@33: else Nenue@33: f= CreateFrame('Frame', 'DevianChannelFrame' .. i, UIParent, DEVIAN_FRAME) Nenue@33: end Nenue@33: --@debug@ Nenue@33: --print(f:GetName()) Nenue@32: Nenue@33: --print('create(2)') Nenue@33: for k,v in pairs(vars) do Nenue@33: f[k] = v Nenue@33: --@debug@ Nenue@33: --print(' f['..type(k)..' '..tostring(k)..'] = '..type(v)..' '..tostring(v)) Nenue@14: end Nenue@14: Nenue@32: f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', vars.x, vars.y) Nenue@32: f:SetSize(vars.width, vars.height) Nenue@32: f:Lower() Nenue@32: f.out:SetFont(db.font, db.fontsize, db.fontoutline) Nenue@32: if (db.current_channel == i) then Nenue@32: f.out.backdrop:SetTexture(unpack(db.frontdrop)) Nenue@32: else Nenue@32: f.out.backdrop:SetTexture(unpack(db.backdrop)) Nenue@32: end Nenue@14: Nenue@33: Nenue@33: Nenue@32: f.Save = Console_Save Nenue@32: f.Minimize = Console_Minimize Nenue@32: f.Maximize = Console_Maximize Nenue@32: f.MinMax = Console_MinMax Nenue@32: f.ToFront = Console_ToFront Nenue@32: f.Toggle = D.Console_Toggle Nenue@32: f:SetScript('OnMouseDown', Console_MouseDown) Nenue@32: f:SetScript('OnMouseUp', Console_MouseUp) Nenue@33: Nenue@32: if vars.minimized then Nenue@32: f:Minimize() Nenue@32: else Nenue@32: f:Maximize() Nenue@32: end Nenue@33: if db.enabled and f.enabled then Nenue@33: f:Show() Nenue@33: end Nenue@32: Nenue@32: return f Nenue@14: end Nenue@14: Nenue@33: --- Updates console information and returns the handle of the channel object that was worked on. Nenue@33: -- When key is nil or not a valid handle, a new channel is created using whatever signature can be found in cinfo. Nenue@33: -- The signature can be passed as a string, or as a table entry under the key 'signature' Nenue@33: -- If the signature of a new channel is also a tag, the channel will be added to that tag Nenue@33: -- @param cinfo string signature of a new channel, or a table of config variables to be imposed on the channel Nenue@33: -- @param key string signature or index number of channel to operate on Nenue@33: -- @usage channel = D:SetChannel('new', nil) -- creates a new channel Nenue@33: -- @usage channel = D:SetChannel({x = 200, y = 100}, 4) -- updates channel #4 Nenue@33: function D:SetChannel(cinfo, key) Nenue@14: local t_info = {} Nenue@33: local channel, isNew, id, sig, t_id Nenue@33: -- obtain source data Nenue@33: if tonumber(key) ~= nil and db.channels[key] then Nenue@33: id = tonumber(key) Nenue@33: elseif D.sigID[tostring(key)] then Nenue@33: id = D.sigID[tostring(key)] Nenue@32: else Nenue@33: id = db.primary_channel Nenue@32: isNew = true Nenue@32: end Nenue@33: local dbvars = db.channels[id] Nenue@33: t_id = id -- overridden later if new Nenue@33: t_info.index = t_id -- Nenue@33: --@debug@ Nenue@33: --print('setchan(1) cinfo, key, id=', cinfo, key, id)--@end-debug@ Nenue@28: Nenue@33: Nenue@33: -- obtain config info Nenue@33: if type(cinfo) == 'string' then Nenue@33: sig = cinfo Nenue@33: cinfo = {signature = sig} Nenue@33: elseif type(cinfo) ~= 'table' then -- stop here if a table wans't passed Nenue@33: error('Expecting table of string as arg1') Nenue@33: elseif cinfo.signature then -- new sig Nenue@33: sig = cinfo.signature Nenue@33: elseif isNew then -- new channel sig Nenue@33: sig = 'Ch' Nenue@33: else -- old sig Nenue@33: sig = db.channels[id].signature Nenue@33: end Nenue@33: t_info.signature = sig Nenue@32: --@debug@ Nenue@33: --print('setchan(2) sig,id,isNew=', sig, id, isNew)--@end-debug@ Nenue@32: Nenue@33: for k,v in pairs(cinfo) do -- allow all cinfo to pass Nenue@33: t_info[k] = v Nenue@32: end Nenue@32: Nenue@33: local blocked = { -- ignore these vars: Nenue@33: ['docked'] = true, -- table Nenue@33: ['dockedTo'] = true, -- table-related Nenue@33: ['signature'] = true} -- already determined Nenue@33: for k,v in pairs(dbvars) do Nenue@33: if not t_info[k] and not blocked[k] then -- already set or blocked? Nenue@33: t_info[k] = v Nenue@33: end Nenue@33: end Nenue@33: -- new channel overrides Nenue@33: if isNew then Nenue@33: if D.sigID[sig]then -- find a non-clashing signature Nenue@33: local result, i = sig, 1 Nenue@33: while D.sigID[result] do Nenue@33: result = sig .. i Nenue@33: i = i + 1 Nenue@33: end Nenue@33: t_info.signature = result Nenue@33: end Nenue@33: t_id = db.max_channel + 1 Nenue@33: t_info.index = t_id Nenue@33: --@debug@ Nenue@33: --print('setchan(3a) isNew, sig, t_info.signature=', isNew, sig, t_info.signature)--@end-debug@ Nenue@33: else Nenue@33: --@debug@ Nenue@33: --print('setchan(3b) isNew, sig, t_info.signature=', isNew, sig, t_info.signature)--@end-debug@ Nenue@28: end Nenue@28: Nenue@33: local channel Nenue@33: if not self.console[t_id] then -- create a frame Nenue@33: if isNew then -- position the channel frame Nenue@33: t_info.x = t_info.x + 20 Nenue@33: t_info.y = t_info.y - 20 Nenue@33: db.channels[t_id] = t_info Nenue@33: --@debug@ Nenue@33: print('setchan(4a)', 't_id, x, y=', t_id, t_info.x, t_info.y)--@end-debug@ Nenue@14: end Nenue@33: channel = CreateConsole(t_id, t_info) Nenue@33: self.console[t_id] = channel Nenue@33: self.sig[t_info.signature] = channel Nenue@33: self.sigID[t_info.signature] = t_id Nenue@33: self.IDsig[t_id] = t_info.signature Nenue@33: Nenue@33: end Nenue@33: channel = self.console[t_id] Nenue@33: if channel.minimized then Nenue@33: channel:Minimize() Nenue@33: else Nenue@33: channel:Maximize() Nenue@14: end Nenue@14: Nenue@33: if channel.enabled and db.enabled then -- hide or show last since Min/Max mess with visibility Nenue@33: print('setchan(5a) enable') Nenue@33: channel:Show() Nenue@33: else Nenue@33: print('setchan(5a) disable') Nenue@33: channel:Hide() Nenue@33: end Nenue@32: --@debug@ Nenue@33: --print('setchan(end); c:IsVisible(), c.enabled, db.enabled=', channel:IsVisible(), channel.enabled, db.enabled)--@end-debug@ Nenue@18: return channel Nenue@14: end Nenue@14: Nenue@32: function D:PrintHelp() Nenue@32: D:Print("|cFFFFFF00/dvn|r", Nenue@32: "\n |cFFFFFF00|r - Loads a saved addon list. List 1 is treated as a gameplay profile and consoles will be disabled by default.") Nenue@32: Nenue@32: D:Print("|cFFFFFF00/resetdvn|r", "- Resets all but profile data SavedVariables.") Nenue@32: D:Print("|cFFFFFF00/cleandvn|r", "- Fully resets SavedVariables, profiles and all.") Nenue@32: end Nenue@32: Nenue@0: function D:OnEnable() Nenue@33: print(MAJOR, MINOR) Nenue@33: Nenue@33: if db.unlisted and #db.unlisted > 0 then Nenue@33: D:Print('New AddOns have been found since the last profile update: '.. table.concat(db.unlisted, ', ')) Nenue@33: table.wipe(db.unlisted) Nenue@33: end Nenue@33: Nenue@33: if db.workspace == 1 then Nenue@33: D:Print('Gameplay mode active (list #'..db.workspace..'). Print handling turned |cFFFFFF00OFF|r.') Nenue@33: else Nenue@33: D:Print('Development mode active (list #'..db.workspace..'). Print handling |cFF00FF00ON|r.') Nenue@33: end Nenue@33: Nenue@33: end Nenue@33: Nenue@33: function D:OnInitialize() Nenue@13: -- commands Nenue@33: self:RegisterChatCommand("cleandvn", function(args) Nenue@33: DevianDB = nil Nenue@33: DevianDB = { Nenue@33: load_message = "All SavedVars wiped." Nenue@33: } Nenue@33: ReloadUI() Nenue@33: end) Nenue@33: self:RegisterChatCommand("resetdvn", function(args) Nenue@33: for k,v in pairs(DevianDB) do Nenue@33: if k ~= 'global' then Nenue@33: DevianDB[k] = nil Nenue@33: end Nenue@33: end Nenue@33: Nenue@33: DevianDB.load_message = "Non-user SavedVars have been reset." Nenue@33: for k,v in pairs(defaults) do Nenue@33: DevianDB[k] = v Nenue@33: end Nenue@33: ReloadUI() Nenue@33: end) Nenue@13: local cmdlist = { Nenue@13: ['dvn'] = ScanAddOnList, Nenue@13: ['devian'] = ScanAddOnList, Nenue@13: ['dvc'] = Console_Toggle, Nenue@13: } Nenue@13: for cmd, func in pairs(cmdlist) do Nenue@13: self:RegisterChatCommand(cmd, func, true) Nenue@13: end Nenue@13: Nenue@33: -- pull defaults Nenue@9: if not _G.DevianDB then Nenue@13: _G.DevianDB = defaults Nenue@9: end Nenue@9: db = _G.DevianDB Nenue@32: self.tags = db.tags Nenue@32: self.channelinfo = db.channels Nenue@0: Nenue@0: if not db[PLAYER_REALM] then Nenue@32: db[PLAYER_REALM] = {[WORKSPACE_ON] = {}, [WORKSPACE_OFF] = {}} Nenue@0: end Nenue@0: Nenue@32: if db.load_message then Nenue@32: D:Print(db.load_message) Nenue@32: db.load_message = nil Nenue@0: end Nenue@0: D.oldprint = getprinthandler() Nenue@0: if not _G.oldprint then Nenue@0: _G.oldprint = D.oldprint Nenue@0: end Nenue@13: Nenue@33: -- Stop here in game mode Nenue@33: if db.workspace == 1 then Nenue@33: return Nenue@33: end Nenue@33: Nenue@32: self.max_channel = 0 Nenue@14: self.num_channels = 0 Nenue@13: self.console = {} Nenue@13: self.sig = {} Nenue@14: self.sigID = {} Nenue@14: self.IDsig = {} Nenue@14: for i, cinfo in pairs(db.channels) do Nenue@14: i = tonumber(i) Nenue@14: if not self.primary_channel then Nenue@14: self.primary_channel = i Nenue@14: end Nenue@14: self:SetChannel(cinfo, i) Nenue@32: self.max_channel = math.max(i, self.max_channel) Nenue@32: self.num_channels = self.num_channels + 1 Nenue@32: end Nenue@32: Nenue@32: for i, channel in pairs(db.channels) do Nenue@32: if type(channel.docked) == 'table' then Nenue@32: oldprint('docking',i, unpack(channel.docked)) Nenue@32: self.DockFrame(i, unpack(channel.docked)) Nenue@14: end Nenue@13: end Nenue@18: Nenue@18: if self.console[db.current_channel] then Nenue@18: self.console[db.current_channel]:ToFront() Nenue@28: -- bring the current channel to the front Nenue@18: end Nenue@33: setprinthandler(Message) Nenue@33: print = function(...) Nenue@33: _G.print('Dvn', ...) Nenue@23: end Nenue@0: end