view ReAction.lua @ 33:c54c481ad0ed

- Moved bar control frame from ConfigUI to Bar - Added LICENSE.txt - added profile management options - other minor cleanup
author Flick <flickerstreak@gmail.com>
date Thu, 03 Apr 2008 20:25:40 +0000
parents 0d95ce7a9ec2
children 52ac6db0c8ca
line wrap: on
line source
-- ReAction.lua
-- See modules/ReAction_ModuleTemplate for Module API listing
-- See Bar.lua for Bar object listing

------ CORE ------
local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction",
  "AceConsole-3.0",
  "AceEvent-3.0"
)
ReAction.version = GetAddOnMetadata("ReAction","Version")
ReAction.revision = tonumber(("$Revision$"):match("%d+"))

------ GLOBALS ------
_G["ReAction"] = ReAction

------ DEBUGGING ------
ReAction.debug = true
if ReAction.debug then
  ReAction.print = function(msg)
    DEFAULT_CHAT_FRAME:AddMessage(msg)
  end
  --seterrorhandler(ReAction.print)
else
  ReAction.print = function() end
end

------ LIBRARIES ------
local L = LibStub("AceLocale-3.0"):GetLocale("ReAction")
ReAction.L = L

------ PRIVATE ------
local SelectBar, DestroyBar, InitializeBars, TearDownBars, DeepCopy, SafeCall, CheckMethod, SlashHandler
do
  local pcall = pcall
  local geterrorhandler = geterrorhandler

  SelectBar = function(x)
    local bar, name
    if type(x) == "string" then
      name = x
      bar = ReAction:GetBar(name)
    elseif ReAction.Bar:IsInstance(x) then
      bar = x
      for k,v in pairs(ReAction.bars) do
        if v == bar then
          name = k
        end
      end
    else
      error("bad argument to SelectBar")
    end
    return bar, name
  end

  DestroyBar = function(x)
    local bar, name = SelectBar(x)
    if name and bar then
      ReAction.bars[name] = nil
      ReAction:CallMethodOnAllModules("RemoveFromBar", bar)
      bar:Destroy()
    end
  end

  InitializeBars = function ()
    if not(ReAction.inited) then
      for name, config in pairs(ReAction.db.profile.bars) do
        if config then
          ReAction:CreateBar(name, config)
        end
      end
      ReAction:CallMethodOnAllBars("ApplyAnchor") -- re-anchor in the case of oddball ordering
      ReAction.inited = true
    end
  end

  TearDownBars = function()
    for name, bar in pairs(ReAction.bars) do
      if bar then
        ReAction.bars[name] = DestroyBar(bar)
      end
    end
    ReAction.inited = false
  end

  DeepCopy = function(x)
    if type(x) ~= "table" then
      return x
    end
    local r = {}
    for k,v in pairs(x) do
      r[k] = DeepCopy(v)
    end
    return r
  end

  SafeCall = function(f, ...)
    if f then
      local success, err = pcall(f,...)
      if not success then
        geterrorhandler()(err)
      end
    end
  end

  CheckMethod = function(m)
    if type(m) == "function" then
      return m
    end
    if type(m) ~= "string" then
      error("Invalid method")
    end
  end

  local function CallOptsModule(method,...)
    local m = ReAction:GetModule("ConfigUI",true)
    if not m then
      LoadAddOn("ReAction_ConfigUI")
      m = ReAction:GetModule("ConfigUI")
    end
    if m and type(m) == "table" and type(m[method]) == "function" then
      m[method](m,...)
    else
      ReAction:Print("Options module not found")
    end
  end

  SlashHandler = function(option)
    if option == "config" then
      CallOptsModule("OpenConfig",true)
    elseif option == "unlock" then
      ReAction:SetConfigMode(true)
    elseif option == "lock" then
      ReAction:SetConfigMode(false)
    else
      ReAction:Print(ReAction.version)
      ReAction:Print("/reaction config")
      ReAction:Print("/reaction unlock")
      ReAction:Print("/reaction lock")
    end
  end
end


