view UI.lua @ 68:1687ae1c6162

fixed :ToFront not remembering the current channel
author Nenue
date Sat, 12 Mar 2016 02:31:55 -0500
parents 516ceb31703d
children e89244da507b
line wrap: on
line source
--- Devian - UI.lua
-- @file-author@
-- @project-revision@ @project-hash@
-- @file-revision@ @file-hash@
-- Created: 12/27/2015 3:01 AM
if not LibStub then
  print('Something has happened...')
end
local _, D = ...
local DEVIAN_FRAME = 'DevianConsole'
local insert, tonumber, pairs, concat = tinsert, tonumber, pairs, table.concat
local L = D.L
local print = D.print




local Console_OnMovementChanged = function(self, event)
  local db = D.db
  if self.enabled then
    if event == 'PLAYER_STARTED_MOVING' then
      self.moveFade:Stop()
      local F1 = self.moveFade.alphaOut
      F1:SetFromAlpha(db.movement_fade_from)
      F1:SetToAlpha(db.movement_fade_to)
      F1:SetDuration(db.movement_fade_time)
      self.moveFade:Play()
      self:EnableMouse(false)
    else
      self.moveFade:Stop()
      local F1 = self.moveFade.alphaOut
      F1:SetToAlpha(db.movement_fade_from)
      F1:SetFromAlpha(db.movement_fade_to)
      F1:SetDuration(db.movement_fade_time)
      self.moveFade:Play()
      self:EnableMouse(true)
    end
  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
  self.out:Hide()
  self:Save()
end

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


local function Console_Save(self)
  local db = D.channels[self.index]
    db.x = self:GetLeft()
    db.y = (self:GetTop() - GetScreenHeight())
    db.width = self:GetWidth()

  if not self.minimized then
    db.height = self:GetHeight()
    self:SetHeight(db.height)
  end

  db.dockedTo = self.dockedTo
  db.docked = self.docked

  db.minimized = self.minimized and true or nil
  db.enabled = self:IsVisible() and true or nil
  db.active = self.active and true or nil
  self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y)
  self:SetWidth(db.width)
end

--- Brings the console to the front.
-- Frame method used to bring a console frame to the front of the display stack.
local function Console_ToFront(c)
  local db = D.db
  local profile = D.currentProfile
  c:Raise()
  c:SetAlpha(db.frontalpha)
  c.out.backdrop:SetTexture(unpack(db.frontdrop))
  c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad))
  c.out.backdrop:SetBlendMode(db.frontblend)
  c.dropmenu.icon:SetVertexColor(unpack(db.frontheader))
  c.title:SetTextColor(unpack(db.frontborder))

  --oldprint('changing current toplevel from', db.current_channel, 'to', c.index)
  profile.current_channel = c.index

  --oldprint('toplevel is now', db.current_channel)
  c:Save()


  -- update dock buttons
  local beacon = D.dock.buttons[c.index]
  beacon.selected = true
  beacon.newMessage = nil
  D.UpdateBeacon(beacon)

  for _, part in pairs(c.border) do
    part:SetTexture(unpack(db.frontborder))
  end

  for id, bc in pairs(D.console) do
    if id ~= c.index then
      bc:SetAlpha(db.backalpha)
      bc.out.backdrop:SetTexture(unpack(db.backdrop))
      bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad))
      bc.out.backdrop:SetBlendMode(db.backblend)
      bc.dropmenu.icon:SetVertexColor(unpack(db.backheader))
      bc.title:SetTextColor(unpack(db.backborder))

      local beacon = D.dock.buttons[bc.index]
      beacon.raised = nil
      beacon.showName = nil
      beacon.selected = nil
      D.UpdateBeacon(beacon)

      for _, part in pairs(bc.border) do
        part:SetTexture(unpack(db.backborder))
      end
    end
  end
end

local function Console_MouseDown(self, button, up)
  if button == 'LeftButton' then
    if up then
      self:StopMovingOrSizing()
      self:ToFront()
      self:Save()
    elseif self.out.grip:IsMouseOver() then
      self:StartSizing()
    else
      self:StartMoving()
    end
  else
    if up then
      self:MinMax()
    end
  end
end
local function Console_MouseUp(self, button)
  return Console_MouseDown(self, button, true)
end


