diff modules/State.lua @ 155:806a61b331a0

Pushed the state implementation into Bar
author Flick <flickerstreak@gmail.com>
date Fri, 15 May 2009 22:38:19 +0000
parents 42cade25d40d
children e77f716af1b7
line wrap: on
line diff
--- a/modules/State.lua	Fri May 08 17:30:22 2009 +0000
+++ b/modules/State.lua	Fri May 15 22:38:19 2009 +0000
@@ -53,24 +53,8 @@
   return r
 end
 
--- set a frame-ref, if the frame is valid, or set nil to the
--- corresponding attribute
-local function SetFrameRef(frame, name, refFrame)
-  if refFrame then
-    local _, explicit = refFrame:IsProtected()
-    if not explicit then
-      refFrame = nil
-    end
-  end
-  if refFrame then
-    frame:SetFrameRef(name,refFrame)
-  else
-    frame:SetAttribute("frameref-"..name,nil)
-  end
-end
 
-
-local InitRules, ApplyStates, CleanupStates, SetProperty, GetProperty, RegisterProperty, ShowAll
+local InitRules, ApplyStates, CleanupStates, SetProperty, GetProperty, RegisterProperty
 
 -- PRIVATE --
 do
@@ -78,250 +62,20 @@
   -- the field names must match the field names of the options table, below
   -- the field values are secure snippets or 'true' to skip the snippet for that property.
   local properties = { 
-    hide = 
-      [[
-        local h = hide and hide[state] and not showAll
-        if h ~= hidden then
-          if h then
-            self:Hide()
-          else
-            self:Show()
-          end
-          hidden = h
-        end
-        if showAll then
-          control:CallMethod("UpdateHiddenLabel", hide and hide[state])
-        end
-      ]],
-
-    --keybindState  TODO: broken
-
-    anchorEnable = 
-      [[
-        local old_anchor = anchorstate
-        anchorstate = (anchorEnable and anchorEnable[state]) and state
-        if old_anchor ~= anchorstate or not set_state then
-          if anchorstate and anchorPoint then
-            if anchorPoint[state] then
-              self:ClearAllPoints()
-              local f = self:GetAttribute("frameref-anchor-"..anchorstate)
-              if f then
-                self:SetPoint(anchorPoint[state], f, anchorRelPoint[state], anchorX[state], anchorY[state])
-              end
-            end
-          elseif defaultAnchor and defaultAnchor.point then
-            self:ClearAllPoints()
-            self:SetPoint(defaultAnchor.point, defaultAnchor.frame, 
-                          defaultAnchor.relPoint, defaultAnchor.x, defaultAnchor.y)
-          end
-        end
-      ]],
-      -- anchorEnable handles all the other bits
+    hide = true,
+    --keybindState = true, TODO: broken
+    anchorEnable = true,
     anchorFrame = true,
     anchorPoint = true,
     anchorRelPoint = true,
     anchorX = true,
     anchorY = true,
-
-
-    enableScale = 
-      [[
-        local old_scale = scalestate
-        scalestate = (enableScale and enableScale[state]) and state
-        if old_scale ~= scalestate or not set_state then
-          if scalestate and scale then
-            if scale[state] then
-              self:SetScale(scale[state])
-            end
-          else
-            self:SetScale(1.0)
-          end
-        end
-      ]],
-      -- enableScale handles scale
+    enableScale = true,
     scale = true,
-
-    enableAlpha = 
-      [[
-        local old_alpha = alphastate
-        alphastate = (enableAlpha and enableAlpha[state]) and state
-        if old_alpha ~= alphastate or not set_state then
-          control:CallMethod("UpdateAlpha", alphastate and alpha[state] or defaultAlpha)
-        end
-      ]],
-      -- enableAlpha handles alpha
+    enableAlpha = true,
     alpha = true,
   }
 
