diff Devian.lua @ 98:33bc8baba858

start of a lot of v3 groundwork based on better knowledge of the addon interface: - use of mixin as a lexical center for generated frames - removal of unfinished segments
author Nenue
date Wed, 26 Oct 2016 10:17:43 -0400
parents f6fae1a4c66c
children 7d94df3804a7
line wrap: on
line diff
--- a/Devian.lua	Tue Oct 25 12:35:12 2016 -0400
+++ b/Devian.lua	Wed Oct 26 10:17:43 2016 -0400
@@ -11,9 +11,8 @@
 
 local ADDON, D = ...
 local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@'
-local D =  LibStub("AceAddon-3.0"):NewAddon(D, "Devian", "AceConsole-3.0", "AceEvent-3.0")
-local L = D.L
-Devian = D
+local D_INITIALIZED
+local next = next
 local sub, GetTime, print, _G = string.sub, GetTime, print, _G
 local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler
 local tinsert, tremove, rawset = tinsert, tremove, rawset
@@ -23,6 +22,28 @@
 local num_dock_tabs = 0
 local charStates ={}
 
+local registeredTags = {}
+
+
+DevianCore = {}
+
+function DevianCore:OnLoad ()
+  self:RegisterEvent('ADDON_LOADED')
+  self:RegisterEvent('PLAYER_LOGIN')
+  self:SetShown(true)
+end
+
+function DevianCore:OnEvent(event, arg)
+  if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then
+    --print(event, arg, DevianDB)
+    if (arg == 'Devian') and not D_INITIALIZED then
+      D_INITIALIZED = true
+      self:Initialize()
+      self:UnregisterAllEvents()
+    end
+  end
+end
+
 DevianLoadMessage = setmetatable({}, {
   __call = function(t, msg)
     rawset(t, #t+1, msg)
@@ -37,7 +58,7 @@
 --@end-debug@
 D.print = function(...)
   if currentProfile and not currentProfile.workspace then
-    return
+    return nop
   end
 
   if D.debugmode then
@@ -50,13 +71,12 @@
 
 D.L = setmetatable({}, {
   __index= function(t,k)
-    return k
+    return tostring(k)
   end,
   __call = function(t,k,...)
-    return format((t[k] or k) , ...)
+    return format((t[k]) , ...)
   end
 })
-D:SetDefaultModuleState(false)
 D.oldprint = getprinthandler()
 if not _G.oldprint then _G.oldprint = D.oldprint end
 
@@ -67,12 +87,12 @@
 local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn
 local UnitName, DisableAddOn = UnitName, DisableAddOn
 
-local db
+local db, L
 local defaults = {
   global = {{}, {}},
   default_channel = {
     signature = 'Main',
-    x = 100, y = 800,
+    x = 100, y = -200,
     height = 500, width = 600,
     enabled = true},
   current_profile = 1,
@@ -149,7 +169,7 @@
     {
       index = 1,
       signature = 'Main',
-      x = 100, y = 800,
+      x = 100, y = -200,
       height = 500, width = 600,
       enabled = true
     }
@@ -184,6 +204,44 @@
   end
 end
 
+D.FixProfile = function(forced)
+
+  local numChannels = 0
+  local minChannel = 400
+  local sortedChannels = {}
+  local sortedTags = {}
+  local maxChannel = 0
+  for k,v in pairs(currentProfile.channels) do
+    numChannels = numChannels + 1
+    maxChannel = max(tonumber(k), maxChannel)
+    minChannel = min(tonumber(k), minChannel)
+    tinsert(sortedChannels, v)
+  end
+  if (maxChannel > numChannels) or forced then
+    oldprint('fixing channels data')
+    table.sort(sortedChannels, function(a,b)
+      return (b.index > a.index)
+    end)
+    for i, info in ipairs(sortedChannels) do
+      for tag, tagSet in pairs(currentProfile.tags) do
+        for _, index in pairs(tagSet) do
+          if index == info.index then
+            sortedTags[tag] = sortedTags[tag] or {}
+            sortedTags[tag][i] = i
+          end
+        end
+      end
+
+      info.index = i
+    end
+    currentProfile.channels = sortedChannels
+    currentProfile.tags = sortedTags
+  else
+    minChannel = 2
+  end
+  currentProfile.lastUpdateFix = MINOR
+end
+
 D.Profile = function (id, name)
 
   if name and not id and db.profilesName[name] then
@@ -229,6 +287,7 @@
     DEVIAN_WORKSPACE = true
     DEVIAN_PNAME = currentProfile.name
     DEVIAN_PID = id
+    print('setting phandler')
     setprinthandler(D.Message)
   else
     DEVIAN_WORKSPACE = false
@@ -237,6 +296,16 @@
   end
   DEVIAN_PID =id
 
+
+  -- Attempt to fix bad data
+  --@debug@
+  MINOR = 70100
+  --@end-debug@
+  if (currentProfile.lastUpdateFix or 0) < MINOR then
+    D.FixProfile(true)
+  end
+
+
   D.unlisted = currentProfile.unlisted
   D.channels = currentProfile.channels
   D.tags = currentProfile.tags
@@ -251,6 +320,8 @@
   D.dock = _G.DevianDock
   D.dock.buttons = D.dock.buttons or {}
 
+
+
   return id, name
 end
 
@@ -450,6 +521,19 @@
   end
 end
 
+D.UpdateTags = function()
+
+  wipe(registeredTags)
+  for tag, tagSet in pairs(currentProfile.tags) do
+    registeredTags[tag] = registeredTags[tag] or {}
+    for _, id in pairs(tagSet) do
+      if D.console[id] then
+        tinsert(registeredTags[tag], D.console[id])
+      end
+    end
+  end
+end
+
 D.Tag = function(self, tag, dest)
   local sig
   if tag ~= nil and dest ~= nil then
@@ -473,11 +557,11 @@
     -- make a new channel?
     local channel
     if not currentProfile.channels[dest] then
-      dest = D.max_channel + 1
+      dest = #D.channels + 1
       D:Print(L('New channel created', sig and (dest..':'..sig) or dest ))
-      channel = D:SetChannel(sig or tag,dest)
+      channel = D:GetOrCreateChannel(dest, tag)
     else
-      channel = D.channels[dest]
+      channel = currentProfile.channels[dest]
     end
     --@debug@
     --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@
@@ -487,13 +571,14 @@
     end
 
     if currentProfile.tags[tag][dest] then -- is tag set?
-    currentProfile.tags[tag][dest] = nil
-    D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature))
+      currentProfile.tags[tag][dest] = nil
+      D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature))
     else
       currentProfile.tags[tag][dest] = dest