--- Constructs the frame object for a console channel
-- Initializes the console channel at a specified index.
-- Configuration data can be overridden by passing a desired settings table.
-- @param i Numeric index of the channel as it manifests in db.channels
-- @param vars Optional settings table to be used.
local function CreateConsole(i, vars)
  local db = D.db
  if tonumber(i) == nil or math.floor(i) ~= i then
    error('Non-integer index value.')
  end
  if not vars then
    vars = D.channels[i] and D.channels[i] or D.channels[db.primary_channel]
  end
  local f
  f= CreateFrame('Frame', 'DevianChannelFrame' .. i, UIParent, DEVIAN_FRAME)

  --@debug@
  --print(f:GetName())

  --print('create(2)')
  for k,v in pairs(vars) do
    f[k] = v
    --@debug@
    --print(' f['..type(k)..' '..tostring(k)..'] = '..type(v)..' '..tostring(v))
  end

  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)
  if (db.current_channel == i) then
    f.out.backdrop:SetTexture(unpack(db.frontdrop))
    f.dropmenu.icon:SetVertexColor(unpack(db.headerfontcolor))
    f.title:SetTextColor(unpack(db.headerfontcolor))
    f.header:SetAlpha(db.headeralpha)
  else
    f.out.backdrop:SetTexture(unpack(db.backdrop))
  end

  f.Save = Console_Save
  f.Minimize = Console_Minimize
  f.Maximize = Console_Maximize
  f.MinMax = Console_MinMax
  f.ToFront = Console_ToFront
  f.Toggle = D.Console_Toggle
  f:SetScript('OnMouseDown', Console_MouseDown)
  f:SetScript('OnMouseUp', Console_MouseUp)
  f.profileID = db.current_profile


  UIDropDownMenu_Initialize(f.menuFrame, function()
    local info = { {
        text= "Close",
        value = "OptClose",
        func = function ()
          f.enabled = nil
          f:Hide()
          f:Save()
        end },--[[
      {
        text = "Dock",
        value = "OptDock",
        func = function() print('Dvn', 'docking shenanary') end }]]
    }
    for _, v in ipairs(info) do
      UIDropDownMenu_AddButton(v)
    end
  end, 'MENU')

  if db.movement_fade then
    f:RegisterEvent('PLAYER_STARTED_MOVING')
    f:RegisterEvent('PLAYER_STOPPED_MOVING')
    f:SetScript('OnEvent', Console_OnMovementChanged)
  end

  D.dock.buttons[i] = CreateFrame('Button', 'Channel'..i..'Beacon', UIParent, 'DevianBeacon')
  D.dock.buttons[i].icon:SetVertexColor(math.random(),math.random(),math.random())
  D.dock.buttons[i].console = f
  D.dock.buttons[i].index = i
  D.dock.buttons[i].caption.name:SetText(vars.signature)
  D.dock.buttons[i]:Show()

  if vars.minimized then
    f:Minimize()
  else
    f:Maximize()
  end
  if db.enabled then
    f.enabled = true
    f:Show()
  end

  return f
end