------ HANDLERS ------
function ReAction:OnInitialize()
  self.db = LibStub("AceDB-3.0"):New("ReAction_DB", 
    { 
      profile = {
        bars = { },
        defaultBar = { }
      }
    }
    -- default profile is character-specific
  )
  self.db.RegisterCallback(self,"OnProfileChanged")
  self.callbacks = LibStub("CallbackHandler-1.0"):New(self)
  self:RegisterChatCommand("reaction", SlashHandler)
  self:RegisterChatCommand("rxn", SlashHandler)
  self:RegisterEvent("PLAYER_REGEN_DISABLED")

  self.bars = {}
end

function ReAction:OnEnable()
  InitializeBars()
end

function ReAction:OnDisable()
  TearDownBars()
end

function ReAction:OnProfileChanged()
  TearDownBars()
  InitializeBars()
end

function ReAction:OnModuleEnable(module)
  if module.ApplyToBar then
    for _, b in pairs(bars) do
      if b then
        module:ApplyToBar(b)
      end
    end
  end
end

function ReAction:OnModuleDisable(module)
  if module.RemoveFromBar then
    for _, b in pairs(bars) do
      if b then
        module:RemoveFromBar(b)
      end
    end
  end
end

function ReAction:PLAYER_REGEN_DISABLED()
  if self.configMode == true then
    UIErrorsFrame:AddMessage(L["ReAction config mode disabled during combat."])
    self:SetConfigMode(false)
  end
end



------ API ------
function ReAction:CallMethodOnAllModules(method, ...)
  local m = CheckMethod(method)
  for _, x in self:IterateModules() do
    if x then
      SafeCall(m or x[method], x, ...)
    end
  end
end

function ReAction:CallMethodOnAllBars(method,...)
  local m = CheckMethod(method)
  for _, x in pairs(self.bars) do
    if x then
      SafeCall(m or x[method], x, ...)
    end
  end
end

function ReAction:CreateBar(name, defaultConfig, prefix)
  local profile = self.db.profile
  defaultConfig = defaultConfig or profile.defaultBar
  prefix = prefix or L["Bar "]
  if not name then
    i = 1
    repeat
      name = prefix..i
      i = i + 1
    until self.bars[name] == nil
  end
  profile.bars[name] = profile.bars[name] or DeepCopy(defaultConfig)
  local bar = self.Bar:new( name, profile.bars[name] )  -- ReAction.Bar defined in Bar.lua
  self:CallMethodOnAllModules("ApplyToBar", bar)
  self.bars[name] = bar
  self.callbacks:Fire("OnCreateBar", bar)
  if self.configMode then
    bar:ShowControls(true)
  end

  return bar
end

function ReAction:EraseBar(x)
  local bar, name = SelectBar(x)
  if name and bar then
    DestroyBar(bar)
    self.db.profile.bars[name] = nil
    self:CallMethodOnAllModules("EraseBarConfig", name)
    self.callbacks:Fire("OnEraseBar",name)
  end
end

function ReAction:GetBar(name)
  return self.bars[name]
end

function ReAction:RenameBar(x, newname)
  local bar, name = SelectBar(x)
  if bar and name and newname then
    if self.bars[newname] then
      error(L["ReAction: name already in use"])
    end
    self.bars[newname] = self.bars[name]
    self.bars[name] = nil
    bar.name = newname or ""
    local cfg = self.db.profile.bars
    cfg[newname], cfg[name] = cfg[name], nil
    self:CallMethodOnAllModules("RenameBarConfig", name, newname)
    self.callbacks:Fire("OnRenameBar", name, newname)
  end
end

ReAction.options = {}
-- See modules/ReAction_ConfigUI for valid options contexts.
function ReAction:RegisterOptions(context, module, opts)
  if module == nil or context == nil then
    error("ReAction:RegisterOptions requires a module object and context ID")
  end
  if not self.options[context] then
    self.options[context] = {}
  end
  self.options[context][module] = opts
  self.callbacks:Fire("OnOptionsRegistered", context, module, opts)
end

function ReAction:GetOptions(context)
  if context then
    if not self.options[context] then
      self.options[context] = { }
    end
    return self.options[context]
  end
end

function ReAction:GetOptionContextList()
  local c = {}
  for k in self.options do
    tinsert(c,k)
  end
  return c
end

function ReAction:RefreshOptions()
  self.callbacks:Fire("OnOptionsRefreshed")
end

function ReAction:SetConfigMode( mode )
  self:CallMethodOnAllBars("ShowControls",mode)
  self:CallMethodOnAllModules("ApplyConfigMode",mode,self.bars)
  self.configMode = mode
end