-      D:Print(L('Tag added to channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature))
+      D:Print(L('Tag added to channel', tag, channel.index, channel.signature))
     end
-    D:UpdateDock()
+    D.UpdateTags()
+    DevianDock:Update()
   else
     D:Print(L['Command tag help'])
   end
@@ -547,35 +632,32 @@
 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint().
 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel.
 -- @param ... Output contents.
-
+local default_sendq = {}
 function D.Message(prefix, ...)
   if not currentProfile.workspace then
     return D.oldprint(prefix, ...)
   end
+  local print = D.oldprint
   prefix =  tostring(prefix)
   if prefix == nil then
     prefix = 'nil*'
   end
 
-  local sendq = {}
+  local sendq = default_sendq
   local tag, id, tagged
   local byName = true
-  if D.tags[prefix] then
-    for _, id in pairs(D.tags[prefix]) do
-      if D.console[id] then
-        sendq[id] = D.console[id]
-        tagged = true
-      end
+
+  if registeredTags[prefix] then
+    sendq = registeredTags[prefix]
+  else
+    if D.sig[prefix] then
+      sendq[D.sig[prefix].index] = D.sig[prefix]
+    elseif not tagged then
+      sendq[1] = D.console[D.primary_channel]
     end
   end
 
-  if D.sig[prefix] then
-    sendq[D.sig[prefix].index] = D.sig[prefix]
-  elseif D.console[prefix] then
-    sendq[D.console[prefix]] = D.console[prefix]
-  elseif not tagged then
-    sendq[D.primary_channel] = D.console[D.primary_channel]
-  end
+
 
   -- color me timbers
   local pcolor
@@ -625,12 +707,11 @@
     if channel.width < 250 then
       prefix = sub(prefix, 0,2)
     end
-    --currentProfile.last_channel = channel.index
-    channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8, nil, nil, prefix, GetTime())
-    if not D.dock.usedButtons[id].newMessage then
-      D.dock.usedButtons[id].newMessage = true
-      D.dock.usedButtons[id].caption.pulse:Play()
-      D.dock.usedButtons[id]:Update()
+    channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8)
+    if channel.Dock and not channel.Dock.newMessage then
+      channel.Dock.newMessage = true
+      channel.Dock.caption.pulse:Play()
+      channel.Dock:Update()
     end
   end
   wipe(buffer)
