view 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
line wrap: on
line source
-- User: Krakyn
-- Created: 11/30/2015 7:46 AM
if not LibStub then
  print('Something has happened...')
end
Devian = LibStub("AceAddon-3.0"):NewAddon("Devian", "AceConsole-3.0", "AceEvent-3.0")
local MAJOR, MINOR = 'Devian-1.3', 'r@project-revision@'
local D = _G.Devian
local STATE_LOW, STATE_HIGH = 1, 2
local PLAYER_REALM = UnitName("player") .. '-' .. GetRealmName()
local DEVIAN_FRAME = 'DevianConsole'
local print = function(...)
  _G.print('Dvn', ...)
end
local db
local defaults = {
  ['global'] = {[STATE_LOW] = {}, [STATE_HIGH] = {}},
  ['tags'] = {},
  ['channels'] = {[1] = {signature = 'Dvn', name = 'Main', header = "%n [%t]", x = 100, y = 800, height = 500, width = 600, enabled = true}},
  current_channel = 1,
  console = true,
  dnd_status = true,
  dnd_message = "Debugging. Your messages may get eaten.",
  font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]],
  fontsize = 13,
  fontoutline = 'NONE',
}


local function ScanAddOnList(cmd, ...)
  local list_state

  local mode = tonumber(cmd:match("%d"))


  print('Starting Addons scan. arg=', mode)
  if mode == nil then
    list_state = db.enabled and STATE_LOW or STATE_HIGH
    db.enabled = (db.enabled == false) and true or false
    print(list_state, db.enabled)

    if list_state == STATE_LOW then
    end

  else
    if mode > 2 then
      print('Something has happened.')
      return
    end
    list_state = mode == STATE_LOW and STATE_LOW or STATE_HIGH


  end
  local char_list, global_list = db[PLAYER_REALM][list_state], db.global[list_state]

  local playername = UnitName("player")

  for i = 1, GetNumAddOns() do
    local name = GetAddOnInfo(i)
    local enableState, globalState = GetAddOnEnableState(playername, i), GetAddOnEnableState(nil, i)

    if mode == STATE_LOW or mode == STATE_HIGH then
      char_list[name] = enableState
      global_list[name] = globalState
    else
      if char_list[name] or global_list[name] then

      if char_list[name] ~= 0 and global_list[name] ~= 0 then
        local value = false
        if char_list[name] == 2 and global_list[name] == 1 then
          value = UnitName("player")
        elseif global_list[name] == 2 then
          value = true
        end
        print('EnableAddOn(', i, ',', value,')')
        EnableAddOn(i, value)
      else
        local value = true
        if char_list[name] == 2 and global_list[name] == 1 then
          value = UnitName("player")
        end
        print('DisableAddOn(', i, ',', value,')')
        DisableAddOn(i,value)
      end
      end

    end
  end

  if mode == nil then
    ReloadUI()
  end
  if mode == STATE_LOW then
    D:Print('Developement AddOn list saved.')
  else
    D:Print('Standard AddOn list saved.')
  end
end


local function Console_MinMax(self)
  if self.minimized then
    self:Maximize()
  else
    self:Minimize()
  end
end

local function Console_Minimize(self)
  self:SetHeight(20)
  self:SetMaxResize(GetScreenWidth(),20)
  self.minimized = true
  return self.out:Hide()
end

local function Console_Maximize(self)
  local db = db.channels[self.index]
  self:SetHeight(db.height)
  self:SetMaxResize(GetScreenWidth(),GetScreenHeight())
  self.minimized = nil
  self.grip:SetTexture(0.5,0.5,0.5)
  return self.out:Show()
end


local function Console_Save(self)
  local db = db.channels[self.index]
  db.y = (self:GetTop() - GetScreenHeight())
  db.x = self:GetLeft()
  db.width = self:GetWidth()
  if not self.minimized then
    db.height = self:GetHeight()
    db.minimized = nil
  else
    db.minimized = true
  end
  if self:IsVisible() then
    db.enabled = true
  else
    db.enabled = nil
  end
  self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y)
end


local function Console_Toggle(input)
  local key = input:gmatch("[%a%d]")
  local search
  if key and D.sig[key] then
    search = {D.sig[key]}
  elseif D.console[key] then
    search = {D.console[key]}
  else
    search = D.console
  end

  for _, c in ipairs(search) do
    if c:IsVisible() then
      c:Hide()
    else
      c:Show()
      c:Maximize()
    end
    c:Save()
  end