-  local weak         = { __mode = "k" }
-  local statedrivers = setmetatable( { }, weak )
-  local keybinds     = setmetatable( { }, weak )
-
-  --
-  -- Secure Handler Snippets
-  --
-  local SetHandlerData, SetStateDriver, SetStateKeybind, RefreshState
-  do
-    local stateHandler_propInit = 
-    [[
-      propfuncs = table.new()
-      local proplist = self:GetAttribute("prop-func-list")
-      for s in string.gmatch(proplist, "(%w+)") do
-        table.insert(propfuncs, s)
-      end
-    ]]
-
-    local onStateHandler = 
-    -- function _onstate-reaction( self, stateid, newstate )
-    [[
-      set_state = newstate
-
-      local oldState = state
-      state = state_override or set_state or state
-      for i = 1, #propfuncs do
-        control:RunAttribute("func-"..propfuncs[i])
-      end
-      
-      control:ChildUpdate()
-
-      if oldState ~= state then
-        control:CallMethod("StateRefresh", state)
-      end
-    ]]
-
-    local onClickHandler = 
-    -- function OnClick( self, button, down )
-    [[
-      if state_override == button then
-        state_override = nil -- toggle
-      else
-        state_override = button
-      end
-    ]] .. onStateHandler
-
-    local function UpdateAlpha( frame, alpha )
-      if alpha then
-        frame:SetAlpha(alpha)
-      end
-    end
-
-    -- Construct a lua assignment as a code string and execute it within the header
-    -- frame's sandbox. 'value' must be a string, boolean, number, or nil. If called
-    -- with four arguments, then it treats 'varname' as an existing global table and
-    -- sets a key-value pair. For a slight efficiency boost, pass the values in as
-    -- attributes and fetch them as attributes from the snippet code, to leverage snippet
-    -- caching.
-    function SetHandlerData( bar, varname, value, key )
-      local f = bar:GetFrame()
-      f:SetAttribute("data-varname",varname)
-      f:SetAttribute("data-value",  value)
-      f:SetAttribute("data-key",    key)
-      f:Execute(
-        [[
-          local name  = self:GetAttribute("data-varname")
-          local value = self:GetAttribute("data-value")
-          local key   = self:GetAttribute("data-key")
-          if name then
-            if key then
-              if not _G[name] then
-                _G[name] = table.new()
-              end
-              _G[name][key] = value
-            else
-              _G[name] = value
-            end
-          end
-        ]])
-    end
-
-    function SetDefaultAnchor( bar )
-      local point, frame, relPoint, x, y = bar:GetAnchor()
-      SetHandlerData(bar, "defaultAnchor", point, "point")
-      SetHandlerData(bar, "defaultAnchor", relPoint, "relPoint")
-      SetHandlerData(bar, "defaultAnchor", x, "x")
-      SetHandlerData(bar, "defaultAnchor", y, "y")
-      SetHandlerData(bar, "defaultAlpha",  bar:GetAlpha())
-
-      local f = bar:GetFrame()
-      f.UpdateAlpha = UpdateAlpha
-      SetFrameRef(f, "defaultAnchor", _G[frame or "UIParent"])
-      f:Execute(
-        [[
-          defaultAnchor.frame = self:GetAttribute("frameref-defaultAnchor")
-        ]])
-    end
-
-    function RefreshState( bar )
-      SetDefaultAnchor(bar)
-      bar:GetFrame():Execute(
-        [[
-          if self:GetAttribute("reaction-refresh") then
-            control:RunAttribute("reaction-refresh")
-          end
-        ]])
-    end
-
-    function SetStateDriver( bar, rule )
-      local f = bar:GetFrame()
-
-      if not f.UpdateHiddenLabel then
-        function f:UpdateHiddenLabel(hide)
-          bar:SetLabelSubtext( hide and L["Hidden"] )
-        end
-      end
-
-      function f:StateRefresh( state )
-        bar:RefreshControls()
-      end
-
-      local props = { }
-      for p, h in pairs(properties) do
-        if type(h) == "string" then
-          table.insert(props,p)
-          f:SetAttribute("func-"..p, h)
-        end
-      end
-      f:SetAttribute("prop-func-list", table.concat(props," "))
-      f:Execute(stateHandler_propInit)
-      f:SetAttribute("reaction-refresh", onStateHandler)
-      
-      if rule and #rule > 0 then
-        f:SetAttribute( "_onstate-reaction", onStateHandler )
-        RegisterStateDriver(f, "reaction", rule)
-        statedrivers[bar] = rule
-      elseif statedrivers[bar] then
-        UnregisterStateDriver(f, "reaction")
-        f:SetAttribute( "_onstate-reaction", nil )
-        statedrivers[bar] = nil
-      end
-    end
-
-    function SetStateKeybind( bar, key, state )
-      local f = bar:GetFrame()
-
-      local kb = keybinds[bar]
-      if kb == nil then
-        if key == nil then
-          -- nothing to do
-          return
-        end
-        kb = { }
-        keybinds[bar] = kb
-      end
-
-      -- clear the old binding, if any
-      if kb[state] then
-        SetOverrideBinding(f, false, kb[state], nil)
-      end
-      kb[state] = key
-
-      if key then
-        f:SetAttribute("_onclick", onClickHandler)
-        SetOverrideBindingClick(f, false, key, state, nil) -- state name is the virtual mouse button
-      end
-    end
-  end
-
   local playerClass = select(2, UnitClass("player"))
   local function ClassFilter(...)
     for i = 1, select('#',...) do