@@ -682,15 +763,15 @@
 end
 
 
-function D:OnInitialize()
+function DevianCore:Initialize()
   L = D.L
 
   -- pull defaults
-  if not _G.DevianDB then
-    _G.DevianDB = defaults
+  if not DevianDB then
+    DevianDB = defaults
   end
+  D.db = _G.DevianDB
   db = _G.DevianDB
-  self.db = db
 
   ---
   if #_G.DevianLoadMessage >= 1 then
@@ -735,16 +816,16 @@
   end
 
 
-  for i, cinfo in pairs(D.channels) do
-    i = tonumber(i)
+
+  for index, cinfo in ipairs(D.channels) do
+    --oldprint(index, cinfo.signature)
     if not D.primary_channel then
-      D.primary_channel = i
+      D.primary_channel = index
     end
-    D:SetChannel(cinfo, i)
-    D.num_channels = D.num_channels + 1
+    D:GetOrCreateChannel(index)
+    D.num_channels = #D.channels
   end
   D.primary_channel = D.primary_channel or 1
-
   D.max_channel = max(D.max_channel, currentProfile.max_channel)
   if currentProfile.max_channel < D.max_channel then
     for i = currentProfile.max_channel, D.max_channel do
@@ -752,14 +833,53 @@
     end
   end
 
+  D.UpdateTags()
+
   if currentProfile.workspace then
     if D.console[currentProfile.current_channel] then
       --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front')
       D.console[currentProfile.current_channel]:ToFront()
       -- bring the current channel to the front
     end
-    _G.DevianDock:Show()
-    D:UpdateDock()
+    DevianDock:Update()
   end
+
+  print('devian')
 end
 
+function D:Print (...)
+  local msg = '|cFF00FF44Devian|r:'
+  for i = 1, select('#', ...) do
+    msg = msg .. ' ' .. tostring(select(i, ...))
+  end
+  DEFAULT_CHAT_FRAME:AddMessage(msg)
+end
+
+function D:GetActiveChannel()
+  return D.console[currentProfile.current_channel]
+end
+
+function D:GetOrCreateChannel(id, name)
+  local info = D.channels[id]
+  local frame = D.console[id]
+  if not frame then
+
+    --print('new frame')
+    frame = CreateFrame('Frame', 'DevianConsole'..id, Devian, 'DevianConsoleTemplate')
+    frame:SetID(id)
+    D.console[id] = frame
+  end
+  if not info then
+    --print('new channel')
+    info = {
+    }
+    D.DeepCopy(defaults.default_channel, info)
+    info.index = id
+    info.signature = name
+    D.channels[id] = info
+  end
+
+
+  frame:Setup(info)
+  return frame
+end
\ No newline at end of file