--- Updates console information and returns the handle of the channel object that was worked on.
-- When key is nil or not a valid handle, a new channel is created using whatever signature can be found in cinfo.
-- The signature can be passed as a string, or as a table entry under the key 'signature'
-- If the signature of a new channel is also a tag, the channel will be added to that tag
-- @param cinfo string signature of a new channel, or a table of config variables to be imposed on the channel
-- @param key string signature or index number of channel to operate on
-- @usage channel = D:SetChannel('new', nil) -- creates a new channel
-- @usage channel = D:SetChannel({x = 200, y = 100}, 4) -- updates channel #4
function D:SetChannel(cinfo, key)
  local profile = D.currentProfile
  local t_info = {}
  local channel, isNew, id, sig, t_id
  --@debug@
  --print('setchan(0) cinfo, key', cinfo, key)--@end-debug@
  -- obtain source data
  if tonumber(key) ~= nil and  D.channels[key] then
    id = tonumber(key)
  elseif D.sigID[tostring(key)] then
    id = D.sigID[tostring(key)]
  else
    id = profile.default_channel
    isNew = true
  end
  local dbvars = D.channels[id]
  t_id = id           -- overridden later if new
  t_info.index = t_id --
  --@debug@
  --print('setchan(1) cinfo, key, id=', cinfo, key, id)--@end-debug@


  -- obtain config info
  if type(cinfo) == 'string' then
    sig = cinfo
    cinfo = {signature = sig}
  elseif type(cinfo) ~= 'table' then -- stop here if a table wans't passed
    error('Expecting table of string as arg1')
  elseif cinfo.signature then -- new sig
    sig = cinfo.signature
  elseif isNew then -- new channel sig
    sig = 'Ch'
  else -- old sig
    sig = D.channels[id].signature
  end
  t_info.signature = sig
  --@debug@
  --print('setchan(2) sig,id,isNew=', sig, id, isNew)--@end-debug@

  for k,v in pairs(cinfo) do -- allow all cinfo to pass
  t_info[k] = v
  end

  local blocked = {          -- ignore these vars:
    ['docked'] = true,       -- table
    ['dockedTo'] = true,     -- table-related
    ['signature'] = true}    -- already determined
  for k,v in pairs(dbvars) do
    if not t_info[k] and not blocked[k] then -- already set or blocked?
    t_info[k] = v
    end
  end
  -- new channel overrides
  if isNew then
    if D.sigID[sig]then -- find a non-clashing signature
    local result, i = sig, 1
    while D.sigID[result] do
      result = sig .. i
      i = i + 1
    end
    t_info.signature = result
    end
    t_id = self.max_channel + 1
    t_info.index = t_id
    --@debug@
    --print('setchan(3a) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@
  else
    --@debug@
    --print('setchan(3b) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@
  end

  local channel
  if not self.console[t_id] then -- create a frame
    if isNew then -- position the channel frame
      profile.max_channel = t_id
      t_info.x = t_info.x + 20
      t_info.y = t_info.y - 20
      profile.channels[t_id] = t_info
      --@debug@
      --print('setchan(4a)', 't_id, x, y=', t_id, t_info.x, t_info.y)--@end-debug@
    end
    channel = CreateConsole(t_id, t_info)
    self.console[t_id] = channel
    self.sig[t_info.signature] = channel
    self.sigID[t_info.signature] = t_id
    self.IDsig[t_id] = t_info.signature
  end
  channel = self.console[t_id]
  if channel.minimized then
    channel:Minimize()
  else
    channel:Maximize()
  end

  if channel.enabled then -- hide or show last since Min/Max mess with visibility
  --print('setchan(5a) enable')
    channel:Show()
    --channel:ToFront()
  else
    --print('setchan(5a) disable')
    channel:Hide()
  end
  --@debug@
  --print('setchan(end); c:IsVisible(), c.enabled, db.enabled=', channel:IsVisible(), channel.enabled, profile.enabled)--@end-debug@
  return channel
end

--- Console frame toggler
-- @paramsig [...]
-- @param ... one or more space-seperated channel keys
function D:Console_Toggle(input, force)
  local profile = D.currentProfile
  --oldprint(input)
  local setAll
  local search = {}
  local key
  local n = 0
  while self:GetArgs(input,1,n) and n < 255 do --should end itself when it gets nil, but
  key, n = self:GetArgs(input,1,n)

  if self.sig[key] then
    --print(key, self.sigID[key])
    insert(search, self.sigID[key])
  elseif self.console[tonumber(key)] then
    --print(key, tonumber(key))
    insert(search, tonumber(key))
  end

  --oldprint(#search, key, n)
  end
  if #search < 1 then
    search = self.sigID
    setAll = true
  end
  if setAll then
    --oldprint('setall', setAll)
    profile.enabled = (not profile.enabled) and true or nil
    if force == 0 then
      profile.enabled = nil
    end
  end

  for i, id in pairs(search) do
    oldprint(i, id)
    local c = self.console[id]
    if setAll then
      c.enabled = profile.enabled and profile.enabled or nil
    else

      profile.enabled = true
      c.enabled = (not c.enabled) and true or nil
      if force == 0 then
        c.enabled = nil
      end
      oldprint(id, '  ', force, c.enabled, profile.enabled)
    end

    if c.enabled or (setAll and profile.enabled) then
      c:Show()
    elseif not (c.enabled and profile.enabled) then
      c:Hide()
    end
    c:Save()
  end

  if setAll then
    if profile.enabled then
      self:Print('toggled all consoles ON')
      if D.console[profile.current_channel] then
        D.console[profile.current_channel]:ToFront()
      end
    else
      self:Print('toggled all consoles OFF')
    end
  else
    local result = {}
    for i, id in pairs(search) do
      result[i] = tostring(id) .. ' = ' .. (self.console[id].enabled and 'ON' or 'OFF')
    end
    self:Print('toggled: '..concat(result, ', '))
  end
end