@@ -345,7 +99,7 @@
     berserker     = { format = "stance:3",       filter = ClassFilter("WARRIOR") },
     caster        = { format = "form:0/2/4/5/6", filter = ClassFilter("DRUID") },
     bear          = { format = "form:1",         filter = ClassFilter("DRUID") },
-    cat           = { format = "form:1",         filter = ClassFilter("DRUID") },
+    cat           = { format = "form:3",         filter = ClassFilter("DRUID") },
     tree          = { format = "form:5",         filter = ClassFilter("DRUID") },
     moonkin       = { format = "form:5",         filter = ClassFilter("DRUID") },
     pet           = { format = "pet" },
@@ -365,35 +119,25 @@
     vehicle       = { format = "target=vehicle,exists,bonusbar:5" },
   }
 
-  -- Have to do these shenanigans instead of hardcoding the stances/forms because the 
-  -- ordering varies if the character is missing a form. For warriors this is rarely
-  -- a problem (c'mon, who actually skips the level 10 def stance quest?) but for druids
-  -- it can be. Some people never bother to do the aquatic form quest until well past
-  -- when they get cat form, and stance 5/6 can be flight, tree, or moonkin depending
-  -- on talents.
+  -- Determine the stance #'s programmatically: they can vary if for some reason the
+  -- player is missing a stance/form (due to not training it). Also moonkin/flight/tree form
+  -- can be stance 5 or 6, depending.
   function InitRules()
     local forms = { }
-      -- sort by icon since it's locale-independent
     for i = 1, GetNumShapeshiftForms() do
-      local icon, name, active = GetShapeshiftFormInfo(i)
-      -- if it's the current form, the icon is wrong (Spell_Nature_WispSplode)
-      -- so capture it from the spell info directly
-      if active then
-        local _1, _2
-        _1, _2, icon = GetSpellInfo(name)
-      end
-      forms[icon] = i;
+      local _, name = GetShapeshiftFormInfo(i)
+      forms[name] = i;
     end
       -- use 9 if not found since 9 is never a valid stance/form
-    local defensive = forms["Interface\\Icons\\Ability_Warrior_DefensiveStance"] or 9
-    local berserker = forms["Interface\\Icons\\Ability_Racial_Avatar"] or 9
-    local bear      = forms["Interface\\Icons\\Ability_Racial_BearForm"] or 9 -- bear and dire bear share the same icon
-    local aquatic   = forms["Interface\\Icons\\Ability_Druid_AquaticForm"] or 9
-    local cat       = forms["Interface\\Icons\\Ability_Druid_CatForm"] or 9
-    local travel    = forms["Interface\\Icons\\Ability_Druid_TravelForm"] or 9
-    local tree      = forms["Interface\\Icons\\Ability_Druid_TreeofLife"] or 9
-    local moonkin   = forms["Interface\\Icons\\Spell_Nature_ForceOfNature"] or 9
-    local flight    = forms["Interface\\Icons\\Ability_Druid_FlightForm"] or 9 -- flight and swift flight share the same icon
+    local defensive = forms[GetSpellInfo(71)] or 9
+    local berserker = forms[GetSpellInfo(2458)] or 9
+    local bear      = forms[GetSpellInfo(9634)] or forms[GetSpellInfo(5487)] or 9
+    local aquatic   = forms[GetSpellInfo(1066)] or 9
+    local cat       = forms[GetSpellInfo(768)] or 9
+    local travel    = forms[GetSpellInfo(783)] or 9
+    local tree      = forms[GetSpellInfo(33891)] or 9
+    local moonkin   = forms[GetSpellInfo(24858)] or 9
+    local flight    = forms[GetSpellInfo(40120)] or forms[GetSpellInfo(33943)] or 9
 
     ruleformats.defensive.format = format("stance:%d",defensive)
     ruleformats.berserker.format = format("stance:%d",berserker)
@@ -445,9 +189,9 @@
       local type = tfetch(state, "rule", "type")
       if type == "keybind" then
         local key = tfetch(state, "rule", "keybind")
-        SetStateKeybind(bar, key, name)
+        bar:SetStateKeybind(key, name)
       else
-        SetStateKeybind(bar, nil, name) -- this clears an existing keybind
+        bar:SetStateKeybind(nil, name) -- this clears an existing keybind
       end
     end
   end
@@ -459,20 +203,21 @@
   function SetProperty( bar, state, propname, value )
     local s = tbuild(module.db.profile.bars, bar:GetName(), "states", state)
     s[propname] = value
-    SetHandlerData(bar, propname, value, state)
-    RefreshState(bar)
+    bar:SetSecureStateData(state, propname, value)
   end
 
   function RegisterProperty( propname, snippet )
-    properties[propname] = snippet or true
+    properties[propname] = true
     for _, bar in ReAction:IterateBars() do
       local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
       if states then
         for name, s in pairs(states) do
-          SetHandlerData(bar, propname, s[propname], name)
+          bar:SetSecureStateData(name, propname, s[propname])
         end
-        SetStateDriver(bar, BuildRule(states))
-        RefreshState(bar)
+        bar:SetStateDriver(BuildRule(states))
+      end
+      if type(snippet) == "string" then
+        bar:SetSecureStateExtension(propname,snippet)
       end
     end
   end
@@ -480,9 +225,14 @@
   function UnregisterProperty( propname )
     properties[propname] = nil
     for _, bar in ReAction:IterateBars() do
-      SetHandlerData(bar, propname, nil)
-      SetStateDriver(bar, BuildRule(states))
-      RefreshState(bar)
+      local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
+      if states then
+        for name, s in pairs(states) do
+          bar:SetSecureStateData(name, propname, nil)
+        end
+      end
+      bar:SetStateDriver(BuildRule(states))
+      bar:SetSecureStateExtension(propname,nil)
     end
   end
 
@@ -492,28 +242,19 @@
       for propname in pairs(properties) do
         for name, s in pairs(states) do
           if propname == "anchorFrame" then
-            SetFrameRef(bar:GetFrame(), "anchor-"..name, _G[s.anchorFrame])
+            bar:SetFrameRef("anchor-"..name, _G[s.anchorFrame])
           else
-            SetHandlerData(bar, propname, s[propname], name)
+            bar:SetSecureStateData(name, propname, s[propname])
           end
         end
       end
       BuildKeybinds(bar, states)
-      SetHandlerData(bar, "showAll", ReAction:GetConfigMode())
-      SetStateDriver(bar, BuildRule(states))
-      RefreshState(bar)
+      bar:SetStateDriver(BuildRule(states))
     end
   end
 
   function CleanupStates( bar )
-    SetStateDriver(bar, nil)
-  end
-
-  function ShowAll( bar, show )
-    if statedrivers[bar] then
-      SetHandlerData(bar, "showAll", show)
-      RefreshState(bar)
-    end
+    bar:SetStateDriver(nil)
   end
 end
 
@@ -539,7 +280,6 @@
   ReAction.RegisterCallback(self, "OnRefreshBar")
   ReAction.RegisterCallback(self, "OnEraseBar")
   ReAction.RegisterCallback(self, "OnRenameBar")
-  ReAction.RegisterCallback(self, "OnConfigModeChanged")
 end
 
 function module:OnEnable()
@@ -551,8 +291,8 @@
   -- This happens both at initial login (after PLAYER_ENTERING_WORLD)
   -- as well as when gaining new abilities. 
   InitRules()
-  for name, bar in ReAction:IterateBars() do
-    self:OnRefreshBar(nil,bar,name)
+  for _, bar in ReAction:IterateBars() do
+    ApplyStates(bar)
   end
 end
 
@@ -576,14 +316,6 @@
   bars[newname], bars[oldname] = bars[oldname], nil
 end
 
-function module:OnConfigModeChanged(event, mode)
-  for name, bar in ReAction:IterateBars() do
-    if self.db.profile.bars[name] then
-      ShowAll(bar, mode)
-    end
-  end
-end
-
 
 
 -- Options --
@@ -1123,7 +855,7 @@
   function StateHandler:SetAnchorFrame(info, value)
     local f = _G[self._anchorframes[value]]
     if f then
-      SetFrameRef(self.bar:GetFrame(), "anchor-"..self:GetName(), f)
+      bar:SetFrameRef("anchor-"..self:GetName(), f)
       self:SetProp(info, f:GetName())
     end
   end
@@ -1341,10 +1073,5 @@
 
 -- Export methods to Bar class --
 
-function ReAction.Bar:GetState()
-  local env = GetManagedEnvironment(self:GetFrame())
-  return env and env.state
-end
-
 ReAction.Bar.GetStateProperty = GetProperty
 ReAction.Bar.SetStateProperty = SetProperty