view modules/Action.lua @ 223:c4b134512c50

Move RegisterBarType from modules to button classes
author Flick <flickerstreak@gmail.com>
date Mon, 22 Nov 2010 10:25:18 -0800
parents a4e7475633b3
children 0e20f65375d5
line wrap: on
line source
local addonName, addonTable = ...
local ReAction = addonTable.ReAction
local L = ReAction.L
local _G = _G
local CreateFrame = CreateFrame
local format = string.format
local wipe = wipe

local weak = { __mode="k" }

-- module declaration
local moduleID = "Action"
local module = ReAction:NewModule( moduleID )

-- Class declarations
local Button = ReAction.Button.Action -- see /classes/ActionButton.lua
local Handle = { }
local PropHandler = { }

-- Event handlers
function module:OnInitialize()
  self.handles = setmetatable({ }, weak)

  ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")

  ReAction.RegisterCallback(self, "OnCreateBar")
  ReAction.RegisterCallback(self, "OnRefreshBar")
  ReAction.RegisterCallback(self, "OnDestroyBar")
end

function module:OnEnable()
  ReAction:GetModule("State"):RegisterStateProperty("page", nil, PropHandler.GetOptions(), PropHandler)
end

function module:OnDisable()
  ReAction:GetModule("State"):UnregisterStateProperty("page")
end

function module:OnCreateBar(event, bar, name)
  if bar.config.type == moduleID then
    if self.handles[bar] == nil then
      self.handles[bar] = Handle:New(bar)
    end
  end
end

function module:OnRefreshBar(event, bar, name)
  if self.handles[bar] then
    self.handles[bar]:Refresh()
  end
end

function module:OnDestroyBar(event, bar, name)
  if self.handles[bar] then
    self.handles[bar]:Destroy()
    self.handles[bar] = nil
  end
end


---- Interface ----
function module:GetBarOptions(bar)
  local h = self.handles[bar]
  if h then
    return h:GetOptions()
  end
end


---- Bar Handle ----

