diff modules/ReAction_Action/ReAction_Action.lua @ 77:da8ba8783924

- added revision updater to each code file - Changed button/bar class mechanic to metatable-based - Changed buttons to live within a sub-frame, to play nicely between show-empty-buttons and hidestates - bar frame is now available only via accessor - Changed some semantics with AddButton/PlaceButton - Cleaned up action buttons options, fixed hide-when-empty option - moved show-action-ID-label as a button method - converted drag overlay from nested-frame to :Raise() - fixed ReAction:SetConfigMode() to not call event when mode doesn't change - Fixed ordering for dynamic state tab (always last)
author Flick <flickerstreak@gmail.com>
date Mon, 23 Jun 2008 22:27:50 +0000
parents 06cd74bdc7da
children 502cdb5666e2
line wrap: on
line diff
--- a/modules/ReAction_Action/ReAction_Action.lua	Thu Jun 19 17:48:57 2008 +0000
+++ b/modules/ReAction_Action/ReAction_Action.lua	Mon Jun 23 22:27:50 2008 +0000
@@ -2,8 +2,10 @@
   ReAction Action button module.
 
   The button module implements standard action button functionality by wrapping Blizzard's 
-  ActionButton frame and associated functions. It also provides some button layout
-  modification tools.
+  ActionButton frame and associated functions.
+
+  It also provides support for multiple pages (interacting with the State module) as well
+  as optional action remapping for possessed targets (mind control).
 
 --]]
 
@@ -13,15 +15,16 @@
 local _G = _G
 local CreateFrame = CreateFrame
 
+ReAction:UpdateRevision("$Revision: 103 $")
+
 -- module declaration
 local moduleID = "Action"
 local module = ReAction:NewModule( moduleID )
 
+-- Button class declaration
+local Button = { }
+
 -- private --
-local function GetBarConfig(bar)
-  return module.db.profile.bars[bar:GetName()]
-end
-
 local function RefreshLite(bar)
   local btns = module.buttons[bar]
   if btns then
@@ -31,8 +34,7 @@
   end
 end
 
-
--- module methods
+-- Event handlers
 function module:OnInitialize()
   self.db = ReAction.db:RegisterNamespace( moduleID,
     { 
@@ -44,21 +46,6 @@
   )
   self.buttons = { }
 
-  ReAction:RegisterOptions(self, {
-      [moduleID] = {
-        type = "group",
-        name = L["Action Bars"],
-        args = {
-          hideEmpty = {
-            type = "toggle",
-            name = L["Hide Empty Buttons"],
-            get  = function() return self.db.profile.hideEmptyButtons end,
-            set  = function(info, val) module:SetHideEmptyButtons(val) end,
-          }
-        }
-      }
-    })
-
   ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
 
   ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar")
@@ -108,11 +95,9 @@
         btnCfg[i] = {}
       end
       if btns[i] == nil then
-        local ok, b = pcall(self.BtnClass.New, self.BtnClass, bar, i, btnCfg[i], barCfg)
-        if ok and b then
-          btns[i] = b
-          bar:AddButton(i,b)
-        end
+        local b = Button:New(bar, i, btnCfg[i], barCfg)
+        btns[i] = b
+        bar:AddButton(i,b)
       end
     end
     for i = n+1, #btns do
@@ -153,77 +138,71 @@
   b[newname], b[oldname] = b[oldname], nil
 end
 
-function module:SetHideEmptyButtons(hide)
-  if hide ~= self.db.profile.hideEmptyButtons then
-    for _, bar in pairs(self.buttons) do
-      for _, b in pairs(bar) do
-        if hide then
-          ActionButton_HideGrid(b.frame)
-        else
-          ActionButton_ShowGrid(b.frame)
-        end
-      end
-    end
-    self.db.profile.hideEmptyButtons = hide
-  end
-end
-
 function module:OnConfigModeChanged(event, mode)
-  for _, bar in ReAction:IterateBars() do
-    if bar and self.buttons[bar] then
-      for _, b in pairs(self.buttons[bar]) do
-        if b then
-          if mode then
-            ActionButton_ShowGrid(b.frame)
-            self:showActionIDLabel(b)
-          else
-            ActionButton_HideGrid(b.frame)
-            self:hideActionIDLabel(b)
-          end
-        end
-      end
+  for _, bar in pairs(self.buttons) do
+    for _, b in pairs(bar) do
+      b:ShowGrid(mode)
+      b:ShowActionIDLabel(mode)
     end
   end
 end
 
-function module:showActionIDLabel(button)
-  if not button.actionIDLabel and button:GetActionID() then
-    local f = button:GetFrame()
-    local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-    label:SetAllPoints()
-    label:SetJustifyH("CENTER")
-    label:SetShadowColor(0,0,0,1)
-    label:SetShadowOffset(2,-2)
-    label:SetText(tostring(button:GetActionID()))
-    button.actionIDLabel = label
-    f:HookScript("OnAttributeChanged", 
-      function(frame, attr, value)
-        if attr == "state-parent" then
-          label:SetText(tostring(button:GetActionID()))
-        end
-      end)
-  end
-  button.actionIDLabel:Show()
-end
-
-function module:hideActionIDLabel(button)
-  if button.actionIDLabel then
-    button.actionIDLabel:Hide()
-  end
-end
-
 
 ---- Options ----
+local Handler = { }
+
+local options = {
+  hideEmpty = {
+    name = L["Hide Empty Buttons"],
+    desc = L["Hide buttons when empty. This option is not supported for multi-state bars"],
+    order = 1,
+    type = "toggle",
+    get  = "GetHideEmpty",
+    set  = "SetHideEmpty",
+  },
+}
+
 function module:GetBarOptions(bar)
   return {
     type = "group",
     name = L["Action Buttons"],
-    hidden = function() return bar.config.type ~= moduleID end,
-    args = {
-    }
+    handler = Handler:New(bar),
+    hidden = "Hidden",
+    args = options
   }
 end
 
+-- options handler private
+do
+  local function GetBarConfig( bar )
+    return module.db.profile.bars[bar:GetName()]
+  end
+
+  function Handler:New(bar)
+    return setmetatable( { bar = bar }, { __index = Handler } )
+  end
+
+  function Handler:Hidden()
+    return self.bar.config.type ~= moduleID
+  end
+
+  function Handler:SetHideEmpty(info, value)
+    local c = GetBarConfig(self.bar)
+    if value ~= c.hideEmpty then
+      for b in self.bar:IterateButtons() do
+        b:ShowGrid(not value)
+      end
+      c.hideEmpty = value
+    end
+  end
+
+  function Handler:GetHideEmpty()
+    return GetBarConfig(self.bar).hideEmpty
+  end
+end
+
+
+------ Button class ------
 
 -- use-count of action IDs
 local nActionIDs = 120
@@ -256,25 +235,17 @@
   end
 })
 
