diff Devian.lua @ 14:5254d1ba6013 v1.2-r15

Multiple output windows can be created for different output prefixes, and prefixes can be designated to an existing or new "console" with /dvn <prefix> <console> Frame objects are generated directly from XML data, and their state information is stored in the object itself to resolve issues with GetWidth() returning old info in some cases. StackFrames and DistributeFrames methods can be invoked from /script to arrange the buffers.
author Nenue
date Sun, 20 Dec 2015 00:46:42 -0500
parents 080dfa4990fb
children 48a1d9c14af5
line wrap: on
line diff
--- a/Devian.lua	Sat Dec 19 07:59:12 2015 -0500
+++ b/Devian.lua	Sun Dec 20 00:46:42 2015 -0500
@@ -17,23 +17,36 @@
   ['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}},
+  primary_channel = 1,
   current_channel = 1,
-  console = true,
+  toggle = true,
   dnd_status = true,
   dnd_message = "Debugging. Your messages may get eaten.",
   font = [[Interface\Addons\Devian\font\SourceCodePro-Regular.ttf]],
   fontsize = 13,
   fontoutline = 'NONE',
+  backdrop = {1,1,1,0.2},
+  backgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.3, 0, 0, 0, 0.5},
+  backblend = 'BLEND',
+  frontdrop = {1,1,1,1},
+  frontgrad = {'VERTICAL', 0.1, 0.1, 0.1, 0.9, 0, 0, 0, 0.9},
+  frontblend = 'BLEND'
 }
 
 
 local function ScanAddOnList(cmd, ...)
   local list_state
 
-  local mode = tonumber(cmd:match("%d"))
+  local args = {}
+  local arg, n = D:GetArgs(cmd, 1)
+  while arg do
+    table.insert(args, arg)
+    arg, n = D:GetArgs(cmd,1,n)
+  end
+  local mode, tag, dest = unpack(args)
 
 
-  print('Starting Addons scan. arg=', mode)
+  -- no args, toggle ui
   if mode == nil then
     list_state = db.enabled and STATE_LOW or STATE_HIGH
     db.enabled = (db.enabled == false) and true or false
@@ -41,15 +54,35 @@
 
     if list_state == STATE_LOW then
     end
-
-  else
+  elseif mode == 'stack' then
+    return D:StackFrames()
+  elseif mode == 'grid' then
+    return D:DistributeFrames()
+  elseif mode == 'tag' then -- tagging
+    if tag ~= nil and dest ~= nil then
+      if not D.console[dest] and not D.sig[dest] then
+        local sig = dest:match('%a')
+        local id = dest:match('%d')
+        if not id then
+          id = self.last_channel + 1
+        end
+        if not sig then
+          sig = tag
+        end
+        D:SetChannel(sig, id)
+      end
+      D:Print('Assigning |cFFFFFF00'..tag..'|r to |cFF00FFFF'.. dest .. '|r')
+    else
+      D:Print('Usage: /dvn tag <prefix> <console name or number>')
+    end
+    return
+  elseif mode ~= nil then
+    mode = tonumber(mode)
     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]
 
@@ -110,7 +143,8 @@
   self:SetHeight(20)
   self:SetMaxResize(GetScreenWidth(),20)
   self.minimized = true
-  return self.out:Hide()
+  self.out:Hide()
+  self:Save()
 end
 
 local function Console_Maximize(self)
@@ -118,59 +152,125 @@
   self:SetHeight(db.height)
   self:SetMaxResize(GetScreenWidth(),GetScreenHeight())
   self.minimized = nil
-  self.grip:SetTexture(0.5,0.5,0.5)
-  return self.out:Show()
+  self.out:Show()
+  self:Save()
 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 self.x then
+    db.x = self.x
+  else
+    db.x = self:GetLeft()
+  end
+
+  if self.y then
+    db.y = self.y
+  else
+    db.y = (self:GetTop() - GetScreenHeight())
+  end
+
+  if self.width then
+    db.width = self.width
+  else
+    db.width = self:GetWidth()
+  end
+
   if not self.minimized then