do
  local options = {
    hideEmpty = {
      name = L["Hide Empty Buttons"],
      order = 1,
      type = "toggle",
      width = "double",
      get  = "GetHideEmpty",
      set  = "SetHideEmpty",
    },
    lockButtons = {
      name = L["Lock Buttons"],
      desc = L["Prevents picking up/dragging actions (use SHIFT to override this behavior)"],
      order = 2,
      type = "toggle",
      get = "GetLockButtons",
      set = "SetLockButtons",
    },
    lockOnlyCombat = {
      name = L["Only in Combat"],
      desc = L["Only lock the buttons when in combat"],
      order = 3,
      type = "toggle",
      disabled = "LockButtonsCombatDisabled",
      get = "GetLockButtonsCombat",
      set = "SetLockButtonsCombat",
    },
    pages = {
      name  = L["# Pages"],
      desc  = L["Use the Dynamic State tab to specify page transitions"],
      order = 4,
      type  = "range",
      min   = 1,
      max   = 10,
      step  = 1,
      get   = "GetNumPages",
      set   = "SetNumPages",
    },
    mindcontrol = {
      name = L["Mind Control Support"],
      desc = L["When possessing a target (e.g. via Mind Control), map the first 12 buttons of this bar to the possessed target's actions."],
      order = 5,
      type = "toggle",
      width = "double",
      set = "SetMindControl",
      get = "GetMindControl",
    },
    vehicle = {
      name = L["Vehicle Support"],
      desc = L["When on a vehicle, map the first 6 buttons of this bar to the vehicle actions. The vehicle-exit button is mapped to the 7th button. Pitch controls are not supported."],
      order = 6,
      type = "toggle",
      width = "double",
      get = "GetVehicle",
      set = "SetVehicle",
    },
    actions = {
      name   = L["Edit Action IDs"],
      order  = 7,
      type   = "group",
      inline = true,
      args   = {
        method = {
          name   = L["Assign"],
          order  = 1,
          type   = "select",
          width  = "double",
          values = { [0] = L["Choose Method..."],
                     [1] = L["Individually"],
                     [2] = L["All at Once"], },
          get    = "GetActionEditMethod",
          set    = "SetActionEditMethod",
        },
        rowSelect = {
          name   = L["Row"],
          desc   = L["Rows are numbered top to bottom"],
          order  = 2,
          type   = "select",
          width  = "half",
          hidden = "IsButtonSelectHidden",
          values = "GetRowList",
          get    = "GetSelectedRow",
          set    = "SetSelectedRow",
        },
        colSelect = {
          name   = L["Col"],
          desc   = L["Columns are numbered left to right"],
          order  = 3,
          type   = "select",
          width  = "half",
          hidden = "IsButtonSelectHidden",
          values = "GetColumnList",
          get    = "GetSelectedColumn",
          set    = "SetSelectedColumn",
        },
        pageSelect = {
          name   = L["Page"],
          order  = 4,
          type   = "select",
          width  = "half",
          hidden = "IsPageSelectHidden",
          values = "GetPageList",
          get    = "GetSelectedPage",
          set    = "SetSelectedPage",
        },
        single = {
          name   = L["Action ID"],
          usage  = L["Specify ID 1-120"],
          order  = 5,
          type   = "input",
          width  = "half",
          hidden = "IsButtonSelectHidden",
          get    = "GetActionID",
          set    = "SetActionID",
          validate = "ValidateActionID",
        },
        multi = {
          name   = L["ID List"],
          usage  = L["Specify a comma-separated list of IDs for each button in the bar (in order). Separate multiple pages with semicolons (;)"],
          order  = 6,
          type   = "input",
          multiline = true,
          width  = "double",
          hidden = "IsMultiIDHidden",
          get    = "GetMultiID",
          set    = "SetMultiID",
          validate = "ValidateMultiID",
        },
      },
    },
  }

  local meta = { __index = Handle }

  function Handle:New( bar )
    local config = bar:GetConfig()
    local self = setmetatable(
      {
        bar = bar,
        config = config,
        btns = { }
      }, 
      meta)
    
    if self.config.buttons == nil then
      self.config.buttons = { }
    end
    self:Refresh()
    return self
  end

  function Handle:Refresh()
    local r, c = self.bar:GetButtonGrid()
    local n = r*c
    local btnCfg = self.config.buttons
    if n ~= #self.btns then
      for i = 1, n do
        if btnCfg[i] == nil then
          btnCfg[i] = {}
        end
        if self.btns[i] == nil then
          local lastButton = self:GetLastButton()
          local hint = lastButton and lastButton.config.actionID
          local b = Button:New(i, self.config, self.bar, hint)
          self.btns[i] = b
          self.bar:AddButton(i,b)
        end
      end
      for i = n+1, #self.btns do
        if self.btns[i] then
          self.bar:RemoveButton(self.btns[i])
          self.btns[i]:Destroy()
          self.btns[i] = nil
          btnCfg[i] = nil
        end
      end
    end
    for _, b in ipairs(self.btns) do
      b:Refresh()
    end
    Button.SetupBarHeader(self.bar,self.config)
    self:UpdateButtonLock()
  end

  function Handle:Destroy()
    for _,b in pairs(self.btns) do
      if b then
        b:Destroy()
      end
    end
  end

  function Handle:UpdateButtonLock()
    Button.SetButtonLock(self.bar, self.config.lockButtons, self.config.lockButtonsCombat)
  end

  function Handle:GetLastButton()
    return self.btns[#self.btns]
  end

    -- options handlers
  function Handle:GetOptions()
    return {
      type = "group",
      name = L["Action Buttons"],
      handler = self,
      args = options
    }
  end

  function Handle:SetHideEmpty(info, value)
    if value ~= self.config.hideEmpty then
      self.config.hideEmpty = value
      for _, b in pairs(self.btns) do
        b:ShowGrid(not value)
      end
    end
  end

  function Handle:GetHideEmpty()
    return self.config.hideEmpty
  end

  function Handle:GetLockButtons()
    return self.config.lockButtons
  end

  function Handle:SetLockButtons(info, value)
    self.config.lockButtons = value
    self:UpdateButtonLock()
  end

  function Handle:GetLockButtonsCombat()
    return self.config.lockButtonsCombat
  end

  function Handle:SetLockButtonsCombat(info, value)
    self.config.lockButtonsCombat = value
    self:UpdateButtonLock()
  end

  function Handle:LockButtonsCombatDisabled()
    return not self.config.lockButtons
  end

  function Handle:GetNumPages()
    return self.config.nPages
  end

  function Handle:SetNumPages(info, value)
    self.config.nPages = value
    self:Refresh()
  end

  function Handle:GetMindControl()
    return self.config.mindcontrol
  end

  function Handle:SetMindControl(info, value)
    self.config.mindcontrol = value
    self:Refresh()
  end

  function Handle:GetVehicle()
    return self.config.vehicle
  end

  function Handle:SetVehicle(info, value)
    self.config.vehicle = value
    self:Refresh()
  end

  function Handle:GetActionEditMethod()
    return self.editMethod or 0
  end

  function Handle:SetActionEditMethod(info, value)
    self.editMethod = value
  end

  function Handle:IsButtonSelectHidden()
    return self.editMethod ~= 1
  end

  function Handle:GetRowList()
    local r,c = self.bar:GetButtonGrid()
    if self.rowList == nil or #self.rowList ~= r then
      local list = { }
      for i = 1, r do
        table.insert(list,i)
      end
      self.rowList = list
    end
    return self.rowList
  end

  function Handle:GetSelectedRow()
    local r, c = self.bar:GetButtonGrid()
    local row = self.selectedRow or 1
    if row > r then
      row = 1
    end
    self.selectedRow = row
    return row
  end

  function Handle:SetSelectedRow(info, value)
    self.selectedRow = value
  end

  function Handle:GetColumnList()
    local r,c = self.bar:GetButtonGrid()
    if self.columnList == nil or #self.columnList ~= c then
      local list = { }
      for i = 1, c do
        table.insert(list,i)
      end
      self.columnList = list
    end
    return self.columnList
  end

  function Handle:GetSelectedColumn()
    local r, c = self.bar:GetButtonGrid()
    local col = self.selectedColumn or 1
    if col > c then
      col = 1
    end
    self.selectedColumn = col
    return col
  end

  function Handle:SetSelectedColumn(info, value)
    self.selectedColumn = value
  end

  function Handle:IsPageSelectHidden()
    return self.editMethod ~= 1 or (self.config.nPages or 1) < 2
  end

  function Handle:GetPageList()
    local n = self.config.nPages or 1
    if self.pageList == nil or #self.pageList ~= n then
      local p = { }
      for i = 1, n do
        table.insert(p,i)
      end
      self.pageList = p
    end
    return self.pageList
  end

  function Handle:GetSelectedPage()
    local p = self.selectedPage or 1
    if p > (self.config.nPages or 1) then
      p = 1
    end
    self.selectedPage = p
    return p
  end

  function Handle:SetSelectedPage(info, value)
    self.selectedPage = value
  end

  function Handle:GetActionID()
    local row = self.selectedRow or 1
    local col = self.selectedColumn or 1
    local r, c = self.bar:GetButtonGrid()
    local n = (row-1) * c + col
    local btn = self.btns[n]
    if btn then
      return tostring(btn:GetActionID(self.selectedPage or 1))
    end
  end

  function Handle:SetActionID(info, value)
    local row = self.selectedRow or 1
    local col = self.selectedColumn or 1
    local r, c = self.bar:GetButtonGrid()
    local n = (row-1) * c + col
    local btn = self.btns[n]
    if btn then
      btn:SetActionID(tonumber(value), self.selectedPage or 1)
    end
  end

  function Handle:ValidateActionID(info, value)
    value = tonumber(value)
    if value == nil or value < 1 or value > 120 then
      return L["Specify ID 1-120"]
    end
    return true
  end

  function Handle:IsMultiIDHidden()
    return self.editMethod ~= 2
  end

  function Handle:GetMultiID()
    local p = { }
    for i = 1, self.config.nPages or 1 do
      local b = { }
      for _, btn in ipairs(self.btns) do
        table.insert(b, btn:GetActionID(i))
      end
      table.insert(p, table.concat(b,","))
    end
    return table.concat(p,";\n")
  end


  local function ParseMultiID(nBtns, nPages, s)
    if s:match("[^%d%s,;]") then
      return nil
    end
    local p = { }
    for list in s:gmatch("[^;]+") do
      local pattern = ("^%s?$"):format(("%s*(%d+)%s*,"):rep(nBtns))
      local ids = { list:match(pattern) }
      if #ids ~= nBtns then
        return nil
      end
      table.insert(p,ids)
    end
    if #p ~= nPages then
      return nil
    end
    return p
  end

  function Handle:SetMultiID(info, value)
    local p = ParseMultiID(#self.btns, self.config.nPages or 1, value)
    for page, b in ipairs(p) do
      for button, id in ipairs(b) do
        self.btns[button]:SetActionID(id, page)
      end
    end
  end

  function Handle:ValidateMultiID(info, value)
    local bad = L["Invalid action ID list string"]
    if value == nil or ParseMultiID(#self.btns, self.config.nPages or 1, value) == nil then
      return bad
    end
    return true
  end
end


------ State property options ------
do
  local pageOptions = {
    page = {
      name     = L["Show Page #"],
      order    = 11,
      type     = "select",
      width    = "half",
      disabled = "IsPageDisabled",
      hidden   = "IsPageHidden",
      values   = "GetPageValues",
      set      = "SetProp",
      get      = "GetPage",
    },
  }

  function PropHandler.GetOptions()
    return pageOptions
  end

  function PropHandler:IsPageDisabled()
    local c = self.bar:GetConfig()
    local n = c and c.nPages or 1
    return not (n > 1)
  end

  function PropHandler:IsPageHidden()
    return not self.bar:GetConfig()
  end

  function PropHandler:GetPageValues()
    if not self._pagevalues then
      self._pagevalues = { }
    end
    local c = self.bar:GetConfig()
    if c then
      local n = c.nPages
        -- cache the results
      if self._npages ~= n then
        self._npages = n
        wipe(self._pagevalues)
        for i = 1, n do
          self._pagevalues["page"..i] = i
        end
      end
    end
    return self._pagevalues
  end

  function PropHandler:GetPage(info)
    return self:GetProp(info) or 1
  end

end