-
-
-
------- Button class ------
-local Button = { }
-
-local function Constructor( self, bar, idx, config, barConfig )
+function Button:New( bar, idx, config, barConfig )
+  -- create new self
+  self = setmetatable( { }, {__index = Button} )
   self.bar, self.idx, self.config, self.barConfig = bar, idx, config, barConfig
 
-  local barFrame = bar:GetFrame()
-
   config.name = config.name or ("ReAction_%s_%d"):format(bar:GetName(),idx)
   self.name = config.name
   config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured
   self.nPages = 1
   
-  local f = CreateFrame("CheckButton", self.name, barFrame, "ActionBarButtonTemplate")
-
-  -- TODO: re-implement ActionButton event handlers that don't do secure stuff
+  local f = CreateFrame("CheckButton", self.name, bar:GetButtonFrame(), "ActionBarButtonTemplate")
 
   -- this will probably cause taint and/or performance problems, using right now for display/debugging purposes
   f:SetScript("OnAttributeChanged", ActionButton_UpdateAction)
@@ -285,19 +256,20 @@
     f:SetAttribute("action-mc", 120 + self.idx)
   end
 
-  barFrame:SetAttribute("addchild",f)
+  self.frame = f
+  self.normalTexture = getglobal(format("%sNormalTexture",f:GetName()))
 
-  self.frame = f
-  self:Refresh()
-
-  if not module.db.profile.hideEmptyButtons then
-    ActionButton_ShowGrid(self.frame)
+  -- initialize the hide state
+  self:ShowGrid(not barConfig.hideEmpty)
+  if ReAction:GetConfigMode() then
+    self:ShowGrid(true)
   end
 
-  if ReAction.configMode then
-    ActionButton_ShowGrid(self.frame)
-    module:showActionIDLabel(self)
-  end
+  -- show the ID label if applicable
+  self:ShowActionIDLabel(ReAction:GetConfigMode())
+
+  self:Refresh()
+  return self
 end
 
 function Button:Destroy()
@@ -367,14 +339,52 @@
   end
 end
 
--- export as a class-factory to module
-module.BtnClass = {
-  New = function(self, ...)
-    local x = { }
-    for k,v in pairs(Button) do
-      x[k] = v
+function Button:ShowGrid( show )
+  if not InCombatLockdown() then
+    -- new in 2.4.1: can't call ActionButton_ShowGrid/HideGrid because they won't update the attribute
+    local f = self.frame
+    local count = f:GetAttribute("showgrid")
+    if show then
+      count = count + 1
+    else
+      count = count - 1
     end
-    Constructor(x, ...)
-    return x
+    if count < 0 then
+      count = 0
+    end
+    f:SetAttribute("showgrid",count)
+
+    if count >= 1 and not f:GetAttribute("statehidden") then
+      self.normalTexture:SetVertexColor(1.0, 1.0, 1.0, 0.5);
+      f:Show()
+    elseif count < 1 and not HasAction(self:GetActionID()) then
+      f:Hide()
+    end
   end
-}
+end
+
+function Button:ShowActionIDLabel( show )
+  if show then
+    local id = self:GetActionID()
+    if not self.actionIDLabel and id and id ~= 0 then
+      local f = self:GetFrame()
+      local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+      label:SetAllPoints()
+      label:SetJustifyH("CENTER")
+      label:SetShadowColor(0,0,0,1)
+      label:SetShadowOffset(2,-2)
+      label:SetText(tostring(id))
+      self.actionIDLabel = label
+      f:HookScript("OnAttributeChanged", 
+        function(frame, attr, value)
+          if attr == "state-parent" then
+            label:SetText(tostring(self:GetActionID()))
+          end
+        end)
+    end
+    self.actionIDLabel:Show()
+  elseif self.actionIDLabel then
+    self.actionIDLabel:Hide()
+  end
+end
+