-    db.height = self:GetHeight()
-    db.minimized = nil
-  else
-    db.minimized = true
+    if self.height then
+      db.height = self.height
+    else
+      db.height = self:GetHeight()
+    end
+    self:SetHeight(db.height)
   end
-  if self:IsVisible() then
-    db.enabled = true
-  else
-    db.enabled = nil
-  end
+
+  db.minimized = self.minimized and true or nil
+  db.enabled = self:IsVisible() and true or nil
+  db.active = self.active and true or nil
+  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)
   self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y)
+  self:SetWidth(db.width)
 end
 
-
+-- Console frame toggler
+-- @paramsig [...]
+-- @param ... one or more space-seperated channel keys
 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]}
+  local search = {}
+  local key, n = D:GetArgs(input, 1)
+  if key then
+    repeat
+      if D.sig[key] then
+        table.insert(search, D.sig[key])
+      elseif D.console[key] then
+        table.insert(search, D.console[key])
+      end
+      key, n = D:GetArgs(input,1,n)
+    until n == 1e9
   else
     search = D.console
   end
 
+  db.toggle = not db.toggle and true or nil
   for _, c in ipairs(search) do
-    if c:IsVisible() then
+    if db.toggle then
+      c:Show()
+    else
+      c.enabled = nil
+      c.minimized = nil
+      c:Maximize()
       c:Hide()
-    else
-      c:Show()
-      c:Maximize()
     end
-    c:Save()
   end
+
+  if db.toggle then
+    D:Print('toggled on?')
+  else
+    D:Print('toggled off?')
+    end
 end
 
---
---
--- Construct a console frame
+-- Bring console to the front
+local function Console_ToFront(c)
+  --print(D.raise_ct, 'Raising', c.signature)
+  --print(unpack(db.frontdrop))
+  --print(unpack(db.frontgrad))
+  --print(db.frontblend)
+  D.raise_ct = D.raise_ct + 1
+  c:Raise()
+  c.out.backdrop:SetTexture(unpack(db.frontdrop))
+  c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad))
+  c.out.backdrop:SetBlendMode(db.frontblend)
+
+  for id, bc in pairs(D.console) do
+    if id ~= c.index then
+      --print(D.raise_ct, 'Lowering', bc.signature)
+      --print(unpack(db.backdrop))
+      --print(unpack(db.backgrad))
+      --print(db.backblend)
+      bc.out.backdrop:SetTexture(unpack(db.backdrop))
+      bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad))
+      bc.out.backdrop:SetBlendMode(db.backblend)
+      end
+  end
+
+end
+
+-- Generate a console frame
+-- @paramsig id, vars
+-- @param id channel number
+-- @param vars alternative config, else uses db.channels[id]
 local function CreateConsole(i, vars)
+
+  if not vars then
+    vars = db.channels[i]
+  end
+
+  print('make:', vars.signature, '(', vars.x, vars.y, ')', vars.width, 'x', vars.height)
   local f = CreateFrame('Frame', 'DevianChannelFrame' .. tostring(i), UIParent, DEVIAN_FRAME)
-  f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.channels[i].x, db.channels[i].y)
+  f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', vars.x, vars.y)
   f:SetSize(vars.width, vars.height)
   f:Lower()
   f.out:SetFont(db.font, db.fontsize, db.fontoutline)
@@ -178,23 +278,34 @@
   f.Minimize = Console_Minimize
   f.Maximize = Console_Maximize
   f.MinMax = Console_MinMax
+  f.ToFront = Console_ToFront
   f.Toggle = D.Console_Toggle
   f.name = vars.name
   f.index = i
+  f.signature = vars.signature
+  f.format = vars.header
+  f.x = vars.x
+  f.y = vars.y
+  f.width = vars.width
+  f.height = vars.height
 
-  if db.channels[i].enabled then
-    f:Show()
+  if vars.enabled  then
+    f.enabled = true
+    if db.toggle then
+      f:Show()
+    end
   end
-  if db.channels[i].minimized then
+  if vars.minimized then
     f:Minimize()
   end
 
   return f
 end
 
