changeset 245:65f2805957a0

No real reason to store some of the code in a subdirectory.
author Flick
date Sat, 26 Mar 2011 12:35:08 -0700
parents f255cd69e890
children 47818b3938c9
files ActionButton.lua BagButton.lua Bar.lua Button.lua MultiCastButton.lua Overlay.lua PetActionButton.lua ReAction.xml StanceButton.lua VehicleExitButton.lua classes/ActionButton.lua classes/BagButton.lua classes/Bar.lua classes/Button.lua classes/MultiCastButton.lua classes/Overlay.lua classes/PetActionButton.lua classes/StanceButton.lua classes/VehicleExitButton.lua classes/classes.xml
diffstat 20 files changed, 4690 insertions(+), 4646 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ActionButton.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,806 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local IsUsableAction = IsUsableAction
+local IsEquippedAction = IsEquippedAction
+local IsConsumableAction = IsConsumableAction
+local IsStackableAction = IsStackableAction
+local GetActionText = GetActionText
+local GetCVar = GetCVar
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+local IsCurrentAction = IsCurrentAction
+local IsAutoRepeatAction = IsAutoRepeatAction
+local IsUsableAction = IsUsableAction
+local IsAttackAction = IsAttackAction
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local GetActionCooldown = GetActionCooldown
+local GetActionTexture = GetActionTexture
+local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME
+local TOOLTIP_UPDATE_TIME = TOOLTIP_UPDATE_TIME
+local IsActionInRange = IsActionInRange
+local InCombatLockdown = InCombatLockdown
+local HasAction = HasAction
+
+--
+-- Secure snippets
+-- These are run within the context of the bar's sandbox, as the
+-- buttons themselves do not have their own sandbox.
+--
+local _onstate_mc = -- function(self, stateid, newstate)
+[[
+  local oldMcVehicleState = mcVehicleState
+  mcVehicleState = newstate
+  control:ChildUpdate()
+  if oldMcVehicleState == "vehicle" or mcVehicleState == "vehicle" then
+    control:ChildUpdate("vehicle")
+  end
+]]
+
+local _childupdate = -- function(self, snippetid, message)
+[[
+  local action = nil
+  if (doVehicle and mcVehicleState == "vehicle") or
+     (doMindControl and mcVehicleState == "mc") then
+    local idx = self:GetAttribute("bar-idx")
+    local maxN = (doVehicle and mcVehicleState == "vehicle") and 7 or 12
+    if idx and idx <= maxN then
+      action = 120 + idx
+    else
+      action = 0
+    end
+  elseif state and settings[state] and settings[state].page then
+    action = self:GetAttribute("action-"..settings[state].page) 
+  end
+  if action == nil then
+    action = self:GetAttribute("default-action")
+  end
+
+  self:SetAttribute("action",action)
+
+  if not self:GetAttribute("showgrid") then
+    local tempShow = self:GetAttribute("showgrid-temp")
+    local evtShow = self:GetAttribute("showgrid-event")
+    if tempShow then tempShow = (tempShow > 0) end
+    if evtShow then evtShow = (evtShow > 0) end
+
+    if tempShow or evtShow or HasAction(action) then
+      self:Show()
+    else
+      self:Hide()
+    end
+  end
+]]
+
+local _childupdate_vehicleExit =  -- function(self, snippetid, message)
+[[
+  local show = (mcVehicleState == "vehicle")
+  if show and doVehicle then
+    self:SetAttribute("type","macro")
+    self:Show()
+  else
+    self:SetAttribute("type","action")
+  end
+  control:CallMethod("ShowVehicleExit",show)
+]]
+
+local _childupdate_showgrid = -- function(self, snippetid, message)
+[[
+  showgrid_event = message
+  self:SetAttribute("showgrid-event",message)
+  if not self:GetAttribute("showgrid") then
+    local count = message + (self:GetAttribute("showgrid-temp") or 0)
+    if count <= 0 then
+      local action = self:GetAttribute("action")
+        -- note that HasAction is not updated on the target of a drag until after ACTIONBAR_HIDEGRID
+        -- so, we set a flag for this button in pre-click/receive-drag and check for it here
+      if HasAction(action) or self:GetAttribute("showgrid-clicked") then
+        if not self:IsShown() then
+          self:Show()
+        end
+        self:SetAttribute("showgrid-clicked",false)
+      else 
+        if self:IsShown() then
+          self:Hide()
+        end
+      end
+    else
+      self:Show()
+    end
+  end
+]]
+
+local _onDragStart = -- function(self, button, kind, value, ...)
+[[
+  if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
+    return kind, value, ...
+  else
+    return "action", self:GetAttribute("action")
+  end
+]]
+
+local _onReceiveDrag = -- function(self, button, kind, value, ...)
+[[
+  if kind ~= "spell" and kind ~= "item" and kind ~= "macro" and kind ~= "flyout" then
+    return kind, value, ...
+  else
+    if showgrid_event and showgrid_event > 0 then
+      self:SetAttribute("showgrid-clicked",true)
+    end
+    return "action", self:GetAttribute("action")
+  end
+]]
+
+local _onClick = -- function(self, button, down)
+[[
+  if showgrid_event and showgrid_event > 0 then
+    self:SetAttribute("showgrid-clicked",true)
+  end
+  return button
+]]
+
+--
+-- private
+--
+local eventList = {
+  "PLAYER_ENTERING_WORLD",
+  "ACTIONBAR_PAGE_CHANGED",
+  "ACTIONBAR_SLOT_CHANGED",
+  "UPDATE_BINDINGS",
+  "ACTIONBAR_UPDATE_STATE",
+  "ACTIONBAR_UPDATE_USABLE",
+  "ACTIONBAR_UPDATE_COOLDOWN",
+  "UNIT_INVENTORY_CHANGED",
+  "LEARNED_SPELL_IN_TAB",
+  "UPDATE_INVENTORY_ALERTS",
+  "PLAYER_TARGET_CHANGED",
+  "TRADE_SKILL_SHOW",
+  "TRADE_SKILL_CLOSE",
+  "PLAYER_ENTER_COMBAT",
+  "PLAYER_LEAVE_COMBAT",
+  "START_AUTOREPEAT_SPELL",
+  "STOP_AUTOREPEAT_SPELL",
+  "UNIT_ENTERED_VEHICLE",
+  "UNIT_EXITED_VEHICLE",
+  "COMPANION_UPDATE",
+}
+
+--
+-- Action Button class
+--
+local buttonTypeID = "Action"
+local Super = ReAction.Button
+local Action = setmetatable( 
+  { 
+    defaultBarConfig = { 
+      type = buttonTypeID,
+      btnWidth = 36,
+      btnHeight = 36,
+      btnRows = 1,
+      btnColumns = 12,
+      spacing = 3,
+      buttons = { },
+    },
+
+    barType = L["Action Bar"],
+    buttonTypeID = buttonTypeID
+  },
+  { __index = Super } )
+
+ReAction.Button.Action = Action
+ReAction:RegisterBarType(Action, true)
+
+function Action:New( config, bar, idx, idHint )
+  local name = format("ReAction_%s_Action_%d",bar:GetName(),idx)
+ 
+  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+  self.barConfig = bar:GetConfig()
+
+  local f = self:GetFrame()
+  local barFrame = bar:GetFrame()
+
+  self.rangeTimer = TOOLTIP_UPDATE_TIME
+
+  -- set up the base action ID
+  self:SetActionIDPool("action",120)
+  config.actionID = self:AcquireActionID(config.actionID, idHint)
+  self.nPages = 1
+
+  -- attribute setup
+  f:SetAttribute("type","action")
+  f:SetAttribute("checkselfcast", true)
+  f:SetAttribute("checkfocuscast", true)
+  f:SetAttribute("action", config.actionID)
+  f:SetAttribute("default-action", config.actionID)
+  f:SetAttribute("bar-idx",idx)
+  f:SetAttribute("showgrid-temp",0)
+  f:SetAttribute("showgrid-event",0)
+  f:SetAttribute("showgrid",not self:GetBarConfig().hideEmpty)
+
+  -- non secure scripts
+  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+  f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
+  f:SetScript("OnUpdate", function(frame, elapsed) self:OnUpdate(elapsed) end)
+  f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
+  f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForDrag("LeftButton", "RightButton")
+  f:RegisterForClicks("AnyUp")
+  for _, evt in pairs(eventList) do
+    f:RegisterEvent(evt)
+  end
+
+  f.action = config.actionID -- need this to support silly ActionButton_UpdateFlyout. Should not taint anything anymore.
+
+  -- secure handlers
+  f:SetAttribute("_childupdate", _childupdate)
+  f:SetAttribute("_childupdate-showgrid",_childupdate_showgrid)
+  barFrame:WrapScript(f, "OnDragStart", _onDragStart)
+  barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
+  barFrame:WrapScript(f, "OnClick", _onClick)
+
+  -- attach to skinner
+  bar:SkinButton(self)
+
+  -- initial display
+  if ReAction:GetConfigMode() then
+    self:ShowGridTemp(true)
+  end
+
+  self:Refresh()
+
+  return self
+end
+
+function Action:Destroy()
+  local f = self:GetFrame()
+  local c = self:GetConfig()
+
+  f:SetAttribute("_childupdate-vehicle",nil)
+  f:SetAttribute("action",c.actionID) -- so that Super.Destroy releases the right one
+
+  if c.pageactions and #c.pageactions > 1 then
+    for i = 2, #c.pageactions do 
+      self:ReleaseActionID(c.pageactions[i])
+      self:ReleaseActionID(id)
+    end
+  end
+  
+  Super.Destroy(self)
+end
+
+function Action:GetBarConfig()
+  -- this is the per-bar Action module config structure,
+  -- not the config structure of the bar itself
+  return self.barConfig
+end
+
+function Action:Refresh()
+  Super.Refresh(self)
+  self:RefreshPages()
+  self:InstallVehicle()
+  self:ShowGrid(not self:GetBarConfig().hideEmpty)
+  self:UpdateAction()
+end
+
+function Action:InstallVehicle()
+  local f = self:GetFrame()
+  if self.idx == 7 and self:GetBarConfig().vehicle then
+    if not self.vehicleInstalled then
+      self.vehicleInstalled = true
+      -- install vehicle-exit button on 7th button (only)
+      f:SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit)
+      f:SetAttribute("macrotext","/run VehicleExit()")
+      self:GetBar():GetFrame().ShowVehicleExit = function(bar,show)
+        self:ShowVehicleExit(show)
+      end
+    end
+    -- setscale blows away tex coords
+    self:UpdateIcon()
+  elseif self.vehicleInstalled then
+    self.vehicleInstalled = false
+    f:SetAttribute("_childupdate-vehicle",nil)
+    f:SetAttribute("macrotext",nil)
+  end
+end
+
+function Action:ShowGrid( show )
+  if not InCombatLockdown() then
+    self.frame:SetAttribute("showgrid", show)
+    self:UpdateShowGrid()
+  end
+end
+
+function Action:ShowGridTemp( show )
+  -- This function only modifies the show-grid when out
+  -- of combat, and is ignored by the secure handler. Use 
+  -- it for configuration modes.
+  if not InCombatLockdown() then
+    local count = self.showGridTempCount or 0
+    if show then
+      count = count + 1
+    else
+      count = count - 1
+    end
+    if count < 0 then count = 0 end
+    self.showGridTempCount = count
+    self:GetFrame():SetAttribute("showgrid-temp",count)
+    self:UpdateShowGrid()
+  end
+end
+
+function Action:UpdateAll()
+  self:UpdateActionIDLabel(ReAction:GetConfigMode())
+  self:UpdateHotkey()
+  self:UpdateShowGrid()
+  self:UpdateIcon()
+  self:UpdateBorder()
+  self:UpdateMacroText()
+  self:UpdateCount()
+  self:UpdateTooltip()
+  self:UpdateCheckedState()
+  self:UpdateUsable()
+  self:UpdateCooldown()
+  self:UpdateFlash()
+end
+
+function Action:UpdateAction()
+  local action = self:GetActionID()
+  if action ~= self.actionID then
+    self.actionID = action
+    self:UpdateAll()
+  end
+end
+
+function Action:UpdateShowGrid()
+  if not InCombatLockdown() then
+    local f = self:GetFrame()
+    local count = (f:GetAttribute("showgrid-event") or 0) +
+                  (self.showGridTempCount or 0) +
+                  (f:GetAttribute("showgrid") and 1 or 0)
+
+    if count <= 0 and not HasAction(self.actionID) then
+      if f:IsShown() then
+        f:Hide()
+      end
+    elseif not f:IsShown() then
+      f:Show()
+    end
+  end
+end
+
+function Action:UpdateIcon()
+  local texture, tLeft, tRight, tTop, tBottom = self:GetIconTexture()
+  local icon = self.frames.icon
+  local hotkey = self.frames.hotkey
+  local f = self:GetFrame()
+  
+  if self.vehicleExitMode then
+    texture = "Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up"
+    icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
+    icon:SetVertexColor(1,1,1)
+  else
+    icon:SetTexCoord(0,1,0,1)
+  end
+
+  if texture then
+    icon:SetTexture(texture)
+    if tLeft then
+      icon:SetTexCoord(tLeft,tRight,tTop,tBottom)
+    end
+    icon:Show()
+    self.rangeTimer = -1
+    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+  else
+    icon:Hide()
+    self.frames.cooldown:Hide()
+    self.rangeTimer = nil
+    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+  end
+end
+
+function Action:GetIconTexture()
+  return GetActionTexture(self.actionID)
+end
+
+function Action:UpdateBorder()
+  local action = self.actionID
+  if ReAction:GetKeybindMode() then
+    self:UpdateKeybindModeDisplay(true)
+  elseif IsEquippedAction(action) then
+    self.frames.border:SetVertexColor(0, 1.0, 0, 0.35)
+    self.frames.border:Show()
+  else
+    self.frames.border:Hide()
+  end
+end
+
+function Action:UpdateMacroText()
+  local action = self.actionID
+  if not IsConsumableAction(action) and not IsStackableAction(action) then
+    self.frames.name:SetText(GetActionText(action))
+  else
+    self.frames.name:SetText("")
+  end
+end
+
+function Action:UpdateCount()
+  local action = self.actionID
+  if IsConsumableAction(action) or IsStackableAction(action) then
+    self.frames.count:SetText(GetActionCount(action))
+  else
+    self.frames.count:SetText("")
+  end
+end
+
+function Action:UpdateTooltip()
+  local f = self:GetFrame()
+  if GameTooltip:GetOwner() == f then
+    self:SetTooltip()
+  end
+end
+
+function Action:SetTooltip()
+  local f = self:GetFrame()
+  if GetCVar("UberTooltips") == "1" then
+    GameTooltip_SetDefaultAnchor(GameTooltip, f)
+  else
+    GameTooltip:SetOwner(f,"ANCHOR_RIGHT")
+  end
+  GameTooltip:SetAction(self.actionID)
+end
+
+function Action:UpdateCheckedState()
+  local action = self.actionID
+  if IsCurrentAction(action) or IsAutoRepeatAction(action) then
+    self:GetFrame():SetChecked(1)
+  else
+    self:GetFrame():SetChecked(0)
+  end
+end
+
+function Action:UpdateUsable()
+  local isUsable, notEnoughMana = self:GetUsable()
+  local noRange = self:GetInRange()
+
+  isUsable = self.vehicleExitMode or (isUsable and not noRange)
+
+  if isUsable then
+    if self.usableStatus ~= "usable" then
+      self.frames.icon:SetVertexColor(1.0, 1.0, 1.0)
+      self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+      self.usableStatus = "usable"
+    end
+  elseif noRange then
+    if self.usableStatus ~= "norange" then
+      self.frames.icon:SetVertexColor(1.0,0.1,0.1)
+      self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+      self.usableStatus = "norange"
+    end
+  elseif notEnoughMana then
+    if self.usableStatus ~= "oom" then
+      self.frames.icon:SetVertexColor(0.5, 0.5, 1.0)
+      self.frames.normalTexture:SetVertexColor(0.5, 0.5, 1.0)
+      self.usableStatus = "oom"
+    end
+  else
+    if self.usableStatus ~= "unusable" then
+      self.frames.icon:SetVertexColor(0.4, 0.4, 0.4)
+      self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+      self.usableStatus = "unusable"
+    end
+  end
+end
+
+function Action:GetUsable()
+  return IsUsableAction(self.actionID)
+end
+
+function Action:GetInRange()
+  return IsActionInRange(self.actionID) == 0
+end
+
+function Action:UpdateCooldown()
+  CooldownFrame_SetTimer(self.frames.cooldown, self:GetCooldown())
+end
+
+function Action:GetCooldown()
+  return GetActionCooldown(self.actionID)
+end
+
+function Action:UpdateFlash()
+  local action = self.actionID
+  self:SetFlash( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) )
+end
+
+function Action:SetFlash(flash)
+  if self.flashing ~= flash then
+    self.flashing = flash
+    self.flashtime = 0
+    if not flash then
+      self.frames.flash:Hide()
+    end
+    self:UpdateCheckedState()
+  end
+end
+
+function Action:RunFlash(elapsed)
+  if self.flashing then
+    local flashtime = self.flashtime - elapsed
+    self.flashtime = flashtime
+    if flashtime <= 0 then
+      local overtime = -flashtime
+      if overtime >= ATTACK_BUTTON_FLASH_TIME then
+        overtime = 0
+      end
+      flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
+      local flash = self.frames.flash
+      if flash:IsShown() then
+        flash:Hide()
+      else
+        flash:Show()
+      end
+    end
+  end
+end
+
+function Action:RunRangeFinder(elapsed)
+  local rangeTimer = self.rangeTimer
+  if rangeTimer then
+    rangeTimer = rangeTimer - elapsed
+    self.rangeTimer = rangeTimer
+    if rangeTimer <= 0 then
+      self:UpdateUsable()
+      self.rangeTimer = TOOLTIP_UPDATE_TIME
+    end
+  end
+end
+
+function Action:GetActionID(page)
+  if page == nil then
+    -- get the effective ID
+    return self:GetFrame():GetAttribute("action")
+  else
+    if page == 1 then
+      return self.config.actionID
+    else
+      return self.config.pageactions and self.config.pageactions[page] or self.config.actionID
+    end
+  end
+end
+
+function Action:SetActionID( id, page )
+  id = tonumber(id)
+  page = tonumber(page)
+  if id == nil or id < 1 or id > 120 then
+    ReAction:UserError(L["Action ID range is 1-120"])
+    return
+  end
+  if page and page ~= 1 then
+    if not self.config.pageactions then
+      self.config.pageactions = { }
+    end
+    self:ReleaseActionID(self.config.pageactions[page])
+    self.config.pageactions[page] = id
+    self:AcquireActionID(self.config.pageactions[page])
+    self.frame:SetAttribute("action-page"..page,id)
+  else
+    self:ReleaseActionID(self.config.actionID)
+    self.config.actionID = id
+    self:AcquireActionID(self.config.actionID)
+    self.frame:SetAttribute("action",id)
+    self.frame:SetAttribute("default-action",id)
+    if self.config.pageactions then
+      self.config.pageactions[1] = id
+      self.frame:SetAttribute("action-page1",id)
+    end
+  end
+end
+
+function Action:RefreshPages( force )
+  local nPages = self:GetBarConfig().nPages
+  if nPages and (nPages ~= self.nPages or force) then
+    local f = self:GetFrame()
+    local c = self.config.pageactions
+    if nPages > 1 and not c then
+      c = { }
+      self.config.pageactions = c
+    end
+    for i = 1, nPages do
+      if i > 1 then
+        c[i] = self:AcquireActionID(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons())
+      else
+        c[i] = self.config.actionID  -- page 1 is the same as the base actionID
+      end
+      f:SetAttribute("action-page"..i,c[i])
+    end
+    for i = nPages+1, #c do
+      self:ReleaseActionID(c[i])
+      c[i] = nil
+      f:SetAttribute("action-page"..i,nil)
+    end
+    self.nPages = nPages
+  end
+end
+
+function Action:SetupBar( bar )
+  Super.SetupBar(self,bar)
+
+  local f = bar:GetFrame()
+  local config = bar:GetConfig()
+  f:SetAttribute("mindcontrol",config.mindcontrol)
+  f:SetAttribute("vehicle",config.vehicle)
+  f:Execute(
+    [[
+    doMindControl = self:GetAttribute("mindcontrol")
+    doVehicle = self:GetAttribute("vehicle")
+    control:ChildUpdate()
+    ]])
+
+  f:SetAttribute("_onstate-mc", _onstate_mc)
+  RegisterStateDriver(f, "mc", "[vehicleui] vehicle; [bonusbar:5] mc; none")
+
+  f:SetAttribute("lockbuttons",config.lockButtons)
+  f:SetAttribute("lockbuttonscombat",config.lockButtonsCombat)
+  f:Execute(
+    [[
+      lockButtons = self:GetAttribute("lockbuttons")
+      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+    ]])
+end
+
+
+function Action:SetButtonLock( bar, lock, lockCombat )
+  local f = bar:GetFrame()
+  f:SetAttribute("lockbuttons",lock)
+  f:SetAttribute("lockbuttonscombat",lockCombat)
+  f:Execute(
+    [[
+      lockButtons = self:GetAttribute("lockbuttons")
+      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+    ]])
+end
+
+
+function Action:ShowVehicleExit(show)
+  self.vehicleExitMode = show and self:GetBarConfig().vehicle
+  self:UpdateIcon()
+end
+
+function Action:OnEnter( )
+  self:SetTooltip()
+end
+
+function Action:OnLeave( )
+  GameTooltip:Hide()
+end
+
+function Action:OnAttributeChanged( attr, value )
+  if attr ~= "statehidden" then
+    self:UpdateAction()
+  end
+  local f = self:GetFrame()
+  f.action = f:GetAttribute("action") -- support ActionButton_UpdateFlyout
+end
+
+function Action:PostClick( )
+  self:UpdateCheckedState()
+end
+
+function Action:OnUpdate( elapsed )
+  self:RunFlash(elapsed)
+  self:RunRangeFinder(elapsed)
+end
+
+function Action:OnDragStart()
+  self:UpdateCheckedState()
+  self:UpdateFlash()
+end
+
+function Action:OnReceiveDrag()
+  self:UpdateCheckedState()
+  self:UpdateFlash()
+end
+
+function Action:OnEvent(event, ...)
+  if self[event] then
+    self[event](self, event, ...)
+  end
+end
+
+function Action:ACTIONBAR_SLOT_CHANGED(event, action)
+  if action == 0 or action == self.actionID then
+    self:UpdateAll()
+  end
+end
+
+function Action:PLAYER_ENTERING_WORLD()
+  self:UpdateAction()
+end
+
+function Action:ACTIONBAR_PAGE_CHANGED()
+  self:UpdateAction()
+end
+
+function Action:UPDATE_BONUS_ACTIONBAR()
+  self:UpdateAction()
+end
+
+function Action:UPDATE_BINDINGS()
+  self:UpdateHotkey()
+end
+
+function Action:PLAYER_TARGET_CHANGED()
+  self.rangeTimer = -1
+end
+
+function Action:ACTIONBAR_UPDATE_STATE()
+  self:UpdateCheckedState()
+end
+
+function Action:TRADE_SKILL_SHOW()
+  self:UpdateCheckedState()
+end
+Action.TRADE_SKILL_CLOSE = Action.TRADE_SKILL_CLOSE
+
+function Action:UNIT_ENTERED_VEHICLE(event,unit)
+  if unit == "player" then
+    self:UpdateCheckedState()
+  end
+end
+Action.UNIT_EXITED_VEHICLE = Action.UNIT_ENTERED_VEHICLE
+
+function Action:COMPANION_UPDATE(event,unit)
+  if unit == "mount" then
+    self:UpdateCheckedState()
+  end
+end
+
+function Action:ACTIONBAR_UPDATE_USABLE()
+  self:UpdateUsable()
+end
+
+function Action:ACTIONBAR_UPDATE_COOLDOWN()
+  self:UpdateCooldown()
+end
+
+function Action:PLAYER_ENTER_COMBAT()
+  if IsAttackAction(self.actionID) then
+    self:SetFlash(true)
+  end
+end
+
+function Action:PLAYER_LEAVE_COMBAT()
+  if IsAttackAction(self.actionID) then
+    self:SetFlash(false)
+  end
+end
+
+function Action:START_AUTOREPEAT_SPELL()
+  if IsAutoRepeatAction(self.actionID) then
+    self:SetFlash(true)
+  end
+end
+
+function Action:STOP_AUTOREPEAT_SPELL()
+  if not IsAttackAction(self.actionID) then
+    self:SetFlash(false)
+  end
+end
+
+function Action:UNIT_INVENTORY_CHANGED(unit)
+  if unit == "player" then
+    self:UpdateTooltip()
+  end
+end
+
+function Action:LEARNED_SPELL_IN_TAB()
+  self:UpdateTooltip()
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BagButton.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,499 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local ContainerIDToInventoryID = ContainerIDToInventoryID
+local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
+local IsModifiedClick = IsModifiedClick
+local CursorHasItem = CursorHasItem
+local GetInventoryItemTexture = GetInventoryItemTexture
+local GetInventorySlotInfo = GetInventorySlotInfo
+local PickupBagFromSlot = PickupBagFromSlot
+local CursorCanGoInSlot = CursorCanGoInSlot
+
+-- class declarations
+local buttonTypeID = "Bag"
+local weak     = { __mode = "k" }
+local Super    = ReAction.Button
+local BagBase  = setmetatable( 
+  { 
+    defaultBarConfig = { 
+      type = buttonTypeID,
+      btnWidth = 30,
+      btnHeight = 30,
+      btnRows = 1,
+      btnColumns = 6,
+      spacing = 4,
+      buttons = { }
+    },
+
+    barType = L["Bag Bar"],
+    buttonTypeID = buttonTypeID,
+
+    allButtons = setmetatable( { }, weak )
+  },
+  { __index = Super } )
+
+local Bag      = setmetatable( { }, { __index = BagBase } )
+local Backpack = setmetatable( { }, { __index = BagBase } )
+local Keyring  = setmetatable( { }, { __index = BagBase } )
+
+ReAction.Button.Bag = BagBase
+ReAction:RegisterBarType(BagBase)
+
+--
+-- Bag Button base class
+--
+
+function BagBase:New( btnCfg, bar, idx, idHint )
+  local name = format("ReAction_%s_Bag_%d",bar:GetName(),idx)
+
+  -- use a variable private leaf implementation class
+  -- unlike traditional OO programming, we can initialize the leaf
+  -- class before initializing its parent
+  local class = Bag
+  if idx == 1 then
+    class = Backpack
+  elseif idx == 6 then
+    class = Keyring
+  end
+  self = class:New(name, btnCfg, bar, idx)
+
+  local f = self:GetFrame()
+  local config = self:GetConfig()
+
+  -- set up the bag ID pool
+  self:SetActionIDPool("bag",6)
+  config.bagID = self:AcquireActionID(config.bagID, idHint, true)
+
+  -- non secure scripts
+  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+  f:SetScript("OnReceiveDrag", function(frame, ...) self:OnReceiveDrag(...) end)
+  f:SetScript("OnClick", function(frame, ...) self:OnClick(...) end)
+
+  -- secure handlers
+  -- (none)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForClicks("LeftButtonUp","RightButtonUp")
+  f:RegisterEvent("UPDATE_BINDINGS")
+
+  -- frame setup
+  f:SetID(self:GetBagID())
+
+  if not f.hotkey then
+    local h = f:CreateFontString(name.."HotKey","ARTWORK","NumberFontNormalSmallGray")
+    h:SetWidth(30)
+    h:SetHeight(10)
+    h:SetJustifyH("RIGHT")
+    h:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2)
+    h:Show()
+    f.hotkey = h
+  end
+
+  if not _G[name.."ItemAnim"] then
+    local anim = CreateFrame("Model",name.."ItemAnim",f,"ItemAnimTemplate")
+    anim:SetPoint("BOTTOMRIGHT",f,"BOTTOMRIGHT",-10,0)
+    anim:Hide()
+  end
+
+  if not f.border then
+    local b = f:CreateTexture(name.."Border","OVERLAY")
+    b:SetAllPoints()
+    b:SetWidth(f:GetWidth()*(62/36))
+    b:SetHeight(f:GetHeight()*(62/36))
+    b:SetTexture("Interface\\Buttons\UI-ActionButton-Border")
+    b:SetBlendMode("ADD")
+    b:Hide()
+    f.border = b
+  end
+
+  self.frames.count:SetDrawLayer("ARTWORK")
+
+  self.frames.hotkey = f.hotkey
+  self.frames.border = _G[name.."Border"]
+  self.frames.icon = _G[name.."IconTexture"]
+  self.frames.anim = _G[name.."ItemAnim"]
+
+  -- initial display
+  if ReAction:GetConfigMode() then
+    self:GetFrame():Show()
+  end
+
+  self:Refresh()
+
+  BagBase.allButtons[self] = true
+
+  return self
+end
+
+function BagBase:Destroy()
+  BagBase.allButtons[self] = nil
+  Super.Destroy(self)
+end
+
+
+function BagBase:GetActionID()
+  return self.config.bagID
+end
+
+function BagBase:GetBagID()
+  return self:GetActionID() - 1
+end
+
+function BagBase:Refresh()
+  Super.Refresh(self)
+  self:UpdateHotkey()
+  self:Update()
+end
+
+function BagBase:Update()
+  self:UpdateChecked()
+end
+
+function BagBase:UpdateChecked(force)
+  if force == nil then
+    for i=1, NUM_CONTAINER_FRAMES do
+      local c = _G["ContainerFrame"..i]
+      if c:GetID() == self:GetBagID() and c:IsShown() then
+        self:GetFrame():SetChecked(1)
+        return
+      end
+    end
+    self:GetFrame():SetChecked(0)
+  end
+  self:GetFrame():SetChecked(force)
+end
+
+function BagBase:OnEvent(evt, ...)
+  if self[evt] then
+    self[evt](self, ...)
+  end
+end
+
+function BagBase:OnEnter()
+  self:SetTooltip()
+end
+
+function BagBase:OnLeave()
+  GameTooltip:Hide()
+end
+
+function BagBase:UPDATE_BINDINGS()
+  self:UpdateHotkey()
+end
+
+function BagBase:IterateAllButtons()
+  return pairs(self.allButtons)
+end
+
+
+--
+-- Bag Button class
+--
+function Bag:New(name, cfg, bar, idx)
+  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
+
+  local f = self:GetFrame()
+
+  f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
+
+  f:RegisterEvent("CURSOR_UPDATE")
+  f:RegisterEvent("BAG_UPDATE")
+  f:RegisterEvent("BAG_CLOSED")
+  f:SetScript("OnDragStart", function(frame, ...) self:OnDragStart(...) end)
+  f:RegisterForDrag("LeftButton")
+
+  -- attach to skinner
+  bar:SkinButton(self,
+    {
+      Icon = _G[name.."IconTexture"]
+    }
+  )
+
+  return self
+end
+
+function Bag:GetInventorySlot()
+  return ContainerIDToInventoryID(self:GetBagID())
+end
+
+function Bag:GetInventorySlotName()
+  return "Bag"..(self:GetBagID()-1).."Slot"
+end
+
+function Bag:SetTooltip()
+  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
+  if not GameTooltip:SetInventoryItem("player", self:GetInventorySlot()) then
+    GameTooltip:SetText(EQUIP_CONTAINER, 1.0, 1.0, 1.0)
+  end
+end
+
+function Bag:Update()
+	local texture = GetInventoryItemTexture("player", self:GetInventorySlot())
+	if texture then
+    self.frames.icon:SetTexture(texture)
+    self.frames.icon:Show()
+    self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+	else
+    local _, bgTex = GetInventorySlotInfo(self:GetInventorySlotName())
+    self.frames.icon:SetTexture(bgTex)
+    self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+	end
+  self:UpdateChecked()
+end
+
+function Bag:OnClick()
+  if IsModifiedClick("OPENALLBAGS") then
+    OpenAllBags()
+  else
+    if not PutItemInBag(self:GetInventorySlot()) then
+      ToggleBag(self:GetBagID())
+    end
+  end
+  self:UpdateChecked()
+end
+
+function Bag:OnReceiveDrag()
+  if CursorHasItem() then
+    PutItemInBag(self:GetInventorySlot())
+  end
+end
+
+function Bag:OnDragStart()
+  PickupBagFromSlot(self:GetInventorySlot())
+  self:Update()
+end
+
+function Bag:BAG_UPDATE(bag)
+  if bag == self:GetBagID() then
+    self:Update()
+  end
+end
+
+function Bag:CURSOR_UPDATE()
+  if CursorCanGoInSlot(self:GetInventorySlot()) then
+    self:GetFrame():LockHighlight()
+  else
+    self:GetFrame():UnlockHighlight()
+  end
+end
+
+function Bag:BAG_CLOSED(bag)
+  if bag == self:GetBagID() then
+    self:Update()
+  end
+end
+
+
+--
+-- Backpack Button class
+--
+function Backpack:New(name, cfg, bar, idx)
+  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
+
+  local f = self:GetFrame()
+  local icon = _G[name.."IconTexture"]
+  icon:SetTexture("Interface\\Buttons\\Button-Backpack-Up")
+  icon:Show()
+  f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
+  f:RegisterEvent("PLAYER_ENTERING_WORLD");
+  f:RegisterEvent("CVAR_UPDATE");
+  f:SetScript("OnShow", function(frame, ...) self:OnShow(...) end)
+
+  -- attach to skinner
+  bar:SkinButton(self,
+    {
+      Icon = _G[name.."IconTexture"]
+    }
+  )
+
+  return self
+end
+
+function Backpack:Update()
+  self:UpdateFreeSlots()
+  self:UpdateChecked()
+end
+
+function Backpack:UpdateFreeSlots()
+  if GetCVar("displayFreeBagSlots") == "1" then
+    local total = 0
+    for i = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
+      local free, family = GetContainerNumFreeSlots(i)
+      if family == 0 then
+        total = total + free
+      end
+    end
+
+    self.freeSlots = total
+    self.frames.count:SetText(format("(%s)", self.freeSlots))
+    self.frames.count:Show()
+  elseif self.frames.count:IsShown() then
+    self.frames.count:Hide()
+  end
+end
+
+function Backpack:SetTooltip()
+  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
+  GameTooltip:SetText(BACKPACK_TOOLTIP, 1.0, 1.0, 1.0)
+  GameTooltip:AddLine(string.format(NUM_FREE_SLOTS, (self.freeSlots or 0)))
+  GameTooltip:Show();
+end
+
+function Backpack:OnShow()
+  self:UpdateFreeSlots()
+end
+
+function Backpack:OnClick()
+  if IsModifiedClick("OPENALLBAGS") then
+    OpenAllBags()
+  else
+    if not PutItemInBackpack() then
+      ToggleBackpack()
+    end
+  end
+  self:UpdateChecked()
+end
+
+function Backpack:OnReceiveDrag()
+  if CursorHasItem() then
+    PutItemInBackpack()
+  end
+end
+
+function Backpack:PLAYER_ENTERING_WORLD()
+  self:CVAR_UPDATE("DISPLAY_FREE_BAG_SLOTS", GetCVar("displayFreeBagSlots"))
+end
+
+function Backpack:CVAR_UPDATE( cvar, value )
+  if cvar == "DISPLAY_FREE_BAG_SLOTS" then
+    if value == "1" then
+      self:GetFrame():RegisterEvent("BAG_UPDATE")
+    else
+      self:GetFrame():UnregisterEvent("BAG_UPDATE")
+    end
+    self:UpdateFreeSlots()
+  end
+end
+
+function Backpack:BAG_UPDATE(bag)
+  if bag >= BACKPACK_CONTAINER and bag <= NUM_BAG_SLOTS then
+    self:UpdateFreeSlots()
+  end
+end
+
+
+--
+-- Keyring Button class
+--
+function Keyring:New(name, cfg, bar, idx)
+  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
+
+  local f = self:GetFrame()
+
+  f:SetWidth(18)
+  f:SetHeight(39)
+
+  local tex = f:GetNormalTexture()
+  tex:ClearAllPoints()
+  tex:SetAllPoints()
+  
+  f:SetNormalTexture("Interface\\Buttons\\UI-Button-KeyRing")
+  f:SetHighlightTexture("Interface\\Buttons\\UI-Button-KeyRing-Highlight")
+  f:SetPushedTexture("Interface\\Buttons\\UI-Button-KeyRing-Down")
+  f:GetNormalTexture():SetTexCoord(0,0.5625,0,0.609375)
+  f:GetHighlightTexture():SetTexCoord(0,0.5625,0,0.609375)
+  f:GetPushedTexture():SetTexCoord(0,0.5625,0,0.609375)
+
+  if not HasKey() then
+    f:Hide()
+  end
+
+  -- DO NOT attach to skinner
+
+  return self
+end
+
+function Keyring:GetBagID()
+  return KEYRING_CONTAINER
+end
+
+function Keyring:Refresh()
+  local f = self:GetFrame()
+  self.bar:PlaceButton( self, f:GetHeight(), f:GetHeight() ) -- use height x height since it's an odd size
+  self:UpdateHotkey()
+  self:Update()
+end
+
+function Keyring:SetTooltip()
+  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT");
+  GameTooltip:SetText(KEYRING, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
+  GameTooltip:AddLine();
+end
+
+function Keyring:OnReceiveDrag()
+  if CursorHasItem() then
+    PutKeyInKeyRing()
+  end
+end
+
+function Keyring:OnClick()
+  if CursorHasItem() then
+    PutKeyInKeyRing()
+  else
+    ToggleKeyRing()
+  end
+  self:UpdateChecked()
+end
+
+function Keyring:ShowGridTemp(show)
+  if not HasKey() then
+    if show then 
+      self:GetFrame():Show()
+    else
+      self:GetFrame():Hide()
+    end
+  end
+end
+
+
+
+-- hook some functions to propagate to our bag buttons
+hooksecurefunc("Disable_BagButtons", 
+  function()
+    for b in BagBase:IterateAllButtons() do
+      local f = b:GetFrame()
+      f:Disable()
+      SetDesaturation(b.frames.icon,1)
+    end
+  end)
+
+hooksecurefunc("Enable_BagButtons",
+  function()
+    for b in BagBase:IterateAllButtons() do
+      local f = b:GetFrame()
+      f:Enable()
+      SetDesaturation(b.frames.icon,nil)
+    end
+  end)
+
+hooksecurefunc("ContainerFrame_OnHide",
+  function()
+    for b in BagBase:IterateAllButtons() do
+      b:Update()
+    end
+  end)
+
+hooksecurefunc("ContainerFrame_OnShow",
+  function()
+    for b in BagBase:IterateAllButtons() do
+      b:Update()
+    end
+  end)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bar.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,854 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local LKB = ReAction.LKB
+local _G = _G
+local CreateFrame = CreateFrame
+local floor = math.floor
+local fmod = math.fmod
+local format = string.format
+local tfetch = addonTable.tfetch
+local tbuild = addonTable.tbuild
+local fieldsort = addonTable.fieldsort
+
+local LSG = LibStub("ReAction-LibShowActionGrid-1.0")
+
+---- Secure snippets ----
+local _reaction_init = 
+[[
+  anchorKeys = newtable("point","relPoint","x","y")
+
+  state = nil
+  set_state = nil
+  state_override = nil
+  unit_exists = nil
+
+  showAll = false
+  hidden = false
+
+  defaultAlpha = 1.0
+  defaultScale = 1.0
+  defaultAnchor = newtable()
+
+  activeStates = newtable()
+  settings = newtable()
+  extensions = newtable()
+]]
+
+local _reaction_refresh = 
+[[
+  local oldState = state
+  state = state_override or set_state or state
+
+  local hide = nil
+  if state then
+    local settings = settings[state]
+    if settings then
+      -- show/hide
+      hide = settings.hide
+      -- re-anchor
+      local old_anchor = activeStates.anchor
+      activeStates.anchor = settings.anchorEnable and state
+      if old_anchor ~= activeStates.anchor or not set_state then
+        if activeStates.anchor then
+          if settings.anchorPoint then
+            self:ClearAllPoints()
+            local f = self:GetAttribute("frameref-anchor-"..state)
+            if f then
+              self:SetPoint(settings.anchorPoint, f, settings.anchorRelPoint, settings.anchorX, settings.anchorY)
+            end
+          end
+        elseif defaultAnchor.point then
+          self:ClearAllPoints()
+          self:SetPoint(defaultAnchor.point, defaultAnchor.frame, 
+                        defaultAnchor.relPoint, defaultAnchor.x, defaultAnchor.y)
+        end
+      end
+      -- re-scale
+      local old_scale = activeStates.scale
+      activeStates.scale = settings.enableScale and state
+      if old_scale ~= activeStates.scale or not set_state then
+        self:SetScale(activeStates.scale and settings.scale or defaultScale)
+      end
+      -- alpha
+      local old_alpha = activeStates.alpha
+      activeStates.alpha = settings.enableAlpha and state
+      if old_alpha ~= activeStates.alpha or not set_state then
+        self:SetAlpha(activeStates.alpha and settings.alpha or defaultAlpha)
+      end
+    end
+  end
+
+  -- hide if state or unit_exists says to
+  hide = not showAll and (hide or unithide)
+  if hide ~= hidden then
+    hidden = hide
+    if hide then
+      self:Hide()
+    else
+      self:Show()
+    end
+  end
+
+  for _, attr in pairs(extensions) do
+    control:RunAttribute(attr)
+  end
+  
+  control:ChildUpdate()
+
+  if showAll then
+    control:CallMethod("UpdateHiddenLabel", state and settings[state] and settings[state].hide)
+  end
+
+  if oldState ~= state then
+    control:CallMethod("StateRefresh", state)
+  end
+]]
+
+local _onstate_reaction = -- function( self, stateid, newstate )
+[[
+  set_state = newstate
+]] .. _reaction_refresh
+
+local _onstate_showgrid = -- function( self, stateid, newstate )
+[[
+  control:ChildUpdate(stateid,newstate)
+  control:CallMethod("UpdateShowGrid")
+]]
+
+local _onstate_unitexists = -- function( self, stateid, newstate )
+[[
+  unithide = not newstate or newstate == "hide"
+]] .. _reaction_refresh
+
+local _onclick =  -- function( self, button, down )
+[[
+  if state_override == button then
+    state_override = nil -- toggle
+  else
+    state_override = button
+  end
+]] .. _reaction_refresh
+
+-- For reference
+-- the option field names must match the field names of the options table, below
+local stateProperties = { 
+  hide = true,
+  --keybindState = true, TODO: broken
+  anchorEnable = true,
+  anchorFrame = true,
+  anchorPoint = true,
+  anchorRelPoint = true,
+  anchorX = true,
+  anchorY = true,
+  enableScale = true,
+  scale = true,
+  enableAlpha = true,
+  alpha = true,
+}
+
+
+
+---- Bar class ----
+local Bar   = { }
+local frameList = { }
+
+ReAction.Bar = Bar -- export to ReAction
+
+function Bar:New( name, config, buttonClass )
+  if type(config) ~= "table" then
+    error("ReAction.Bar: config table required")
+  end
+
+  -- create new self
+  self = setmetatable( 
+    { 
+      config      = config,
+      name        = name,
+      buttons     = { },
+      buttonClass = buttonClass,
+      width       = config.width or 480,
+      height      = config.height or 40,
+    }, 
+    {__index = self} )
+  
+  -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
+  -- not mouse-clickable by the user.
+  local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
+  name = name and "ReAction-"..name
+  local f = name and frameList[name]
+  if not f then
+    f = CreateFrame("Button", name, parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
+    if name then
+      frameList[name] = f
+    end
+  end
+  f:SetFrameStrata("MEDIUM")
+  f:SetWidth(self.width)
+  f:SetHeight(self.height)
+  f:SetAlpha(config.alpha or 1.0)
+  f:Show()
+  f:EnableMouse(false)
+  f:SetClampedToScreen(true)
+  LSG:AddFrame(f)
+
+  -- secure handlers
+  f:Execute(_reaction_init)
+  f:SetAttribute("_onstate-reaction",   _onstate_reaction)
+  f:SetAttribute("_onstate-showgrid",   _onstate_showgrid)
+  f:SetAttribute("_onstate-unitexists", _onstate_unitexists)
+  f:SetAttribute("_onclick",            _onclick)
+
+  -- secure handler CallMethod()s
+  f.UpdateShowGrid    = function() self:UpdateShowGrid() end
+  f.StateRefresh      = function() self:RefreshControls() end
+  f.UpdateHiddenLabel = function(f,hidden) self:SetLabelSubtext(hidden and L["Hidden"]) end
+
+  -- Override the default frame accessor to provide strict read-only access
+  function self:GetFrame()
+    return f
+  end
+
+  self:ApplyAnchor()
+  self:SetConfigMode(ReAction:GetConfigMode())
+  self:SetKeybindMode(ReAction:GetKeybindMode())
+
+  if ReAction.LBF then
+    local g = ReAction.LBF:Group(L["ReAction"], self.name)
+    self.config.ButtonFacade = self.config.ButtonFacade or {
+      skinID = "Blizzard",
+      backdrop = true,
+      gloss = 0,
+      colors = {},
+    }
+    local c = self.config.ButtonFacade
+    g:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
+    self.LBFGroup = g
+  end
+
+  ReAction.RegisterCallback(self, "OnConfigModeChanged")
+
+  buttonClass:SetupBar(self)
+  self:ApplyStates()
+
+  return self
+end
+
+function Bar:Destroy()
+  local f = self:GetFrame()
+  self:CleanupStates()
+  for idx, b in self:IterateButtons() do
+    b:Destroy()
+  end
+  f:UnregisterAllEvents()
+  self:ShowControls(false)
+  ReAction.UnregisterAllCallbacks(self)
+  LKB.UnregisterAllCallbacks(self)
+  if self.LBFGroup then
+    self.LBFGroup:Delete(true)
+  end
+  LSG:RemoveFrame(f)
+  f:SetParent(UIParent)
+  f:ClearAllPoints()
+  f:Hide()
+end
+
+--
+-- Events
+--
+
+function Bar:OnConfigModeChanged(event, mode)
+  self:SetConfigMode(mode)
+end
+
+--
+-- Accessors
+--
+
+function Bar:GetName()
+  return self.name
+end
+
+-- only ReAction:RenameBar() should call this function. Calling from any other
+-- context will desync the bar list in the ReAction class.
+function Bar:SetName(name)
+  if self.LBFGroup then
+    -- LBF doesn't offer a method of renaming a group, so delete and remake the group.
+    local c = self.config.ButtonFacade
+    local g = ReAction.LBF:Group(L["ReAction"], name)
+    for idx, b in self:IterateButtons() do
+      self.LBFGroup:RemoveButton(b:GetFrame(), true)
+      g:AddButton(b:GetFrame())
+    end
+    self.LBFGroup:Delete(true)
+    self.LBFGroup = g
+    self.LBFGroup:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
+  end
+  self.name = name
+  if self.overlay then
+    self.overlay:SetLabel(self.name)
+  end
+end
+
+function Bar:GetFrame()
+  -- this method is included for documentation purposes. It is overridden
+  -- for each object in the :New() method.
+  error("Invalid Bar object: used without initialization")
+end
+
+function Bar:GetButton(idx)
+  return self.buttons[idx]
+end
+
+function Bar:GetButtonClass()
+  return self.buttonClass
+end
+
+function Bar:GetConfig()
+  return self.config
+end
+
+function Bar:GetAnchor()
+  local c = self.config
+  return (c.point or "CENTER"), 
+         (c.anchor or self:GetFrame():GetParent():GetName()), 
+         (c.relpoint or c.point or "CENTER"), 
+         (c.x or 0), 
+         (c.y or 0)
+end
+
+function Bar:SetAnchor(point, frame, relativePoint, x, y)
+  local c = self.config
+  c.point = point or c.point
+  c.anchor = frame or c.anchor
+  c.relpoint = relativePoint or c.relpoint
+  c.x = x or c.x
+  c.y = y or c.y
+  self:ApplyAnchor()
+end
+
+function Bar:GetSize()
+  local f = self:GetFrame()
+  return f:GetWidth(), f:GetHeight()
+end
+
+function Bar:SetSize(w,h)
+  local f = self:GetFrame()
+  self.config.width = w
+  self.config.height = h
+  f:SetWidth(w)
+  f:SetHeight(h)
+end
+
+function Bar:GetButtonSize()
+  local w = self.config.btnWidth or 32
+  local h = self.config.btnHeight or 32
+  -- TODO: get from modules?
+  return w,h
+end
+
+function Bar:SetButtonSize(w,h)
+  if w > 0 and h > 0 then
+    self.config.btnWidth = w
+    self.config.btnHeight = h
+  end
+end
+
+function Bar:GetNumButtons()
+  local r,c = self:GetButtonGrid()
+  return r*c
+end
+
+function Bar:GetButtonGrid()
+  local cfg = self.config
+  local r = cfg.btnRows or 1
+  local c = cfg.btnColumns or 1
+  local s = cfg.spacing or 4
+  return r,c,s
+end
+
+function Bar:SetButtonGrid(r,c,s)
+  if r > 0 and c > 0 and s > 0 then
+    local cfg = self.config
+    cfg.btnRows = r
+    cfg.btnColumns = c
+    cfg.spacing = s
+  end
+  self.buttonClass:SetupBar(self)
+end
+
+function Bar:GetAlpha()
+  return self.config.alpha or 1.0
+end
+
+function Bar:SetAlpha(value)
+  self.config.alpha = value
+  self:GetFrame():SetAlpha(value or 1.0)
+  self:UpdateDefaultStateAlpha()
+end
+
+function Bar:IterateButtons()
+  -- iterator returns idx, button, but does NOT iterate in index order
+  return pairs(self.buttons)
+end
+
+--
+-- Methods
+--
+
+function Bar:SetConfigMode(mode)
+  self:SetSecureData("showAll",mode)
+  self:ShowControls(mode)
+  for idx, b in self:IterateButtons() do
+    b:ShowGridTemp(mode)
+    b:UpdateActionIDLabel(mode)
+  end
+end
+
+function Bar:SetKeybindMode(mode)
+  self:SetSecureData("showAll",mode)
+  for idx, b in self:IterateButtons() do
+    b:SetKeybindMode(mode)
+  end
+end
+
+function Bar:ApplyAnchor()
+  local f = self:GetFrame()
+  local c = self.config
+  local p = c.point
+
+  f:SetWidth(c.width)
+  f:SetHeight(c.height)
+  f:ClearAllPoints()
+  
+  if p then
+    local a = f:GetParent()
+    if c.anchor then
+      local bar = ReAction:GetBar(c.anchor)
+      if bar then
+        a = bar:GetFrame()
+      else
+        a = _G[c.anchor]
+      end
+    end
+    local fr = a or f:GetParent()
+    f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
+  else
+    f:SetPoint("CENTER")
+  end
+
+  self:UpdateDefaultStateAnchor()
+end
+
+function Bar:ClipNButtons( n )
+  local cfg = self.config
+  local r = cfg.btnRows or 1
+  local c = cfg.btnColumns or 1
+
+  cfg.btnRows = ceil(n/c)
+  cfg.btnColumns = min(n,c)
+end
+
+function Bar:AddButton(idx, button)
+  local f = self:GetFrame()
+
+  self.buttons[idx] = button
+
+  -- Store a properly wrapped reference to the child frame as an attribute 
+  -- (accessible via "frameref-btn#")
+  f:SetFrameRef(format("btn%d",idx), button:GetFrame())
+
+  -- button constructors are responsible for calling SkinButton
+end
+
+function Bar:RemoveButton(button)
+  local idx = button:GetIndex()
+  if idx then
+    self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
+    self.buttons[idx] = nil
+  end
+  if self.LBFGroup then
+    self.LBFGroup:RemoveButton(button:GetFrame(),true)
+  end
+end
+
+function Bar:PlaceButton(button, baseW, baseH)
+  local idx = button:GetIndex()
+  if idx then 
+    local r, c, s = self:GetButtonGrid()
+    local bh, bw = self:GetButtonSize()
+    local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
+    local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
+    local scale = bw/baseW
+    local b = button:GetFrame()
+
+    b:ClearAllPoints()
+    b:SetPoint("TOPLEFT",x/scale,y/scale)
+    b:SetScale(scale)
+  end
+end
+
+function Bar:SkinButton( button, data )
+  if self.LBFGroup then
+    self.LBFGroup:AddButton(button:GetFrame(), data)
+  end
+end
+
+function Bar:UpdateShowGrid()
+  for idx, button in self:IterateButtons() do
+    button:UpdateShowGrid()
+  end
+end
+
+function Bar:ShowControls(show)
+  if show then
+    if not self.overlay then
+      self.overlay = Bar.Overlay:New(self) -- see Overlay.lua
+    end
+    self.overlay:Show()
+    self:RefreshSecureState()
+  elseif self.overlay then
+    self.overlay:Hide()
+  end
+end
+
+function Bar:RefreshControls()
+  if self.overlay and self.overlay:IsShown() then
+    self.overlay:RefreshControls()
+  end
+end
+
+function Bar:SetLabelSubtext(text)
+  if self.overlay then 
+    self.overlay:SetLabelSubtext(text) 
+  end
+end
+
+--
+-- Secure state functions
+--
+
+function Bar:GetSecureState()
+  local env = GetManagedEnvironment(self:GetFrame())
+  return env and env.state
+end
+
+function Bar:GetStateProperty(state, propname)
+  return tfetch(self:GetConfig(), "states", state, propname)
+end
+
+function Bar:SetStateProperty(state, propname, value)
+  local s = tbuild(self:GetConfig(), "states", state)
+  s[propname] = value
+  self:SetSecureStateData(state, propname, value)
+end
+
+function Bar:ApplyStates()
+  local states = tfetch(self:GetConfig(), "states")
+  if states then
+    self:SetStateDriver(states)
+  end
+end
+
+function Bar:CleanupStates()
+  self:SetStateDriver(nil)
+end
+
+function Bar:RefreshSecureState()
+  self:GetFrame():Execute(_reaction_refresh)
+end
+
+-- usage: SetSecureData(globalname, [tblkey1, tblkey2, ...], value)
+function Bar:SetSecureData( ... )
+  local n = select('#',...)
+  if n < 2 then
+    error("ReAction.Bar:SetSecureData() requires at least 2 arguments")
+  end
+  local f = self:GetFrame()
+  f:SetAttribute("data-depth",n-1)
+  f:SetAttribute("data-value",select(n,...))
+  for i = 1, n-1 do
+    local key = select(i,...)
+    if key == nil then
+      error("ReAction.Bar:SetSecureData() - nil table key in argument list (#"..i..")")
+    end
+    f:SetAttribute("data-key-"..i, key)
+  end
+  f:Execute(
+    [[
+      local n = self:GetAttribute("data-depth")
+      if n > 0 then
+        local value = self:GetAttribute("data-value")
+        local t = _G
+        for i = 1, n do
+          local key = self:GetAttribute("data-key-"..i)
+          if not key then return end
+          if not t[key] then
+            t[key] = newtable()
+          end
+          if i == n then
+            t[key] = value
+          else
+            t = t[key]
+          end
+        end
+      end
+    ]])
+  self:RefreshSecureState()
+end
+
+function Bar:SetSecureStateData( state, key, value )
+  self:SetSecureData("settings",state,key,value)
+end
+
+-- sets a snippet to be run as an extension to _onstate-reaction
+function Bar:SetSecureStateExtension( id, snippet )
+  if id == nil then
+    error("ReAction.Bar:SetSecureStateExtension() requires an id")
+  end
+  local f = self:GetFrame()
+  f:SetAttribute("input-secure-ext-id",id)
+  f:SetAttribute("secure-ext-"..id,snippet)
+  f:Execute(
+    [[
+      local id = self:GetAttribute("input-secure-ext-id")
+      if id then
+        extensions[id] = self:GetAttribute("secure-ext-"..id) or nil
+      end
+    ]])
+  self:RefreshSecureState()
+end
+
+function Bar:SetFrameRef( name, refFrame )
+  if refFrame then
+    local _, explicit = refFrame:IsProtected()
+    if not explicit then
+      refFrame = nil
+    end
+  end
+  if refFrame then
+    self:GetFrame():SetFrameRef(name,refFrame)
+  else
+    self:GetFrame():SetAttribute("frameref-"..name,nil)
+  end
+end
+
+function Bar:SetStateDriver( states )
+  if states then
+    for state, props in pairs(states) do
+      self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
+      for propname, value in pairs(props) do
+        if propname == "anchorFrame" then
+          self:SetFrameRef("anchor-"..state, _G[value])
+        elseif propname == "rule" then
+          -- do nothing
+        else
+          self:SetSecureStateData(state, propname, value)
+        end
+      end
+    end
+  end
+  local rule = states and self:BuildStateRule(states)
+  if rule then
+    RegisterStateDriver(self:GetFrame(),"reaction",rule)
+  elseif self.statedriver then
+    UnregisterStateDriver(self:GetFrame(),"reaction")
+  end
+  self.statedriver = rule
+  self:BuildStateKeybinds(states)
+  self:RefreshSecureState()
+end
+
+-- pass unit=nil to set up the unit elsewhere, if you want something more complex
+function Bar:RegisterUnitWatch( unit, enable )
+  local f = self:GetFrame()
+  if unit then
+    f:SetAttribute("unit",unit)
+  end
+  if enable then
+    if not self.unitwatch then
+      RegisterUnitWatch(self:GetFrame(),true)
+    end
+  elseif self.unitwatch then
+    UnregisterUnitWatch(self:GetFrame())
+  end
+  self.unitwatch = enable
+  self:RefreshSecureState()
+end
+
+function Bar:SetStateKeybind( key, state )
+  local f = self:GetFrame()
+  local binds = self.statebinds
+  if not binds then
+    binds = { }
+    self.statebinds = binds
+  end
+
+  -- clear the old binding, if any
+  if binds[state] then
+    SetOverrideBinding(f, false, binds[state], nil)
+  end
+
+  if key then
+    SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
+  end
+  binds[state] = key
+end
+
+function Bar:GetStateKeybind( state )
+  if self.statebinds and state then
+    return self.statebinds[state]
+  end
+end
+
+function Bar:UpdateDefaultStateAnchor()
+  local point, frame, relPoint, x, y = self:GetAnchor()
+  local f = self:GetFrame()
+  f:SetAttribute("defaultAnchor-point",point)
+  f:SetAttribute("defaultAnchor-relPoint",relPoint)
+  f:SetAttribute("defaultAnchor-x",x)
+  f:SetAttribute("defaultAnchor-y",y)
+  self:SetFrameRef("defaultAnchor",_G[frame or "UIParent"])
+  f:Execute([[
+    for _, k in pairs(anchorKeys) do
+      defaultAnchor[k] = self:GetAttribute("defaultAnchor-"..k)
+    end
+    defaultAnchor.frame = self:GetAttribute("frameref-defaultAnchor")
+  ]])
+end
+
+function Bar:UpdateDefaultStateAlpha()
+  local f = self:GetFrame()
+  f:SetAttribute("defaultAlpha",self:GetAlpha())
+  f:Execute([[
+    defaultAlpha = self:GetAttribute("defaultAlpha")
+  ]])
+end
+
+---- secure state driver rules ----
+
+local playerClass = select(2, UnitClass("player"))
+local function ClassFilter(...)
+  for i = 1, select('#',...) do
+    if playerClass == select(i,...) then
+      return false
+    end
+  end
+  return true
+end
+
+local ruleformats = { 
+  stealth       = { format = "stealth",        filter = ClassFilter("ROGUE","DRUID") },
+  nostealth     = { format = "nostealth",      filter = ClassFilter("ROGUE","DRUID") },
+  shadowdance   = { format = "bonusbar:2",     filter = ClassFilter("ROGUE") },
+  shadowform    = { format = "form:1",         filter = ClassFilter("PRIEST") },
+  noshadowform  = { format = "noform",         filter = ClassFilter("PRIEST") },
+  battle        = { format = "stance:1",       filter = ClassFilter("WARRIOR") },
+  defensive     = { format = "stance:2",       filter = ClassFilter("WARRIOR") },
+  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:3",         filter = ClassFilter("DRUID") },
+  tree          = { format = "form:5",         filter = ClassFilter("DRUID") },
+  moonkin       = { format = "form:5",         filter = ClassFilter("DRUID") },
+  demon         = { format = "form:2",         filter = ClassFilter("WARLOCK") },
+  nodemon       = { format = "noform",         filter = ClassFilter("WARLOCK") },
+  pet           = { format = "pet" },
+  nopet         = { format = "nopet" },
+  harm          = { format = "@target,harm" },
+  help          = { format = "@target,help" },
+  notarget      = { format = "@target,noexists" },
+  focusharm     = { format = "@focus,harm" },
+  focushelp     = { format = "@focus,help" },
+  nofocus       = { format = "@focus,noexists" },
+  raid          = { format = "group:raid" },
+  party         = { format = "group:party" },
+  solo          = { format = "nogroup" },
+  combat        = { format = "combat" },
+  nocombat      = { format = "nocombat" },
+  possess       = { format = "@vehicle,noexists,bonusbar:5" },
+  vehicle       = { format = "@vehicle,exists,bonusbar:5" },
+}
+
+function Bar.InitRuleFormats()
+  local forms = { }
+  for i = 1, GetNumShapeshiftForms() do
+    local _, name = GetShapeshiftFormInfo(i)
+    forms[name] = i;
+  end
+    -- use 9 if not found since 9 is never a valid stance/form
+  local defensive = forms[GetSpellInfo(71)] or 9
+  local berserker = forms[GetSpellInfo(2458)] or 9
+  local bear      = 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 = "stance:"..defensive
+  ruleformats.berserker.format = "stance:"..berserker
+  ruleformats.caster.format    = format("form:0/%d/%d/%d", aquatic, travel, flight)
+  ruleformats.bear.format      = "form:"..bear
+  ruleformats.cat.format       = "form:"..cat
+  ruleformats.tree.format      = "form:"..tree
+  ruleformats.moonkin.format   = "form:"..moonkin
+end
+
+function Bar:BuildStateRule(states)
+  -- states is a table :
+  --   states[statename].rule = {
+  --     order = #,
+  --     type = "default"/"custom"/"any"/"all",
+  --     values = { ... }, -- keys of ruleformats[]
+  --     custom = "...",
+  --   }
+  local rules = { }
+  local default
+
+  for idx, state in ipairs(fieldsort(states, "rule", "order")) do
+    local c = states[state].rule
+    local type = c.type
+    if type == "default" then
+      default = default or state
+    elseif type == "custom" then
+      if c.custom then
+        -- strip out all spaces from the custom rule
+        table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
+      end
+    elseif type == "any" or type == "all" then
+      if c.values then
+        local clauses = { }
+        for key, value in pairs(c.values) do
+          if ruleformats[key] and not ruleformats[key].filter then
+            table.insert(clauses, ruleformats[key].format)
+          end
+        end
+        if #clauses > 0 then
+          local sep = (type == "any") and "][" or ","
+          table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
+        end
+      end
+    end
+  end
+  -- make sure that the default, if any, is last
+  if default then
+    table.insert(rules, default)
+  end
+  return table.concat(rules,";")
+end
+
+function Bar:BuildStateKeybinds( states )
+  if states then
+    for name, state in pairs(states) do
+      local rule = tfetch(state, "rule")
+      if rule and rule.type == "keybind" then
+        self:SetStateKeybind(rule.keybind, name)
+      else
+        self:SetStateKeybind(nil, name) -- this clears an existing keybind
+      end
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Button.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,359 @@
+--[[
+  ReAction Button base class
+--]]
+
+-- local imports
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local LKB = ReAction.LKB
+local _G = _G
+local CreateFrame = CreateFrame
+local GetBindingKey = GetBindingKey
+local format = string.format
+
+-- private
+local trash = CreateFrame("Frame")
+local frameList = { }
+local idPools = { }
+
+local function kb_onEnter( frame )
+  LKB:Set(frame)
+end
+
+-- Button class
+local buttonTypeID = "Button"
+local Button = { 
+  defaultBarConfig = {
+    type = buttonTypeID,
+    btnWidth = 36,
+    btnHeight = 36,
+    btnRows = 1,
+    btnColumns = 12,
+    spacing = 3
+  },
+  barType = L["Button Bar"]
+} 
+
+ReAction.Button = Button -- export to ReAction
+
+function Button:New( name, config, bar, idx, inherits, buttonType )
+  buttonType = buttonType or "CheckButton"
+
+  -- create new self
+  self = setmetatable( 
+    { 
+      bar = bar,
+      idx = idx,
+      config = config,
+      name = name,
+    }, 
+    { __index = self } )
+
+  -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
+  -- existing globals. Can't set to nil in the global because it's then tainted.
+  -- Caller is responsible for ensuring global uniqueness of names.
+  local f = name and frameList[name]
+  if f then
+    f:SetParent(bar:GetFrame())
+  else
+    f = CreateFrame(buttonType, name, bar:GetFrame(), inherits)
+    if name then
+      frameList[name] = f
+    end
+  end
+
+  self.frame = f
+
+  local frames = { }
+  self.frames = frames
+  frames.icon          = _G[name.."Icon"]
+  frames.flash         = _G[name.."Flash"]
+  frames.hotkey        = _G[name.."HotKey"]
+  frames.count         = _G[name.."Count"]
+  frames.name          = _G[name.."Name"]
+  frames.border        = _G[name.."Border"]
+  frames.cooldown      = _G[name.."Cooldown"]
+  frames.normalTexture = _G[name.."NormalTexture"]
+
+  if config then
+    config.name = name
+  end
+
+  -- install LibKeyBound handlers onto frame
+  function f:GetActionName()
+    return format("%s:%s", bar:GetName(), idx)
+  end
+
+  local clickBinding = format("CLICK %s:LeftButton", name)
+  function f:GetHotkey()
+    return LKB:ToShortKey(GetBindingKey(clickBinding))
+  end
+
+  return self
+end
+
+function Button:Destroy()
+  local f = self:GetFrame()
+  f:UnregisterAllEvents()
+  self:ReleaseActionID(self:GetActionID())
+  if f then
+    f:Hide()
+    f:SetParent(trash)
+    f:ClearAllPoints()
+  end
+end
+
+function Button:GetBar()
+  return self.bar
+end
+
+function Button:GetFrame()
+  return self.frame
+end
+
+function Button:GetIndex()
+  return self.idx
+end
+
+function Button:GetName()
+  return self.name
+end
+
+function Button:GetDefaultBarConfig()
+  return self.defaultBarConfig
+end
+
+function Button:GetBarType()
+  return self.barType
+end
+
+function Button:GetButtonTypeID()
+  return self.buttonTypeID
+end
+
+function Button:GetConfig()
+  return self.config
+end
+
+function Button:GetActionID()
+  -- derived classes should override this
+  return nil
+end
+
+function Button:SetActionIDPool( poolID, maxID )
+  self.actionPoolID = poolID
+  self.actionMaxID = maxID
+end
+
+function Button:SetupBar( bar )
+  local config = bar:GetConfig()
+  if not config.buttons then
+    config.buttons = { }
+  end
+  local btnCfg = config.buttons
+
+  local r, c = bar:GetButtonGrid()
+  local n = r*c
+  local cfgN = n
+
+  local hint = nil
+  local i = 1
+  repeat
+    local b = bar:GetButton(i)
+    if b then
+      if i > n then
+        bar:RemoveButton(b)
+        b:Destroy()
+        if i > cfgN then
+          btnCfg[i] = nil
+        end
+      else
+        b:Refresh()
+        hint = b:GetActionID()
+      end
+    elseif i <= n then
+      local cfg = btnCfg[i] or { }
+      local success, r = pcall(self.New, self, cfg, bar, i, hint)  -- note call semantics for derived class constructors
+      if success and r then
+        b = r
+        bar:AddButton(i,b)
+        btnCfg[i] = cfg
+        b:Refresh()
+        hint = b:GetActionID()
+      else
+        n = i - 1
+        if not success then
+          bar:ClipNButtons(n)
+          cfgN = n
+          geterrorhandler()(r)
+        end
+      end
+    end
+    i = i + 1
+  until b == nil
+end
+
+function Button:AcquireActionID( id, hint, unique )
+  local poolID = self.actionPoolID
+  local maxID = self.actionMaxID
+  if not poolID or not maxID then
+    error("AcquireActionID: must setup pool first with SetActionIDPool")
+  end
+  local pool = idPools[poolID]
+  if not pool then
+    pool = { nWraps = 0, useCount = { } }
+    for i = 1, maxID do
+      pool.useCount[i] = 0
+    end
+    idPools[poolID] = pool
+  end
+  local useCount = pool.useCount
+  if id == nil then
+    repeat
+      local nWraps = pool.nWraps or 0
+      if hint and (useCount[hint] == nil or useCount[hint] == nWraps) then
+        id = hint
+      else
+        local start = hint or 1
+        for i = start, maxID do
+          if useCount[i] == nil or useCount[i] == nWraps then
+            id = i
+            break
+          end
+        end
+        if not id then
+          for i = 1, start do
+            if useCount[i] == nil or useCount[i] == nWraps then
+              id = i
+              break
+            end
+          end
+        end
+      end
+      if id == nil then
+        if unique then
+          return nil
+        end
+        pool.nWraps = nWraps + 1
+      end
+    until id ~= nil
+  end
+  useCount[id] = (useCount[id] or 0) + 1
+  return id
+end
+
+function Button:ReleaseActionID( id )
+  local poolID = self.actionPoolID
+  if not poolID  then
+    error("ReleaseActionID: must setup pool first with SetActionIDPool")
+  end
+  local pool = idPools[poolID]
+  if pool and id and pool.useCount[id] then
+    pool.useCount[id] = pool.useCount[id] - 1
+    pool.nWraps = min(pool.useCount[id], pool.nWraps)
+  end
+end
+
+function Button:Refresh()
+  local f = self:GetFrame()
+  self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() )
+end
+
+function Button:SetKeybindMode( mode )
+  local f = self.frame
+  if mode then
+    self.oldOnEnter = f:GetScript("OnEnter")
+    f:SetScript("OnEnter", kb_onEnter)
+  elseif self.oldOnEnter then
+    f:SetScript("OnEnter", self.oldOnEnter)
+    self.oldOnEnter = nil
+  end
+  self:ShowGridTemp(mode)
+  self:UpdateKeybindModeDisplay( mode )
+end
+
+function Button:UpdateKeybindModeDisplay( mode )
+  local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))]
+  if border then
+    if mode then
+      border:SetVertexColor(LKB:GetColorKeyBoundMode())
+      border:Show()
+    else
+      border:Hide()
+    end
+  end
+end
+
+function Button:UpdateHotkey( hotkey )
+  hotkey = hotkey or self.frames.hotkey
+  if not hotkey then
+    hotkey = _G[self:GetName().."HotKey"]
+    self.frames.hotkey = hotkey
+  end
+  if hotkey then
+    local txt = self.frame:GetHotkey()
+    hotkey:SetText( txt )
+    if txt == nil or txt == "" then
+      hotkey:Hide()
+    else
+      hotkey:Show()
+    end
+  end
+end
+
+function Button:GetActionIDLabel( create )
+  local f = self:GetFrame()
+  if not f.actionIDLabel and create then
+    local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+    label:SetAllPoints()
+    label:SetJustifyH("CENTER")
+    label:SetShadowColor(0,0,0,1)
+    label:SetShadowOffset(2,-2)
+    f.actionIDLabel = label -- store the label with the frame for recycling
+  end
+  return f.actionIDLabel
+end
+
+function Button:UpdateActionIDLabel( show )
+  local label = self:GetActionIDLabel( show )
+  if label then
+    if show then
+      local id = self:GetActionID()
+      if id then
+        label:SetText(tostring(id))
+        label:Show()
+        return
+      end
+    end
+    label:Hide()
+  end
+end
+
+function Button:SetNormalVertexColor( r, g, b, a )
+  if ReAction.LBF then
+    ReAction.LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a)
+  else
+    self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a)
+  end
+end
+
+function Button:GetNormalVertexColor()
+  if ReAction.LBF then
+    return ReAction.LBF:GetNormalVertexColor(self:GetFrame())
+  else
+    return self:GetFrame():GetNormalTexture():GetVertexColor()
+  end
+end
+
+function Button:UpdateShowGrid()
+ -- does nothing by default
+end
+
+function Button:ShowGridTemp(show)
+  -- does nothing by default
+end
+
+function Button:ShowGrid(show)
+  -- does nothing by default
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MultiCastButton.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,779 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local unpack = unpack
+local GetCVar = GetCVar
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local InCombatLockdown = InCombatLockdown
+local IsUsableSpell = IsUsableSpell
+local IsUsableAction = IsUsableAction
+local IsSpellKnown = IsSpellKnown
+local IsSpellInRange = IsSpellInRange
+local IsActionInRange = IsActionInRange
+local GetSpellInfo = GetSpellInfo
+local GetSpellCooldown = GetSpellCooldown
+local GetActionCooldown = GetActionCooldown
+local GetSpellTexture = GetSpellTexture
+local GetActionTexture = GetActionTexture
+local GetMultiCastTotemSpells = GetMultiCastTotemSpells
+
+--[[
+  Blizzard Constants:
+    - NUM_MULTI_CAST_BUTTONS_PER_PAGE = 4
+    - NUM_MULTI_CAST_PAGES = 3
+    - SHAMAN_TOTEM_PRIORITIES = { } -- sets the order of the totems
+    - TOTEM_MULTI_CAST_SUMMON_SPELLS = { } -- list of summon spellIDs
+    - TOTEM_MULTI_CAST_RECALL_SPELLS = { } -- list of recall spellIDs
+
+  Blizzard Events:
+    - UPDATE_MULTI_CAST_ACTIONBAR
+
+  Blizzard APIs:
+    - GetMultiCastBarOffset() : returns 6
+
+    - SetMultiCastSpell(actionID, spellID) (protected) OR
+         SetAttribute("type","multispell")
+         SetAttribute("action",actionID)
+         SetAttribute("spell",spellID)
+
+         note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(),
+               so that's action ID 132-144.
+
+    - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot)
+        returns spellIDs for all known totems that fit that slot. This function is available in
+        the secure environment.
+
+  Blizzard textures:
+    All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
+    texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
+    this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
+
+    Each totem button and arrow has a colored border indicating its elemental type.
+
+    TODO: 
+      - make whether to show the colored border configurable (looks really bad with ButtonFacade:Zoomed)
+      - apply ButtonFacade to the flyout buttons? Or at least zoom the textures slightly?
+      - use a multiplier with SetTexCoord on totem bar texture?
+
+  Design Notes:
+    - Only the header has a secure context. All other frames execute in its context.
+
+    - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are 
+      GetBonusBarOffset()=6, 132-144) with 3 pages of 4 buttons. The paging is controlled by
+      the summon flyout, which is also paged with the summon spells (the recall button is not paged)
+    
+    - A spell list is updated in the secure context at setup time (TODO: redo setup when learning new 
+      spells) with the list of spells known for each slot.
+    
+    - Each button (except recall) has an arrow button which appears on mouseover and when clicked
+      opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not
+      appear.
+    
+    - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child
+      of the bar. Each time the flyout panel is opened, the individual  buttons grab their corresponding
+      spell/type from the list, according to the slot which opened the flyout. Each button either sets
+      the current page (summon) or sets a multispell to an actionID via type="multispell". None of them
+      actually cast any spells (though, I suppose we could modify this so that e.g. configurable 
+      right-click casts the spell). The flyout also has a close button which closes the flyout: the
+      flyout-open code positions the close button anchored to the last button in the flyout (which 
+      changes dynamically because each slot has a different number of items in the list).
+
+    - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of 
+      the summon spells is cast from elsewhere.
+
+    - The default UI has Call of the Elements always selected on UI load. This module remembers the last
+      selected one and restores it.
+
+
+]]--
+
+
+--
+-- Secure snippets
+--
+
+-- bar
+local _bar_init = -- function(self)
+[[
+  -- set up some globals in the secure environment
+  flyout               = self:GetFrameRef("flyout")
+  flyoutSlot           = nil
+  summonSlot           = self:GetAttribute("summonSlot")
+  recallSlot           = self:GetAttribute("recallSlot")
+  baseActionID         = self:GetAttribute("baseActionID")
+  slotsPerPage         = self:GetAttribute("slotsPerPage")
+  currentPage          = currentPage or self:GetAttribute("lastSummon") or 1
+
+  totemIDsBySlot = newtable()
+  for i = 1, slotsPerPage do
+    totemIDsBySlot[i] = self:GetAttribute("TOTEM_PRIORITY_"..i)
+  end
+
+  -- these are set up in bar:SetupBar()
+  flyoutChildren = flyoutChildren or newtable()
+  summonSpells = summonSpells or newtable()
+]]
+
+local _onstate_multispellpage = -- function(self, stateid, newstate)
+[[
+  currentPage = tonumber(newstate)
+  control:CallMethod("UpdateLastSummon",currentPage)
+  control:ChildUpdate()
+]]
+
+
+-- buttons
+local _childupdate = -- function(self, snippetid, message)
+[[
+  local t = self:GetAttribute("type")
+  self:SetAttribute(t, self:GetAttribute(t.."-page"..currentPage))
+]]
+
+local _onEnter = -- function(self)
+  -- for whatever reason, RegisterAutoHide is unreliable
+  -- unless you re-anchor the frame prior to calling it.
+  -- Even then, it's still not terribly reliable.
+[[
+  local slot = self:GetAttribute("bar-idx")
+  local arrow = owner:GetFrameRef("arrow-"..slot)
+  if arrow and not arrow:IsShown() and not (flyout:IsVisible() and flyoutSlot == slot) then
+    arrow:ClearAllPoints()
+    arrow:SetPoint("BOTTOM",self,"TOP",0,0)
+    arrow:Show()
+    arrow:RegisterAutoHide(0)
+    arrow:AddToAutoHide(self)
+  end
+]]
+
+
+-- flyout arrow
+local _arrow_openFlyout = -- function(self)
+[[
+  local slot = self:GetAttribute("bar-idx")
+  local totemID = totemIDsBySlot[slot - (summonSlot or 0)]
+  if totemID == 0 then
+    totemID = "summon"
+  end
+
+  local lastButton, lastPage
+  for page, b in ipairs(flyoutChildren) do
+    b:Hide()
+    b:SetAttribute("totemSlot",totemID)
+    if slot == summonSlot then
+      local spellID = self:GetParent():GetAttribute("spell-page"..page)
+      if spellID then
+        b:SetAttribute("type","changePage")
+        b:SetAttribute("spell",spellID)
+        b:Show()
+        lastButton = b
+        lastPage = page
+      end
+    else
+      local spell = select(page, 0, GetMultiCastTotemSpells(totemID) )
+      if spell then
+        b:SetAttribute("type","multispell")
+        b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID)
+        b:SetAttribute("spell", spell)
+        b:Show()
+        lastButton = b
+        lastPage = page
+      end
+    end
+  end
+
+  local close = owner:GetFrameRef("close")
+  if lastButton and close then
+    close:ClearAllPoints()
+    close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring
+    close:Show()
+    control:CallMethod("UpdateFlyoutTextures",totemID)
+  end
+
+  flyout:ClearAllPoints()
+  flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0)  -- TODO: better anchoring
+  if lastPage then
+    flyout:SetHeight(lastPage * 27 + (close and close:GetHeight() or 0))
+  end
+  flyout:Show()
+  flyout:RegisterAutoHide(1) -- TODO: configurable
+  flyout:AddToAutoHide(owner)
+  flyoutSlot = slot
+  self:Hide()
+]]
+
+local _closeFlyout = -- function(self)
+[[
+  flyout:Hide()
+]]
+
+
+-- flyout child buttons
+local _flyout_child_preClick = -- function(self, button, down)
+[[
+  local button = button
+  if self:GetAttribute("type") == "changePage" then
+    owner:SetAttribute("state-multispellpage",self:GetAttribute("index"))
+    self:GetParent():Hide()
+    return false
+  else
+    return nil, "close"
+  end
+]]
+
+local _flyout_child_postClick = -- function(self, message, button, down)
+[[
+  if message == "close" then
+    self:GetParent():Hide() -- hide flyout after selecting
+  end
+]]
+
+
+--
+-- The Blizzard totem bar textures are all actually one big texture,
+-- with texcoord offsets. Shamelessly stolen from FrameXML/MultiCastActionBarFrame.lua
+--
+local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar"
+local FLYOUT_UP_BUTTON_HL_TCOORDS   = { 72/128,  92/128, 88/256,  98/256 }
+local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128,  92/128, 69/256,  79/256 }
+
+local SLOT_EMPTY_TCOORDS = {
+  [EARTH_TOTEM_SLOT] = {  66/128,  96/128,   3/256,  33/256 },
+	[FIRE_TOTEM_SLOT]  = {  67/128,  97/128, 100/256, 130/256 },
+	[WATER_TOTEM_SLOT] = {  39/128,  69/128, 209/256, 239/256 },
+	[AIR_TOTEM_SLOT]   = {  66/128,  96/128,  36/256,  66/256 },
+}
+
+local SLOT_OVERLAY_TCOORDS = {
+	[EARTH_TOTEM_SLOT] = {   1/128,  35/128, 172/256, 206/256 },
+	[FIRE_TOTEM_SLOT]  = {  36/128,  70/128, 172/256, 206/256 },
+	[WATER_TOTEM_SLOT] = {   1/128,  35/128, 207/256, 240/256 },
+	[AIR_TOTEM_SLOT]   = {  36/128,  70/128, 137/256, 171/256 },
+}
+
+local FLYOUT_UP_BUTTON_TCOORDS = {
+	["summon"]         = {  99/128, 127/128,  84/256, 102/256 },
+	[EARTH_TOTEM_SLOT] = {  99/128, 127/128, 160/256, 178/256 },
+	[FIRE_TOTEM_SLOT]  = {  99/128, 127/128, 122/256, 140/256 },
+	[WATER_TOTEM_SLOT] = {  99/128, 127/128, 199/256, 217/256 },
+	[AIR_TOTEM_SLOT]   = {  99/128, 127/128, 237/256, 255/256 },
+}
+
+local FLYOUT_DOWN_BUTTON_TCOORDS = {
+	["summon"]         = {  99/128, 127/128,  65/256,  83/256 },
+	[EARTH_TOTEM_SLOT] = {  99/128, 127/128, 141/256, 159/256 },
+	[FIRE_TOTEM_SLOT]  = {  99/128, 127/128, 103/256, 121/256 },
+	[WATER_TOTEM_SLOT] = {  99/128, 127/128, 180/256, 198/256 },
+	[AIR_TOTEM_SLOT]   = {  99/128, 127/128, 218/256, 236/256 },
+}
+
+local FLYOUT_TOP_TCOORDS = {
+	["summon"]         = {  33/128,  65/128,   1/256,  23/256 },
+	[EARTH_TOTEM_SLOT] = {   0/128,  32/128,  46/256,  68/256 },
+	[FIRE_TOTEM_SLOT]  = {  33/128,  65/128,  46/256,  68/256 },
+	[WATER_TOTEM_SLOT] = {   0/128,  32/128,   1/256,  23/256 },
+	[AIR_TOTEM_SLOT]   = {   0/128,  32/128,  91/256, 113/256 },
+}
+
+local FLYOUT_MIDDLE_TCOORDS = {
+	["summon"]         = {  33/128,  65/128,  23/256,  43/256 },
+	[EARTH_TOTEM_SLOT] = {   0/128,  32/128,  68/256,  88/256 },
+	[FIRE_TOTEM_SLOT]  = {  33/128,  65/128,  68/256,  88/256 },
+	[WATER_TOTEM_SLOT] = {   0/128,  32/128,  23/256,  43/256 },
+	[AIR_TOTEM_SLOT]   = {   0/128,  32/128, 113/256, 133/256 },
+}
+
+local eventList = { 
+  "ACTIONBAR_SLOT_CHANGED",
+  "ACTIONBAR_UPDATE_STATE",
+  "ACTIONBAR_UPDATE_USABLE",
+  "ACTIONBAR_UPDATE_COOLDOWN",
+  "UPDATE_BINDINGS",
+  "UPDATE_MULTI_CAST_ACTIONBAR",
+}
+
+--
+-- MultiCast Button class
+-- Inherits implementation methods from Action button class, but circumvents the constructor
+-- and redefines/removes some methods.
+--
+local buttonTypeID = "Totem"
+local Super = ReAction.Button
+local Action = ReAction.Button.Action
+local MultiCast = setmetatable( 
+  { 
+    defaultBarConfig = { 
+      type = buttonTypeID,
+      btnWidth = 36,
+      btnHeight = 36,
+      btnRows = 1,
+      btnColumns = 6,
+      spacing = 3,
+      buttons = { }
+    },
+
+    barType = L["Totem Bar"], 
+    buttonTypeID = buttonTypeID
+  },
+  { __index = Action } )
+
+ReAction.Button.MultiCast = MultiCast
+ReAction:RegisterBarType(MultiCast)
+
+function MultiCast:New( btnConfig, bar, idx )
+  local maxIndex = bar.nTotemSlots or 0
+  if bar.summonSlot then
+    maxIndex = maxIndex + 1
+  end
+  if bar.recallSlot then
+    maxIndex = maxIndex + 1
+  end
+
+  if not bar.hasMulticast or idx > maxIndex then
+    return false
+  end
+
+  if idx < 1 then
+    error("invalid index")
+  end
+
+  local name = format("ReAction_%s_Totem_%d",bar:GetName(),idx)
+ 
+  self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+  local barFrame = bar:GetFrame()
+  local f = self:GetFrame()
+
+  -- attributes
+  local page = (idx == bar.recallSlot) and 1 or bar:GetConfig().lastSummon or 1
+  if idx == bar.recallSlot or idx == bar.summonSlot then
+    f:SetAttribute("type","spell")
+    local spells = (idx == bar.summonSlot) and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS
+    f:SetAttribute("spell",spells[page])
+    for i, spell in ipairs(spells) do 
+      if spell and IsSpellKnown(spell) then
+        f:SetAttribute("spell-page"..i, spell)
+      end
+    end
+  else
+    local offset = bar.summonSlot and 1 or 0
+    local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset]
+    local baseAction = barFrame:GetAttribute("baseActionID") + slot
+    self.totemSlot = slot
+    f:SetAttribute("type","action")
+    f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
+    for i = 1, NUM_MULTI_CAST_PAGES do
+      f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
+    end
+    if not f.overlayTex then
+      local tx = f:CreateTexture("OVERLAY")
+      tx:SetTexture(TOTEM_TEXTURE)
+      tx:SetTexCoord(unpack(SLOT_OVERLAY_TCOORDS[self.totemSlot]))
+      tx:SetWidth(34)
+      tx:SetHeight(34)
+      tx:SetPoint("CENTER")
+      tx:Show()
+      f.overlayTex = tx
+    end
+  end
+  f:SetAttribute("bar-idx",idx)
+
+  -- non secure scripts
+  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+  f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
+
+  -- secure handlers
+  if idx ~= bar.recallSlot then
+    f:SetAttribute("_childupdate",_childupdate)
+  end
+  barFrame:WrapScript(f, "OnEnter", _onEnter)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForClicks("AnyUp")
+  for _, evt in pairs(eventList) do
+    f:RegisterEvent(evt)
+  end
+
+  -- Set up a proxy for the icon texture for use with ButtonFacade
+  local SetTexCoordRaw = self.frames.icon.SetTexCoord
+  self.frames.icon.SetTexCoord = function( tx, ... )
+    if self:GetIconTexture() == TOTEM_TEXTURE then
+      SetTexCoordRaw(tx,select(2,self:GetIconTexture()))
+    else
+      SetTexCoordRaw(tx,...)
+    end
+  end
+
+  -- attach to skinner
+  bar:SkinButton(self)
+
+  f:Show()
+
+  -- open arrow and flyout background textures
+  if idx ~= bar.recallSlot then
+    local arrow = f._arrowFrame or CreateFrame("Button", nil, f, "SecureFrameTemplate")
+    f._arrowFrame = arrow
+    arrow:SetWidth(28)
+    arrow:SetHeight(18)
+    arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
+    arrow:SetNormalTexture(TOTEM_TEXTURE)
+    local slot = self.totemSlot or "summon"
+    arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS[slot]) )
+    arrow:SetHighlightTexture(TOTEM_TEXTURE)
+    arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
+    arrow:SetAttribute("bar-idx",idx)
+    arrow:Hide()
+    barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
+    barFrame:SetFrameRef("arrow-"..idx,arrow)
+  end
+
+  self:Refresh()
+
+  return self
+end
+
+function MultiCast:Destroy()
+  local barFrame = self.bar:GetFrame()
+  local f = self:GetFrame()
+  pcall( barFrame.UnwrapScript, barFrame, f, "OnEnter" ) -- ignore errors
+  if f._arrowFrame then
+    pcall( barFrame.UnwrapScript, barFrame, f._arrowFrame,"OnClick" ) -- ignore errors
+  end
+  Super.Destroy(self)
+end
+
+function MultiCast:Refresh()
+  Super.Refresh(self)
+  self:UpdateAction()
+end
+
+function MultiCast:ShowGrid( show )
+end
+
+function MultiCast:ShowGridTemp( show )
+end
+
+function MultiCast:AcquireActionID()
+end
+
+function MultiCast:ReleaseActionID()
+end
+
+function MultiCast:UpdateShowGrid()
+end
+
+function MultiCast:UpdateBorder()
+end
+
+function MultiCast:UpdateMacroText()
+end
+
+function MultiCast:UpdateCount()
+end
+
+function MultiCast:UpdateCheckedState()
+  local action = self:GetActionID()
+  if action and IsCurrentAction(action) then
+    self:GetFrame():SetChecked(1)
+  else
+    self:GetFrame():SetChecked(0)
+  end
+end
+
+function MultiCast:RefreshHasActionAttributes()
+end
+
+function MultiCast:UpdateFlash()
+end
+
+function MultiCast:GetIconTexture()
+  local tx
+  if self.spellID then
+    tx = GetSpellTexture(GetSpellInfo(self.spellID))
+  elseif self.actionID then
+    tx = GetActionTexture(self.actionID)
+  end
+  if tx then
+    return tx
+  else
+    return TOTEM_TEXTURE, unpack(SLOT_EMPTY_TCOORDS[self.totemSlot or 1])
+  end
+end
+
+function MultiCast:UpdateAction()
+  local action = self:GetActionID()
+  if action then
+    if action ~= self.actionID then
+      self.actionID = action
+      self:UpdateAll()
+    end
+  else
+    local spellID = self:GetSpellID()
+    if spellID ~= self.spellID then
+      self.spellID = spellID
+      self:UpdateAll()
+    end
+  end
+end
+
+function MultiCast:GetActionID(page)
+  return self:GetFrame():GetAttribute("action")
+end
+
+function MultiCast:GetSpellID(page)
+  return self:GetFrame():GetAttribute("spell")
+end
+
+function MultiCast:SetActionID( id  )
+  error("Can not set action ID of multicast buttons")
+end
+
+function MultiCast:SetTooltip()
+  local barFrame = self:GetFrame()
+  if GetCVar("UberTooltips") == "1" then
+    GameTooltip_SetDefaultAnchor(GameTooltip, barFrame)
+  else
+    GameTooltip:SetOwner(barFrame)
+  end
+  if self.spellID then
+    GameTooltip:SetSpellByID(self.spellID,false,true)
+  elseif self.actionID then
+    GameTooltip:SetAction(self.actionID)
+  end
+end
+
+function MultiCast:GetUsable()
+  if self.spellID then
+    return IsUsableSpell((GetSpellInfo(self.spellID)))
+  elseif self.actionID then
+    return IsUsableAction(self.actionID)
+  end
+end
+
+function MultiCast:GetInRange()
+  if self.spellID then
+    return IsSpellInRange((GetSpellInfo(self.spellID))) == 0
+  elseif self.actionID then
+    return IsActionInRange(self.actionID) == 0
+  end
+end
+
+function MultiCast:GetCooldown()
+  if self.spellID then
+    return GetSpellCooldown((GetSpellInfo(self.spellID)))
+  elseif self.actionID then
+    return GetActionCooldown(self.actionID)
+  else
+    return 0, 0, 0
+  end
+end
+
+function MultiCast:UPDATE_MULTI_CAST_ACTIONBAR()
+  self:UpdateAll()
+end
+
+
+--
+-- flyout setup
+--
+local function ShowFlyoutTooltip(frame)
+  if GetCVar("UberTooltips") == "1" then
+    GameTooltip_SetDefaultAnchor(GameTooltip, frame)
+  else
+    GameTooltip:SetOwner(frame)
+  end
+  local spell = frame:GetAttribute("spell")
+  if spell == nil or spell == 0 then
+    GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
+  else
+    GameTooltip:SetSpellByID(spell,false,true)
+  end
+end
+
+local function HideFlyoutTooltip()
+  GameTooltip:Hide()
+end
+
+local function UpdateFlyoutIcon(frame)
+  local spellID = frame:GetAttribute("spell")
+  if spellID == 0 or spellID == nil then
+    frame.icon:SetTexture(TOTEM_TEXTURE)
+    local slot = tonumber(frame:GetAttribute("totemSlot")) or 1
+    frame.icon:SetTexCoord( unpack(SLOT_EMPTY_TCOORDS[slot]) )
+  else
+    frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
+    frame.icon:SetTexCoord(0,1,0,1)
+  end
+end
+
+function MultiCast:SetupBar( bar )
+  Super.SetupBar(self,bar)
+
+  local slot = 0
+  local nTotemSlots = 0
+  local summonSlot = nil
+  local recallSlot = nil
+
+  -- figure out the capabilities of the character
+	for i, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do 
+    if spell and IsSpellKnown(spell) then
+      slot = 1
+      summonSlot = 1
+    end
+	end
+
+  for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
+		local totem = SHAMAN_TOTEM_PRIORITIES[i];
+		if GetTotemInfo(totem) and GetMultiCastTotemSpells(totem) then
+      nTotemSlots = nTotemSlots + 1
+      slot = slot + 1
+    end
+  end
+
+  slot = slot + 1
+	for i, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do 
+    if spell and IsSpellKnown(spell) then
+      recallSlot = slot
+    end
+	end
+
+  if nTotemSlots == 0 then
+    bar.hasMulticast = false -- no multicast capability
+    return
+  end
+
+  bar.hasMulticast = true
+  bar.summonSlot   = summonSlot
+  bar.recallSlot   = recallSlot
+  bar.nTotemSlots  = nTotemSlots
+
+
+  local f = bar:GetFrame()
+
+  -- init bar secure environment
+  f:SetAttribute("lastSummon", bar:GetConfig().lastSummon)
+  f:SetAttribute("summonSlot", summonSlot)
+  f:SetAttribute("recallSlot", recallSlot)
+  f:SetAttribute("slotsPerPage", NUM_MULTI_CAST_BUTTONS_PER_PAGE)
+  f:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS)
+  for i, p in ipairs(SHAMAN_TOTEM_PRIORITIES) do
+    f:SetAttribute("TOTEM_PRIORITY_"..i,p)
+  end
+  f:SetAttribute("_onstate-multispellpage", _onstate_multispellpage)
+
+  function f:UpdateLastSummon(value)
+    bar:GetConfig().lastSummon = value
+  end
+
+  -- create flyout container frame and close arrow
+  local flyout = bar._flyoutFrame
+  if not flyout then
+    flyout = CreateFrame("Frame", nil, f, "SecureFrameTemplate")
+    bar._flyoutFrame = flyout
+    f:SetFrameRef("flyout",flyout)
+    flyout.buttons = { }
+    flyout:Hide()
+    flyout:SetWidth(24)
+    flyout:SetHeight(1)
+    flyout:SetPoint("BOTTOM",f,"TOP",0,0)
+
+    local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
+    close:SetWidth(28)
+    close:SetHeight(18)
+    close:SetPoint("BOTTOM",flyout,"TOP")
+    close:SetNormalTexture(TOTEM_TEXTURE)
+    close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS["summon"]))
+    close:SetHighlightTexture(TOTEM_TEXTURE)
+    close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
+    f:SetFrameRef("close",close)
+    f:WrapScript(close, "OnClick", _closeFlyout)
+    close:Show()
+
+    local midTx = flyout:CreateTexture("BACKGROUND")
+    midTx:SetWidth(32)
+    midTx:SetHeight(20)
+    midTx:SetPoint("BOTTOM")
+    midTx:SetTexture(TOTEM_TEXTURE)
+    midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS["summon"]))
+    midTx:Show()
+
+    local topTx = flyout:CreateTexture("BACKGROUND")
+    topTx:SetWidth(32)
+    topTx:SetHeight(20)
+    topTx:SetTexture(TOTEM_TEXTURE)
+    midTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS["summon"]))
+    topTx:SetPoint("BOTTOM",midTx,"TOP",0,-10)
+    topTx:Show()
+
+    function flyout:UpdateTextures(slot)
+      slot = slot or "summon"
+      close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS[slot]))
+      midTx:ClearAllPoints()
+      midTx:SetPoint("BOTTOM")
+      midTx:SetPoint("TOP",close,"BOTTOM",0,0)
+      midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS[slot]))
+      topTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS[slot]))
+    end
+
+    -- create flyout buttons
+    for i = 1, 10 do -- maximum 9 spells + 1 empty slot
+      local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
+      b:SetWidth(24)
+      b:SetHeight(24)
+      local prev = flyout.buttons[i-1]
+      b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring
+      b.icon = b:CreateTexture("BACKGROUND")
+      b.icon:SetAllPoints()
+      b.icon:Show()
+      b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
+      b:GetHighlightTexture():SetBlendMode("ADD")
+      b:RegisterForClicks("AnyUp")
+      b:SetScript("OnShow",UpdateFlyoutIcon)
+      b:SetScript("OnEnter",ShowFlyoutTooltip)
+      b:SetScript("OnLeave",HideFlyoutTooltip)
+      b:SetAttribute("index",i)
+      f:SetAttribute("flyout-child-idx",i)
+      f:SetFrameRef("flyout-child",b)
+      f:Execute([[
+          flyoutChildren = flyoutChildren or newtable()
+          flyoutChildren[self:GetAttribute("flyout-child-idx")] = self:GetFrameRef("flyout-child")
+        ]])
+      f:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick)
+      b:Show()
+      flyout.buttons[i] = b
+    end
+  end
+
+  -- scale flyout frame
+  local scale = bar:GetButtonSize() / 36
+  flyout:SetScale(scale)
+
+  function f:UpdateFlyoutTextures(slot)
+    flyout:UpdateTextures(slot)
+  end
+
+  -- re-execute setup when new spells are loaded
+  if not f.events_registered then
+    f:RegisterEvent("UPDATE_MULTI_CAST_ACTIONBAR")
+    f:RegisterEvent("PLAYER_ENTERING_WORLD")
+      -- Bar.frame does not use OnEvent
+    f:SetScript("OnEvent", 
+      function()
+        if not InCombatLockdown() then
+          self:SetupBar(bar)
+        end
+      end)
+    f.events_registered = true
+  end
+
+
+  f:Execute(_bar_init)
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Overlay.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,754 @@
+local addonName, addonTable = ...
+local ReAction               = addonTable.ReAction
+local L                      = ReAction.L
+local LKB                    = ReAction.LKB
+local CreateFrame            = CreateFrame
+local InCombatLockdown       = InCombatLockdown
+local floor                  = math.floor
+local min                    = math.min
+local format                 = string.format
+local GameTooltip            = GameTooltip
+local Bar                    = ReAction.Bar
+local GetSize                = Bar.GetSize
+local SetSize                = Bar.SetSize
+local GetButtonSize          = Bar.GetButtonSize
+local GetButtonGrid          = Bar.GetButtonGrid
+local SetButtonSize          = Bar.SetButtonSize
+local SetButtonGrid          = Bar.SetButtonGrid
+local ApplyAnchor            = Bar.ApplyAnchor
+local GameTooltipTextRight1  = GameTooltipTextRight1
+local GameTooltipTextRight2  = GameTooltipTextRight2
+local GameTooltipTextRight3  = GameTooltipTextRight3
+
+--
+-- Wrap some of the bar manipulators to make them state-aware
+--
+local function SetAnchor( bar, point, frame, relPoint, x, y )
+  local state = bar:GetSecureState()
+  if state then
+    local anchorstate = bar:GetStateProperty(state, "anchorEnable")
+    if anchorstate then
+      bar:SetStateProperty(state, "anchorFrame", frame)
+      bar:SetStateProperty(state, "anchorPoint", point)
+      bar:SetStateProperty(state, "anchorRelPoint", relPoint)
+      bar:SetStateProperty(state, "anchorX", x or 0)
+      bar:SetStateProperty(state, "anchorY", y or 0)
+      bar:SetAnchor(bar:GetAnchor())
+      return
+    end
+  end
+  bar:SetAnchor(point, frame, relPoint, x, y)
+end
+
+local function GetStateScale( bar )
+  local state = bar:GetSecureState()
+  if state and bar:GetStateProperty(state, "enableScale") then
+    return bar:GetStateProperty(state, "scale")
+  end
+end
+
+local function SetStateScale( bar, scale )
+  local state = bar:GetSecureState()
+  if state and bar:GetStateProperty(state, "enableScale") then
+    bar:SetStateProperty(state, "scale", scale)
+  end
+end
+
+
+--
+-- Bar config overlay
+--
+
+local function GetNormalTextColor()
+  return 1.0, 1.0, 1.0, 1.0
+end
+
+local function GetAnchoredTextColor()
+  return 1.0, 1.0, 1.0, 1.0
+end
+
+local function GetNormalBgColor()
+  return 0.7, 0.7, 1.0, 0.3
+end
+
+local function GetAnchoredBgColor()
+  return 0.9, 0.2, 0.7, 0.3
+end
+
+local function StoreSize(bar)
+  local f = bar:GetFrame()
+  SetSize( bar, f:GetWidth(), f:GetHeight() )
+end
+
+local function StoreExtents(bar)
+  local f = bar:GetFrame()
+  local p, fr, rp, x, y = f:GetPoint(1)
+  fr = fr and fr:GetName() or "UIParent"
+  SetAnchor( bar, p, fr, rp, x, y )
+  SetSize( bar, f:GetWidth(), f:GetHeight() )
+end
+
+local function RecomputeButtonSize(bar)
+  local w, h = GetSize(bar)
+  local bw, bh = GetButtonSize(bar)
+  local r, c, s = GetButtonGrid(bar)
+
+  local scaleW = (floor(w/c) - s) / bw
+  local scaleH = (floor(h/r) - s) / bh
+  local scale = min(scaleW, scaleH)
+
+  SetButtonSize(bar, scale * bw, scale * bh, s)
+end
+
+local function ComputeBarScale(bar, overlay)
+  local w, h = overlay:GetWidth() - 8, overlay:GetHeight() - 8
+  local bw, bh = GetButtonSize(bar)
+  local r, c, s = GetButtonGrid(bar)
+
+  local scaleW = w / (c*(bw+s))
+  local scaleH = h / (r*(bh+s))
+  local scale = min(scaleW, scaleH)
+
+  if scale > 2.5 then
+    scale = 2.5
+  elseif scale < 0.25 then
+    scale = 0.25
+  end
+
+  return scale
+end
+
+local function RecomputeButtonSpacing(bar)
+  local w, h = GetSize(bar)
+  local bw, bh = GetButtonSize(bar)
+  local r, c, s = GetButtonGrid(bar)
+
+  SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh))
+end
+
+local function RecomputeGrid(bar)
+  local w, h = GetSize(bar)
+  local bw, bh = GetButtonSize(bar)
+  local r, c, s = GetButtonGrid(bar)
+
+  SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s)
+end
+
+local function ClampToButtons(bar)
+  local bw, bh = GetButtonSize(bar)
+  local r, c, s = GetButtonGrid(bar)
+  SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1)
+end
+
+local function HideGameTooltip()
+  GameTooltip:Hide()
+end
+
+local anchorInside  = { inside = true }
+local anchorOutside = { outside = true }
+local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" }
+local oppositeEdges = {
+  TOP = "BOTTOM",
+  BOTTOM = "TOP",
+  LEFT = "RIGHT",
+  RIGHT = "LEFT"
+}
+local pointsOnEdge = {
+  BOTTOM = { "BOTTOM", "BOTTOMLEFT",  "BOTTOMRIGHT",  },
+  TOP    = { "TOP",    "TOPLEFT",     "TOPRIGHT",     },
+  RIGHT  = { "RIGHT",  "BOTTOMRIGHT", "TOPRIGHT",     },
+  LEFT   = { "LEFT",   "BOTTOMLEFT",  "TOPLEFT",      },
+}
+local edgeSelector = {
+  BOTTOM = 1,  -- select x of x,y
+  TOP    = 1,  -- select x of x,y
+  LEFT   = 2,  -- select y of x,y
+  RIGHT  = 2,  -- select y of x,y  
+}
+local snapPoints = {
+  [anchorOutside] = {
+    BOTTOMLEFT  = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"},
+    BOTTOM      = {"TOP"},
+    BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"},
+    RIGHT       = {"LEFT"},
+    TOPRIGHT    = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"},
+    TOP         = {"BOTTOM"},
+    TOPLEFT     = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"},
+    LEFT        = {"RIGHT"},
+    CENTER      = {"CENTER"}
+  },
+  [anchorInside] = {
+    BOTTOMLEFT  = {"BOTTOMLEFT"},
+    BOTTOM      = {"BOTTOM"},
+    BOTTOMRIGHT = {"BOTTOMRIGHT"},
+    RIGHT       = {"RIGHT"},
+    TOPRIGHT    = {"TOPRIGHT"},
+    TOP         = {"TOP"},
+    TOPLEFT     = {"TOPLEFT"},
+    LEFT        = {"LEFT"},
+    CENTER      = {"CENTER"}
+  }
+}
+local insidePointOffsetFuncs = {
+  BOTTOMLEFT  = function(x, y) return x, y end,
+  BOTTOM      = function(x, y) return 0, y end,
+  BOTTOMRIGHT = function(x, y) return -x, y end,
+  RIGHT       = function(x, y) return -x, 0 end,
+  TOPRIGHT    = function(x, y) return -x, -y end,
+  TOP         = function(x, y) return 0, -y end,
+  TOPLEFT     = function(x, y) return x, -y end,
+  LEFT        = function(x, y) return x, 0 end,
+  CENTER      = function(x, y) return x, y end,
+}
+local pointCoordFuncs = {
+  BOTTOMLEFT  = function(f) return f:GetLeft(),  f:GetBottom() end,
+  BOTTOM      = function(f) return nil,          f:GetBottom() end,
+  BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end,
+  RIGHT       = function(f) return f:GetRight(), nil end,
+  TOPRIGHT    = function(f) return f:GetRight(), f:GetTop() end,
+  TOP         = function(f) return nil,          f:GetTop() end,
+  TOPLEFT     = function(f) return f:GetLeft(),  f:GetTop() end,
+  LEFT        = function(f) return f:GetLeft(),  nil end,
+  CENTER      = function(f) return f:GetCenter() end,
+}
+local edgeBoundsFuncs = {
+  BOTTOM = function(f) return f:GetLeft(), f:GetRight() end,
+  LEFT   = function(f) return f:GetBottom(), f:GetTop() end
+}
+edgeBoundsFuncs.TOP   = edgeBoundsFuncs.BOTTOM
+edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT
+local cornerTexCoords = {
+              -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
+  TOPLEFT     = { 1,   1,   1,   0,   0,   1,   0,   0 },
+  TOPRIGHT    = { 1,   0,   0,   0,   1,   1,   0,   1 },
+  BOTTOMLEFT  = { 0,   1,   1,   1,   0,   0,   1,   0 },
+  BOTTOMRIGHT = { 0,   0,   0,   1,   1,   0,   1,   1 },
+}
+
+-- Returns absolute coordinates x,y of the named point 'p' of frame 'f'
+local function GetPointCoords( f, p )
+  local x, y = pointCoordFuncs[p](f)
+  if not(x and y) then
+    local cx, cy = f:GetCenter()
+    x = x or cx
+    y = y or cy
+  end
+  return x, y
+end
+
+
+-- Returns true if frame 'f1' can be anchored to frame 'f2'
+local function CheckAnchorable( f1, f2 )
+  -- can't anchor a frame to itself or to nil
+  if f1 == f2 or f2 == nil then
+    return false
+  end
+  
+  -- can always anchor to UIParent
+  if f2 == UIParent then
+    return true
+  end
+  
+  -- also can't do circular anchoring of frames 
+  -- walk the anchor chain, which generally shouldn't be that expensive
+  -- (who nests draggables that deep anyway?)
+  for i = 1, f2:GetNumPoints() do
+    local _, f = f2:GetPoint(i)
+    if not f then f = f2:GetParent() end
+    return CheckAnchorable(f1,f)
+  end
+  
+  return true
+end
+
+-- Returns true if frames f1 and f2 specified edges overlap
+local function CheckEdgeOverlap( f1, f2, e )
+  local l1, u1 = edgeBoundsFuncs[e](f1)
+  local l2, u2 = edgeBoundsFuncs[e](f2)
+  return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2
+end
+
+-- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2
+local function CheckPointEdgeOverlap( f1, p1, f2, e2 )
+  local l, u = edgeBoundsFuncs[e2](f2)
+  local x, y = GetPointCoords(f1,p1)
+  x = select(edgeSelector[e2], x, y)
+  return l <= x and x <= u
+end
+
+-- Returns the distance between corresponding edges. It is 
+-- assumed that the passed in edges e1 and e2 are the same or opposites
+local function GetEdgeDistance( f1, f2, e1, e2 )
+  local x1, y1 = pointCoordFuncs[e1](f1)
+  local x2, y2 = pointCoordFuncs[e2](f2)
+  return math.abs((x1 or y1) - (x2 or y2))
+end
+
+local globalSnapTargets = { [UIParent] = anchorInside }
+
+local function GetClosestFrameEdge(f1,f2,a)
+  local dist, edge, opp
+  if f2:IsVisible() and CheckAnchorable(f1,f2) then
+    for _, e in pairs(edges) do
+      local o = a.inside and e or oppositeEdges[e]
+      if CheckEdgeOverlap(f1,f2,e) then
+        local d = GetEdgeDistance(f1, f2, e, o)
+        if not dist or (d < dist) then
+          dist, edge, opp = d, e, o
+        end
+      end
+    end
+  end
+  return dist, edge, opp
+end
+
+local function GetClosestVisibleEdge( f )
+  local r, o, e1, e2
+  local a = anchorOutside
+  for _, b in ReAction:IterateBars() do
+    local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a)
+    if d and (not r or d < r) then
+      r, o, e1, e2 = d, b:GetFrame(), e, opp
+    end
+  end
+  for f2, a2 in pairs(globalSnapTargets) do
+    local d, e, opp = GetClosestFrameEdge(f,f2,a2)
+    if d and (not r or d < r) then
+      r, o, e1, e2, a = d, f2, e, opp, a2
+    end
+  end
+  return o, e1, e2, a
+end
+
+local function GetClosestVisiblePoint(f1)
+  local f2, e1, e2, a = GetClosestVisibleEdge(f1)
+  if f2 then
+    local rsq, p, rp, x, y
+    -- iterate pointsOnEdge in order and use < to prefer edge centers to corners
+    for _, p1 in ipairs(pointsOnEdge[e1]) do
+      if CheckPointEdgeOverlap(f1,p1,f2,e2) then
+        for _, p2 in pairs(snapPoints[a][p1]) do
+          local x1, y1 = GetPointCoords(f1,p1)
+          local x2, y2 = GetPointCoords(f2,p2)
+          local dx = x1 - x2
+          local dy = y1 - y2
+          local rsq2 = dx*dx + dy*dy
+          if not rsq or rsq2 < rsq then
+            rsq, p, rp, x, y = rsq2, p1, p2, dx, dy
+          end
+        end
+      end
+    end
+    return f2, p, rp, x, y
+  end
+end
+
+local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff)
+  local o, p, rp, x, y = GetClosestVisiblePoint(f1)
+  local s = false
+
+  local insideOffsetFunc = p and insidePointOffsetFuncs[p]
+  local coordFunc = p and pointCoordFuncs[p]
+  if not insideOffsetFunc or not coordFunc then
+    return
+  end
+  
+  local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0)
+  local xx, yy = coordFunc(f1)
+  if xx and yy then
+    if math.abs(x) <= rx then
+      if math.abs(y) <= ry then
+        x = sx
+        y = sy
+        s = true
+      elseif CheckEdgeOverlap(f1,o,"LEFT") then
+        x = sx
+        s = true
+      end
+    elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then
+      y = sy
+      s = true
+    end
+  elseif xx then
+    if math.abs(x) <= rx then
+      x = sx
+      s = true
+      if math.abs(y) <= ry then
+        y = sy
+      end
+    end
+  elseif yy then
+    if math.abs(y) <= ry then
+      y = sy
+      s = true
+      if math.abs(x) <= rx then
+        x = sx
+      end
+    end
+  end
+
+  -- correct for some Lua oddities with doubles
+  if x == -0 then x = 0 end
+  if y == -0 then y = 0 end
+  
+  if s then
+    return o, p, rp, math.floor(x), math.floor(y)
+  end
+end
+
+local function CreateSnapIndicator()
+  local si = CreateFrame("Frame",nil,UIParent)
+  si:SetFrameStrata("HIGH")
+  si:SetHeight(16)
+  si:SetWidth(16)
+  local tex = si:CreateTexture()
+  tex:SetAllPoints()
+  tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
+  tex:SetBlendMode("ADD")
+  tex:SetDrawLayer("OVERLAY")
+  return si
+end
+
+local si1 = CreateSnapIndicator()
+local si2 = CreateSnapIndicator()
+
+local function DisplaySnapIndicator( f, rx, ry, xOff, yOff )
+  local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff)
+  if o then
+    si1:ClearAllPoints()
+    si2:ClearAllPoints()
+    si1:SetPoint("CENTER", f, p, 0, 0)
+    local xx, yy = pointCoordFuncs[rp](o)
+    x = math.abs(x) <=rx and xx and 0 or x
+    y = math.abs(y) <=ry and yy and 0 or y
+    si2:SetPoint("CENTER", o, rp, x, y)
+    si1:Show()
+    si2:Show()
+  else
+    if si1:IsVisible() then
+      si1:Hide()
+      si2:Hide()
+    end
+  end
+  return o, p
+end
+
+local function HideSnapIndicator()
+  if si1:IsVisible() then
+    si1:Hide()
+    si2:Hide()
+  end
+end
+
+local function UpdateLabelString(overlay)
+  local label = overlay.labelString
+  if label then
+    local name = overlay.labelName
+    if name and overlay.labelSubtext then
+      name = format("%s (%s)", name, overlay.labelSubtext)
+    end
+    label:SetText(name or "")
+  end
+end
+
+local function CreateControls(bar)
+  local f = bar:GetFrame()
+
+  f:SetMovable(true)
+  f:SetResizable(true)
+
+  -- child of UIParent so that alpha and scale doesn't propagate to it
+  local overlay = CreateFrame("Button", nil, UIParent)
+  overlay:EnableMouse(true)
+  overlay:SetFrameLevel(10) -- set it above the buttons
+  overlay:SetPoint("TOPLEFT", f, "TOPLEFT", -4, 4)
+  overlay:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 4, -4)
+  overlay:SetBackdrop({
+    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+    tile = true,
+    tileSize = 16,
+    edgeSize = 16,
+    insets = { left = 0, right = 0, top = 0, bottom = 0 },
+  })
+
+  -- textures
+  local bgTex = overlay:CreateTexture(nil,"BACKGROUND")
+  bgTex:SetTexture(0.7,0.7,1.0,0.2)
+  bgTex:SetPoint("TOPLEFT",4,-4)
+  bgTex:SetPoint("BOTTOMRIGHT",-4,4)
+  local hTex = overlay:CreateTexture(nil,"HIGHLIGHT")
+  hTex:SetTexture(0.7,0.7,1.0,0.2)
+  hTex:SetPoint("TOPLEFT",4,-4)
+  hTex:SetPoint("BOTTOMRIGHT",-4,4)
+  hTex:SetBlendMode("ADD")
+  local aTex = overlay:CreateTexture(nil,"ARTWORK")
+  aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
+  aTex:SetWidth(16)
+  aTex:SetHeight(16)
+  aTex:Hide()
+
+  -- label
+  local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+  label:SetAllPoints()
+  label:SetJustifyH("CENTER")
+  label:SetShadowColor(0,0,0,1)
+  label:SetShadowOffset(3,-3)
+  label:SetTextColor(GetNormalTextColor())
+  label:SetText(bar:GetName())
+  label:Show()
+  overlay.labelString = label
+  overlay.labelName = bar:GetName()
+
+  local function UpdateAnchorDecoration()
+    local point, anchor, relPoint, x, y = f:GetPoint(1)
+    if point then
+      local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
+      if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then
+        bgTex:SetTexture( GetAnchoredBgColor() )
+        hTex:SetTexture( GetAnchoredBgColor() )
+        label:SetTextColor( GetAnchoredTextColor() )
+        aTex:ClearAllPoints()
+        aTex:SetPoint(point)
+        aTex:Show()
+        return
+      end
+    end
+    bgTex:SetTexture( GetNormalBgColor() )
+    hTex:SetTexture( GetNormalBgColor() )
+    label:SetTextColor( GetNormalTextColor() )
+    aTex:Hide()
+  end
+
+  local function StopResize()
+    f:StopMovingOrSizing()
+    f.isMoving = false
+    f:SetScript("OnUpdate",nil)
+    StoreSize(bar)
+    ClampToButtons(bar)
+    ReAction:RefreshEditor()
+  end
+
+  local function CornerUpdate()
+    local bw, bh = GetButtonSize(bar)
+    local r, c, s = GetButtonGrid(bar)
+    local ss = GetStateScale(bar)
+    if IsShiftKeyDown() then
+      if ss then
+        f:SetMinResize( ((s+bw)*c*0.25)/ss, ((s+bh)*r*0.25)/ss )
+        f:SetMaxResize( ((s+bw)*c*2.5 + 1)/ss, ((s+bh)*r*2.5 + 1)/ss )
+        scale = ComputeBarScale(bar, overlay)
+      else
+        f:SetMinResize( (s+12)*c+1, (s+12)*r+1 )
+        f:SetMaxResize( (s+128)*c+1, (s+128)*r+1 )
+        RecomputeButtonSize(bar)
+      end
+    elseif not ss and IsAltKeyDown() then
+      f:SetMinResize( bw*c, bh*r )
+      f:SetMaxResize( 2*bw*c, 2*bh*r )
+      RecomputeButtonSpacing(bar)
+    else
+      f:SetMinResize( bw+s+1, bh+s+1 )
+      f:SetMaxResize( 50*(bw+s)+1, 50*(bh+s)+1 )
+      RecomputeGrid(bar)
+    end
+    GameTooltipTextRight2:SetText(format("%d x %d",r,c))
+
+    local ss = GetStateScale(bar)
+    if ss then
+      GameTooltipTextRight4:SetText(format("%d%%", scale*100))
+    else
+      local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
+      GameTooltipTextRight3:SetText(size)
+      GameTooltipTextRight4:SetText(tostring(s))
+    end
+  end
+
+  -- corner drag handles
+  for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do
+    local corner = CreateFrame("Frame",nil,overlay)
+    corner:EnableMouse(true)
+    corner:SetWidth(16)
+    corner:SetHeight(16)
+    corner:SetPoint(point)
+
+    local tex = corner:CreateTexture(nil,"HIGHLIGHT")
+    tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner")
+    tex:SetTexCoord(unpack(cornerTexCoords[point]))
+    tex:SetBlendMode("ADD")
+    tex:SetAlpha(0.6)
+    tex:SetAllPoints()
+    
+    corner:SetScript("OnMouseDown",
+      function(_,btn)
+        f:SetScript("OnUpdate", CornerUpdate)
+        f:StartSizing(point)
+      end
+    )
+    corner:SetScript("OnMouseUp",
+      function()
+        local ss = GetStateScale(bar)
+        if ss then
+          SetStateScale(bar, ComputeBarScale(bar, overlay))
+        end
+        StopResize()
+      end)
+    corner:SetScript("OnEnter",
+      function()
+        local bw, bh = GetButtonSize(bar)
+        local r, c, s = bar:GetButtonGrid()
+        local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
+        local ss = GetStateScale(bar)
+        local state = bar:GetSecureState()
+        GameTooltip:SetOwner(f, "ANCHOR_"..point)
+        if ss then
+          GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
+        else
+          GameTooltip:AddLine(bar:GetName())
+        end
+        GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c))
+        if ss then
+          GameTooltip:AddLine(L["State Scale Override"])
+          GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to change scale:"]), format("%d%%", bar:GetStateProperty(state,"scale")*100))
+        else
+          GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), tostring(floor(size)))
+          GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"],  L["to change spacing:"]), tostring(floor(s)))
+        end
+        GameTooltip:Show()
+      end
+    )
+    corner:SetScript("OnLeave", 
+      function()
+        GameTooltip:Hide()
+        f:SetScript("OnUpdate",nil)
+      end
+    )
+  end
+
+  overlay:RegisterForDrag("LeftButton")
+  overlay:RegisterForClicks("RightButtonUp")
+  
+  overlay:SetScript("OnDragStart",
+    function()
+      f:StartMoving()
+      f.isMoving = true
+      local w,h = bar:GetButtonSize()
+      f:ClearAllPoints()
+      UpdateAnchorDecoration()
+      f:SetScript("OnUpdate", function()
+          if IsShiftKeyDown() then
+            local f, p = DisplaySnapIndicator(f,w,h)
+          else
+            HideSnapIndicator()
+          end
+        end)
+    end
+  )
+
+  local function UpdateDragTooltip()
+    GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT")
+    local ss = GetStateScale(bar)
+    local state = bar:GetSecureState()
+    if ss then
+      GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
+    else
+      GameTooltip:AddLine(bar:GetName())
+    end
+    GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"]))
+    GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"]))
+    GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."]))
+    local point, frame, relpoint, x, y = bar:GetFrame():GetPoint(1)
+    if point then
+      local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
+      if (frame and frame ~= UIParent) or (ofsx == 0 and ofsy == 0) then
+        frame = frame or UIParent
+        GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],frame:GetName()))
+      end
+    end
+    GameTooltip:Show()
+  end
+
+  overlay:SetScript("OnDragStop",
+    function()
+      f:StopMovingOrSizing()
+      f.isMoving = false
+      f:SetScript("OnUpdate",nil)
+
+      if IsShiftKeyDown() then
+        local w, h = bar:GetButtonSize()
+        local a, p, rp, x, y = GetClosestPointSnapped(f,w,h)
+        if a then
+          f:ClearAllPoints()
+          f:SetPoint(p,a,rp,x,y)
+        end
+        HideSnapIndicator()
+      end
+
+      StoreExtents(bar)
+      ReAction:RefreshEditor()
+      UpdateDragTooltip()
+      UpdateAnchorDecoration()
+    end
+  )
+
+  overlay:SetScript("OnEnter",
+    function()
+      UpdateDragTooltip()
+    end
+  )
+
+  overlay:SetScript("OnLeave", HideGameTooltip)
+
+  overlay:SetScript("OnClick",
+    function()
+      ReAction:ShowEditor(bar)
+    end
+  )
+
+  function overlay:RefreshControls()
+    UpdateAnchorDecoration()
+  end
+
+  overlay:SetScript("OnShow", overlay.RefreshControls)
+
+  if ReAction:GetKeybindMode() then
+    overlay:SetFrameLevel(1)
+  end
+
+  UpdateLabelString(overlay)
+  UpdateAnchorDecoration()
+
+  return overlay
+end
+
+
+-- export methods to the Bar prototype
+Bar.Overlay = { }
+function Bar.Overlay:New( bar )
+  return setmetatable( {frame = CreateControls(bar)}, {__index=self} )
+end
+
+function Bar.Overlay:SetLabel(name)
+  self.frame.labelName = name
+  UpdateLabelString(self.frame)
+end
+
+function Bar.Overlay:SetLabelSubtext(text)
+  self.frame.labelSubtext = text
+  UpdateLabelString(self.frame)
+end
+
+function Bar.Overlay:Show()
+  self.frame:Show()
+end
+
+function Bar.Overlay:Hide()
+  self.frame:Hide()
+end
+
+function Bar.Overlay:IsShown()
+  return self.frame:IsShown()
+end
+
+function Bar.Overlay:RefreshControls()
+  self.frame:RefreshControls()
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PetActionButton.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,324 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local InCombatLockdown = InCombatLockdown
+local GetPetActionInfo = GetPetActionInfo
+local GetPetActionSlotUsable = GetPetActionSlotUsable
+local GetPetActionCooldown = GetPetActionCooldown
+local AutoCastShine_AutoCastStart = AutoCastShine_AutoCastStart
+local AutoCastShine_AutoCastStop = AutoCastShine_AutoCastStop
+local SetDesaturation = SetDesaturation
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+
+--
+-- Secure snippets
+-- These are run within the context of the bar's sandbox, as the
+-- buttons themselves do not have their own sandbox.
+--
+local _onDragStart = -- function(self, button, kind, value, ...)
+[[
+  if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
+    return kind, value, ...
+  else
+    return "petaction", self:GetAttribute("action")
+  end
+]]
+
+local _onReceiveDrag = -- function(self, button, kind, value, ...)
+[[
+  if kind then -- pet spells on the cursor return nil from GetCursorInfo(), which is very strange
+    return kind, value, ...
+  end
+  return "petaction", self:GetAttribute("action")
+]]
+
+--
+-- private
+--
+local eventList = {
+"PLAYER_CONTROL_LOST",
+"PLAYER_CONTROL_GAINED",
+"PLAYER_FARSIGHT_FOCUS_CHANGED",
+"UNIT_PET",
+"UNIT_FLAGS",
+"UNIT_AURA",
+"PET_BAR_UPDATE",
+"PET_BAR_UPDATE_COOLDOWN",
+"PET_BAR_UPDATE_USABLE",
+"UPDATE_BINDINGS",
+}
+
+--
+-- Pet Action Button class
+--
+local buttonTypeID = "PetAction"
+local Super = ReAction.Button
+local Pet = setmetatable( 
+  { 
+    defaultBarConfig = { 
+      type = buttonTypeID,
+      btnWidth = 30,
+      btnHeight = 30,
+      btnRows = 1,
+      btnColumns = 10,
+      spacing = 8,
+      buttons = { }
+    },
+
+    barType = L["Pet Action Bar"], 
+    buttonTypeID = buttonTypeID
+  },
+  { __index = Super } )
+
+ReAction.Button.PetAction = Pet
+ReAction:RegisterBarType(Pet)
+
+function Pet:New( config, bar, idx, idHint )
+  local name = format("ReAction_%s_PetAction_%d",bar:GetName(),idx)
+ 
+  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+  local f = self:GetFrame()
+  if not f.autoCastTexture then
+    -- store autocast stuff with the frame for recycling
+    local tex = f:CreateTexture(nil,"OVERLAY")
+    tex:SetTexture([[Interface\Buttons\UI-AutoCastableOverlay]])
+    tex:SetHeight(58)
+    tex:SetWidth(58)
+    tex:SetPoint("CENTER")
+    f.autoCastTexture = tex
+    f.autoCastShine = CreateFrame("Frame",name.."Shine",f,"AutoCastShineTemplate") -- create after autocast texture so it's on top
+    -- move the cooldown around
+    local cd = self.frames.cooldown
+    cd:ClearAllPoints()
+    cd:SetWidth(33)
+    cd:SetHeight(33)
+    cd:SetPoint("CENTER", f, "CENTER", -2, -1)
+    -- resize to 30x30
+    f:SetHeight(30)
+    f:SetWidth(30)
+    local nt = _G[name.."NormalTexture"]
+    nt:SetHeight(54)
+    nt:SetWidth(54)
+  end
+  local barFrame = bar:GetFrame()
+
+  -- set up the base action ID
+  self:SetActionIDPool("pet",10)
+  config.actionID = self:AcquireActionID(config.actionID, idHint, true)
+
+  -- attribute setup
+  -- There's no secure way to do PetAutoCastToggle by actionID, so use
+  -- a click-through proxy to the Blizzard pet buttons for right-click
+  -- Note that technically this doesn't do PetStopAttack() when 
+  -- IsPetAttackActive() is true: however that's only true when using
+  -- Eyes of the Beast and appears not to really do anything (at least
+  -- I can't find any difference)
+  f:SetAttribute("type","pet")
+  f:SetAttribute("type2","click")
+  f:SetAttribute("clickbutton2",_G["PetActionButton"..config.actionID])
+  f:SetAttribute("action",config.actionID)
+  f:SetAttribute("checkselfcast", true)
+  f:SetAttribute("checkfocuscast", true)
+
+  -- non secure scripts
+  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+  f:SetScript("PreClick", function(frame) self:PreClick() end)
+  f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
+  f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
+
+  -- secure handlers
+  barFrame:WrapScript(f, "OnDragStart", _onDragStart)
+  barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForDrag("LeftButton", "RightButton")
+  f:RegisterForClicks("AnyUp")
+  for _, evt in pairs(eventList) do
+    f:RegisterEvent(evt)
+  end
+
+  -- attach to skinner
+  bar:SkinButton(self,
+   {
+     AutoCast = f.autoCastShine,
+     AutoCastable = f.autoCastTexture
+   })
+
+  self:Refresh()
+  f:Show()
+
+  return self
+end
+
+function Pet:SetupBar(bar)
+  Super.SetupBar(self,bar)
+
+  -- auto show/hide when pet exists
+  bar:RegisterUnitWatch("pet",true)
+
+  self:UpdateButtonLock(bar)
+end
+
+function Pet:UpdateButtonLock(bar)
+  local f = bar:GetFrame()
+  f:SetAttribute("lockbuttons",bar.config.lockButtons)
+  f:SetAttribute("lockbuttonscombat",bar.config.lockButtonsCombat)
+  f:Execute(
+    [[
+      lockButtons = self:GetAttribute("lockbuttons")
+      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+    ]])
+end
+
+function Pet:Refresh()
+  Super.Refresh(self)
+  self:Update()
+  self:UpdateHotkey()
+end
+
+function Pet:GetActionID()
+  return self.config.actionID
+end
+
+function Pet:SetActionID(id)
+  if not InCombatLockdown() then
+    if id < 0 or id > 10 then
+      ReAction:UserError(L["Pet action ID range is 1-10"])
+      return
+    end
+    self.config.actionID = id
+    f:SetAttribute("clickbutton2",_G["PetActionButton"..id])
+    f:SetAttribute("action",id)
+    self:Update()
+    self:UpdateHotkey()
+  end
+end
+
+function Pet:Update()
+  local action = self.config.actionID
+  local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(action)
+  local f = self:GetFrame()
+  local icon = self.frames.icon
+
+  if isToken then
+    icon:SetTexture(_G[texture])
+    self.tooltipName = _G[name]
+  else
+    icon:SetTexture(texture)
+    self.tooltipName = name
+  end
+
+  self.isToken = isToken
+	self.tooltipSubtext = subtext
+  f:SetChecked( isActive and 1 or 0 )
+
+  if autoCastAllowed then
+    f.autoCastTexture:Show()
+  else
+    f.autoCastTexture:Hide()
+  end
+
+  if autoCastEnabled then
+    AutoCastShine_AutoCastStart(f.autoCastShine)
+  else
+    AutoCastShine_AutoCastStop(f.autoCastShine)
+  end
+
+  if texture then
+    if GetPetActionSlotUsable(action) then
+      SetDesaturation(icon,nil)
+    else
+      SetDesaturation(icon,1)
+    end
+    icon:Show()
+    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+  else
+    icon:Hide()
+    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+  end
+
+  self:UpdateCooldown()
+end
+
+function Pet:UpdateCooldown()
+  CooldownFrame_SetTimer(self.frames.cooldown, GetPetActionCooldown(self.config.actionID))
+end
+
+function Pet:SetTooltip()
+  if self.tooltipName then
+    local f = self:GetFrame()
+    local uber = GetCVar("UberTooltips")
+    if self.isToken or (uber == "0") then
+      if uber == "0" then
+        GameTooltip:SetOwner(f, "ANCHOR_RIGHT")
+      else
+        GameTooltip_SetDefaultAnchor(GameTooltip, f)
+      end
+      GameTooltip:SetText(self.tooltipName)
+      if self.tooltipSubtext then
+        GameTooltip:AddLine(self.tooltipSubtext, "", 0.5, 0.5, 0.5)
+      end
+      GameTooltip:Show()
+    else
+      GameTooltip_SetDefaultAnchor(GameTooltip, f)
+      GameTooltip:SetPetAction(self.config.actionID)
+    end
+  else
+    GameTooltip:Hide()
+  end
+end
+
+function Pet:OnEvent(event, unit)
+  if event =="PET_BAR_UPDATE_COOLDOWN" then
+    self:UpdateCooldown()
+  elseif event == "UPDATE_BINDINGS" then
+    self:UpdateHotkey()
+  elseif event == "UNIT_PET" then
+    if unit == "player" then
+      self:Update()
+    end
+  elseif event == "UNIT_FLAGS" or event == "UNIT_AURA" then
+    if unit == "pet" then
+      self:Update()
+    end
+  else
+    self:Update()
+  end
+end
+
+function Pet:OnEnter()
+  self:SetTooltip()
+end
+
+function Pet:OnLeave()
+  GameTooltip:Hide()
+end
+
+function Pet:OnAttributeChanged(attr,value)
+  self:Update()
+end
+
+function Pet:PreClick()
+  self:GetFrame():SetChecked(0)
+end
+
+function Pet:OnDragStart()
+  self:SetChecked(0)
+  self:Update()
+end
+
+function Pet:OnReceiveDrag()
+  self:SetChecked(0)
+  self:Update()
+end
+
--- a/ReAction.xml	Sat Mar 26 12:26:55 2011 -0700
+++ b/ReAction.xml	Sat Mar 26 12:35:08 2011 -0700
@@ -7,9 +7,15 @@
 
   <Script file="ReAction.lua"/>
   <Script file="Profile.lua"/>
-
-  <Include file="classes\classes.xml"/>
-
+  <Script file="Bar.lua"/>
+  <Script file="Overlay.lua"/>
+  <Script file="Button.lua"/>
+  <Script file="ActionButton.lua"/>
+  <Script file="PetActionButton.lua"/>
+  <Script file="StanceButton.lua"/>
+  <Script file="BagButton.lua"/>
+  <Script file="VehicleExitButton.lua"/>
+  <Script file="MultiCastButton.lua"/>
   <Script file="Options.lua"/>
   <Script file="Editor.lua"/>
 </Ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StanceButton.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,198 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local InCombatLockdown = InCombatLockdown
+local GetNumShapeshiftForms = GetNumShapeshiftForms
+local GetShapeshiftFormInfo = GetShapeshiftFormInfo
+local IsUsableSpell = IsUsableSpell
+local GetSpellInfo = GetSpellInfo
+
+--
+-- private
+--
+local playerClass = select(2,UnitClass("player"))
+
+local eventList = {
+  "PLAYER_REGEN_ENABLED",
+  "PLAYER_ENTERING_WORLD",
+  "UPDATE_SHAPESHIFT_FORM",
+  "UPDATE_SHAPESHIFT_FORMS",
+  "UPDATE_SHAPESHIFT_USABLE",
+  "UPDATE_SHAPESHIFT_COOLDOWN",
+  "UPDATE_BINDINGS",
+}
+
+--
+-- Stance Button class
+--
+local buttonTypeID = "Stance"
+local Super = ReAction.Button
+local Stance = setmetatable(
+  { 
+    defaultConfig = { 
+      type = buttonTypeID,
+      btnHeight = 36,
+      btnWidth = 36,
+      btnRows = 1,
+      btnColumns = 6,
+      spacing = 3
+    }, 
+
+    barType = L["Stance Bar"], 
+    buttonTypeID = buttonTypeID
+  },
+  { __index = Super } )
+
+ReAction.Button.Stance = Stance
+ReAction:RegisterBarType(Stance)
+
+function Stance:New( config, bar, idx, idHint )
+  local name = format("ReAction_%s_Stance_%d",bar:GetName(),idx)
+ 
+  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+  local f = self:GetFrame()
+  local barFrame = bar:GetFrame()
+  local config = self:GetConfig()
+
+  -- set up the base stance ID
+  self:SetActionIDPool("stance",8)
+  config.stanceID = self:AcquireActionID(config.stanceID, idHint, true)
+
+  -- attribute setup
+  f:SetAttribute("type","spell")
+
+  -- non secure scripts
+  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+  f:SetScript("PreClick", function(frame, ...) self:PreClick(...) end)
+
+  -- secure handlers
+  -- (none)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForClicks("AnyUp")
+  for _, evt in pairs(eventList) do
+    f:RegisterEvent(evt)
+  end
+
+  -- attach to skinner
+  bar:SkinButton(self)
+
+  -- initial display
+  if ReAction:GetConfigMode() then
+    self:GetFrame():Show()
+  end
+
+  self:Refresh()
+
+  return self
+end
+
+function Stance:GetActionID()
+  return self.config.stanceID
+end
+
+function Stance:UpdateAction()
+  if InCombatLockdown() then
+    self.updatePending = true
+  else
+    self.updatePending = false
+    local idx = self:GetActionID()
+    local f = self:GetFrame()
+    if idx > GetNumShapeshiftForms() then
+      f:Hide()
+    else
+      f:SetAttribute("spell", select(2,GetShapeshiftFormInfo(idx)))
+      f:Show()
+      self:Update()
+    end
+  end
+end
+
+function Stance:Refresh()
+  Super.Refresh(self)
+  self:UpdateHotkey()
+  self:UpdateAction()
+end
+
+function Stance:Update()
+  local texture, _, isActive, isCastable = GetShapeshiftFormInfo(self:GetActionID())
+  
+  local icon = self.frames.icon
+  icon:SetTexture(texture)
+  self:GetFrame():SetChecked( isActive and 1 or 0 )
+  if isCastable then
+    self.frames.hotkey:Show()
+    icon:SetVertexColor(1.0, 1.0, 1.0)
+  else
+    icon:SetVertexColor(0.4, 0.4, 0.4)
+  end
+
+  self:UpdateCooldown()
+end
+
+function Stance:UpdateCooldown()
+  local start, duration, enabled = GetShapeshiftFormCooldown(self:GetActionID())
+  if start then
+    CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enabled)
+  end
+end
+
+function Stance:SetTooltip()
+  if GetCVar("UberTooltips") == "1" then
+    GameTooltip_SetDefaultAnchor(GameTooltip, self:GetFrame())
+  else
+    GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT")
+  end
+  GameTooltip:SetShapeshift(self:GetActionID())
+end
+
+function Stance:OnEnter()
+  self:SetTooltip()
+end
+
+function Stance:OnLeave()
+  GameTooltip:Hide()
+end
+
+function Stance:PreClick()
+  local f = self:GetFrame()
+  f:SetChecked( not f:GetChecked() )
+end
+
+function Stance:OnEvent(event, arg)
+  if event == "PLAYER_REGEN_ENABLED" then
+    if self.updatePending then
+      self:UpdateAction()
+    end
+  elseif event == "UPDATE_SHAPESHIFT_COOLDOWN" then
+    self:UpdateCooldown()
+  elseif event == "UPDATE_SHAPESHIFT_FORMS" then
+    self:UpdateAction()
+  elseif event == "UNIT_AURA" then
+    if arg == "player" then
+      self:Update()
+    end
+  elseif event == "UPDATE_BINDINGS" then
+    self:UpdateHotkey()
+  else
+    self:Update()
+  end
+end
+
+function Stance:ShowGridTemp(show)
+  if show then
+    self:GetFrame():Show()
+  else
+    self:UpdateAction()
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VehicleExitButton.lua	Sat Mar 26 12:35:08 2011 -0700
@@ -0,0 +1,108 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local format = string.format
+
+--
+-- VExitButton Button class
+--
+local buttonTypeID = "VehicleExit"
+local Super = ReAction.Button
+local VExitButton = setmetatable(
+  { 
+    defaultBarConfig = { 
+      type = buttonTypeID ,
+      btnWidth = 36,
+      btnHeight = 36,
+      btnRows = 1,
+      btnColumns = 1,
+      spacing = 3,
+      buttons = { }
+    },
+
+    barType = L["Exit Vehicle Floater"], 
+    buttonTypeID = buttonTypeID
+  }, 
+  { __index = Super } )
+
+ReAction.Button.VehicleExit = VExitButton
+ReAction:RegisterBarType(VExitButton)
+
+function VExitButton:New( config, bar, idx )
+  local name = format("ReAction_%s_VehicleExit_%d",bar:GetName(),idx)
+ 
+  self = Super.New(self, name, config, bar, idx, "SecureFrameTemplate, ActionButtonTemplate", "Button")
+
+  -- frame setup
+  local f = self:GetFrame()
+  self.frames.icon:SetTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up")
+  self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
+
+  -- attribute setup
+  -- (none)
+
+  -- non secure scripts
+  f:SetScript("OnClick", VehicleExit)
+  f:SetScript("OnEnter", function(frame) GameTooltip_AddNewbieTip(frame, LEAVE_VEHICLE, 1.0, 1.0, 1.0, nil) end)
+  f:SetScript("OnLeave", GameTooltip_Hide)
+  f:SetScript("OnEvent", function(frame, evt, ...) self:OnEvent(evt,...) end)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForClicks("AnyUp")
+  f:RegisterEvent("UPDATE_BINDINGS")
+
+  -- attach to skinner
+  bar:SkinButton(self)
+
+  self:Refresh()
+  self:UpdateHotkey()
+
+  return self
+end
+
+function VExitButton:SetupBar(bar)
+  Super.SetupBar(self,bar)
+  self:UpdateRegistration(bar)
+end
+
+function VExitButton:GetActionID()
+  return 1
+end
+
+function VExitButton:Refresh()
+  Super.Refresh(self)
+  -- it seems that setscale kills the texcoord, have to refresh it
+  self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375) 
+end
+
+function VExitButton:OnEvent(event, ...)
+  if self[event] then
+    self[event](self, event, ...)
+  end
+end
+
+function VExitButton:UPDATE_BINDINGS()
+  self:UpdateHotkey()
+end
+
+function VExitButton:UpdateRegistration(bar)
+  -- auto show/hide when on a vehicle
+  local config = bar:GetConfig()
+  local f = bar:GetFrame()
+  if config.withControls then
+    if bar.vehicleExitStateRegistered then
+      UnregisterStateDriver(f, "unitexists")
+      bar.vehicleExitStateRegistered = false
+    end
+    bar:RegisterUnitWatch("vehicle",true)
+  else
+    bar:RegisterUnitWatch("vehicle",false)
+    if not bar.vehicleExitStateRegistered then
+      f:SetAttribute("unit","vehicle")
+      RegisterStateDriver(f, "unitexists", "[target=vehicle,exists,novehicleui] show; hide") -- spoof onstate-unitexists
+      bar.vehicleExitStateRegistered = true
+    end
+  end
+end
+
--- a/classes/ActionButton.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,806 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local IsUsableAction = IsUsableAction
-local IsEquippedAction = IsEquippedAction
-local IsConsumableAction = IsConsumableAction
-local IsStackableAction = IsStackableAction
-local GetActionText = GetActionText
-local GetCVar = GetCVar
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-local IsCurrentAction = IsCurrentAction
-local IsAutoRepeatAction = IsAutoRepeatAction
-local IsUsableAction = IsUsableAction
-local IsAttackAction = IsAttackAction
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local GetActionCooldown = GetActionCooldown
-local GetActionTexture = GetActionTexture
-local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME
-local TOOLTIP_UPDATE_TIME = TOOLTIP_UPDATE_TIME
-local IsActionInRange = IsActionInRange
-local InCombatLockdown = InCombatLockdown
-local HasAction = HasAction
-
---
--- Secure snippets
--- These are run within the context of the bar's sandbox, as the
--- buttons themselves do not have their own sandbox.
---
-local _onstate_mc = -- function(self, stateid, newstate)
-[[
-  local oldMcVehicleState = mcVehicleState
-  mcVehicleState = newstate
-  control:ChildUpdate()
-  if oldMcVehicleState == "vehicle" or mcVehicleState == "vehicle" then
-    control:ChildUpdate("vehicle")
-  end
-]]
-
-local _childupdate = -- function(self, snippetid, message)
-[[
-  local action = nil
-  if (doVehicle and mcVehicleState == "vehicle") or
-     (doMindControl and mcVehicleState == "mc") then
-    local idx = self:GetAttribute("bar-idx")
-    local maxN = (doVehicle and mcVehicleState == "vehicle") and 7 or 12
-    if idx and idx <= maxN then
-      action = 120 + idx
-    else
-      action = 0
-    end
-  elseif state and settings[state] and settings[state].page then
-    action = self:GetAttribute("action-"..settings[state].page) 
-  end
-  if action == nil then
-    action = self:GetAttribute("default-action")
-  end
-
-  self:SetAttribute("action",action)
-
-  if not self:GetAttribute("showgrid") then
-    local tempShow = self:GetAttribute("showgrid-temp")
-    local evtShow = self:GetAttribute("showgrid-event")
-    if tempShow then tempShow = (tempShow > 0) end
-    if evtShow then evtShow = (evtShow > 0) end
-
-    if tempShow or evtShow or HasAction(action) then
-      self:Show()
-    else
-      self:Hide()
-    end
-  end
-]]
-
-local _childupdate_vehicleExit =  -- function(self, snippetid, message)
-[[
-  local show = (mcVehicleState == "vehicle")
-  if show and doVehicle then
-    self:SetAttribute("type","macro")
-    self:Show()
-  else
-    self:SetAttribute("type","action")
-  end
-  control:CallMethod("ShowVehicleExit",show)
-]]
-
-local _childupdate_showgrid = -- function(self, snippetid, message)
-[[
-  showgrid_event = message
-  self:SetAttribute("showgrid-event",message)
-  if not self:GetAttribute("showgrid") then
-    local count = message + (self:GetAttribute("showgrid-temp") or 0)
-    if count <= 0 then
-      local action = self:GetAttribute("action")
-        -- note that HasAction is not updated on the target of a drag until after ACTIONBAR_HIDEGRID
-        -- so, we set a flag for this button in pre-click/receive-drag and check for it here
-      if HasAction(action) or self:GetAttribute("showgrid-clicked") then
-        if not self:IsShown() then
-          self:Show()
-        end
-        self:SetAttribute("showgrid-clicked",false)
-      else 
-        if self:IsShown() then
-          self:Hide()
-        end
-      end
-    else
-      self:Show()
-    end
-  end
-]]
-
-local _onDragStart = -- function(self, button, kind, value, ...)
-[[
-  if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
-    return kind, value, ...
-  else
-    return "action", self:GetAttribute("action")
-  end
-]]
-
-local _onReceiveDrag = -- function(self, button, kind, value, ...)
-[[
-  if kind ~= "spell" and kind ~= "item" and kind ~= "macro" and kind ~= "flyout" then
-    return kind, value, ...
-  else
-    if showgrid_event and showgrid_event > 0 then
-      self:SetAttribute("showgrid-clicked",true)
-    end
-    return "action", self:GetAttribute("action")
-  end
-]]
-
-local _onClick = -- function(self, button, down)
-[[
-  if showgrid_event and showgrid_event > 0 then
-    self:SetAttribute("showgrid-clicked",true)
-  end
-  return button
-]]
-
---
--- private
---
-local eventList = {
-  "PLAYER_ENTERING_WORLD",
-  "ACTIONBAR_PAGE_CHANGED",
-  "ACTIONBAR_SLOT_CHANGED",
-  "UPDATE_BINDINGS",
-  "ACTIONBAR_UPDATE_STATE",
-  "ACTIONBAR_UPDATE_USABLE",
-  "ACTIONBAR_UPDATE_COOLDOWN",
-  "UNIT_INVENTORY_CHANGED",
-  "LEARNED_SPELL_IN_TAB",
-  "UPDATE_INVENTORY_ALERTS",
-  "PLAYER_TARGET_CHANGED",
-  "TRADE_SKILL_SHOW",
-  "TRADE_SKILL_CLOSE",
-  "PLAYER_ENTER_COMBAT",
-  "PLAYER_LEAVE_COMBAT",
-  "START_AUTOREPEAT_SPELL",
-  "STOP_AUTOREPEAT_SPELL",
-  "UNIT_ENTERED_VEHICLE",
-  "UNIT_EXITED_VEHICLE",
-  "COMPANION_UPDATE",
-}
-
---
--- Action Button class
---
-local buttonTypeID = "Action"
-local Super = ReAction.Button
-local Action = setmetatable( 
-  { 
-    defaultBarConfig = { 
-      type = buttonTypeID,
-      btnWidth = 36,
-      btnHeight = 36,
-      btnRows = 1,
-      btnColumns = 12,
-      spacing = 3,
-      buttons = { },
-    },
-
-    barType = L["Action Bar"],
-    buttonTypeID = buttonTypeID
-  },
-  { __index = Super } )
-
-ReAction.Button.Action = Action
-ReAction:RegisterBarType(Action, true)
-
-function Action:New( config, bar, idx, idHint )
-  local name = format("ReAction_%s_Action_%d",bar:GetName(),idx)
- 
-  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
-  self.barConfig = bar:GetConfig()
-
-  local f = self:GetFrame()
-  local barFrame = bar:GetFrame()
-
-  self.rangeTimer = TOOLTIP_UPDATE_TIME
-
-  -- set up the base action ID
-  self:SetActionIDPool("action",120)
-  config.actionID = self:AcquireActionID(config.actionID, idHint)
-  self.nPages = 1
-
-  -- attribute setup
-  f:SetAttribute("type","action")
-  f:SetAttribute("checkselfcast", true)
-  f:SetAttribute("checkfocuscast", true)
-  f:SetAttribute("action", config.actionID)
-  f:SetAttribute("default-action", config.actionID)
-  f:SetAttribute("bar-idx",idx)
-  f:SetAttribute("showgrid-temp",0)
-  f:SetAttribute("showgrid-event",0)
-  f:SetAttribute("showgrid",not self:GetBarConfig().hideEmpty)
-
-  -- non secure scripts
-  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
-  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
-  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
-  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
-  f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
-  f:SetScript("OnUpdate", function(frame, elapsed) self:OnUpdate(elapsed) end)
-  f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
-  f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
-
-  -- event registration
-  f:EnableMouse(true)
-  f:RegisterForDrag("LeftButton", "RightButton")
-  f:RegisterForClicks("AnyUp")
-  for _, evt in pairs(eventList) do
-    f:RegisterEvent(evt)
-  end
-
-  f.action = config.actionID -- need this to support silly ActionButton_UpdateFlyout. Should not taint anything anymore.
-
-  -- secure handlers
-  f:SetAttribute("_childupdate", _childupdate)
-  f:SetAttribute("_childupdate-showgrid",_childupdate_showgrid)
-  barFrame:WrapScript(f, "OnDragStart", _onDragStart)
-  barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
-  barFrame:WrapScript(f, "OnClick", _onClick)
-
-  -- attach to skinner
-  bar:SkinButton(self)
-
-  -- initial display
-  if ReAction:GetConfigMode() then
-    self:ShowGridTemp(true)
-  end
-
-  self:Refresh()
-
-  return self
-end
-
-function Action:Destroy()
-  local f = self:GetFrame()
-  local c = self:GetConfig()
-
-  f:SetAttribute("_childupdate-vehicle",nil)
-  f:SetAttribute("action",c.actionID) -- so that Super.Destroy releases the right one
-
-  if c.pageactions and #c.pageactions > 1 then
-    for i = 2, #c.pageactions do 
-      self:ReleaseActionID(c.pageactions[i])
-      self:ReleaseActionID(id)
-    end
-  end
-  
-  Super.Destroy(self)
-end
-
-function Action:GetBarConfig()
-  -- this is the per-bar Action module config structure,
-  -- not the config structure of the bar itself
-  return self.barConfig
-end
-
-function Action:Refresh()
-  Super.Refresh(self)
-  self:RefreshPages()
-  self:InstallVehicle()
-  self:ShowGrid(not self:GetBarConfig().hideEmpty)
-  self:UpdateAction()
-end
-
-function Action:InstallVehicle()
-  local f = self:GetFrame()
-  if self.idx == 7 and self:GetBarConfig().vehicle then
-    if not self.vehicleInstalled then
-      self.vehicleInstalled = true
-      -- install vehicle-exit button on 7th button (only)
-      f:SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit)
-      f:SetAttribute("macrotext","/run VehicleExit()")
-      self:GetBar():GetFrame().ShowVehicleExit = function(bar,show)
-        self:ShowVehicleExit(show)
-      end
-    end
-    -- setscale blows away tex coords
-    self:UpdateIcon()
-  elseif self.vehicleInstalled then
-    self.vehicleInstalled = false
-    f:SetAttribute("_childupdate-vehicle",nil)
-    f:SetAttribute("macrotext",nil)
-  end
-end
-
-function Action:ShowGrid( show )
-  if not InCombatLockdown() then
-    self.frame:SetAttribute("showgrid", show)
-    self:UpdateShowGrid()
-  end
-end
-
-function Action:ShowGridTemp( show )
-  -- This function only modifies the show-grid when out
-  -- of combat, and is ignored by the secure handler. Use 
-  -- it for configuration modes.
-  if not InCombatLockdown() then
-    local count = self.showGridTempCount or 0
-    if show then
-      count = count + 1
-    else
-      count = count - 1
-    end
-    if count < 0 then count = 0 end
-    self.showGridTempCount = count
-    self:GetFrame():SetAttribute("showgrid-temp",count)
-    self:UpdateShowGrid()
-  end
-end
-
-function Action:UpdateAll()
-  self:UpdateActionIDLabel(ReAction:GetConfigMode())
-  self:UpdateHotkey()
-  self:UpdateShowGrid()
-  self:UpdateIcon()
-  self:UpdateBorder()
-  self:UpdateMacroText()
-  self:UpdateCount()
-  self:UpdateTooltip()
-  self:UpdateCheckedState()
-  self:UpdateUsable()
-  self:UpdateCooldown()
-  self:UpdateFlash()
-end
-
-function Action:UpdateAction()
-  local action = self:GetActionID()
-  if action ~= self.actionID then
-    self.actionID = action
-    self:UpdateAll()
-  end
-end
-
-function Action:UpdateShowGrid()
-  if not InCombatLockdown() then
-    local f = self:GetFrame()
-    local count = (f:GetAttribute("showgrid-event") or 0) +
-                  (self.showGridTempCount or 0) +
-                  (f:GetAttribute("showgrid") and 1 or 0)
-
-    if count <= 0 and not HasAction(self.actionID) then
-      if f:IsShown() then
-        f:Hide()
-      end
-    elseif not f:IsShown() then
-      f:Show()
-    end
-  end
-end
-
-function Action:UpdateIcon()
-  local texture, tLeft, tRight, tTop, tBottom = self:GetIconTexture()
-  local icon = self.frames.icon
-  local hotkey = self.frames.hotkey
-  local f = self:GetFrame()
-  
-  if self.vehicleExitMode then
-    texture = "Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up"
-    icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
-    icon:SetVertexColor(1,1,1)
-  else
-    icon:SetTexCoord(0,1,0,1)
-  end
-
-  if texture then
-    icon:SetTexture(texture)
-    if tLeft then
-      icon:SetTexCoord(tLeft,tRight,tTop,tBottom)
-    end
-    icon:Show()
-    self.rangeTimer = -1
-    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
-  else
-    icon:Hide()
-    self.frames.cooldown:Hide()
-    self.rangeTimer = nil
-    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
-  end
-end
-
-function Action:GetIconTexture()
-  return GetActionTexture(self.actionID)
-end
-
-function Action:UpdateBorder()
-  local action = self.actionID
-  if ReAction:GetKeybindMode() then
-    self:UpdateKeybindModeDisplay(true)
-  elseif IsEquippedAction(action) then
-    self.frames.border:SetVertexColor(0, 1.0, 0, 0.35)
-    self.frames.border:Show()
-  else
-    self.frames.border:Hide()
-  end
-end
-
-function Action:UpdateMacroText()
-  local action = self.actionID
-  if not IsConsumableAction(action) and not IsStackableAction(action) then
-    self.frames.name:SetText(GetActionText(action))
-  else
-    self.frames.name:SetText("")
-  end
-end
-
-function Action:UpdateCount()
-  local action = self.actionID
-  if IsConsumableAction(action) or IsStackableAction(action) then
-    self.frames.count:SetText(GetActionCount(action))
-  else
-    self.frames.count:SetText("")
-  end
-end
-
-function Action:UpdateTooltip()
-  local f = self:GetFrame()
-  if GameTooltip:GetOwner() == f then
-    self:SetTooltip()
-  end
-end
-
-function Action:SetTooltip()
-  local f = self:GetFrame()
-  if GetCVar("UberTooltips") == "1" then
-    GameTooltip_SetDefaultAnchor(GameTooltip, f)
-  else
-    GameTooltip:SetOwner(f,"ANCHOR_RIGHT")
-  end
-  GameTooltip:SetAction(self.actionID)
-end
-
-function Action:UpdateCheckedState()
-  local action = self.actionID
-  if IsCurrentAction(action) or IsAutoRepeatAction(action) then
-    self:GetFrame():SetChecked(1)
-  else
-    self:GetFrame():SetChecked(0)
-  end
-end
-
-function Action:UpdateUsable()
-  local isUsable, notEnoughMana = self:GetUsable()
-  local noRange = self:GetInRange()
-
-  isUsable = self.vehicleExitMode or (isUsable and not noRange)
-
-  if isUsable then
-    if self.usableStatus ~= "usable" then
-      self.frames.icon:SetVertexColor(1.0, 1.0, 1.0)
-      self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
-      self.usableStatus = "usable"
-    end
-  elseif noRange then
-    if self.usableStatus ~= "norange" then
-      self.frames.icon:SetVertexColor(1.0,0.1,0.1)
-      self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
-      self.usableStatus = "norange"
-    end
-  elseif notEnoughMana then
-    if self.usableStatus ~= "oom" then
-      self.frames.icon:SetVertexColor(0.5, 0.5, 1.0)
-      self.frames.normalTexture:SetVertexColor(0.5, 0.5, 1.0)
-      self.usableStatus = "oom"
-    end
-  else
-    if self.usableStatus ~= "unusable" then
-      self.frames.icon:SetVertexColor(0.4, 0.4, 0.4)
-      self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
-      self.usableStatus = "unusable"
-    end
-  end
-end
-
-function Action:GetUsable()
-  return IsUsableAction(self.actionID)
-end
-
-function Action:GetInRange()
-  return IsActionInRange(self.actionID) == 0
-end
-
-function Action:UpdateCooldown()
-  CooldownFrame_SetTimer(self.frames.cooldown, self:GetCooldown())
-end
-
-function Action:GetCooldown()
-  return GetActionCooldown(self.actionID)
-end
-
-function Action:UpdateFlash()
-  local action = self.actionID
-  self:SetFlash( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) )
-end
-
-function Action:SetFlash(flash)
-  if self.flashing ~= flash then
-    self.flashing = flash
-    self.flashtime = 0
-    if not flash then
-      self.frames.flash:Hide()
-    end
-    self:UpdateCheckedState()
-  end
-end
-
-function Action:RunFlash(elapsed)
-  if self.flashing then
-    local flashtime = self.flashtime - elapsed
-    self.flashtime = flashtime
-    if flashtime <= 0 then
-      local overtime = -flashtime
-      if overtime >= ATTACK_BUTTON_FLASH_TIME then
-        overtime = 0
-      end
-      flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
-      local flash = self.frames.flash
-      if flash:IsShown() then
-        flash:Hide()
-      else
-        flash:Show()
-      end
-    end
-  end
-end
-
-function Action:RunRangeFinder(elapsed)
-  local rangeTimer = self.rangeTimer
-  if rangeTimer then
-    rangeTimer = rangeTimer - elapsed
-    self.rangeTimer = rangeTimer
-    if rangeTimer <= 0 then
-      self:UpdateUsable()
-      self.rangeTimer = TOOLTIP_UPDATE_TIME
-    end
-  end
-end
-
-function Action:GetActionID(page)
-  if page == nil then
-    -- get the effective ID
-    return self:GetFrame():GetAttribute("action")
-  else
-    if page == 1 then
-      return self.config.actionID
-    else
-      return self.config.pageactions and self.config.pageactions[page] or self.config.actionID
-    end
-  end
-end
-
-function Action:SetActionID( id, page )
-  id = tonumber(id)
-  page = tonumber(page)
-  if id == nil or id < 1 or id > 120 then
-    ReAction:UserError(L["Action ID range is 1-120"])
-    return
-  end
-  if page and page ~= 1 then
-    if not self.config.pageactions then
-      self.config.pageactions = { }
-    end
-    self:ReleaseActionID(self.config.pageactions[page])
-    self.config.pageactions[page] = id
-    self:AcquireActionID(self.config.pageactions[page])
-    self.frame:SetAttribute("action-page"..page,id)
-  else
-    self:ReleaseActionID(self.config.actionID)
-    self.config.actionID = id
-    self:AcquireActionID(self.config.actionID)
-    self.frame:SetAttribute("action",id)
-    self.frame:SetAttribute("default-action",id)
-    if self.config.pageactions then
-      self.config.pageactions[1] = id
-      self.frame:SetAttribute("action-page1",id)
-    end
-  end
-end
-
-function Action:RefreshPages( force )
-  local nPages = self:GetBarConfig().nPages
-  if nPages and (nPages ~= self.nPages or force) then
-    local f = self:GetFrame()
-    local c = self.config.pageactions
-    if nPages > 1 and not c then
-      c = { }
-      self.config.pageactions = c
-    end
-    for i = 1, nPages do
-      if i > 1 then
-        c[i] = self:AcquireActionID(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons())
-      else
-        c[i] = self.config.actionID  -- page 1 is the same as the base actionID
-      end
-      f:SetAttribute("action-page"..i,c[i])
-    end
-    for i = nPages+1, #c do
-      self:ReleaseActionID(c[i])
-      c[i] = nil
-      f:SetAttribute("action-page"..i,nil)
-    end
-    self.nPages = nPages
-  end
-end
-
-function Action:SetupBar( bar )
-  Super.SetupBar(self,bar)
-
-  local f = bar:GetFrame()
-  local config = bar:GetConfig()
-  f:SetAttribute("mindcontrol",config.mindcontrol)
-  f:SetAttribute("vehicle",config.vehicle)
-  f:Execute(
-    [[
-    doMindControl = self:GetAttribute("mindcontrol")
-    doVehicle = self:GetAttribute("vehicle")
-    control:ChildUpdate()
-    ]])
-
-  f:SetAttribute("_onstate-mc", _onstate_mc)
-  RegisterStateDriver(f, "mc", "[vehicleui] vehicle; [bonusbar:5] mc; none")
-
-  f:SetAttribute("lockbuttons",config.lockButtons)
-  f:SetAttribute("lockbuttonscombat",config.lockButtonsCombat)
-  f:Execute(
-    [[
-      lockButtons = self:GetAttribute("lockbuttons")
-      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
-    ]])
-end
-
-
-function Action:SetButtonLock( bar, lock, lockCombat )
-  local f = bar:GetFrame()
-  f:SetAttribute("lockbuttons",lock)
-  f:SetAttribute("lockbuttonscombat",lockCombat)
-  f:Execute(
-    [[
-      lockButtons = self:GetAttribute("lockbuttons")
-      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
-    ]])
-end
-
-
-function Action:ShowVehicleExit(show)
-  self.vehicleExitMode = show and self:GetBarConfig().vehicle
-  self:UpdateIcon()
-end
-
-function Action:OnEnter( )
-  self:SetTooltip()
-end
-
-function Action:OnLeave( )
-  GameTooltip:Hide()
-end
-
-function Action:OnAttributeChanged( attr, value )
-  if attr ~= "statehidden" then
-    self:UpdateAction()
-  end
-  local f = self:GetFrame()
-  f.action = f:GetAttribute("action") -- support ActionButton_UpdateFlyout
-end
-
-function Action:PostClick( )
-  self:UpdateCheckedState()
-end
-
-function Action:OnUpdate( elapsed )
-  self:RunFlash(elapsed)
-  self:RunRangeFinder(elapsed)
-end
-
-function Action:OnDragStart()
-  self:UpdateCheckedState()
-  self:UpdateFlash()
-end
-
-function Action:OnReceiveDrag()
-  self:UpdateCheckedState()
-  self:UpdateFlash()
-end
-
-function Action:OnEvent(event, ...)
-  if self[event] then
-    self[event](self, event, ...)
-  end
-end
-
-function Action:ACTIONBAR_SLOT_CHANGED(event, action)
-  if action == 0 or action == self.actionID then
-    self:UpdateAll()
-  end
-end
-
-function Action:PLAYER_ENTERING_WORLD()
-  self:UpdateAction()
-end
-
-function Action:ACTIONBAR_PAGE_CHANGED()
-  self:UpdateAction()
-end
-
-function Action:UPDATE_BONUS_ACTIONBAR()
-  self:UpdateAction()
-end
-
-function Action:UPDATE_BINDINGS()
-  self:UpdateHotkey()
-end
-
-function Action:PLAYER_TARGET_CHANGED()
-  self.rangeTimer = -1
-end
-
-function Action:ACTIONBAR_UPDATE_STATE()
-  self:UpdateCheckedState()
-end
-
-function Action:TRADE_SKILL_SHOW()
-  self:UpdateCheckedState()
-end
-Action.TRADE_SKILL_CLOSE = Action.TRADE_SKILL_CLOSE
-
-function Action:UNIT_ENTERED_VEHICLE(event,unit)
-  if unit == "player" then
-    self:UpdateCheckedState()
-  end
-end
-Action.UNIT_EXITED_VEHICLE = Action.UNIT_ENTERED_VEHICLE
-
-function Action:COMPANION_UPDATE(event,unit)
-  if unit == "mount" then
-    self:UpdateCheckedState()
-  end
-end
-
-function Action:ACTIONBAR_UPDATE_USABLE()
-  self:UpdateUsable()
-end
-
-function Action:ACTIONBAR_UPDATE_COOLDOWN()
-  self:UpdateCooldown()
-end
-
-function Action:PLAYER_ENTER_COMBAT()
-  if IsAttackAction(self.actionID) then
-    self:SetFlash(true)
-  end
-end
-
-function Action:PLAYER_LEAVE_COMBAT()
-  if IsAttackAction(self.actionID) then
-    self:SetFlash(false)
-  end
-end
-
-function Action:START_AUTOREPEAT_SPELL()
-  if IsAutoRepeatAction(self.actionID) then
-    self:SetFlash(true)
-  end
-end
-
-function Action:STOP_AUTOREPEAT_SPELL()
-  if not IsAttackAction(self.actionID) then
-    self:SetFlash(false)
-  end
-end
-
-function Action:UNIT_INVENTORY_CHANGED(unit)
-  if unit == "player" then
-    self:UpdateTooltip()
-  end
-end
-
-function Action:LEARNED_SPELL_IN_TAB()
-  self:UpdateTooltip()
-end
--- a/classes/BagButton.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,499 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local GetCVar = GetCVar
-local ContainerIDToInventoryID = ContainerIDToInventoryID
-local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
-local IsModifiedClick = IsModifiedClick
-local CursorHasItem = CursorHasItem
-local GetInventoryItemTexture = GetInventoryItemTexture
-local GetInventorySlotInfo = GetInventorySlotInfo
-local PickupBagFromSlot = PickupBagFromSlot
-local CursorCanGoInSlot = CursorCanGoInSlot
-
--- class declarations
-local buttonTypeID = "Bag"
-local weak     = { __mode = "k" }
-local Super    = ReAction.Button
-local BagBase  = setmetatable( 
-  { 
-    defaultBarConfig = { 
-      type = buttonTypeID,
-      btnWidth = 30,
-      btnHeight = 30,
-      btnRows = 1,
-      btnColumns = 6,
-      spacing = 4,
-      buttons = { }
-    },
-
-    barType = L["Bag Bar"],
-    buttonTypeID = buttonTypeID,
-
-    allButtons = setmetatable( { }, weak )
-  },
-  { __index = Super } )
-
-local Bag      = setmetatable( { }, { __index = BagBase } )
-local Backpack = setmetatable( { }, { __index = BagBase } )
-local Keyring  = setmetatable( { }, { __index = BagBase } )
-
-ReAction.Button.Bag = BagBase
-ReAction:RegisterBarType(BagBase)
-
---
--- Bag Button base class
---
-
-function BagBase:New( btnCfg, bar, idx, idHint )
-  local name = format("ReAction_%s_Bag_%d",bar:GetName(),idx)
-
-  -- use a variable private leaf implementation class
-  -- unlike traditional OO programming, we can initialize the leaf
-  -- class before initializing its parent
-  local class = Bag
-  if idx == 1 then
-    class = Backpack
-  elseif idx == 6 then
-    class = Keyring
-  end
-  self = class:New(name, btnCfg, bar, idx)
-
-  local f = self:GetFrame()
-  local config = self:GetConfig()
-
-  -- set up the bag ID pool
-  self:SetActionIDPool("bag",6)
-  config.bagID = self:AcquireActionID(config.bagID, idHint, true)
-
-  -- non secure scripts
-  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
-  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
-  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
-  f:SetScript("OnReceiveDrag", function(frame, ...) self:OnReceiveDrag(...) end)
-  f:SetScript("OnClick", function(frame, ...) self:OnClick(...) end)
-
-  -- secure handlers
-  -- (none)
-
-  -- event registration
-  f:EnableMouse(true)
-  f:RegisterForClicks("LeftButtonUp","RightButtonUp")
-  f:RegisterEvent("UPDATE_BINDINGS")
-
-  -- frame setup
-  f:SetID(self:GetBagID())
-
-  if not f.hotkey then
-    local h = f:CreateFontString(name.."HotKey","ARTWORK","NumberFontNormalSmallGray")
-    h:SetWidth(30)
-    h:SetHeight(10)
-    h:SetJustifyH("RIGHT")
-    h:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2)
-    h:Show()
-    f.hotkey = h
-  end
-
-  if not _G[name.."ItemAnim"] then
-    local anim = CreateFrame("Model",name.."ItemAnim",f,"ItemAnimTemplate")
-    anim:SetPoint("BOTTOMRIGHT",f,"BOTTOMRIGHT",-10,0)
-    anim:Hide()
-  end
-
-  if not f.border then
-    local b = f:CreateTexture(name.."Border","OVERLAY")
-    b:SetAllPoints()
-    b:SetWidth(f:GetWidth()*(62/36))
-    b:SetHeight(f:GetHeight()*(62/36))
-    b:SetTexture("Interface\\Buttons\UI-ActionButton-Border")
-    b:SetBlendMode("ADD")
-    b:Hide()
-    f.border = b
-  end
-
-  self.frames.count:SetDrawLayer("ARTWORK")
-
-  self.frames.hotkey = f.hotkey
-  self.frames.border = _G[name.."Border"]
-  self.frames.icon = _G[name.."IconTexture"]
-  self.frames.anim = _G[name.."ItemAnim"]
-
-  -- initial display
-  if ReAction:GetConfigMode() then
-    self:GetFrame():Show()
-  end
-
-  self:Refresh()
-
-  BagBase.allButtons[self] = true
-
-  return self
-end
-
-function BagBase:Destroy()
-  BagBase.allButtons[self] = nil
-  Super.Destroy(self)
-end
-
-
-function BagBase:GetActionID()
-  return self.config.bagID
-end
-
-function BagBase:GetBagID()
-  return self:GetActionID() - 1
-end
-
-function BagBase:Refresh()
-  Super.Refresh(self)
-  self:UpdateHotkey()
-  self:Update()
-end
-
-function BagBase:Update()
-  self:UpdateChecked()
-end
-
-function BagBase:UpdateChecked(force)
-  if force == nil then
-    for i=1, NUM_CONTAINER_FRAMES do
-      local c = _G["ContainerFrame"..i]
-      if c:GetID() == self:GetBagID() and c:IsShown() then
-        self:GetFrame():SetChecked(1)
-        return
-      end
-    end
-    self:GetFrame():SetChecked(0)
-  end
-  self:GetFrame():SetChecked(force)
-end
-
-function BagBase:OnEvent(evt, ...)
-  if self[evt] then
-    self[evt](self, ...)
-  end
-end
-
-function BagBase:OnEnter()
-  self:SetTooltip()
-end
-
-function BagBase:OnLeave()
-  GameTooltip:Hide()
-end
-
-function BagBase:UPDATE_BINDINGS()
-  self:UpdateHotkey()
-end
-
-function BagBase:IterateAllButtons()
-  return pairs(self.allButtons)
-end
-
-
---
--- Bag Button class
---
-function Bag:New(name, cfg, bar, idx)
-  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
-
-  local f = self:GetFrame()
-
-  f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
-
-  f:RegisterEvent("CURSOR_UPDATE")
-  f:RegisterEvent("BAG_UPDATE")
-  f:RegisterEvent("BAG_CLOSED")
-  f:SetScript("OnDragStart", function(frame, ...) self:OnDragStart(...) end)
-  f:RegisterForDrag("LeftButton")
-
-  -- attach to skinner
-  bar:SkinButton(self,
-    {
-      Icon = _G[name.."IconTexture"]
-    }
-  )
-
-  return self
-end
-
-function Bag:GetInventorySlot()
-  return ContainerIDToInventoryID(self:GetBagID())
-end
-
-function Bag:GetInventorySlotName()
-  return "Bag"..(self:GetBagID()-1).."Slot"
-end
-
-function Bag:SetTooltip()
-  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
-  if not GameTooltip:SetInventoryItem("player", self:GetInventorySlot()) then
-    GameTooltip:SetText(EQUIP_CONTAINER, 1.0, 1.0, 1.0)
-  end
-end
-
-function Bag:Update()
-	local texture = GetInventoryItemTexture("player", self:GetInventorySlot())
-	if texture then
-    self.frames.icon:SetTexture(texture)
-    self.frames.icon:Show()
-    self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
-	else
-    local _, bgTex = GetInventorySlotInfo(self:GetInventorySlotName())
-    self.frames.icon:SetTexture(bgTex)
-    self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
-	end
-  self:UpdateChecked()
-end
-
-function Bag:OnClick()
-  if IsModifiedClick("OPENALLBAGS") then
-    OpenAllBags()
-  else
-    if not PutItemInBag(self:GetInventorySlot()) then
-      ToggleBag(self:GetBagID())
-    end
-  end
-  self:UpdateChecked()
-end
-
-function Bag:OnReceiveDrag()
-  if CursorHasItem() then
-    PutItemInBag(self:GetInventorySlot())
-  end
-end
-
-function Bag:OnDragStart()
-  PickupBagFromSlot(self:GetInventorySlot())
-  self:Update()
-end
-
-function Bag:BAG_UPDATE(bag)
-  if bag == self:GetBagID() then
-    self:Update()
-  end
-end
-
-function Bag:CURSOR_UPDATE()
-  if CursorCanGoInSlot(self:GetInventorySlot()) then
-    self:GetFrame():LockHighlight()
-  else
-    self:GetFrame():UnlockHighlight()
-  end
-end
-
-function Bag:BAG_CLOSED(bag)
-  if bag == self:GetBagID() then
-    self:Update()
-  end
-end
-
-
---
--- Backpack Button class
---
-function Backpack:New(name, cfg, bar, idx)
-  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
-
-  local f = self:GetFrame()
-  local icon = _G[name.."IconTexture"]
-  icon:SetTexture("Interface\\Buttons\\Button-Backpack-Up")
-  icon:Show()
-  f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
-  f:RegisterEvent("PLAYER_ENTERING_WORLD");
-  f:RegisterEvent("CVAR_UPDATE");
-  f:SetScript("OnShow", function(frame, ...) self:OnShow(...) end)
-
-  -- attach to skinner
-  bar:SkinButton(self,
-    {
-      Icon = _G[name.."IconTexture"]
-    }
-  )
-
-  return self
-end
-
-function Backpack:Update()
-  self:UpdateFreeSlots()
-  self:UpdateChecked()
-end
-
-function Backpack:UpdateFreeSlots()
-  if GetCVar("displayFreeBagSlots") == "1" then
-    local total = 0
-    for i = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
-      local free, family = GetContainerNumFreeSlots(i)
-      if family == 0 then
-        total = total + free
-      end
-    end
-
-    self.freeSlots = total
-    self.frames.count:SetText(format("(%s)", self.freeSlots))
-    self.frames.count:Show()
-  elseif self.frames.count:IsShown() then
-    self.frames.count:Hide()
-  end
-end
-
-function Backpack:SetTooltip()
-  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
-  GameTooltip:SetText(BACKPACK_TOOLTIP, 1.0, 1.0, 1.0)
-  GameTooltip:AddLine(string.format(NUM_FREE_SLOTS, (self.freeSlots or 0)))
-  GameTooltip:Show();
-end
-
-function Backpack:OnShow()
-  self:UpdateFreeSlots()
-end
-
-function Backpack:OnClick()
-  if IsModifiedClick("OPENALLBAGS") then
-    OpenAllBags()
-  else
-    if not PutItemInBackpack() then
-      ToggleBackpack()
-    end
-  end
-  self:UpdateChecked()
-end
-
-function Backpack:OnReceiveDrag()
-  if CursorHasItem() then
-    PutItemInBackpack()
-  end
-end
-
-function Backpack:PLAYER_ENTERING_WORLD()
-  self:CVAR_UPDATE("DISPLAY_FREE_BAG_SLOTS", GetCVar("displayFreeBagSlots"))
-end
-
-function Backpack:CVAR_UPDATE( cvar, value )
-  if cvar == "DISPLAY_FREE_BAG_SLOTS" then
-    if value == "1" then
-      self:GetFrame():RegisterEvent("BAG_UPDATE")
-    else
-      self:GetFrame():UnregisterEvent("BAG_UPDATE")
-    end
-    self:UpdateFreeSlots()
-  end
-end
-
-function Backpack:BAG_UPDATE(bag)
-  if bag >= BACKPACK_CONTAINER and bag <= NUM_BAG_SLOTS then
-    self:UpdateFreeSlots()
-  end
-end
-
-
---
--- Keyring Button class
---
-function Keyring:New(name, cfg, bar, idx)
-  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )
-
-  local f = self:GetFrame()
-
-  f:SetWidth(18)
-  f:SetHeight(39)
-
-  local tex = f:GetNormalTexture()
-  tex:ClearAllPoints()
-  tex:SetAllPoints()
-  
-  f:SetNormalTexture("Interface\\Buttons\\UI-Button-KeyRing")
-  f:SetHighlightTexture("Interface\\Buttons\\UI-Button-KeyRing-Highlight")
-  f:SetPushedTexture("Interface\\Buttons\\UI-Button-KeyRing-Down")
-  f:GetNormalTexture():SetTexCoord(0,0.5625,0,0.609375)
-  f:GetHighlightTexture():SetTexCoord(0,0.5625,0,0.609375)
-  f:GetPushedTexture():SetTexCoord(0,0.5625,0,0.609375)
-
-  if not HasKey() then
-    f:Hide()
-  end
-
-  -- DO NOT attach to skinner
-
-  return self
-end
-
-function Keyring:GetBagID()
-  return KEYRING_CONTAINER
-end
-
-function Keyring:Refresh()
-  local f = self:GetFrame()
-  self.bar:PlaceButton( self, f:GetHeight(), f:GetHeight() ) -- use height x height since it's an odd size
-  self:UpdateHotkey()
-  self:Update()
-end
-
-function Keyring:SetTooltip()
-  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT");
-  GameTooltip:SetText(KEYRING, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
-  GameTooltip:AddLine();
-end
-
-function Keyring:OnReceiveDrag()
-  if CursorHasItem() then
-    PutKeyInKeyRing()
-  end
-end
-
-function Keyring:OnClick()
-  if CursorHasItem() then
-    PutKeyInKeyRing()
-  else
-    ToggleKeyRing()
-  end
-  self:UpdateChecked()
-end
-
-function Keyring:ShowGridTemp(show)
-  if not HasKey() then
-    if show then 
-      self:GetFrame():Show()
-    else
-      self:GetFrame():Hide()
-    end
-  end
-end
-
-
-
--- hook some functions to propagate to our bag buttons
-hooksecurefunc("Disable_BagButtons", 
-  function()
-    for b in BagBase:IterateAllButtons() do
-      local f = b:GetFrame()
-      f:Disable()
-      SetDesaturation(b.frames.icon,1)
-    end
-  end)
-
-hooksecurefunc("Enable_BagButtons",
-  function()
-    for b in BagBase:IterateAllButtons() do
-      local f = b:GetFrame()
-      f:Enable()
-      SetDesaturation(b.frames.icon,nil)
-    end
-  end)
-
-hooksecurefunc("ContainerFrame_OnHide",
-  function()
-    for b in BagBase:IterateAllButtons() do
-      b:Update()
-    end
-  end)
-
-hooksecurefunc("ContainerFrame_OnShow",
-  function()
-    for b in BagBase:IterateAllButtons() do
-      b:Update()
-    end
-  end)
--- a/classes/Bar.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,854 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local LKB = ReAction.LKB
-local _G = _G
-local CreateFrame = CreateFrame
-local floor = math.floor
-local fmod = math.fmod
-local format = string.format
-local tfetch = addonTable.tfetch
-local tbuild = addonTable.tbuild
-local fieldsort = addonTable.fieldsort
-
-local LSG = LibStub("ReAction-LibShowActionGrid-1.0")
-
----- Secure snippets ----
-local _reaction_init = 
-[[
-  anchorKeys = newtable("point","relPoint","x","y")
-
-  state = nil
-  set_state = nil
-  state_override = nil
-  unit_exists = nil
-
-  showAll = false
-  hidden = false
-
-  defaultAlpha = 1.0
-  defaultScale = 1.0
-  defaultAnchor = newtable()
-
-  activeStates = newtable()
-  settings = newtable()
-  extensions = newtable()
-]]
-
-local _reaction_refresh = 
-[[
-  local oldState = state
-  state = state_override or set_state or state
-
-  local hide = nil
-  if state then
-    local settings = settings[state]
-    if settings then
-      -- show/hide
-      hide = settings.hide
-      -- re-anchor
-      local old_anchor = activeStates.anchor
-      activeStates.anchor = settings.anchorEnable and state
-      if old_anchor ~= activeStates.anchor or not set_state then
-        if activeStates.anchor then
-          if settings.anchorPoint then
-            self:ClearAllPoints()
-            local f = self:GetAttribute("frameref-anchor-"..state)
-            if f then
-              self:SetPoint(settings.anchorPoint, f, settings.anchorRelPoint, settings.anchorX, settings.anchorY)
-            end
-          end
-        elseif defaultAnchor.point then
-          self:ClearAllPoints()
-          self:SetPoint(defaultAnchor.point, defaultAnchor.frame, 
-                        defaultAnchor.relPoint, defaultAnchor.x, defaultAnchor.y)
-        end
-      end
-      -- re-scale
-      local old_scale = activeStates.scale
-      activeStates.scale = settings.enableScale and state
-      if old_scale ~= activeStates.scale or not set_state then
-        self:SetScale(activeStates.scale and settings.scale or defaultScale)
-      end
-      -- alpha
-      local old_alpha = activeStates.alpha
-      activeStates.alpha = settings.enableAlpha and state
-      if old_alpha ~= activeStates.alpha or not set_state then
-        self:SetAlpha(activeStates.alpha and settings.alpha or defaultAlpha)
-      end
-    end
-  end
-
-  -- hide if state or unit_exists says to
-  hide = not showAll and (hide or unithide)
-  if hide ~= hidden then
-    hidden = hide
-    if hide then
-      self:Hide()
-    else
-      self:Show()
-    end
-  end
-
-  for _, attr in pairs(extensions) do
-    control:RunAttribute(attr)
-  end
-  
-  control:ChildUpdate()
-
-  if showAll then
-    control:CallMethod("UpdateHiddenLabel", state and settings[state] and settings[state].hide)
-  end
-
-  if oldState ~= state then
-    control:CallMethod("StateRefresh", state)
-  end
-]]
-
-local _onstate_reaction = -- function( self, stateid, newstate )
-[[
-  set_state = newstate
-]] .. _reaction_refresh
-
-local _onstate_showgrid = -- function( self, stateid, newstate )
-[[
-  control:ChildUpdate(stateid,newstate)
-  control:CallMethod("UpdateShowGrid")
-]]
-
-local _onstate_unitexists = -- function( self, stateid, newstate )
-[[
-  unithide = not newstate or newstate == "hide"
-]] .. _reaction_refresh
-
-local _onclick =  -- function( self, button, down )
-[[
-  if state_override == button then
-    state_override = nil -- toggle
-  else
-    state_override = button
-  end
-]] .. _reaction_refresh
-
--- For reference
--- the option field names must match the field names of the options table, below
-local stateProperties = { 
-  hide = true,
-  --keybindState = true, TODO: broken
-  anchorEnable = true,
-  anchorFrame = true,
-  anchorPoint = true,
-  anchorRelPoint = true,
-  anchorX = true,
-  anchorY = true,
-  enableScale = true,
-  scale = true,
-  enableAlpha = true,
-  alpha = true,
-}
-
-
-
----- Bar class ----
-local Bar   = { }
-local frameList = { }
-
-ReAction.Bar = Bar -- export to ReAction
-
-function Bar:New( name, config, buttonClass )
-  if type(config) ~= "table" then
-    error("ReAction.Bar: config table required")
-  end
-
-  -- create new self
-  self = setmetatable( 
-    { 
-      config      = config,
-      name        = name,
-      buttons     = { },
-      buttonClass = buttonClass,
-      width       = config.width or 480,
-      height      = config.height or 40,
-    }, 
-    {__index = self} )
-  
-  -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
-  -- not mouse-clickable by the user.
-  local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
-  name = name and "ReAction-"..name
-  local f = name and frameList[name]
-  if not f then
-    f = CreateFrame("Button", name, parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
-    if name then
-      frameList[name] = f
-    end
-  end
-  f:SetFrameStrata("MEDIUM")
-  f:SetWidth(self.width)
-  f:SetHeight(self.height)
-  f:SetAlpha(config.alpha or 1.0)
-  f:Show()
-  f:EnableMouse(false)
-  f:SetClampedToScreen(true)
-  LSG:AddFrame(f)
-
-  -- secure handlers
-  f:Execute(_reaction_init)
-  f:SetAttribute("_onstate-reaction",   _onstate_reaction)
-  f:SetAttribute("_onstate-showgrid",   _onstate_showgrid)
-  f:SetAttribute("_onstate-unitexists", _onstate_unitexists)
-  f:SetAttribute("_onclick",            _onclick)
-
-  -- secure handler CallMethod()s
-  f.UpdateShowGrid    = function() self:UpdateShowGrid() end
-  f.StateRefresh      = function() self:RefreshControls() end
-  f.UpdateHiddenLabel = function(f,hidden) self:SetLabelSubtext(hidden and L["Hidden"]) end
-
-  -- Override the default frame accessor to provide strict read-only access
-  function self:GetFrame()
-    return f
-  end
-
-  self:ApplyAnchor()
-  self:SetConfigMode(ReAction:GetConfigMode())
-  self:SetKeybindMode(ReAction:GetKeybindMode())
-
-  if ReAction.LBF then
-    local g = ReAction.LBF:Group(L["ReAction"], self.name)
-    self.config.ButtonFacade = self.config.ButtonFacade or {
-      skinID = "Blizzard",
-      backdrop = true,
-      gloss = 0,
-      colors = {},
-    }
-    local c = self.config.ButtonFacade
-    g:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
-    self.LBFGroup = g
-  end
-
-  ReAction.RegisterCallback(self, "OnConfigModeChanged")
-
-  buttonClass:SetupBar(self)
-  self:ApplyStates()
-
-  return self
-end
-
-function Bar:Destroy()
-  local f = self:GetFrame()
-  self:CleanupStates()
-  for idx, b in self:IterateButtons() do
-    b:Destroy()
-  end
-  f:UnregisterAllEvents()
-  self:ShowControls(false)
-  ReAction.UnregisterAllCallbacks(self)
-  LKB.UnregisterAllCallbacks(self)
-  if self.LBFGroup then
-    self.LBFGroup:Delete(true)
-  end
-  LSG:RemoveFrame(f)
-  f:SetParent(UIParent)
-  f:ClearAllPoints()
-  f:Hide()
-end
-
---
--- Events
---
-
-function Bar:OnConfigModeChanged(event, mode)
-  self:SetConfigMode(mode)
-end
-
---
--- Accessors
---
-
-function Bar:GetName()
-  return self.name
-end
-
--- only ReAction:RenameBar() should call this function. Calling from any other
--- context will desync the bar list in the ReAction class.
-function Bar:SetName(name)
-  if self.LBFGroup then
-    -- LBF doesn't offer a method of renaming a group, so delete and remake the group.
-    local c = self.config.ButtonFacade
-    local g = ReAction.LBF:Group(L["ReAction"], name)
-    for idx, b in self:IterateButtons() do
-      self.LBFGroup:RemoveButton(b:GetFrame(), true)
-      g:AddButton(b:GetFrame())
-    end
-    self.LBFGroup:Delete(true)
-    self.LBFGroup = g
-    self.LBFGroup:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
-  end
-  self.name = name
-  if self.overlay then
-    self.overlay:SetLabel(self.name)
-  end
-end
-
-function Bar:GetFrame()
-  -- this method is included for documentation purposes. It is overridden
-  -- for each object in the :New() method.
-  error("Invalid Bar object: used without initialization")
-end
-
-function Bar:GetButton(idx)
-  return self.buttons[idx]
-end
-
-function Bar:GetButtonClass()
-  return self.buttonClass
-end
-
-function Bar:GetConfig()
-  return self.config
-end
-
-function Bar:GetAnchor()
-  local c = self.config
-  return (c.point or "CENTER"), 
-         (c.anchor or self:GetFrame():GetParent():GetName()), 
-         (c.relpoint or c.point or "CENTER"), 
-         (c.x or 0), 
-         (c.y or 0)
-end
-
-function Bar:SetAnchor(point, frame, relativePoint, x, y)
-  local c = self.config
-  c.point = point or c.point
-  c.anchor = frame or c.anchor
-  c.relpoint = relativePoint or c.relpoint
-  c.x = x or c.x
-  c.y = y or c.y
-  self:ApplyAnchor()
-end
-
-function Bar:GetSize()
-  local f = self:GetFrame()
-  return f:GetWidth(), f:GetHeight()
-end
-
-function Bar:SetSize(w,h)
-  local f = self:GetFrame()
-  self.config.width = w
-  self.config.height = h
-  f:SetWidth(w)
-  f:SetHeight(h)
-end
-
-function Bar:GetButtonSize()
-  local w = self.config.btnWidth or 32
-  local h = self.config.btnHeight or 32
-  -- TODO: get from modules?
-  return w,h
-end
-
-function Bar:SetButtonSize(w,h)
-  if w > 0 and h > 0 then
-    self.config.btnWidth = w
-    self.config.btnHeight = h
-  end
-end
-
-function Bar:GetNumButtons()
-  local r,c = self:GetButtonGrid()
-  return r*c
-end
-
-function Bar:GetButtonGrid()
-  local cfg = self.config
-  local r = cfg.btnRows or 1
-  local c = cfg.btnColumns or 1
-  local s = cfg.spacing or 4
-  return r,c,s
-end
-
-function Bar:SetButtonGrid(r,c,s)
-  if r > 0 and c > 0 and s > 0 then
-    local cfg = self.config
-    cfg.btnRows = r
-    cfg.btnColumns = c
-    cfg.spacing = s
-  end
-  self.buttonClass:SetupBar(self)
-end
-
-function Bar:GetAlpha()
-  return self.config.alpha or 1.0
-end
-
-function Bar:SetAlpha(value)
-  self.config.alpha = value
-  self:GetFrame():SetAlpha(value or 1.0)
-  self:UpdateDefaultStateAlpha()
-end
-
-function Bar:IterateButtons()
-  -- iterator returns idx, button, but does NOT iterate in index order
-  return pairs(self.buttons)
-end
-
---
--- Methods
---
-
-function Bar:SetConfigMode(mode)
-  self:SetSecureData("showAll",mode)
-  self:ShowControls(mode)
-  for idx, b in self:IterateButtons() do
-    b:ShowGridTemp(mode)
-    b:UpdateActionIDLabel(mode)
-  end
-end
-
-function Bar:SetKeybindMode(mode)
-  self:SetSecureData("showAll",mode)
-  for idx, b in self:IterateButtons() do
-    b:SetKeybindMode(mode)
-  end
-end
-
-function Bar:ApplyAnchor()
-  local f = self:GetFrame()
-  local c = self.config
-  local p = c.point
-
-  f:SetWidth(c.width)
-  f:SetHeight(c.height)
-  f:ClearAllPoints()
-  
-  if p then
-    local a = f:GetParent()
-    if c.anchor then
-      local bar = ReAction:GetBar(c.anchor)
-      if bar then
-        a = bar:GetFrame()
-      else
-        a = _G[c.anchor]
-      end
-    end
-    local fr = a or f:GetParent()
-    f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
-  else
-    f:SetPoint("CENTER")
-  end
-
-  self:UpdateDefaultStateAnchor()
-end
-
-function Bar:ClipNButtons( n )
-  local cfg = self.config
-  local r = cfg.btnRows or 1
-  local c = cfg.btnColumns or 1
-
-  cfg.btnRows = ceil(n/c)
-  cfg.btnColumns = min(n,c)
-end
-
-function Bar:AddButton(idx, button)
-  local f = self:GetFrame()
-
-  self.buttons[idx] = button
-
-  -- Store a properly wrapped reference to the child frame as an attribute 
-  -- (accessible via "frameref-btn#")
-  f:SetFrameRef(format("btn%d",idx), button:GetFrame())
-
-  -- button constructors are responsible for calling SkinButton
-end
-
-function Bar:RemoveButton(button)
-  local idx = button:GetIndex()
-  if idx then
-    self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
-    self.buttons[idx] = nil
-  end
-  if self.LBFGroup then
-    self.LBFGroup:RemoveButton(button:GetFrame(),true)
-  end
-end
-
-function Bar:PlaceButton(button, baseW, baseH)
-  local idx = button:GetIndex()
-  if idx then 
-    local r, c, s = self:GetButtonGrid()
-    local bh, bw = self:GetButtonSize()
-    local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
-    local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
-    local scale = bw/baseW
-    local b = button:GetFrame()
-
-    b:ClearAllPoints()
-    b:SetPoint("TOPLEFT",x/scale,y/scale)
-    b:SetScale(scale)
-  end
-end
-
-function Bar:SkinButton( button, data )
-  if self.LBFGroup then
-    self.LBFGroup:AddButton(button:GetFrame(), data)
-  end
-end
-
-function Bar:UpdateShowGrid()
-  for idx, button in self:IterateButtons() do
-    button:UpdateShowGrid()
-  end
-end
-
-function Bar:ShowControls(show)
-  if show then
-    if not self.overlay then
-      self.overlay = Bar.Overlay:New(self) -- see Overlay.lua
-    end
-    self.overlay:Show()
-    self:RefreshSecureState()
-  elseif self.overlay then
-    self.overlay:Hide()
-  end
-end
-
-function Bar:RefreshControls()
-  if self.overlay and self.overlay:IsShown() then
-    self.overlay:RefreshControls()
-  end
-end
-
-function Bar:SetLabelSubtext(text)
-  if self.overlay then 
-    self.overlay:SetLabelSubtext(text) 
-  end
-end
-
---
--- Secure state functions
---
-
-function Bar:GetSecureState()
-  local env = GetManagedEnvironment(self:GetFrame())
-  return env and env.state
-end
-
-function Bar:GetStateProperty(state, propname)
-  return tfetch(self:GetConfig(), "states", state, propname)
-end
-
-function Bar:SetStateProperty(state, propname, value)
-  local s = tbuild(self:GetConfig(), "states", state)
-  s[propname] = value
-  self:SetSecureStateData(state, propname, value)
-end
-
-function Bar:ApplyStates()
-  local states = tfetch(self:GetConfig(), "states")
-  if states then
-    self:SetStateDriver(states)
-  end
-end
-
-function Bar:CleanupStates()
-  self:SetStateDriver(nil)
-end
-
-function Bar:RefreshSecureState()
-  self:GetFrame():Execute(_reaction_refresh)
-end
-
--- usage: SetSecureData(globalname, [tblkey1, tblkey2, ...], value)
-function Bar:SetSecureData( ... )
-  local n = select('#',...)
-  if n < 2 then
-    error("ReAction.Bar:SetSecureData() requires at least 2 arguments")
-  end
-  local f = self:GetFrame()
-  f:SetAttribute("data-depth",n-1)
-  f:SetAttribute("data-value",select(n,...))
-  for i = 1, n-1 do
-    local key = select(i,...)
-    if key == nil then
-      error("ReAction.Bar:SetSecureData() - nil table key in argument list (#"..i..")")
-    end
-    f:SetAttribute("data-key-"..i, key)
-  end
-  f:Execute(
-    [[
-      local n = self:GetAttribute("data-depth")
-      if n > 0 then
-        local value = self:GetAttribute("data-value")
-        local t = _G
-        for i = 1, n do
-          local key = self:GetAttribute("data-key-"..i)
-          if not key then return end
-          if not t[key] then
-            t[key] = newtable()
-          end
-          if i == n then
-            t[key] = value
-          else
-            t = t[key]
-          end
-        end
-      end
-    ]])
-  self:RefreshSecureState()
-end
-
-function Bar:SetSecureStateData( state, key, value )
-  self:SetSecureData("settings",state,key,value)
-end
-
--- sets a snippet to be run as an extension to _onstate-reaction
-function Bar:SetSecureStateExtension( id, snippet )
-  if id == nil then
-    error("ReAction.Bar:SetSecureStateExtension() requires an id")
-  end
-  local f = self:GetFrame()
-  f:SetAttribute("input-secure-ext-id",id)
-  f:SetAttribute("secure-ext-"..id,snippet)
-  f:Execute(
-    [[
-      local id = self:GetAttribute("input-secure-ext-id")
-      if id then
-        extensions[id] = self:GetAttribute("secure-ext-"..id) or nil
-      end
-    ]])
-  self:RefreshSecureState()
-end
-
-function Bar:SetFrameRef( name, refFrame )
-  if refFrame then
-    local _, explicit = refFrame:IsProtected()
-    if not explicit then
-      refFrame = nil
-    end
-  end
-  if refFrame then
-    self:GetFrame():SetFrameRef(name,refFrame)
-  else
-    self:GetFrame():SetAttribute("frameref-"..name,nil)
-  end
-end
-
-function Bar:SetStateDriver( states )
-  if states then
-    for state, props in pairs(states) do
-      self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
-      for propname, value in pairs(props) do
-        if propname == "anchorFrame" then
-          self:SetFrameRef("anchor-"..state, _G[value])
-        elseif propname == "rule" then
-          -- do nothing
-        else
-          self:SetSecureStateData(state, propname, value)
-        end
-      end
-    end
-  end
-  local rule = states and self:BuildStateRule(states)
-  if rule then
-    RegisterStateDriver(self:GetFrame(),"reaction",rule)
-  elseif self.statedriver then
-    UnregisterStateDriver(self:GetFrame(),"reaction")
-  end
-  self.statedriver = rule
-  self:BuildStateKeybinds(states)
-  self:RefreshSecureState()
-end
-
--- pass unit=nil to set up the unit elsewhere, if you want something more complex
-function Bar:RegisterUnitWatch( unit, enable )
-  local f = self:GetFrame()
-  if unit then
-    f:SetAttribute("unit",unit)
-  end
-  if enable then
-    if not self.unitwatch then
-      RegisterUnitWatch(self:GetFrame(),true)
-    end
-  elseif self.unitwatch then
-    UnregisterUnitWatch(self:GetFrame())
-  end
-  self.unitwatch = enable
-  self:RefreshSecureState()
-end
-
-function Bar:SetStateKeybind( key, state )
-  local f = self:GetFrame()
-  local binds = self.statebinds
-  if not binds then
-    binds = { }
-    self.statebinds = binds
-  end
-
-  -- clear the old binding, if any
-  if binds[state] then
-    SetOverrideBinding(f, false, binds[state], nil)
-  end
-
-  if key then
-    SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
-  end
-  binds[state] = key
-end
-
-function Bar:GetStateKeybind( state )
-  if self.statebinds and state then
-    return self.statebinds[state]
-  end
-end
-
-function Bar:UpdateDefaultStateAnchor()
-  local point, frame, relPoint, x, y = self:GetAnchor()
-  local f = self:GetFrame()
-  f:SetAttribute("defaultAnchor-point",point)
-  f:SetAttribute("defaultAnchor-relPoint",relPoint)
-  f:SetAttribute("defaultAnchor-x",x)
-  f:SetAttribute("defaultAnchor-y",y)
-  self:SetFrameRef("defaultAnchor",_G[frame or "UIParent"])
-  f:Execute([[
-    for _, k in pairs(anchorKeys) do
-      defaultAnchor[k] = self:GetAttribute("defaultAnchor-"..k)
-    end
-    defaultAnchor.frame = self:GetAttribute("frameref-defaultAnchor")
-  ]])
-end
-
-function Bar:UpdateDefaultStateAlpha()
-  local f = self:GetFrame()
-  f:SetAttribute("defaultAlpha",self:GetAlpha())
-  f:Execute([[
-    defaultAlpha = self:GetAttribute("defaultAlpha")
-  ]])
-end
-
----- secure state driver rules ----
-
-local playerClass = select(2, UnitClass("player"))
-local function ClassFilter(...)
-  for i = 1, select('#',...) do
-    if playerClass == select(i,...) then
-      return false
-    end
-  end
-  return true
-end
-
-local ruleformats = { 
-  stealth       = { format = "stealth",        filter = ClassFilter("ROGUE","DRUID") },
-  nostealth     = { format = "nostealth",      filter = ClassFilter("ROGUE","DRUID") },
-  shadowdance   = { format = "bonusbar:2",     filter = ClassFilter("ROGUE") },
-  shadowform    = { format = "form:1",         filter = ClassFilter("PRIEST") },
-  noshadowform  = { format = "noform",         filter = ClassFilter("PRIEST") },
-  battle        = { format = "stance:1",       filter = ClassFilter("WARRIOR") },
-  defensive     = { format = "stance:2",       filter = ClassFilter("WARRIOR") },
-  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:3",         filter = ClassFilter("DRUID") },
-  tree          = { format = "form:5",         filter = ClassFilter("DRUID") },
-  moonkin       = { format = "form:5",         filter = ClassFilter("DRUID") },
-  demon         = { format = "form:2",         filter = ClassFilter("WARLOCK") },
-  nodemon       = { format = "noform",         filter = ClassFilter("WARLOCK") },
-  pet           = { format = "pet" },
-  nopet         = { format = "nopet" },
-  harm          = { format = "@target,harm" },
-  help          = { format = "@target,help" },
-  notarget      = { format = "@target,noexists" },
-  focusharm     = { format = "@focus,harm" },
-  focushelp     = { format = "@focus,help" },
-  nofocus       = { format = "@focus,noexists" },
-  raid          = { format = "group:raid" },
-  party         = { format = "group:party" },
-  solo          = { format = "nogroup" },
-  combat        = { format = "combat" },
-  nocombat      = { format = "nocombat" },
-  possess       = { format = "@vehicle,noexists,bonusbar:5" },
-  vehicle       = { format = "@vehicle,exists,bonusbar:5" },
-}
-
-function Bar.InitRuleFormats()
-  local forms = { }
-  for i = 1, GetNumShapeshiftForms() do
-    local _, name = GetShapeshiftFormInfo(i)
-    forms[name] = i;
-  end
-    -- use 9 if not found since 9 is never a valid stance/form
-  local defensive = forms[GetSpellInfo(71)] or 9
-  local berserker = forms[GetSpellInfo(2458)] or 9
-  local bear      = 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 = "stance:"..defensive
-  ruleformats.berserker.format = "stance:"..berserker
-  ruleformats.caster.format    = format("form:0/%d/%d/%d", aquatic, travel, flight)
-  ruleformats.bear.format      = "form:"..bear
-  ruleformats.cat.format       = "form:"..cat
-  ruleformats.tree.format      = "form:"..tree
-  ruleformats.moonkin.format   = "form:"..moonkin
-end
-
-function Bar:BuildStateRule(states)
-  -- states is a table :
-  --   states[statename].rule = {
-  --     order = #,
-  --     type = "default"/"custom"/"any"/"all",
-  --     values = { ... }, -- keys of ruleformats[]
-  --     custom = "...",
-  --   }
-  local rules = { }
-  local default
-
-  for idx, state in ipairs(fieldsort(states, "rule", "order")) do
-    local c = states[state].rule
-    local type = c.type
-    if type == "default" then
-      default = default or state
-    elseif type == "custom" then
-      if c.custom then
-        -- strip out all spaces from the custom rule
-        table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
-      end
-    elseif type == "any" or type == "all" then
-      if c.values then
-        local clauses = { }
-        for key, value in pairs(c.values) do
-          if ruleformats[key] and not ruleformats[key].filter then
-            table.insert(clauses, ruleformats[key].format)
-          end
-        end
-        if #clauses > 0 then
-          local sep = (type == "any") and "][" or ","
-          table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
-        end
-      end
-    end
-  end
-  -- make sure that the default, if any, is last
-  if default then
-    table.insert(rules, default)
-  end
-  return table.concat(rules,";")
-end
-
-function Bar:BuildStateKeybinds( states )
-  if states then
-    for name, state in pairs(states) do
-      local rule = tfetch(state, "rule")
-      if rule and rule.type == "keybind" then
-        self:SetStateKeybind(rule.keybind, name)
-      else
-        self:SetStateKeybind(nil, name) -- this clears an existing keybind
-      end
-    end
-  end
-end
-
--- a/classes/Button.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,359 +0,0 @@
---[[
-  ReAction Button base class
---]]
-
--- local imports
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local LKB = ReAction.LKB
-local _G = _G
-local CreateFrame = CreateFrame
-local GetBindingKey = GetBindingKey
-local format = string.format
-
--- private
-local trash = CreateFrame("Frame")
-local frameList = { }
-local idPools = { }
-
-local function kb_onEnter( frame )
-  LKB:Set(frame)
-end
-
--- Button class
-local buttonTypeID = "Button"
-local Button = { 
-  defaultBarConfig = {
-    type = buttonTypeID,
-    btnWidth = 36,
-    btnHeight = 36,
-    btnRows = 1,
-    btnColumns = 12,
-    spacing = 3
-  },
-  barType = L["Button Bar"]
-} 
-
-ReAction.Button = Button -- export to ReAction
-
-function Button:New( name, config, bar, idx, inherits, buttonType )
-  buttonType = buttonType or "CheckButton"
-
-  -- create new self
-  self = setmetatable( 
-    { 
-      bar = bar,
-      idx = idx,
-      config = config,
-      name = name,
-    }, 
-    { __index = self } )
-
-  -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
-  -- existing globals. Can't set to nil in the global because it's then tainted.
-  -- Caller is responsible for ensuring global uniqueness of names.
-  local f = name and frameList[name]
-  if f then
-    f:SetParent(bar:GetFrame())
-  else
-    f = CreateFrame(buttonType, name, bar:GetFrame(), inherits)
-    if name then
-      frameList[name] = f
-    end
-  end
-
-  self.frame = f
-
-  local frames = { }
-  self.frames = frames
-  frames.icon          = _G[name.."Icon"]
-  frames.flash         = _G[name.."Flash"]
-  frames.hotkey        = _G[name.."HotKey"]
-  frames.count         = _G[name.."Count"]
-  frames.name          = _G[name.."Name"]
-  frames.border        = _G[name.."Border"]
-  frames.cooldown      = _G[name.."Cooldown"]
-  frames.normalTexture = _G[name.."NormalTexture"]
-
-  if config then
-    config.name = name
-  end
-
-  -- install LibKeyBound handlers onto frame
-  function f:GetActionName()
-    return format("%s:%s", bar:GetName(), idx)
-  end
-
-  local clickBinding = format("CLICK %s:LeftButton", name)
-  function f:GetHotkey()
-    return LKB:ToShortKey(GetBindingKey(clickBinding))
-  end
-
-  return self
-end
-
-function Button:Destroy()
-  local f = self:GetFrame()
-  f:UnregisterAllEvents()
-  self:ReleaseActionID(self:GetActionID())
-  if f then
-    f:Hide()
-    f:SetParent(trash)
-    f:ClearAllPoints()
-  end
-end
-
-function Button:GetBar()
-  return self.bar
-end
-
-function Button:GetFrame()
-  return self.frame
-end
-
-function Button:GetIndex()
-  return self.idx
-end
-
-function Button:GetName()
-  return self.name
-end
-
-function Button:GetDefaultBarConfig()
-  return self.defaultBarConfig
-end
-
-function Button:GetBarType()
-  return self.barType
-end
-
-function Button:GetButtonTypeID()
-  return self.buttonTypeID
-end
-
-function Button:GetConfig()
-  return self.config
-end
-
-function Button:GetActionID()
-  -- derived classes should override this
-  return nil
-end
-
-function Button:SetActionIDPool( poolID, maxID )
-  self.actionPoolID = poolID
-  self.actionMaxID = maxID
-end
-
-function Button:SetupBar( bar )
-  local config = bar:GetConfig()
-  if not config.buttons then
-    config.buttons = { }
-  end
-  local btnCfg = config.buttons
-
-  local r, c = bar:GetButtonGrid()
-  local n = r*c
-  local cfgN = n
-
-  local hint = nil
-  local i = 1
-  repeat
-    local b = bar:GetButton(i)
-    if b then
-      if i > n then
-        bar:RemoveButton(b)
-        b:Destroy()
-        if i > cfgN then
-          btnCfg[i] = nil
-        end
-      else
-        b:Refresh()
-        hint = b:GetActionID()
-      end
-    elseif i <= n then
-      local cfg = btnCfg[i] or { }
-      local success, r = pcall(self.New, self, cfg, bar, i, hint)  -- note call semantics for derived class constructors
-      if success and r then
-        b = r
-        bar:AddButton(i,b)
-        btnCfg[i] = cfg
-        b:Refresh()
-        hint = b:GetActionID()
-      else
-        n = i - 1
-        if not success then
-          bar:ClipNButtons(n)
-          cfgN = n
-          geterrorhandler()(r)
-        end
-      end
-    end
-    i = i + 1
-  until b == nil
-end
-
-function Button:AcquireActionID( id, hint, unique )
-  local poolID = self.actionPoolID
-  local maxID = self.actionMaxID
-  if not poolID or not maxID then
-    error("AcquireActionID: must setup pool first with SetActionIDPool")
-  end
-  local pool = idPools[poolID]
-  if not pool then
-    pool = { nWraps = 0, useCount = { } }
-    for i = 1, maxID do
-      pool.useCount[i] = 0
-    end
-    idPools[poolID] = pool
-  end
-  local useCount = pool.useCount
-  if id == nil then
-    repeat
-      local nWraps = pool.nWraps or 0
-      if hint and (useCount[hint] == nil or useCount[hint] == nWraps) then
-        id = hint
-      else
-        local start = hint or 1
-        for i = start, maxID do
-          if useCount[i] == nil or useCount[i] == nWraps then
-            id = i
-            break
-          end
-        end
-        if not id then
-          for i = 1, start do
-            if useCount[i] == nil or useCount[i] == nWraps then
-              id = i
-              break
-            end
-          end
-        end
-      end
-      if id == nil then
-        if unique then
-          return nil
-        end
-        pool.nWraps = nWraps + 1
-      end
-    until id ~= nil
-  end
-  useCount[id] = (useCount[id] or 0) + 1
-  return id
-end
-
-function Button:ReleaseActionID( id )
-  local poolID = self.actionPoolID
-  if not poolID  then
-    error("ReleaseActionID: must setup pool first with SetActionIDPool")
-  end
-  local pool = idPools[poolID]
-  if pool and id and pool.useCount[id] then
-    pool.useCount[id] = pool.useCount[id] - 1
-    pool.nWraps = min(pool.useCount[id], pool.nWraps)
-  end
-end
-
-function Button:Refresh()
-  local f = self:GetFrame()
-  self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() )
-end
-
-function Button:SetKeybindMode( mode )
-  local f = self.frame
-  if mode then
-    self.oldOnEnter = f:GetScript("OnEnter")
-    f:SetScript("OnEnter", kb_onEnter)
-  elseif self.oldOnEnter then
-    f:SetScript("OnEnter", self.oldOnEnter)
-    self.oldOnEnter = nil
-  end
-  self:ShowGridTemp(mode)
-  self:UpdateKeybindModeDisplay( mode )
-end
-
-function Button:UpdateKeybindModeDisplay( mode )
-  local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))]
-  if border then
-    if mode then
-      border:SetVertexColor(LKB:GetColorKeyBoundMode())
-      border:Show()
-    else
-      border:Hide()
-    end
-  end
-end
-
-function Button:UpdateHotkey( hotkey )
-  hotkey = hotkey or self.frames.hotkey
-  if not hotkey then
-    hotkey = _G[self:GetName().."HotKey"]
-    self.frames.hotkey = hotkey
-  end
-  if hotkey then
-    local txt = self.frame:GetHotkey()
-    hotkey:SetText( txt )
-    if txt == nil or txt == "" then
-      hotkey:Hide()
-    else
-      hotkey:Show()
-    end
-  end
-end
-
-function Button:GetActionIDLabel( create )
-  local f = self:GetFrame()
-  if not f.actionIDLabel and create then
-    local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-    label:SetAllPoints()
-    label:SetJustifyH("CENTER")
-    label:SetShadowColor(0,0,0,1)
-    label:SetShadowOffset(2,-2)
-    f.actionIDLabel = label -- store the label with the frame for recycling
-  end
-  return f.actionIDLabel
-end
-
-function Button:UpdateActionIDLabel( show )
-  local label = self:GetActionIDLabel( show )
-  if label then
-    if show then
-      local id = self:GetActionID()
-      if id then
-        label:SetText(tostring(id))
-        label:Show()
-        return
-      end
-    end
-    label:Hide()
-  end
-end
-
-function Button:SetNormalVertexColor( r, g, b, a )
-  if ReAction.LBF then
-    ReAction.LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a)
-  else
-    self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a)
-  end
-end
-
-function Button:GetNormalVertexColor()
-  if ReAction.LBF then
-    return ReAction.LBF:GetNormalVertexColor(self:GetFrame())
-  else
-    return self:GetFrame():GetNormalTexture():GetVertexColor()
-  end
-end
-
-function Button:UpdateShowGrid()
- -- does nothing by default
-end
-
-function Button:ShowGridTemp(show)
-  -- does nothing by default
-end
-
-function Button:ShowGrid(show)
-  -- does nothing by default
-end
--- a/classes/MultiCastButton.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,779 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local unpack = unpack
-local GetCVar = GetCVar
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local InCombatLockdown = InCombatLockdown
-local IsUsableSpell = IsUsableSpell
-local IsUsableAction = IsUsableAction
-local IsSpellKnown = IsSpellKnown
-local IsSpellInRange = IsSpellInRange
-local IsActionInRange = IsActionInRange
-local GetSpellInfo = GetSpellInfo
-local GetSpellCooldown = GetSpellCooldown
-local GetActionCooldown = GetActionCooldown
-local GetSpellTexture = GetSpellTexture
-local GetActionTexture = GetActionTexture
-local GetMultiCastTotemSpells = GetMultiCastTotemSpells
-
---[[
-  Blizzard Constants:
-    - NUM_MULTI_CAST_BUTTONS_PER_PAGE = 4
-    - NUM_MULTI_CAST_PAGES = 3
-    - SHAMAN_TOTEM_PRIORITIES = { } -- sets the order of the totems
-    - TOTEM_MULTI_CAST_SUMMON_SPELLS = { } -- list of summon spellIDs
-    - TOTEM_MULTI_CAST_RECALL_SPELLS = { } -- list of recall spellIDs
-
-  Blizzard Events:
-    - UPDATE_MULTI_CAST_ACTIONBAR
-
-  Blizzard APIs:
-    - GetMultiCastBarOffset() : returns 6
-
-    - SetMultiCastSpell(actionID, spellID) (protected) OR
-         SetAttribute("type","multispell")
-         SetAttribute("action",actionID)
-         SetAttribute("spell",spellID)
-
-         note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(),
-               so that's action ID 132-144.
-
-    - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot)
-        returns spellIDs for all known totems that fit that slot. This function is available in
-        the secure environment.
-
-  Blizzard textures:
-    All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
-    texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
-    this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
-
-    Each totem button and arrow has a colored border indicating its elemental type.
-
-    TODO: 
-      - make whether to show the colored border configurable (looks really bad with ButtonFacade:Zoomed)
-      - apply ButtonFacade to the flyout buttons? Or at least zoom the textures slightly?
-      - use a multiplier with SetTexCoord on totem bar texture?
-
-  Design Notes:
-    - Only the header has a secure context. All other frames execute in its context.
-
-    - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are 
-      GetBonusBarOffset()=6, 132-144) with 3 pages of 4 buttons. The paging is controlled by
-      the summon flyout, which is also paged with the summon spells (the recall button is not paged)
-    
-    - A spell list is updated in the secure context at setup time (TODO: redo setup when learning new 
-      spells) with the list of spells known for each slot.
-    
-    - Each button (except recall) has an arrow button which appears on mouseover and when clicked
-      opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not
-      appear.
-    
-    - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child
-      of the bar. Each time the flyout panel is opened, the individual  buttons grab their corresponding
-      spell/type from the list, according to the slot which opened the flyout. Each button either sets
-      the current page (summon) or sets a multispell to an actionID via type="multispell". None of them
-      actually cast any spells (though, I suppose we could modify this so that e.g. configurable 
-      right-click casts the spell). The flyout also has a close button which closes the flyout: the
-      flyout-open code positions the close button anchored to the last button in the flyout (which 
-      changes dynamically because each slot has a different number of items in the list).
-
-    - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of 
-      the summon spells is cast from elsewhere.
-
-    - The default UI has Call of the Elements always selected on UI load. This module remembers the last
-      selected one and restores it.
-
-
-]]--
-
-
---
--- Secure snippets
---
-
--- bar
-local _bar_init = -- function(self)
-[[
-  -- set up some globals in the secure environment
-  flyout               = self:GetFrameRef("flyout")
-  flyoutSlot           = nil
-  summonSlot           = self:GetAttribute("summonSlot")
-  recallSlot           = self:GetAttribute("recallSlot")
-  baseActionID         = self:GetAttribute("baseActionID")
-  slotsPerPage         = self:GetAttribute("slotsPerPage")
-  currentPage          = currentPage or self:GetAttribute("lastSummon") or 1
-
-  totemIDsBySlot = newtable()
-  for i = 1, slotsPerPage do
-    totemIDsBySlot[i] = self:GetAttribute("TOTEM_PRIORITY_"..i)
-  end
-
-  -- these are set up in bar:SetupBar()
-  flyoutChildren = flyoutChildren or newtable()
-  summonSpells = summonSpells or newtable()
-]]
-
-local _onstate_multispellpage = -- function(self, stateid, newstate)
-[[
-  currentPage = tonumber(newstate)
-  control:CallMethod("UpdateLastSummon",currentPage)
-  control:ChildUpdate()
-]]
-
-
--- buttons
-local _childupdate = -- function(self, snippetid, message)
-[[
-  local t = self:GetAttribute("type")
-  self:SetAttribute(t, self:GetAttribute(t.."-page"..currentPage))
-]]
-
-local _onEnter = -- function(self)
-  -- for whatever reason, RegisterAutoHide is unreliable
-  -- unless you re-anchor the frame prior to calling it.
-  -- Even then, it's still not terribly reliable.
-[[
-  local slot = self:GetAttribute("bar-idx")
-  local arrow = owner:GetFrameRef("arrow-"..slot)
-  if arrow and not arrow:IsShown() and not (flyout:IsVisible() and flyoutSlot == slot) then
-    arrow:ClearAllPoints()
-    arrow:SetPoint("BOTTOM",self,"TOP",0,0)
-    arrow:Show()
-    arrow:RegisterAutoHide(0)
-    arrow:AddToAutoHide(self)
-  end
-]]
-
-
--- flyout arrow
-local _arrow_openFlyout = -- function(self)
-[[
-  local slot = self:GetAttribute("bar-idx")
-  local totemID = totemIDsBySlot[slot - (summonSlot or 0)]
-  if totemID == 0 then
-    totemID = "summon"
-  end
-
-  local lastButton, lastPage
-  for page, b in ipairs(flyoutChildren) do
-    b:Hide()
-    b:SetAttribute("totemSlot",totemID)
-    if slot == summonSlot then
-      local spellID = self:GetParent():GetAttribute("spell-page"..page)
-      if spellID then
-        b:SetAttribute("type","changePage")
-        b:SetAttribute("spell",spellID)
-        b:Show()
-        lastButton = b
-        lastPage = page
-      end
-    else
-      local spell = select(page, 0, GetMultiCastTotemSpells(totemID) )
-      if spell then
-        b:SetAttribute("type","multispell")
-        b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID)
-        b:SetAttribute("spell", spell)
-        b:Show()
-        lastButton = b
-        lastPage = page
-      end
-    end
-  end
-
-  local close = owner:GetFrameRef("close")
-  if lastButton and close then
-    close:ClearAllPoints()
-    close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring
-    close:Show()
-    control:CallMethod("UpdateFlyoutTextures",totemID)
-  end
-
-  flyout:ClearAllPoints()
-  flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0)  -- TODO: better anchoring
-  if lastPage then
-    flyout:SetHeight(lastPage * 27 + (close and close:GetHeight() or 0))
-  end
-  flyout:Show()
-  flyout:RegisterAutoHide(1) -- TODO: configurable
-  flyout:AddToAutoHide(owner)
-  flyoutSlot = slot
-  self:Hide()
-]]
-
-local _closeFlyout = -- function(self)
-[[
-  flyout:Hide()
-]]
-
-
--- flyout child buttons
-local _flyout_child_preClick = -- function(self, button, down)
-[[
-  local button = button
-  if self:GetAttribute("type") == "changePage" then
-    owner:SetAttribute("state-multispellpage",self:GetAttribute("index"))
-    self:GetParent():Hide()
-    return false
-  else
-    return nil, "close"
-  end
-]]
-
-local _flyout_child_postClick = -- function(self, message, button, down)
-[[
-  if message == "close" then
-    self:GetParent():Hide() -- hide flyout after selecting
-  end
-]]
-
-
---
--- The Blizzard totem bar textures are all actually one big texture,
--- with texcoord offsets. Shamelessly stolen from FrameXML/MultiCastActionBarFrame.lua
---
-local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar"
-local FLYOUT_UP_BUTTON_HL_TCOORDS   = { 72/128,  92/128, 88/256,  98/256 }
-local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128,  92/128, 69/256,  79/256 }
-
-local SLOT_EMPTY_TCOORDS = {
-  [EARTH_TOTEM_SLOT] = {  66/128,  96/128,   3/256,  33/256 },
-	[FIRE_TOTEM_SLOT]  = {  67/128,  97/128, 100/256, 130/256 },
-	[WATER_TOTEM_SLOT] = {  39/128,  69/128, 209/256, 239/256 },
-	[AIR_TOTEM_SLOT]   = {  66/128,  96/128,  36/256,  66/256 },
-}
-
-local SLOT_OVERLAY_TCOORDS = {
-	[EARTH_TOTEM_SLOT] = {   1/128,  35/128, 172/256, 206/256 },
-	[FIRE_TOTEM_SLOT]  = {  36/128,  70/128, 172/256, 206/256 },
-	[WATER_TOTEM_SLOT] = {   1/128,  35/128, 207/256, 240/256 },
-	[AIR_TOTEM_SLOT]   = {  36/128,  70/128, 137/256, 171/256 },
-}
-
-local FLYOUT_UP_BUTTON_TCOORDS = {
-	["summon"]         = {  99/128, 127/128,  84/256, 102/256 },
-	[EARTH_TOTEM_SLOT] = {  99/128, 127/128, 160/256, 178/256 },
-	[FIRE_TOTEM_SLOT]  = {  99/128, 127/128, 122/256, 140/256 },
-	[WATER_TOTEM_SLOT] = {  99/128, 127/128, 199/256, 217/256 },
-	[AIR_TOTEM_SLOT]   = {  99/128, 127/128, 237/256, 255/256 },
-}
-
-local FLYOUT_DOWN_BUTTON_TCOORDS = {
-	["summon"]         = {  99/128, 127/128,  65/256,  83/256 },
-	[EARTH_TOTEM_SLOT] = {  99/128, 127/128, 141/256, 159/256 },
-	[FIRE_TOTEM_SLOT]  = {  99/128, 127/128, 103/256, 121/256 },
-	[WATER_TOTEM_SLOT] = {  99/128, 127/128, 180/256, 198/256 },
-	[AIR_TOTEM_SLOT]   = {  99/128, 127/128, 218/256, 236/256 },
-}
-
-local FLYOUT_TOP_TCOORDS = {
-	["summon"]         = {  33/128,  65/128,   1/256,  23/256 },
-	[EARTH_TOTEM_SLOT] = {   0/128,  32/128,  46/256,  68/256 },
-	[FIRE_TOTEM_SLOT]  = {  33/128,  65/128,  46/256,  68/256 },
-	[WATER_TOTEM_SLOT] = {   0/128,  32/128,   1/256,  23/256 },
-	[AIR_TOTEM_SLOT]   = {   0/128,  32/128,  91/256, 113/256 },
-}
-
-local FLYOUT_MIDDLE_TCOORDS = {
-	["summon"]         = {  33/128,  65/128,  23/256,  43/256 },
-	[EARTH_TOTEM_SLOT] = {   0/128,  32/128,  68/256,  88/256 },
-	[FIRE_TOTEM_SLOT]  = {  33/128,  65/128,  68/256,  88/256 },
-	[WATER_TOTEM_SLOT] = {   0/128,  32/128,  23/256,  43/256 },
-	[AIR_TOTEM_SLOT]   = {   0/128,  32/128, 113/256, 133/256 },
-}
-
-local eventList = { 
-  "ACTIONBAR_SLOT_CHANGED",
-  "ACTIONBAR_UPDATE_STATE",
-  "ACTIONBAR_UPDATE_USABLE",
-  "ACTIONBAR_UPDATE_COOLDOWN",
-  "UPDATE_BINDINGS",
-  "UPDATE_MULTI_CAST_ACTIONBAR",
-}
-
---
--- MultiCast Button class
--- Inherits implementation methods from Action button class, but circumvents the constructor
--- and redefines/removes some methods.
---
-local buttonTypeID = "Totem"
-local Super = ReAction.Button
-local Action = ReAction.Button.Action
-local MultiCast = setmetatable( 
-  { 
-    defaultBarConfig = { 
-      type = buttonTypeID,
-      btnWidth = 36,
-      btnHeight = 36,
-      btnRows = 1,
-      btnColumns = 6,
-      spacing = 3,
-      buttons = { }
-    },
-
-    barType = L["Totem Bar"], 
-    buttonTypeID = buttonTypeID
-  },
-  { __index = Action } )
-
-ReAction.Button.MultiCast = MultiCast
-ReAction:RegisterBarType(MultiCast)
-
-function MultiCast:New( btnConfig, bar, idx )
-  local maxIndex = bar.nTotemSlots or 0
-  if bar.summonSlot then
-    maxIndex = maxIndex + 1
-  end
-  if bar.recallSlot then
-    maxIndex = maxIndex + 1
-  end
-
-  if not bar.hasMulticast or idx > maxIndex then
-    return false
-  end
-
-  if idx < 1 then
-    error("invalid index")
-  end
-
-  local name = format("ReAction_%s_Totem_%d",bar:GetName(),idx)
- 
-  self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
-
-  local barFrame = bar:GetFrame()
-  local f = self:GetFrame()
-
-  -- attributes
-  local page = (idx == bar.recallSlot) and 1 or bar:GetConfig().lastSummon or 1
-  if idx == bar.recallSlot or idx == bar.summonSlot then
-    f:SetAttribute("type","spell")
-    local spells = (idx == bar.summonSlot) and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS
-    f:SetAttribute("spell",spells[page])
-    for i, spell in ipairs(spells) do 
-      if spell and IsSpellKnown(spell) then
-        f:SetAttribute("spell-page"..i, spell)
-      end
-    end
-  else
-    local offset = bar.summonSlot and 1 or 0
-    local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset]
-    local baseAction = barFrame:GetAttribute("baseActionID") + slot
-    self.totemSlot = slot
-    f:SetAttribute("type","action")
-    f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
-    for i = 1, NUM_MULTI_CAST_PAGES do
-      f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
-    end
-    if not f.overlayTex then
-      local tx = f:CreateTexture("OVERLAY")
-      tx:SetTexture(TOTEM_TEXTURE)
-      tx:SetTexCoord(unpack(SLOT_OVERLAY_TCOORDS[self.totemSlot]))
-      tx:SetWidth(34)
-      tx:SetHeight(34)
-      tx:SetPoint("CENTER")
-      tx:Show()
-      f.overlayTex = tx
-    end
-  end
-  f:SetAttribute("bar-idx",idx)
-
-  -- non secure scripts
-  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
-  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
-  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
-  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
-  f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
-
-  -- secure handlers
-  if idx ~= bar.recallSlot then
-    f:SetAttribute("_childupdate",_childupdate)
-  end
-  barFrame:WrapScript(f, "OnEnter", _onEnter)
-
-  -- event registration
-  f:EnableMouse(true)
-  f:RegisterForClicks("AnyUp")
-  for _, evt in pairs(eventList) do
-    f:RegisterEvent(evt)
-  end
-
-  -- Set up a proxy for the icon texture for use with ButtonFacade
-  local SetTexCoordRaw = self.frames.icon.SetTexCoord
-  self.frames.icon.SetTexCoord = function( tx, ... )
-    if self:GetIconTexture() == TOTEM_TEXTURE then
-      SetTexCoordRaw(tx,select(2,self:GetIconTexture()))
-    else
-      SetTexCoordRaw(tx,...)
-    end
-  end
-
-  -- attach to skinner
-  bar:SkinButton(self)
-
-  f:Show()
-
-  -- open arrow and flyout background textures
-  if idx ~= bar.recallSlot then
-    local arrow = f._arrowFrame or CreateFrame("Button", nil, f, "SecureFrameTemplate")
-    f._arrowFrame = arrow
-    arrow:SetWidth(28)
-    arrow:SetHeight(18)
-    arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
-    arrow:SetNormalTexture(TOTEM_TEXTURE)
-    local slot = self.totemSlot or "summon"
-    arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS[slot]) )
-    arrow:SetHighlightTexture(TOTEM_TEXTURE)
-    arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
-    arrow:SetAttribute("bar-idx",idx)
-    arrow:Hide()
-    barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
-    barFrame:SetFrameRef("arrow-"..idx,arrow)
-  end
-
-  self:Refresh()
-
-  return self
-end
-
-function MultiCast:Destroy()
-  local barFrame = self.bar:GetFrame()
-  local f = self:GetFrame()
-  pcall( barFrame.UnwrapScript, barFrame, f, "OnEnter" ) -- ignore errors
-  if f._arrowFrame then
-    pcall( barFrame.UnwrapScript, barFrame, f._arrowFrame,"OnClick" ) -- ignore errors
-  end
-  Super.Destroy(self)
-end
-
-function MultiCast:Refresh()
-  Super.Refresh(self)
-  self:UpdateAction()
-end
-
-function MultiCast:ShowGrid( show )
-end
-
-function MultiCast:ShowGridTemp( show )
-end
-
-function MultiCast:AcquireActionID()
-end
-
-function MultiCast:ReleaseActionID()
-end
-
-function MultiCast:UpdateShowGrid()
-end
-
-function MultiCast:UpdateBorder()
-end
-
-function MultiCast:UpdateMacroText()
-end
-
-function MultiCast:UpdateCount()
-end
-
-function MultiCast:UpdateCheckedState()
-  local action = self:GetActionID()
-  if action and IsCurrentAction(action) then
-    self:GetFrame():SetChecked(1)
-  else
-    self:GetFrame():SetChecked(0)
-  end
-end
-
-function MultiCast:RefreshHasActionAttributes()
-end
-
-function MultiCast:UpdateFlash()
-end
-
-function MultiCast:GetIconTexture()
-  local tx
-  if self.spellID then
-    tx = GetSpellTexture(GetSpellInfo(self.spellID))
-  elseif self.actionID then
-    tx = GetActionTexture(self.actionID)
-  end
-  if tx then
-    return tx
-  else
-    return TOTEM_TEXTURE, unpack(SLOT_EMPTY_TCOORDS[self.totemSlot or 1])
-  end
-end
-
-function MultiCast:UpdateAction()
-  local action = self:GetActionID()
-  if action then
-    if action ~= self.actionID then
-      self.actionID = action
-      self:UpdateAll()
-    end
-  else
-    local spellID = self:GetSpellID()
-    if spellID ~= self.spellID then
-      self.spellID = spellID
-      self:UpdateAll()
-    end
-  end
-end
-
-function MultiCast:GetActionID(page)
-  return self:GetFrame():GetAttribute("action")
-end
-
-function MultiCast:GetSpellID(page)
-  return self:GetFrame():GetAttribute("spell")
-end
-
-function MultiCast:SetActionID( id  )
-  error("Can not set action ID of multicast buttons")
-end
-
-function MultiCast:SetTooltip()
-  local barFrame = self:GetFrame()
-  if GetCVar("UberTooltips") == "1" then
-    GameTooltip_SetDefaultAnchor(GameTooltip, barFrame)
-  else
-    GameTooltip:SetOwner(barFrame)
-  end
-  if self.spellID then
-    GameTooltip:SetSpellByID(self.spellID,false,true)
-  elseif self.actionID then
-    GameTooltip:SetAction(self.actionID)
-  end
-end
-
-function MultiCast:GetUsable()
-  if self.spellID then
-    return IsUsableSpell((GetSpellInfo(self.spellID)))
-  elseif self.actionID then
-    return IsUsableAction(self.actionID)
-  end
-end
-
-function MultiCast:GetInRange()
-  if self.spellID then
-    return IsSpellInRange((GetSpellInfo(self.spellID))) == 0
-  elseif self.actionID then
-    return IsActionInRange(self.actionID) == 0
-  end
-end
-
-function MultiCast:GetCooldown()
-  if self.spellID then
-    return GetSpellCooldown((GetSpellInfo(self.spellID)))
-  elseif self.actionID then
-    return GetActionCooldown(self.actionID)
-  else
-    return 0, 0, 0
-  end
-end
-
-function MultiCast:UPDATE_MULTI_CAST_ACTIONBAR()
-  self:UpdateAll()
-end
-
-
---
--- flyout setup
---
-local function ShowFlyoutTooltip(frame)
-  if GetCVar("UberTooltips") == "1" then
-    GameTooltip_SetDefaultAnchor(GameTooltip, frame)
-  else
-    GameTooltip:SetOwner(frame)
-  end
-  local spell = frame:GetAttribute("spell")
-  if spell == nil or spell == 0 then
-    GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
-  else
-    GameTooltip:SetSpellByID(spell,false,true)
-  end
-end
-
-local function HideFlyoutTooltip()
-  GameTooltip:Hide()
-end
-
-local function UpdateFlyoutIcon(frame)
-  local spellID = frame:GetAttribute("spell")
-  if spellID == 0 or spellID == nil then
-    frame.icon:SetTexture(TOTEM_TEXTURE)
-    local slot = tonumber(frame:GetAttribute("totemSlot")) or 1
-    frame.icon:SetTexCoord( unpack(SLOT_EMPTY_TCOORDS[slot]) )
-  else
-    frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
-    frame.icon:SetTexCoord(0,1,0,1)
-  end
-end
-
-function MultiCast:SetupBar( bar )
-  Super.SetupBar(self,bar)
-
-  local slot = 0
-  local nTotemSlots = 0
-  local summonSlot = nil
-  local recallSlot = nil
-
-  -- figure out the capabilities of the character
-	for i, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do 
-    if spell and IsSpellKnown(spell) then
-      slot = 1
-      summonSlot = 1
-    end
-	end
-
-  for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
-		local totem = SHAMAN_TOTEM_PRIORITIES[i];
-		if GetTotemInfo(totem) and GetMultiCastTotemSpells(totem) then
-      nTotemSlots = nTotemSlots + 1
-      slot = slot + 1
-    end
-  end
-
-  slot = slot + 1
-	for i, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do 
-    if spell and IsSpellKnown(spell) then
-      recallSlot = slot
-    end
-	end
-
-  if nTotemSlots == 0 then
-    bar.hasMulticast = false -- no multicast capability
-    return
-  end
-
-  bar.hasMulticast = true
-  bar.summonSlot   = summonSlot
-  bar.recallSlot   = recallSlot
-  bar.nTotemSlots  = nTotemSlots
-
-
-  local f = bar:GetFrame()
-
-  -- init bar secure environment
-  f:SetAttribute("lastSummon", bar:GetConfig().lastSummon)
-  f:SetAttribute("summonSlot", summonSlot)
-  f:SetAttribute("recallSlot", recallSlot)
-  f:SetAttribute("slotsPerPage", NUM_MULTI_CAST_BUTTONS_PER_PAGE)
-  f:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS)
-  for i, p in ipairs(SHAMAN_TOTEM_PRIORITIES) do
-    f:SetAttribute("TOTEM_PRIORITY_"..i,p)
-  end
-  f:SetAttribute("_onstate-multispellpage", _onstate_multispellpage)
-
-  function f:UpdateLastSummon(value)
-    bar:GetConfig().lastSummon = value
-  end
-
-  -- create flyout container frame and close arrow
-  local flyout = bar._flyoutFrame
-  if not flyout then
-    flyout = CreateFrame("Frame", nil, f, "SecureFrameTemplate")
-    bar._flyoutFrame = flyout
-    f:SetFrameRef("flyout",flyout)
-    flyout.buttons = { }
-    flyout:Hide()
-    flyout:SetWidth(24)
-    flyout:SetHeight(1)
-    flyout:SetPoint("BOTTOM",f,"TOP",0,0)
-
-    local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
-    close:SetWidth(28)
-    close:SetHeight(18)
-    close:SetPoint("BOTTOM",flyout,"TOP")
-    close:SetNormalTexture(TOTEM_TEXTURE)
-    close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS["summon"]))
-    close:SetHighlightTexture(TOTEM_TEXTURE)
-    close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
-    f:SetFrameRef("close",close)
-    f:WrapScript(close, "OnClick", _closeFlyout)
-    close:Show()
-
-    local midTx = flyout:CreateTexture("BACKGROUND")
-    midTx:SetWidth(32)
-    midTx:SetHeight(20)
-    midTx:SetPoint("BOTTOM")
-    midTx:SetTexture(TOTEM_TEXTURE)
-    midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS["summon"]))
-    midTx:Show()
-
-    local topTx = flyout:CreateTexture("BACKGROUND")
-    topTx:SetWidth(32)
-    topTx:SetHeight(20)
-    topTx:SetTexture(TOTEM_TEXTURE)
-    midTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS["summon"]))
-    topTx:SetPoint("BOTTOM",midTx,"TOP",0,-10)
-    topTx:Show()
-
-    function flyout:UpdateTextures(slot)
-      slot = slot or "summon"
-      close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS[slot]))
-      midTx:ClearAllPoints()
-      midTx:SetPoint("BOTTOM")
-      midTx:SetPoint("TOP",close,"BOTTOM",0,0)
-      midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS[slot]))
-      topTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS[slot]))
-    end
-
-    -- create flyout buttons
-    for i = 1, 10 do -- maximum 9 spells + 1 empty slot
-      local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
-      b:SetWidth(24)
-      b:SetHeight(24)
-      local prev = flyout.buttons[i-1]
-      b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring
-      b.icon = b:CreateTexture("BACKGROUND")
-      b.icon:SetAllPoints()
-      b.icon:Show()
-      b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
-      b:GetHighlightTexture():SetBlendMode("ADD")
-      b:RegisterForClicks("AnyUp")
-      b:SetScript("OnShow",UpdateFlyoutIcon)
-      b:SetScript("OnEnter",ShowFlyoutTooltip)
-      b:SetScript("OnLeave",HideFlyoutTooltip)
-      b:SetAttribute("index",i)
-      f:SetAttribute("flyout-child-idx",i)
-      f:SetFrameRef("flyout-child",b)
-      f:Execute([[
-          flyoutChildren = flyoutChildren or newtable()
-          flyoutChildren[self:GetAttribute("flyout-child-idx")] = self:GetFrameRef("flyout-child")
-        ]])
-      f:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick)
-      b:Show()
-      flyout.buttons[i] = b
-    end
-  end
-
-  -- scale flyout frame
-  local scale = bar:GetButtonSize() / 36
-  flyout:SetScale(scale)
-
-  function f:UpdateFlyoutTextures(slot)
-    flyout:UpdateTextures(slot)
-  end
-
-  -- re-execute setup when new spells are loaded
-  if not f.events_registered then
-    f:RegisterEvent("UPDATE_MULTI_CAST_ACTIONBAR")
-    f:RegisterEvent("PLAYER_ENTERING_WORLD")
-      -- Bar.frame does not use OnEvent
-    f:SetScript("OnEvent", 
-      function()
-        if not InCombatLockdown() then
-          self:SetupBar(bar)
-        end
-      end)
-    f.events_registered = true
-  end
-
-
-  f:Execute(_bar_init)
-end
-
--- a/classes/Overlay.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,754 +0,0 @@
-local addonName, addonTable = ...
-local ReAction               = addonTable.ReAction
-local L                      = ReAction.L
-local LKB                    = ReAction.LKB
-local CreateFrame            = CreateFrame
-local InCombatLockdown       = InCombatLockdown
-local floor                  = math.floor
-local min                    = math.min
-local format                 = string.format
-local GameTooltip            = GameTooltip
-local Bar                    = ReAction.Bar
-local GetSize                = Bar.GetSize
-local SetSize                = Bar.SetSize
-local GetButtonSize          = Bar.GetButtonSize
-local GetButtonGrid          = Bar.GetButtonGrid
-local SetButtonSize          = Bar.SetButtonSize
-local SetButtonGrid          = Bar.SetButtonGrid
-local ApplyAnchor            = Bar.ApplyAnchor
-local GameTooltipTextRight1  = GameTooltipTextRight1
-local GameTooltipTextRight2  = GameTooltipTextRight2
-local GameTooltipTextRight3  = GameTooltipTextRight3
-
---
--- Wrap some of the bar manipulators to make them state-aware
---
-local function SetAnchor( bar, point, frame, relPoint, x, y )
-  local state = bar:GetSecureState()
-  if state then
-    local anchorstate = bar:GetStateProperty(state, "anchorEnable")
-    if anchorstate then
-      bar:SetStateProperty(state, "anchorFrame", frame)
-      bar:SetStateProperty(state, "anchorPoint", point)
-      bar:SetStateProperty(state, "anchorRelPoint", relPoint)
-      bar:SetStateProperty(state, "anchorX", x or 0)
-      bar:SetStateProperty(state, "anchorY", y or 0)
-      bar:SetAnchor(bar:GetAnchor())
-      return
-    end
-  end
-  bar:SetAnchor(point, frame, relPoint, x, y)
-end
-
-local function GetStateScale( bar )
-  local state = bar:GetSecureState()
-  if state and bar:GetStateProperty(state, "enableScale") then
-    return bar:GetStateProperty(state, "scale")
-  end
-end
-
-local function SetStateScale( bar, scale )
-  local state = bar:GetSecureState()
-  if state and bar:GetStateProperty(state, "enableScale") then
-    bar:SetStateProperty(state, "scale", scale)
-  end
-end
-
-
---
--- Bar config overlay
---
-
-local function GetNormalTextColor()
-  return 1.0, 1.0, 1.0, 1.0
-end
-
-local function GetAnchoredTextColor()
-  return 1.0, 1.0, 1.0, 1.0
-end
-
-local function GetNormalBgColor()
-  return 0.7, 0.7, 1.0, 0.3
-end
-
-local function GetAnchoredBgColor()
-  return 0.9, 0.2, 0.7, 0.3
-end
-
-local function StoreSize(bar)
-  local f = bar:GetFrame()
-  SetSize( bar, f:GetWidth(), f:GetHeight() )
-end
-
-local function StoreExtents(bar)
-  local f = bar:GetFrame()
-  local p, fr, rp, x, y = f:GetPoint(1)
-  fr = fr and fr:GetName() or "UIParent"
-  SetAnchor( bar, p, fr, rp, x, y )
-  SetSize( bar, f:GetWidth(), f:GetHeight() )
-end
-
-local function RecomputeButtonSize(bar)
-  local w, h = GetSize(bar)
-  local bw, bh = GetButtonSize(bar)
-  local r, c, s = GetButtonGrid(bar)
-
-  local scaleW = (floor(w/c) - s) / bw
-  local scaleH = (floor(h/r) - s) / bh
-  local scale = min(scaleW, scaleH)
-
-  SetButtonSize(bar, scale * bw, scale * bh, s)
-end
-
-local function ComputeBarScale(bar, overlay)
-  local w, h = overlay:GetWidth() - 8, overlay:GetHeight() - 8
-  local bw, bh = GetButtonSize(bar)
-  local r, c, s = GetButtonGrid(bar)
-
-  local scaleW = w / (c*(bw+s))
-  local scaleH = h / (r*(bh+s))
-  local scale = min(scaleW, scaleH)
-
-  if scale > 2.5 then
-    scale = 2.5
-  elseif scale < 0.25 then
-    scale = 0.25
-  end
-
-  return scale
-end
-
-local function RecomputeButtonSpacing(bar)
-  local w, h = GetSize(bar)
-  local bw, bh = GetButtonSize(bar)
-  local r, c, s = GetButtonGrid(bar)
-
-  SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh))
-end
-
-local function RecomputeGrid(bar)
-  local w, h = GetSize(bar)
-  local bw, bh = GetButtonSize(bar)
-  local r, c, s = GetButtonGrid(bar)
-
-  SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s)
-end
-
-local function ClampToButtons(bar)
-  local bw, bh = GetButtonSize(bar)
-  local r, c, s = GetButtonGrid(bar)
-  SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1)
-end
-
-local function HideGameTooltip()
-  GameTooltip:Hide()
-end
-
-local anchorInside  = { inside = true }
-local anchorOutside = { outside = true }
-local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" }
-local oppositeEdges = {
-  TOP = "BOTTOM",
-  BOTTOM = "TOP",
-  LEFT = "RIGHT",
-  RIGHT = "LEFT"
-}
-local pointsOnEdge = {
-  BOTTOM = { "BOTTOM", "BOTTOMLEFT",  "BOTTOMRIGHT",  },
-  TOP    = { "TOP",    "TOPLEFT",     "TOPRIGHT",     },
-  RIGHT  = { "RIGHT",  "BOTTOMRIGHT", "TOPRIGHT",     },
-  LEFT   = { "LEFT",   "BOTTOMLEFT",  "TOPLEFT",      },
-}
-local edgeSelector = {
-  BOTTOM = 1,  -- select x of x,y
-  TOP    = 1,  -- select x of x,y
-  LEFT   = 2,  -- select y of x,y
-  RIGHT  = 2,  -- select y of x,y  
-}
-local snapPoints = {
-  [anchorOutside] = {
-    BOTTOMLEFT  = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"},
-    BOTTOM      = {"TOP"},
-    BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"},
-    RIGHT       = {"LEFT"},
-    TOPRIGHT    = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"},
-    TOP         = {"BOTTOM"},
-    TOPLEFT     = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"},
-    LEFT        = {"RIGHT"},
-    CENTER      = {"CENTER"}
-  },
-  [anchorInside] = {
-    BOTTOMLEFT  = {"BOTTOMLEFT"},
-    BOTTOM      = {"BOTTOM"},
-    BOTTOMRIGHT = {"BOTTOMRIGHT"},
-    RIGHT       = {"RIGHT"},
-    TOPRIGHT    = {"TOPRIGHT"},
-    TOP         = {"TOP"},
-    TOPLEFT     = {"TOPLEFT"},
-    LEFT        = {"LEFT"},
-    CENTER      = {"CENTER"}
-  }
-}
-local insidePointOffsetFuncs = {
-  BOTTOMLEFT  = function(x, y) return x, y end,
-  BOTTOM      = function(x, y) return 0, y end,
-  BOTTOMRIGHT = function(x, y) return -x, y end,
-  RIGHT       = function(x, y) return -x, 0 end,
-  TOPRIGHT    = function(x, y) return -x, -y end,
-  TOP         = function(x, y) return 0, -y end,
-  TOPLEFT     = function(x, y) return x, -y end,
-  LEFT        = function(x, y) return x, 0 end,
-  CENTER      = function(x, y) return x, y end,
-}
-local pointCoordFuncs = {
-  BOTTOMLEFT  = function(f) return f:GetLeft(),  f:GetBottom() end,
-  BOTTOM      = function(f) return nil,          f:GetBottom() end,
-  BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end,
-  RIGHT       = function(f) return f:GetRight(), nil end,
-  TOPRIGHT    = function(f) return f:GetRight(), f:GetTop() end,
-  TOP         = function(f) return nil,          f:GetTop() end,
-  TOPLEFT     = function(f) return f:GetLeft(),  f:GetTop() end,
-  LEFT        = function(f) return f:GetLeft(),  nil end,
-  CENTER      = function(f) return f:GetCenter() end,
-}
-local edgeBoundsFuncs = {
-  BOTTOM = function(f) return f:GetLeft(), f:GetRight() end,
-  LEFT   = function(f) return f:GetBottom(), f:GetTop() end
-}
-edgeBoundsFuncs.TOP   = edgeBoundsFuncs.BOTTOM
-edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT
-local cornerTexCoords = {
-              -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
-  TOPLEFT     = { 1,   1,   1,   0,   0,   1,   0,   0 },
-  TOPRIGHT    = { 1,   0,   0,   0,   1,   1,   0,   1 },
-  BOTTOMLEFT  = { 0,   1,   1,   1,   0,   0,   1,   0 },
-  BOTTOMRIGHT = { 0,   0,   0,   1,   1,   0,   1,   1 },
-}
-
--- Returns absolute coordinates x,y of the named point 'p' of frame 'f'
-local function GetPointCoords( f, p )
-  local x, y = pointCoordFuncs[p](f)
-  if not(x and y) then
-    local cx, cy = f:GetCenter()
-    x = x or cx
-    y = y or cy
-  end
-  return x, y
-end
-
-
--- Returns true if frame 'f1' can be anchored to frame 'f2'
-local function CheckAnchorable( f1, f2 )
-  -- can't anchor a frame to itself or to nil
-  if f1 == f2 or f2 == nil then
-    return false
-  end
-  
-  -- can always anchor to UIParent
-  if f2 == UIParent then
-    return true
-  end
-  
-  -- also can't do circular anchoring of frames 
-  -- walk the anchor chain, which generally shouldn't be that expensive
-  -- (who nests draggables that deep anyway?)
-  for i = 1, f2:GetNumPoints() do
-    local _, f = f2:GetPoint(i)
-    if not f then f = f2:GetParent() end
-    return CheckAnchorable(f1,f)
-  end
-  
-  return true
-end
-
--- Returns true if frames f1 and f2 specified edges overlap
-local function CheckEdgeOverlap( f1, f2, e )
-  local l1, u1 = edgeBoundsFuncs[e](f1)
-  local l2, u2 = edgeBoundsFuncs[e](f2)
-  return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2
-end
-
--- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2
-local function CheckPointEdgeOverlap( f1, p1, f2, e2 )
-  local l, u = edgeBoundsFuncs[e2](f2)
-  local x, y = GetPointCoords(f1,p1)
-  x = select(edgeSelector[e2], x, y)
-  return l <= x and x <= u
-end
-
--- Returns the distance between corresponding edges. It is 
--- assumed that the passed in edges e1 and e2 are the same or opposites
-local function GetEdgeDistance( f1, f2, e1, e2 )
-  local x1, y1 = pointCoordFuncs[e1](f1)
-  local x2, y2 = pointCoordFuncs[e2](f2)
-  return math.abs((x1 or y1) - (x2 or y2))
-end
-
-local globalSnapTargets = { [UIParent] = anchorInside }
-
-local function GetClosestFrameEdge(f1,f2,a)
-  local dist, edge, opp
-  if f2:IsVisible() and CheckAnchorable(f1,f2) then
-    for _, e in pairs(edges) do
-      local o = a.inside and e or oppositeEdges[e]
-      if CheckEdgeOverlap(f1,f2,e) then
-        local d = GetEdgeDistance(f1, f2, e, o)
-        if not dist or (d < dist) then
-          dist, edge, opp = d, e, o
-        end
-      end
-    end
-  end
-  return dist, edge, opp
-end
-
-local function GetClosestVisibleEdge( f )
-  local r, o, e1, e2
-  local a = anchorOutside
-  for _, b in ReAction:IterateBars() do
-    local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a)
-    if d and (not r or d < r) then
-      r, o, e1, e2 = d, b:GetFrame(), e, opp
-    end
-  end
-  for f2, a2 in pairs(globalSnapTargets) do
-    local d, e, opp = GetClosestFrameEdge(f,f2,a2)
-    if d and (not r or d < r) then
-      r, o, e1, e2, a = d, f2, e, opp, a2
-    end
-  end
-  return o, e1, e2, a
-end
-
-local function GetClosestVisiblePoint(f1)
-  local f2, e1, e2, a = GetClosestVisibleEdge(f1)
-  if f2 then
-    local rsq, p, rp, x, y
-    -- iterate pointsOnEdge in order and use < to prefer edge centers to corners
-    for _, p1 in ipairs(pointsOnEdge[e1]) do
-      if CheckPointEdgeOverlap(f1,p1,f2,e2) then
-        for _, p2 in pairs(snapPoints[a][p1]) do
-          local x1, y1 = GetPointCoords(f1,p1)
-          local x2, y2 = GetPointCoords(f2,p2)
-          local dx = x1 - x2
-          local dy = y1 - y2
-          local rsq2 = dx*dx + dy*dy
-          if not rsq or rsq2 < rsq then
-            rsq, p, rp, x, y = rsq2, p1, p2, dx, dy
-          end
-        end
-      end
-    end
-    return f2, p, rp, x, y
-  end
-end
-
-local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff)
-  local o, p, rp, x, y = GetClosestVisiblePoint(f1)
-  local s = false
-
-  local insideOffsetFunc = p and insidePointOffsetFuncs[p]
-  local coordFunc = p and pointCoordFuncs[p]
-  if not insideOffsetFunc or not coordFunc then
-    return
-  end
-  
-  local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0)
-  local xx, yy = coordFunc(f1)
-  if xx and yy then
-    if math.abs(x) <= rx then
-      if math.abs(y) <= ry then
-        x = sx
-        y = sy
-        s = true
-      elseif CheckEdgeOverlap(f1,o,"LEFT") then
-        x = sx
-        s = true
-      end
-    elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then
-      y = sy
-      s = true
-    end
-  elseif xx then
-    if math.abs(x) <= rx then
-      x = sx
-      s = true
-      if math.abs(y) <= ry then
-        y = sy
-      end
-    end
-  elseif yy then
-    if math.abs(y) <= ry then
-      y = sy
-      s = true
-      if math.abs(x) <= rx then
-        x = sx
-      end
-    end
-  end
-
-  -- correct for some Lua oddities with doubles
-  if x == -0 then x = 0 end
-  if y == -0 then y = 0 end
-  
-  if s then
-    return o, p, rp, math.floor(x), math.floor(y)
-  end
-end
-
-local function CreateSnapIndicator()
-  local si = CreateFrame("Frame",nil,UIParent)
-  si:SetFrameStrata("HIGH")
-  si:SetHeight(16)
-  si:SetWidth(16)
-  local tex = si:CreateTexture()
-  tex:SetAllPoints()
-  tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
-  tex:SetBlendMode("ADD")
-  tex:SetDrawLayer("OVERLAY")
-  return si
-end
-
-local si1 = CreateSnapIndicator()
-local si2 = CreateSnapIndicator()
-
-local function DisplaySnapIndicator( f, rx, ry, xOff, yOff )
-  local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff)
-  if o then
-    si1:ClearAllPoints()
-    si2:ClearAllPoints()
-    si1:SetPoint("CENTER", f, p, 0, 0)
-    local xx, yy = pointCoordFuncs[rp](o)
-    x = math.abs(x) <=rx and xx and 0 or x
-    y = math.abs(y) <=ry and yy and 0 or y
-    si2:SetPoint("CENTER", o, rp, x, y)
-    si1:Show()
-    si2:Show()
-  else
-    if si1:IsVisible() then
-      si1:Hide()
-      si2:Hide()
-    end
-  end
-  return o, p
-end
-
-local function HideSnapIndicator()
-  if si1:IsVisible() then
-    si1:Hide()
-    si2:Hide()
-  end
-end
-
-local function UpdateLabelString(overlay)
-  local label = overlay.labelString
-  if label then
-    local name = overlay.labelName
-    if name and overlay.labelSubtext then
-      name = format("%s (%s)", name, overlay.labelSubtext)
-    end
-    label:SetText(name or "")
-  end
-end
-
-local function CreateControls(bar)
-  local f = bar:GetFrame()
-
-  f:SetMovable(true)
-  f:SetResizable(true)
-
-  -- child of UIParent so that alpha and scale doesn't propagate to it
-  local overlay = CreateFrame("Button", nil, UIParent)
-  overlay:EnableMouse(true)
-  overlay:SetFrameLevel(10) -- set it above the buttons
-  overlay:SetPoint("TOPLEFT", f, "TOPLEFT", -4, 4)
-  overlay:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 4, -4)
-  overlay:SetBackdrop({
-    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
-    tile = true,
-    tileSize = 16,
-    edgeSize = 16,
-    insets = { left = 0, right = 0, top = 0, bottom = 0 },
-  })
-
-  -- textures
-  local bgTex = overlay:CreateTexture(nil,"BACKGROUND")
-  bgTex:SetTexture(0.7,0.7,1.0,0.2)
-  bgTex:SetPoint("TOPLEFT",4,-4)
-  bgTex:SetPoint("BOTTOMRIGHT",-4,4)
-  local hTex = overlay:CreateTexture(nil,"HIGHLIGHT")
-  hTex:SetTexture(0.7,0.7,1.0,0.2)
-  hTex:SetPoint("TOPLEFT",4,-4)
-  hTex:SetPoint("BOTTOMRIGHT",-4,4)
-  hTex:SetBlendMode("ADD")
-  local aTex = overlay:CreateTexture(nil,"ARTWORK")
-  aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
-  aTex:SetWidth(16)
-  aTex:SetHeight(16)
-  aTex:Hide()
-
-  -- label
-  local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
-  label:SetAllPoints()
-  label:SetJustifyH("CENTER")
-  label:SetShadowColor(0,0,0,1)
-  label:SetShadowOffset(3,-3)
-  label:SetTextColor(GetNormalTextColor())
-  label:SetText(bar:GetName())
-  label:Show()
-  overlay.labelString = label
-  overlay.labelName = bar:GetName()
-
-  local function UpdateAnchorDecoration()
-    local point, anchor, relPoint, x, y = f:GetPoint(1)
-    if point then
-      local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
-      if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then
-        bgTex:SetTexture( GetAnchoredBgColor() )
-        hTex:SetTexture( GetAnchoredBgColor() )
-        label:SetTextColor( GetAnchoredTextColor() )
-        aTex:ClearAllPoints()
-        aTex:SetPoint(point)
-        aTex:Show()
-        return
-      end
-    end
-    bgTex:SetTexture( GetNormalBgColor() )
-    hTex:SetTexture( GetNormalBgColor() )
-    label:SetTextColor( GetNormalTextColor() )
-    aTex:Hide()
-  end
-
-  local function StopResize()
-    f:StopMovingOrSizing()
-    f.isMoving = false
-    f:SetScript("OnUpdate",nil)
-    StoreSize(bar)
-    ClampToButtons(bar)
-    ReAction:RefreshEditor()
-  end
-
-  local function CornerUpdate()
-    local bw, bh = GetButtonSize(bar)
-    local r, c, s = GetButtonGrid(bar)
-    local ss = GetStateScale(bar)
-    if IsShiftKeyDown() then
-      if ss then
-        f:SetMinResize( ((s+bw)*c*0.25)/ss, ((s+bh)*r*0.25)/ss )
-        f:SetMaxResize( ((s+bw)*c*2.5 + 1)/ss, ((s+bh)*r*2.5 + 1)/ss )
-        scale = ComputeBarScale(bar, overlay)
-      else
-        f:SetMinResize( (s+12)*c+1, (s+12)*r+1 )
-        f:SetMaxResize( (s+128)*c+1, (s+128)*r+1 )
-        RecomputeButtonSize(bar)
-      end
-    elseif not ss and IsAltKeyDown() then
-      f:SetMinResize( bw*c, bh*r )
-      f:SetMaxResize( 2*bw*c, 2*bh*r )
-      RecomputeButtonSpacing(bar)
-    else
-      f:SetMinResize( bw+s+1, bh+s+1 )
-      f:SetMaxResize( 50*(bw+s)+1, 50*(bh+s)+1 )
-      RecomputeGrid(bar)
-    end
-    GameTooltipTextRight2:SetText(format("%d x %d",r,c))
-
-    local ss = GetStateScale(bar)
-    if ss then
-      GameTooltipTextRight4:SetText(format("%d%%", scale*100))
-    else
-      local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
-      GameTooltipTextRight3:SetText(size)
-      GameTooltipTextRight4:SetText(tostring(s))
-    end
-  end
-
-  -- corner drag handles
-  for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do
-    local corner = CreateFrame("Frame",nil,overlay)
-    corner:EnableMouse(true)
-    corner:SetWidth(16)
-    corner:SetHeight(16)
-    corner:SetPoint(point)
-
-    local tex = corner:CreateTexture(nil,"HIGHLIGHT")
-    tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner")
-    tex:SetTexCoord(unpack(cornerTexCoords[point]))
-    tex:SetBlendMode("ADD")
-    tex:SetAlpha(0.6)
-    tex:SetAllPoints()
-    
-    corner:SetScript("OnMouseDown",
-      function(_,btn)
-        f:SetScript("OnUpdate", CornerUpdate)
-        f:StartSizing(point)
-      end
-    )
-    corner:SetScript("OnMouseUp",
-      function()
-        local ss = GetStateScale(bar)
-        if ss then
-          SetStateScale(bar, ComputeBarScale(bar, overlay))
-        end
-        StopResize()
-      end)
-    corner:SetScript("OnEnter",
-      function()
-        local bw, bh = GetButtonSize(bar)
-        local r, c, s = bar:GetButtonGrid()
-        local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
-        local ss = GetStateScale(bar)
-        local state = bar:GetSecureState()
-        GameTooltip:SetOwner(f, "ANCHOR_"..point)
-        if ss then
-          GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
-        else
-          GameTooltip:AddLine(bar:GetName())
-        end
-        GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c))
-        if ss then
-          GameTooltip:AddLine(L["State Scale Override"])
-          GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to change scale:"]), format("%d%%", bar:GetStateProperty(state,"scale")*100))
-        else
-          GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), tostring(floor(size)))
-          GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"],  L["to change spacing:"]), tostring(floor(s)))
-        end
-        GameTooltip:Show()
-      end
-    )
-    corner:SetScript("OnLeave", 
-      function()
-        GameTooltip:Hide()
-        f:SetScript("OnUpdate",nil)
-      end
-    )
-  end
-
-  overlay:RegisterForDrag("LeftButton")
-  overlay:RegisterForClicks("RightButtonUp")
-  
-  overlay:SetScript("OnDragStart",
-    function()
-      f:StartMoving()
-      f.isMoving = true
-      local w,h = bar:GetButtonSize()
-      f:ClearAllPoints()
-      UpdateAnchorDecoration()
-      f:SetScript("OnUpdate", function()
-          if IsShiftKeyDown() then
-            local f, p = DisplaySnapIndicator(f,w,h)
-          else
-            HideSnapIndicator()
-          end
-        end)
-    end
-  )
-
-  local function UpdateDragTooltip()
-    GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT")
-    local ss = GetStateScale(bar)
-    local state = bar:GetSecureState()
-    if ss then
-      GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
-    else
-      GameTooltip:AddLine(bar:GetName())
-    end
-    GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"]))
-    GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"]))
-    GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."]))
-    local point, frame, relpoint, x, y = bar:GetFrame():GetPoint(1)
-    if point then
-      local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
-      if (frame and frame ~= UIParent) or (ofsx == 0 and ofsy == 0) then
-        frame = frame or UIParent
-        GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],frame:GetName()))
-      end
-    end
-    GameTooltip:Show()
-  end
-
-  overlay:SetScript("OnDragStop",
-    function()
-      f:StopMovingOrSizing()
-      f.isMoving = false
-      f:SetScript("OnUpdate",nil)
-
-      if IsShiftKeyDown() then
-        local w, h = bar:GetButtonSize()
-        local a, p, rp, x, y = GetClosestPointSnapped(f,w,h)
-        if a then
-          f:ClearAllPoints()
-          f:SetPoint(p,a,rp,x,y)
-        end
-        HideSnapIndicator()
-      end
-
-      StoreExtents(bar)
-      ReAction:RefreshEditor()
-      UpdateDragTooltip()
-      UpdateAnchorDecoration()
-    end
-  )
-
-  overlay:SetScript("OnEnter",
-    function()
-      UpdateDragTooltip()
-    end
-  )
-
-  overlay:SetScript("OnLeave", HideGameTooltip)
-
-  overlay:SetScript("OnClick",
-    function()
-      ReAction:ShowEditor(bar)
-    end
-  )
-
-  function overlay:RefreshControls()
-    UpdateAnchorDecoration()
-  end
-
-  overlay:SetScript("OnShow", overlay.RefreshControls)
-
-  if ReAction:GetKeybindMode() then
-    overlay:SetFrameLevel(1)
-  end
-
-  UpdateLabelString(overlay)
-  UpdateAnchorDecoration()
-
-  return overlay
-end
-
-
--- export methods to the Bar prototype
-Bar.Overlay = { }
-function Bar.Overlay:New( bar )
-  return setmetatable( {frame = CreateControls(bar)}, {__index=self} )
-end
-
-function Bar.Overlay:SetLabel(name)
-  self.frame.labelName = name
-  UpdateLabelString(self.frame)
-end
-
-function Bar.Overlay:SetLabelSubtext(text)
-  self.frame.labelSubtext = text
-  UpdateLabelString(self.frame)
-end
-
-function Bar.Overlay:Show()
-  self.frame:Show()
-end
-
-function Bar.Overlay:Hide()
-  self.frame:Hide()
-end
-
-function Bar.Overlay:IsShown()
-  return self.frame:IsShown()
-end
-
-function Bar.Overlay:RefreshControls()
-  self.frame:RefreshControls()
-end
\ No newline at end of file
--- a/classes/PetActionButton.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local GetCVar = GetCVar
-local InCombatLockdown = InCombatLockdown
-local GetPetActionInfo = GetPetActionInfo
-local GetPetActionSlotUsable = GetPetActionSlotUsable
-local GetPetActionCooldown = GetPetActionCooldown
-local AutoCastShine_AutoCastStart = AutoCastShine_AutoCastStart
-local AutoCastShine_AutoCastStop = AutoCastShine_AutoCastStop
-local SetDesaturation = SetDesaturation
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-
---
--- Secure snippets
--- These are run within the context of the bar's sandbox, as the
--- buttons themselves do not have their own sandbox.
---
-local _onDragStart = -- function(self, button, kind, value, ...)
-[[
-  if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
-    return kind, value, ...
-  else
-    return "petaction", self:GetAttribute("action")
-  end
-]]
-
-local _onReceiveDrag = -- function(self, button, kind, value, ...)
-[[
-  if kind then -- pet spells on the cursor return nil from GetCursorInfo(), which is very strange
-    return kind, value, ...
-  end
-  return "petaction", self:GetAttribute("action")
-]]
-
---
--- private
---
-local eventList = {
-"PLAYER_CONTROL_LOST",
-"PLAYER_CONTROL_GAINED",
-"PLAYER_FARSIGHT_FOCUS_CHANGED",
-"UNIT_PET",
-"UNIT_FLAGS",
-"UNIT_AURA",
-"PET_BAR_UPDATE",
-"PET_BAR_UPDATE_COOLDOWN",
-"PET_BAR_UPDATE_USABLE",
-"UPDATE_BINDINGS",
-}
-
---
--- Pet Action Button class
---
-local buttonTypeID = "PetAction"
-local Super = ReAction.Button
-local Pet = setmetatable( 
-  { 
-    defaultBarConfig = { 
-      type = buttonTypeID,
-      btnWidth = 30,
-      btnHeight = 30,
-      btnRows = 1,
-      btnColumns = 10,
-      spacing = 8,
-      buttons = { }
-    },
-
-    barType = L["Pet Action Bar"], 
-    buttonTypeID = buttonTypeID
-  },
-  { __index = Super } )
-
-ReAction.Button.PetAction = Pet
-ReAction:RegisterBarType(Pet)
-
-function Pet:New( config, bar, idx, idHint )
-  local name = format("ReAction_%s_PetAction_%d",bar:GetName(),idx)
- 
-  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
-
-  local f = self:GetFrame()
-  if not f.autoCastTexture then
-    -- store autocast stuff with the frame for recycling
-    local tex = f:CreateTexture(nil,"OVERLAY")
-    tex:SetTexture([[Interface\Buttons\UI-AutoCastableOverlay]])
-    tex:SetHeight(58)
-    tex:SetWidth(58)
-    tex:SetPoint("CENTER")
-    f.autoCastTexture = tex
-    f.autoCastShine = CreateFrame("Frame",name.."Shine",f,"AutoCastShineTemplate") -- create after autocast texture so it's on top
-    -- move the cooldown around
-    local cd = self.frames.cooldown
-    cd:ClearAllPoints()
-    cd:SetWidth(33)
-    cd:SetHeight(33)
-    cd:SetPoint("CENTER", f, "CENTER", -2, -1)
-    -- resize to 30x30
-    f:SetHeight(30)
-    f:SetWidth(30)
-    local nt = _G[name.."NormalTexture"]
-    nt:SetHeight(54)
-    nt:SetWidth(54)
-  end
-  local barFrame = bar:GetFrame()
-
-  -- set up the base action ID
-  self:SetActionIDPool("pet",10)
-  config.actionID = self:AcquireActionID(config.actionID, idHint, true)
-
-  -- attribute setup
-  -- There's no secure way to do PetAutoCastToggle by actionID, so use
-  -- a click-through proxy to the Blizzard pet buttons for right-click
-  -- Note that technically this doesn't do PetStopAttack() when 
-  -- IsPetAttackActive() is true: however that's only true when using
-  -- Eyes of the Beast and appears not to really do anything (at least
-  -- I can't find any difference)
-  f:SetAttribute("type","pet")
-  f:SetAttribute("type2","click")
-  f:SetAttribute("clickbutton2",_G["PetActionButton"..config.actionID])
-  f:SetAttribute("action",config.actionID)
-  f:SetAttribute("checkselfcast", true)
-  f:SetAttribute("checkfocuscast", true)
-
-  -- non secure scripts
-  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
-  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
-  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
-  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
-  f:SetScript("PreClick", function(frame) self:PreClick() end)
-  f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
-  f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
-
-  -- secure handlers
-  barFrame:WrapScript(f, "OnDragStart", _onDragStart)
-  barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
-
-  -- event registration
-  f:EnableMouse(true)
-  f:RegisterForDrag("LeftButton", "RightButton")
-  f:RegisterForClicks("AnyUp")
-  for _, evt in pairs(eventList) do
-    f:RegisterEvent(evt)
-  end
-
-  -- attach to skinner
-  bar:SkinButton(self,
-   {
-     AutoCast = f.autoCastShine,
-     AutoCastable = f.autoCastTexture
-   })
-
-  self:Refresh()
-  f:Show()
-
-  return self
-end
-
-function Pet:SetupBar(bar)
-  Super.SetupBar(self,bar)
-
-  -- auto show/hide when pet exists
-  bar:RegisterUnitWatch("pet",true)
-
-  self:UpdateButtonLock(bar)
-end
-
-function Pet:UpdateButtonLock(bar)
-  local f = bar:GetFrame()
-  f:SetAttribute("lockbuttons",bar.config.lockButtons)
-  f:SetAttribute("lockbuttonscombat",bar.config.lockButtonsCombat)
-  f:Execute(
-    [[
-      lockButtons = self:GetAttribute("lockbuttons")
-      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
-    ]])
-end
-
-function Pet:Refresh()
-  Super.Refresh(self)
-  self:Update()
-  self:UpdateHotkey()
-end
-
-function Pet:GetActionID()
-  return self.config.actionID
-end
-
-function Pet:SetActionID(id)
-  if not InCombatLockdown() then
-    if id < 0 or id > 10 then
-      ReAction:UserError(L["Pet action ID range is 1-10"])
-      return
-    end
-    self.config.actionID = id
-    f:SetAttribute("clickbutton2",_G["PetActionButton"..id])
-    f:SetAttribute("action",id)
-    self:Update()
-    self:UpdateHotkey()
-  end
-end
-
-function Pet:Update()
-  local action = self.config.actionID
-  local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(action)
-  local f = self:GetFrame()
-  local icon = self.frames.icon
-
-  if isToken then
-    icon:SetTexture(_G[texture])
-    self.tooltipName = _G[name]
-  else
-    icon:SetTexture(texture)
-    self.tooltipName = name
-  end
-
-  self.isToken = isToken
-	self.tooltipSubtext = subtext
-  f:SetChecked( isActive and 1 or 0 )
-
-  if autoCastAllowed then
-    f.autoCastTexture:Show()
-  else
-    f.autoCastTexture:Hide()
-  end
-
-  if autoCastEnabled then
-    AutoCastShine_AutoCastStart(f.autoCastShine)
-  else
-    AutoCastShine_AutoCastStop(f.autoCastShine)
-  end
-
-  if texture then
-    if GetPetActionSlotUsable(action) then
-      SetDesaturation(icon,nil)
-    else
-      SetDesaturation(icon,1)
-    end
-    icon:Show()
-    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
-  else
-    icon:Hide()
-    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
-  end
-
-  self:UpdateCooldown()
-end
-
-function Pet:UpdateCooldown()
-  CooldownFrame_SetTimer(self.frames.cooldown, GetPetActionCooldown(self.config.actionID))
-end
-
-function Pet:SetTooltip()
-  if self.tooltipName then
-    local f = self:GetFrame()
-    local uber = GetCVar("UberTooltips")
-    if self.isToken or (uber == "0") then
-      if uber == "0" then
-        GameTooltip:SetOwner(f, "ANCHOR_RIGHT")
-      else
-        GameTooltip_SetDefaultAnchor(GameTooltip, f)
-      end
-      GameTooltip:SetText(self.tooltipName)
-      if self.tooltipSubtext then
-        GameTooltip:AddLine(self.tooltipSubtext, "", 0.5, 0.5, 0.5)
-      end
-      GameTooltip:Show()
-    else
-      GameTooltip_SetDefaultAnchor(GameTooltip, f)
-      GameTooltip:SetPetAction(self.config.actionID)
-    end
-  else
-    GameTooltip:Hide()
-  end
-end
-
-function Pet:OnEvent(event, unit)
-  if event =="PET_BAR_UPDATE_COOLDOWN" then
-    self:UpdateCooldown()
-  elseif event == "UPDATE_BINDINGS" then
-    self:UpdateHotkey()
-  elseif event == "UNIT_PET" then
-    if unit == "player" then
-      self:Update()
-    end
-  elseif event == "UNIT_FLAGS" or event == "UNIT_AURA" then
-    if unit == "pet" then
-      self:Update()
-    end
-  else
-    self:Update()
-  end
-end
-
-function Pet:OnEnter()
-  self:SetTooltip()
-end
-
-function Pet:OnLeave()
-  GameTooltip:Hide()
-end
-
-function Pet:OnAttributeChanged(attr,value)
-  self:Update()
-end
-
-function Pet:PreClick()
-  self:GetFrame():SetChecked(0)
-end
-
-function Pet:OnDragStart()
-  self:SetChecked(0)
-  self:Update()
-end
-
-function Pet:OnReceiveDrag()
-  self:SetChecked(0)
-  self:Update()
-end
-
--- a/classes/StanceButton.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local _G = _G
-local CreateFrame = CreateFrame
-local format = string.format
-local GetCVar = GetCVar
-local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
-local CooldownFrame_SetTimer = CooldownFrame_SetTimer
-local InCombatLockdown = InCombatLockdown
-local GetNumShapeshiftForms = GetNumShapeshiftForms
-local GetShapeshiftFormInfo = GetShapeshiftFormInfo
-local IsUsableSpell = IsUsableSpell
-local GetSpellInfo = GetSpellInfo
-
---
--- private
---
-local playerClass = select(2,UnitClass("player"))
-
-local eventList = {
-  "PLAYER_REGEN_ENABLED",
-  "PLAYER_ENTERING_WORLD",
-  "UPDATE_SHAPESHIFT_FORM",
-  "UPDATE_SHAPESHIFT_FORMS",
-  "UPDATE_SHAPESHIFT_USABLE",
-  "UPDATE_SHAPESHIFT_COOLDOWN",
-  "UPDATE_BINDINGS",
-}
-
---
--- Stance Button class
---
-local buttonTypeID = "Stance"
-local Super = ReAction.Button
-local Stance = setmetatable(
-  { 
-    defaultConfig = { 
-      type = buttonTypeID,
-      btnHeight = 36,
-      btnWidth = 36,
-      btnRows = 1,
-      btnColumns = 6,
-      spacing = 3
-    }, 
-
-    barType = L["Stance Bar"], 
-    buttonTypeID = buttonTypeID
-  },
-  { __index = Super } )
-
-ReAction.Button.Stance = Stance
-ReAction:RegisterBarType(Stance)
-
-function Stance:New( config, bar, idx, idHint )
-  local name = format("ReAction_%s_Stance_%d",bar:GetName(),idx)
- 
-  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
-
-  local f = self:GetFrame()
-  local barFrame = bar:GetFrame()
-  local config = self:GetConfig()
-
-  -- set up the base stance ID
-  self:SetActionIDPool("stance",8)
-  config.stanceID = self:AcquireActionID(config.stanceID, idHint, true)
-
-  -- attribute setup
-  f:SetAttribute("type","spell")
-
-  -- non secure scripts
-  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
-  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
-  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
-  f:SetScript("PreClick", function(frame, ...) self:PreClick(...) end)
-
-  -- secure handlers
-  -- (none)
-
-  -- event registration
-  f:EnableMouse(true)
-  f:RegisterForClicks("AnyUp")
-  for _, evt in pairs(eventList) do
-    f:RegisterEvent(evt)
-  end
-
-  -- attach to skinner
-  bar:SkinButton(self)
-
-  -- initial display
-  if ReAction:GetConfigMode() then
-    self:GetFrame():Show()
-  end
-
-  self:Refresh()
-
-  return self
-end
-
-function Stance:GetActionID()
-  return self.config.stanceID
-end
-
-function Stance:UpdateAction()
-  if InCombatLockdown() then
-    self.updatePending = true
-  else
-    self.updatePending = false
-    local idx = self:GetActionID()
-    local f = self:GetFrame()
-    if idx > GetNumShapeshiftForms() then
-      f:Hide()
-    else
-      f:SetAttribute("spell", select(2,GetShapeshiftFormInfo(idx)))
-      f:Show()
-      self:Update()
-    end
-  end
-end
-
-function Stance:Refresh()
-  Super.Refresh(self)
-  self:UpdateHotkey()
-  self:UpdateAction()
-end
-
-function Stance:Update()
-  local texture, _, isActive, isCastable = GetShapeshiftFormInfo(self:GetActionID())
-  
-  local icon = self.frames.icon
-  icon:SetTexture(texture)
-  self:GetFrame():SetChecked( isActive and 1 or 0 )
-  if isCastable then
-    self.frames.hotkey:Show()
-    icon:SetVertexColor(1.0, 1.0, 1.0)
-  else
-    icon:SetVertexColor(0.4, 0.4, 0.4)
-  end
-
-  self:UpdateCooldown()
-end
-
-function Stance:UpdateCooldown()
-  local start, duration, enabled = GetShapeshiftFormCooldown(self:GetActionID())
-  if start then
-    CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enabled)
-  end
-end
-
-function Stance:SetTooltip()
-  if GetCVar("UberTooltips") == "1" then
-    GameTooltip_SetDefaultAnchor(GameTooltip, self:GetFrame())
-  else
-    GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT")
-  end
-  GameTooltip:SetShapeshift(self:GetActionID())
-end
-
-function Stance:OnEnter()
-  self:SetTooltip()
-end
-
-function Stance:OnLeave()
-  GameTooltip:Hide()
-end
-
-function Stance:PreClick()
-  local f = self:GetFrame()
-  f:SetChecked( not f:GetChecked() )
-end
-
-function Stance:OnEvent(event, arg)
-  if event == "PLAYER_REGEN_ENABLED" then
-    if self.updatePending then
-      self:UpdateAction()
-    end
-  elseif event == "UPDATE_SHAPESHIFT_COOLDOWN" then
-    self:UpdateCooldown()
-  elseif event == "UPDATE_SHAPESHIFT_FORMS" then
-    self:UpdateAction()
-  elseif event == "UNIT_AURA" then
-    if arg == "player" then
-      self:Update()
-    end
-  elseif event == "UPDATE_BINDINGS" then
-    self:UpdateHotkey()
-  else
-    self:Update()
-  end
-end
-
-function Stance:ShowGridTemp(show)
-  if show then
-    self:GetFrame():Show()
-  else
-    self:UpdateAction()
-  end
-end
--- a/classes/VehicleExitButton.lua	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-local addonName, addonTable = ...
-local ReAction = addonTable.ReAction
-local L = ReAction.L
-local format = string.format
-
---
--- VExitButton Button class
---
-local buttonTypeID = "VehicleExit"
-local Super = ReAction.Button
-local VExitButton = setmetatable(
-  { 
-    defaultBarConfig = { 
-      type = buttonTypeID ,
-      btnWidth = 36,
-      btnHeight = 36,
-      btnRows = 1,
-      btnColumns = 1,
-      spacing = 3,
-      buttons = { }
-    },
-
-    barType = L["Exit Vehicle Floater"], 
-    buttonTypeID = buttonTypeID
-  }, 
-  { __index = Super } )
-
-ReAction.Button.VehicleExit = VExitButton
-ReAction:RegisterBarType(VExitButton)
-
-function VExitButton:New( config, bar, idx )
-  local name = format("ReAction_%s_VehicleExit_%d",bar:GetName(),idx)
- 
-  self = Super.New(self, name, config, bar, idx, "SecureFrameTemplate, ActionButtonTemplate", "Button")
-
-  -- frame setup
-  local f = self:GetFrame()
-  self.frames.icon:SetTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up")
-  self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
-
-  -- attribute setup
-  -- (none)
-
-  -- non secure scripts
-  f:SetScript("OnClick", VehicleExit)
-  f:SetScript("OnEnter", function(frame) GameTooltip_AddNewbieTip(frame, LEAVE_VEHICLE, 1.0, 1.0, 1.0, nil) end)
-  f:SetScript("OnLeave", GameTooltip_Hide)
-  f:SetScript("OnEvent", function(frame, evt, ...) self:OnEvent(evt,...) end)
-
-  -- event registration
-  f:EnableMouse(true)
-  f:RegisterForClicks("AnyUp")
-  f:RegisterEvent("UPDATE_BINDINGS")
-
-  -- attach to skinner
-  bar:SkinButton(self)
-
-  self:Refresh()
-  self:UpdateHotkey()
-
-  return self
-end
-
-function VExitButton:SetupBar(bar)
-  Super.SetupBar(self,bar)
-  self:UpdateRegistration(bar)
-end
-
-function VExitButton:GetActionID()
-  return 1
-end
-
-function VExitButton:Refresh()
-  Super.Refresh(self)
-  -- it seems that setscale kills the texcoord, have to refresh it
-  self.frames.icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375) 
-end
-
-function VExitButton:OnEvent(event, ...)
-  if self[event] then
-    self[event](self, event, ...)
-  end
-end
-
-function VExitButton:UPDATE_BINDINGS()
-  self:UpdateHotkey()
-end
-
-function VExitButton:UpdateRegistration(bar)
-  -- auto show/hide when on a vehicle
-  local config = bar:GetConfig()
-  local f = bar:GetFrame()
-  if config.withControls then
-    if bar.vehicleExitStateRegistered then
-      UnregisterStateDriver(f, "unitexists")
-      bar.vehicleExitStateRegistered = false
-    end
-    bar:RegisterUnitWatch("vehicle",true)
-  else
-    bar:RegisterUnitWatch("vehicle",false)
-    if not bar.vehicleExitStateRegistered then
-      f:SetAttribute("unit","vehicle")
-      RegisterStateDriver(f, "unitexists", "[target=vehicle,exists,novehicleui] show; hide") -- spoof onstate-unitexists
-      bar.vehicleExitStateRegistered = true
-    end
-  end
-end
-
--- a/classes/classes.xml	Sat Mar 26 12:26:55 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-<Ui xmlns="http://www.blizzard.com/wow/ui/" 
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-    xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
-
-<Script file="Bar.lua"/>
-<Script file="Overlay.lua"/>
-<Script file="Button.lua"/>
-<Script file="ActionButton.lua"/>
-<Script file="PetActionButton.lua"/>
-<Script file="StanceButton.lua"/>
-<Script file="BagButton.lua"/>
-<Script file="VehicleExitButton.lua"/>
-<Script file="MultiCastButton.lua"/>
-
-</Ui>
\ No newline at end of file