end

--
--
-- Construct a console frame
local function CreateConsole(i, vars)
  local f = CreateFrame('Frame', 'DevianChannelFrame' .. tostring(i), UIParent, DEVIAN_FRAME)
  f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.channels[i].x, db.channels[i].y)
  f:SetSize(vars.width, vars.height)
  f:Lower()
  f.out:SetFont(db.font, db.fontsize, db.fontoutline)
  f.Save = Console_Save
  f.Minimize = Console_Minimize
  f.Maximize = Console_Maximize
  f.MinMax = Console_MinMax
  f.Toggle = D.Console_Toggle
  f.name = vars.name
  f.index = i

  if db.channels[i].enabled then
    f:Show()
  end
  if db.channels[i].minimized then
    f:Minimize()
  end

  return f
end

--
--
-- Send a message somewhere
local function Message(prefix, ...)
  if prefix == nil then
    prefix = 1
  end

  local channel
  local byName = true
  if D.sig[prefix] then
    channel = D.sig[prefix]
  elseif D.console[prefix] then
    channel = D.console[prefix]
    byName = nil
  else
    channel = D.console[1]
  end



  -- color me timbers
  local pcolor
  if D.tags[prefix] then
    pcolor = db.tags[prefix]
  elseif byName then
    local c  = {0, 0, 0 }
    local max = string.len(prefix)
    for i = 1, max, 3 do
        for k, v in ipairs(c) do
          local j = i + (k - 1)
          c[k] = c[k] + (j <= max and string.byte(prefix,j) or 0)
        end
    end
    for k,v in ipairs(c) do
      c[k] = c[k] % 255
      if c[k] < 64 then
        c[k] = 0
      elseif c[k] > 127 then
        c[k] = 255
      end
    end
    D.tags[prefix] = string.format('%02X%02X%02X', unpack(c))
  end

  local buffer = {'|cFF'.. D.tags[prefix]..prefix ..'|r'}
  for i = 1, select('#',...) do
    local var = select(i, ...)

    if type(var) == 'table' then
      var = '<table>'
    elseif type(var) == 'boolean' then
      var = var and 'true' or 'false'
    elseif type(var) == 'function' then
      var = '<funcref>'
    elseif type(var) == 'nil' then
      var = 'nil'
    end

    table.insert(buffer, var)
  end
  channel.out:AddMessage(table.concat(buffer, ' '))
  table.wipe(buffer)
end

function D:OnEnable()
  -- commands
  local cmdlist = {
    ['dvn'] = ScanAddOnList,
    ['devian'] = ScanAddOnList,
    ['dvc'] = Console_Toggle,
  }
  for cmd, func in pairs(cmdlist) do
    self:RegisterChatCommand(cmd, func, true)
  end

  if db.enabled == true then
    D:Print('Standard AddOn list active. Type /dvn to switch to development mode.')
  else
    D:Print('Development AddOn list active. Type /dvn to revert to regular operation.')
  end

end


function D:OnInitialize()
  -- emergency button
  self:RegisterChatCommand("cleandvn", function(args)
    DevianDB = nil
    ReloadUI()
    end)

  -- savedvars
  local cherry = false
  if not _G.DevianDB then
    _G.DevianDB = defaults
    cherry = "Type /dvnsave to snapshot your current UI"
  end
  db = _G.DevianDB

  if not db[PLAYER_REALM] then
    db[PLAYER_REALM] = {[STATE_LOW] = {}, [STATE_HIGH] = {}}
    if not cherry then
      cherry = "This character didn't have an AddOn table."
    end
  end

  -- copy tags
  self.tags = {}
  for n, c in pairs(db.tags) do
    self.tags[n] = c
  end
  if cherry then
    D:Print(cherry)
  end
  D.oldprint = getprinthandler()
  if not _G.oldprint then
    _G.oldprint = D.oldprint
  end

  self.console = {}
  self.sig = {}
  for i, cinfo in ipairs(db.channels) do
    self.console[i] = CreateConsole(i, cinfo)
    self.sig[cinfo.signature] = self.console[i]
  end
  setprinthandler(Message)
  print(MAJOR, MINOR)
end