---
---
--- Send a message somewhere
+-- Print to Devian output
+-- @paramsig tag, ...
+-- @param tag channel signature or number used to select console
+-- @param ... print arguments
 local function Message(prefix, ...)
   if prefix == nil then
     prefix = 1
@@ -210,9 +321,6 @@
   else
     channel = D.console[1]
   end
-
-
-
   -- color me timbers
   local pcolor
   if D.tags[prefix] then
@@ -257,6 +365,89 @@
   table.wipe(buffer)
 end
 
+-- Spaces each frame evenly across the screen
+function D:DistributeFrames() --
+  print('frame grid:', max, num_side)
+  local max = self.num_channels
+  local num_side = math.ceil(math.sqrt(max))
+  local w = GetScreenWidth() / num_side
+  local h = GetScreenHeight() / num_side
+  for i, frame in pairs(D.console) do
+    local dx = (i-1) % num_side
+    local dy = math.floor((i-1) / num_side)
+
+    print('move:', frame.signature, 'dx=', dx, 'dy=', dy)
+    print('move:', frame.signature, '                                       x=', dx * w, 'y=', -(dy * h), 'h=', h, 'w=', w)
+    frame.width = w
+    frame.height = h
+    frame.x = dx * w
+    frame.y = -(dy * h)
+    frame:Save()
+  end
+
+end
+
+-- Place all frames stacked beneath the primary frame
+-- @paramsig
+function D:StackFrames()
+  local last
+  for i, frame in pairs(self.console) do
+    if last then
+      frame.x = last.x
+      frame.y = last.y - 20
+    else
+      frame.x = (GetScreenWidth()-frame:GetWidth())/2
+      frame.y = 0
+    end
+    frame:Save()
+    last = frame
+  end
+end
+
+-- Creates or updates a console frame
+-- @paramsig cinfo [, i]
+-- @param cinfo an array from db.channels[x] or the desired string signature
+-- @param id when set, the console at that index will be assigned all parameters in cinfo
+function D:SetChannel(cinfo, i)
+  print('join:', i , cinfo)
+  local t_info = {}
+  if type(cinfo) ~= 'table' then
+    t_info.signature = tostring(cinfo)
+    cinfo = {}
+  end
+  local srcdb = db.channels[self.primary_channel]
+  if i ~= nil then
+    i = tonumber(i)
+    if db.channels[i] then
+      print('pull vars from '..db.channels[i].signature)
+      cinfo = db.channels[i]
+      srcdb = cinfo
+    end
+  end
+
+  for k,v in pairs(srcdb) do
+    if not t_info[k] then
+      if cinfo[k] then
+        print('- pulling', k..':',v)
+        t_info[k] = cinfo[k]
+      end
+    end
+  end
+
+  if not db.channels[i] then
+    t_info.x = t_info.x + 20
+    t_info.y = t_info.y - 20
+    db.channels[i] = t_info
+  end
+  if not self.console[i] then
+    self.console[i] = CreateConsole(i, t_info)
+  end
+
+  self.sig[cinfo.signature] = self.console[i]
+  self.sigID[cinfo.signature] = i
+  self.IDsig[i] = cinfo.signature
+end
+
 function D:OnEnable()
   -- commands
   local cmdlist = {
@@ -276,7 +467,6 @@
 
 end
 
-
 function D:OnInitialize()
   -- emergency button
   self:RegisterChatCommand("cleandvn", function(args)
@@ -312,11 +502,23 @@
     _G.oldprint = D.oldprint
   end
 
+  self.raise_ct = 0
+  self.last_channel = 0
+  self.num_channels = 0
   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]
+  self.sigID = {}
+  self.IDsig = {}
+  for i, cinfo in pairs(db.channels) do
+    i = tonumber(i)
+    if not self.primary_channel then
+      self.primary_channel = i
+    end
+    self:SetChannel(cinfo, i)
+    if i > self.last_channel then
+      self.last_channel = i
+    end
+    self.num_channels = self.num_channels + 1
   end
   setprinthandler(Message)
   print(MAJOR, MINOR)