changeset 4:dfd829db3ad0

(none)
author Flick <flickerstreak@gmail.com>
date Tue, 20 Mar 2007 21:19:34 +0000
parents f5607e135c37
children 27aeec452e7f
files Button.lua ReAction.lua ReBar.lua ReBar.xml ReBinder.lua ReBinder.xml classes/ReAction.lua classes/ReBar.lua classes/ReBar.xml classes/ReBinder.lua classes/ReBinder.xml main.lua
diffstat 12 files changed, 2310 insertions(+), 2253 deletions(-) [+]
line wrap: on
line diff
--- a/Button.lua	Tue Mar 20 21:11:15 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,773 +0,0 @@
--- private constants
-local namePrefix = "ReActionButton"
-local _G = getfenv(0)
-local ACTION_FREE = { }
-local MAX_ACTIONS = 120
-
-local hotKeyDefaultColor    = { r=1.0, g=1.0, b=1.0, a=1.0 }
-local hotKeyDisabledColor   = { r=0.6, g=0.6, b=0.6, a=1.0 }
-local hotKeyOutOfRangeColor = { r=1.0, g=0.2, b=0.2, a=1.0 }
-
-local hotKeyModifierColors = {
-  S = { r=0.6, g=0.6, b=1.0, a=1.0 },  -- shift
-  C = { r=1.0, g=0.82, b=0, a=1.0 },  -- ctrl
-  A = { r=0.1, g=1.0, b=0.1, a=1.0 },  -- alt
-}
-
--- TODO: localize these key names with GetBindingText(KEY_)
-local keybindAbbreviations = {
-  ["Mouse Button "] = "M-",
-  ["Spacebar"] = "Sp",
-  ["Num Pad "] = "Num-",
-  ["Page Up"]  = "PgUp",
-  ["Page Down"] = "PgDn",
-  [" Arrow"] = "",
-}
-
-local equippedActionBorderColor = { r=0, g=1.0, b=0, a=0.35 }
-
-local actionUsableColor        = { r=1.0, g=1.0, b=1.0, a=1.0 }
-local actionNotUsableColor     = { r=0.4, g=0.4, b=0.4, a=1.0 }
-local actionNotEnoughManaColor = { r=0.2, g=0.2, b=0.7, a=1.0 }
-local actionOutOfRangeColor    = { r=1.0, g=0.2, b=0.2, a=1.0 }
-
--- private variables
-local kbValidate = AceLibrary("AceConsole-2.0").keybindingValidateFunc
-local actionButtonTbl = { }
-
-
-
--- ReActionButton is a class prototype object.
-ReActionButton = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
-
--------------------
--- Class methods
--------------------
-
--- In addition to supporting the 'new' creation method (in which case an action ID must be specified directly),
--- ReActionButton supports the 'acquire'/'release' creation method, which recycles objects and manages actionID assignment.
-
-function ReActionButton:acquire(parent, config, barIdx)
-  local id = nil
-  for i = 1, MAX_ACTIONS do
-    if actionButtonTbl[i] == nil or actionButtonTbl[i].inUse == false then
-      id = i
-      break
-    end
-  end
-
-  if id == nil then return nil end  -- all buttons and action ids are in use
-
-  local hint = config.actionIDs[barIdx]
-  if hint and (actionButtonTbl[hint] == nil or actionButtonTbl[hint].inUse == false) then
-    id = hint
-  end
-
-  if actionButtonTbl[id] == nil then 
-    actionButtonTbl[id] = { }
-  end
-  local t = actionButtonTbl[id]
-
-  t.inUse = true
-  if t.button then
-    t.button:Configure(parent,config,barIdx)
-  else
-    t.button = self:new(parent,config,barIdx,id)
-  end
-
-  -- fix screwy config with overlapping IDs
-  config.actionIDs[barIdx] = id
-  return t.button
-end
-
-function ReActionButton:release( b )
-  if b then
-    actionButtonTbl[b:GetActionID()].inUse = false
-    b:Recycle()
-  end
-end
-
-
-
-function ReActionButton:ShowAllActionIDs()
-  for _, b in ipairs(actionButtonTbl) do
-    b:ShowActionID()
-  end
-end
-
-function ReActionButton:HideAllActionIDs()
-  for _, b in ipairs(actionButtonTbl) do
-    b:HideActionID()
-  end
-end
-
-
-----------------------
--- Instance methods
-----------------------
-function ReActionButton.prototype:init( parentFrame, config, barIdx, id )
-  ReActionButton.super.prototype.init(self)
-
-  -- create the button widget
-  self.name = namePrefix..id
-  self.button = CreateFrame("CheckButton", self.name, parentFrame, "ReActionButtonTemplate")
-  
-  -- store references to the various sub-frames so we don't have to look it up all the time
-  self.frames      = {
-    hotkey         = _G[self.name.."HotKey"],
-    count          = _G[self.name.."Count"],
-    cooldown       = _G[self.name.."Cooldown"],
---    nCooldown      = _G[self.name.."CooldownNumeric"],
-    macro          = _G[self.name.."Name"],
-    icon           = _G[self.name.."Icon"],
-    border         = _G[self.name.."Border"],
-    normalTexture  = _G[self.name.."NormalTexture"],
-    flash          = _G[self.name.."Flash"],
-    actionID       = _G[self.name.."ActionID"],
-  }
-
-  -- provide a reference back to this object for the frame to use in event handlers
-  self.button.rxnBtn = self
-
-  -- set the action ID
-  self:SetActionID(id)
-
-  -- register button with ReBinder for keybinding
-  ReBinder:AddKeybindTarget(self.button)
-
-  -- initialize
-  self:Configure(parentFrame, config, barIdx)
-end
-
-local function tcopy(t)
-  local r = { }
-  for k, v in pairs(t) do
-    r[k] = (type(v) == "table" and tcopy(v) or v)
-  end
-  return r
-end
-
-function ReActionButton.prototype:Recycle()
-  local b = self.button
-
-  self:SetKeyBinding(nil)
-  self:UpdateDisplay()
-  b:UnregisterAllEvents()
-  b:SetParent(ReActionButtonRecycleFrame)
-  b:ClearAllPoints()
-  b:SetPoint("TOPLEFT",0,0)
-  b:Hide()
-  self.config = tcopy(self.config) -- ew, but necessary
-end
-
-function ReActionButton.prototype:BarUnlocked()
-  self:ShowGridTmp()
-end
-
-function ReActionButton.prototype:BarLocked()
-  self:HideGridTmp()
-end
-
-
--- set the button location
-function ReActionButton.prototype:PlaceButton(point, x, y, sz)
-  local b = self.button
-  local scale = sz / 36
-  b:ClearAllPoints()
-  b:SetScale( scale )
-  b:SetPoint(point,x/scale,y/scale)
-end
-
-
-function ReActionButton.prototype:ShowActionID()
-  self.frames.actionID:Show()
-end
-
-function ReActionButton.prototype:HideActionID()
-  self.frames.actionID:Hide()
-end
-
-
-
--- configuration and setup
-function ReActionButton.prototype:Configure( parentFrame, config, barIdx )
-  self.config   = config
-  self.barIdx   = barIdx
-  self.showGridTmp_ = 0
-
-  self.button:ClearAllPoints()
-  self.button:SetParent(parentFrame)
-
-  self:SetupAttributes()
-  self:RegisterStaticEvents()
-
-  self:ApplyLayout()
-  self:ApplyStyle()
-
-  self:UpdateDisplay()
-end
-
-function ReActionButton.prototype:SetupAttributes()
-  local b = self.button
-  b:SetAttribute("type", "action")
-	b:SetAttribute("shift-type*", ATTRIBUTE_NOOP)
-	b:SetAttribute("checkselfcast", true)
-	b:SetAttribute("useparent-unit", true)
-end
-
-function ReActionButton.prototype:RegisterStaticEvents()
-	self:RegisterEvent("PLAYER_ENTERING_WORLD")
-	self:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
-	self:RegisterEvent("UPDATE_BINDINGS")
-  self:RegisterEvent("ACTIONBAR_SHOWGRID")
-  self:RegisterEvent("ACTIONBAR_HIDEGRID")
-end
-
-function ReActionButton.prototype:RegisterActionEvents()
-  self:RegisterEvent("ACTIONBAR_UPDATE_STATE")
-  self:RegisterEvent("ACTIONBAR_UPDATE_USABLE")
-  self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN", "ACTIONBAR_UPDATE_USABLE")
-  self:RegisterEvent("UPDATE_INVENTORY_ALERTS", "ACTIONBAR_UPDATE_USABLE")
-  self:RegisterEvent("PLAYER_AURAS_CHANGED", "ACTIONBAR_UPDATE_USABLE")
-  self:RegisterEvent("PLAYER_TARGET_CHANGED", "ACTIONBAR_UPDATE_USABLE")
-  self:RegisterEvent("UNIT_INVENTORY_CHANGED")
-  self:RegisterEvent("CRAFT_SHOW")
-  self:RegisterEvent("CRAFT_CLOSE", "CRAFT_SHOW")
-  self:RegisterEvent("TRADE_SKILL_SHOW", "CRAFT_SHOW")
-  self:RegisterEvent("TRADE_SKILL_CLOSE", "CRAFT_SHOW")
-  self:RegisterEvent("PLAYER_ENTER_COMBAT", "CRAFT_SHOW")
-  self:RegisterEvent("PLAYER_LEAVE_COMBAT")
-  self:RegisterEvent("START_AUTOREPEAT_SPELL")
-  self:RegisterEvent("STOP_AUTOREPEAT_SPELL")
-
-  self.button:SetScript("OnUpdate", function() self:OnUpdate(arg1) end)
-  self.actionEventsRegistered = true
-end
-
-function ReActionButton.prototype:UnregisterActionEvents()
-  self:UnregisterEvent("ACTIONBAR_UPDATE_STATE")
-  self:UnregisterEvent("ACTIONBAR_UPDATE_USABLE")
-  self:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN")
-  self:UnregisterEvent("UPDATE_INVENTORY_ALERTS")
-  self:UnregisterEvent("PLAYER_AURAS_CHANGED")
-  self:UnregisterEvent("PLAYER_TARGET_CHANGED")
-  self:UnregisterEvent("UNIT_INVENTORY_CHANGED")
-  self:UnregisterEvent("CRAFT_SHOW")
-  self:UnregisterEvent("CRAFT_CLOSE")
-  self:UnregisterEvent("TRADE_SKILL_SHOW")
-  self:UnregisterEvent("TRADE_SKILL_CLOSE")
-  self:UnregisterEvent("PLAYER_ENTER_COMBAT")
-  self:UnregisterEvent("PLAYER_LEAVE_COMBAT")
-  self:UnregisterEvent("START_AUTOREPEAT_SPELL")
-  self:UnregisterEvent("STOP_AUTOREPEAT_SPELL")
-
-  self.button:SetScript("OnUpdate", nil)
-  self.actionEventsRegistered = false
-end
-
-
--- event handlers
-function ReActionButton.prototype:ACTIONBAR_SLOT_CHANGED()
-  if arg1 == 0 or arg1 == self:GetActionID() then
-    self:UpdateDisplay()
-  end
-end
-
-function ReActionButton.prototype:PLAYER_ENTERING_WORLD()
-  self:UpdateDisplay()
-end
-
-function ReActionButton.prototype:UPDATE_BINDINGS()
-  self:UpdateDisplay()
-end
-
-function ReActionButton.prototype:ACTIONBAR_SHOWGRID()
-  self:ShowGridTmp()
-end
-
-function ReActionButton.prototype:ACTIONBAR_HIDEGRID()
-  self:HideGridTmp()
-end
-
-function ReActionButton.prototype:ACTIONBAR_UPDATE_STATE()
-  self:UpdateCheckedState()
-end
-
-function ReActionButton.prototype:ACTIONBAR_UPDATE_USABLE()
-  self:UpdateUsable()
-  self:UpdateCooldown()
-  self:ColorHotKey()
-end
-
-function ReActionButton.prototype:UNIT_INVENTORY_CHANGED()
-  if arg1 == "player" then
-    self:UpdateDisplay()
-  end
-end
-
-function ReActionButton.prototype:CRAFT_SHOW()
-  self:UpdateCheckedState()
-end
-
-function ReActionButton.prototype:PLAYER_ENTER_COMBAT()
-  if IsAttackAction(self:GetActionID()) then
-    self:StartFlash()
-  end
-end
-
-function ReActionButton.prototype:PLAYER_LEAVE_COMBAT()
-  if IsAttackAction(self:GetActionID()) then
-    self:StopFlash()
-  end
-end
-
-function ReActionButton.prototype:START_AUTOREPEAT_SPELL()
-  if IsAutoRepeatAction(self:GetActionID()) then
-    self:StartFlash()
-  end
-end
-
-function ReActionButton.prototype:STOP_AUTOREPEAT_SPELL()
-  if self:IsFlashing() and not IsAttackAction(self:GetActionID()) then
-    self:StopFlash()
-  end
-end
-
-
--- OnUpdate handler
-function ReActionButton.prototype:OnUpdate(elapsed)
-  local action = self:GetActionID()
-  local f = self.frames
-
-  -- handle flashing
-	if self:IsFlashing() then
-		self.flashtime = self.flashtime - elapsed
-		if self.flashtime <= 0 then
-			local overtime = -self.flashtime
-			if overtime >= ATTACK_BUTTON_FLASH_TIME then
-				overtime = 0
-			end
-			self.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
-
-			if f.flash:IsVisible() then
-        f.flash:Hide()
-      else
-        f.flash:Show()
-			end
-		end
-	end
-	
-	-- Handle range indicator
-	if self.rangeTimer then
-		self.rangeTimer = self.rangeTimer - elapsed
-		if self.rangeTimer <= 0 then
-      self:ColorHotKey()
-      self:UpdateUsable()
-			self.rangeTimer = TOOLTIP_UPDATE_TIME
-		end
-	end
-
-  -- handle toltip update
-  if self.tooltipTime then
-    self.tooltipTime = self.tooltipTime - elapsed
-    if self.tooltipTime <= 0 then
-      if GameTooltip:IsOwned(self.button) then
-        self:UpdateTooltip()
-      else
-        self.tooltipTime = nil
-      end
-    end
-  end
-end
-
-
-
-
--- keybinding functions
-function ReActionButton.prototype:SetKeyBinding( k )
-  if k == nil or kbValidate(k) then
-    local current = self:GetKeyBinding()
-  	ClearOverrideBindings(self.button)
-    if current then
-      SetBinding(current,nil)
-    end
-    if k then
-      SetBindingClick(k, self.name, "LeftButton")
-    end
-  end
-end
-
-function ReActionButton.prototype:GetKeyBinding()
-  return GetBindingKey("CLICK "..self.name..":LeftButton")
-end
-
--- action ID functions
-function ReActionButton.prototype:SetActionID( id )
-  self.actionID = tonumber(id) -- force data integrity
-  self:ApplyActionID()
-end
-
-function ReActionButton.prototype:GetActionID()
-  return self.actionID
-end
-
-function ReActionButton.prototype:ApplyActionID()
-  local action = tonumber(self:GetActionID())
-  self.button:SetAttribute("action",action)
-  self.frames.actionID:SetText(action or "")
-end
-
-function ReActionButton.prototype:ShowActionID()
-  self.frames.actionID:Show()
-end
-
-function ReActionButton.prototype:HideActionID()
-  self.frames.actionID:Hide()
-end
-
-function ReActionButton:ShowAllActionIDs() -- class-wide function
-  for _, tbl in pairs(actionButtonTbl) do
-    if tbl.button then tbl.button:ShowActionID() end
-  end
-end
-
-function ReActionButton:HideAllActionIDs() -- class-wide function
-  for _, tbl in pairs(actionButtonTbl) do
-    if tbl.button then tbl.button:HideActionID() end
-  end
-end
-
-
--- action transfer functions
-function ReActionButton.prototype:ShouldPickupAction(mouseButton)
-	return IsShiftKeyDown() and not SecureButton_GetModifiedAttribute(self.button, "type", mouseButton)
-end
-
-function ReActionButton.prototype:ShowGridTmp()
-  self.showGridTmp_ = self.showGridTmp_ + 1
-  self:UpdateVisibility()
-end
-
-function ReActionButton.prototype:HideGridTmp()
-  self.showGridTmp_ = self.showGridTmp_ - 1
-  self:UpdateVisibility()
-end
-
-function ReActionButton.prototype:ShowGrid()
-  self.config.showGrid = true
-  self:UpdateVisibility()
-end
-
-function ReActionButton.prototype:HideGrid()
-  self.config.showGrid = false
-  self:UpdateVisibility()
-end
-
-
-
--- layout & style functions
-function ReActionButton.prototype:ApplyLayout()
-  local f = self.frames
-
-  if self.config.keyBindLoc then
-    local h = f.hotkey
-    local loc = self.config.keyBindLoc
-    local top = string.match(loc,"TOP")
-    local bottom = string.match(loc, "BOTTOM")
-    h:ClearAllPoints()
-    h:SetWidth(40)
-    h:SetPoint(top or bottom,0,top and 2 or -2)
-    local j
-    if string.match(loc,"LEFT") then
-      j = "LEFT"
-    elseif string.match(loc,"RIGHT") then
-      j = "RIGHT"
-    else
-      j = "CENTER"
-    end
-    h:SetJustifyH(j)
-  end
-
-  if self.config.stackCountLoc then
-    local c = f.count
-    local loc = self.config.stackCountLoc
-    local top = string.match(loc,"TOP")
-    local bottom = string.match(loc, "BOTTOM")
-    c:ClearAllPoints()
-    c:SetWidth(40)
-    c:SetPoint(top or bottom,0,top and 2 or -2)
-    local j
-    if string.match(loc,"LEFT") then
-      j = "LEFT"
-    elseif string.match(loc,"RIGHT") then
-      j = "RIGHT"
-    else
-      j = "CENTER"
-    end
-    c:SetJustifyH(j)
-  end
-
-  if self.config.showKeyBind then
-    f.hotkey:Show()
-  else
-    f.hotkey:Hide()
-  end
-    
-  if self.config.showStackCount then
-    f.count:Show()
-  else
-    f.count:Hide()
-  end
-
---[[
-  if self.config.showNumericCooldown then
-    f.nCooldown:Show()
-  else
-    f.nCooldown:Hide()
-  end
-]]
-
-  if self.config.showMacroName then
-    f.macro:Show()
-  else
-    f.macro:Hide()
-  end
-end
-
-function ReActionButton.prototype:ApplyStyle()
-  local f = self.frames
-  -- for now, just a static style
-  f.hotkey:SetFontObject(NumberFontNormal)
-  f.count:SetFontObject(NumberFontNormalYellow)
-end
-
-
-
--- start/stop flashing
-function ReActionButton.prototype:StartFlash()
-  self.flashing = true
-  self.flashtime = 0
-  self:UpdateCheckedState()
-end
-
-function ReActionButton.prototype:StopFlash()
-  self.flashing = false
-  self.frames.flash:Hide()
-  self:UpdateCheckedState()
-end
-
-function ReActionButton.prototype:IsFlashing()
-  return self.flashing
-end
-
-
-
-
-
--- set the tooltip
-function ReActionButton.prototype:SetTooltip()
-  GameTooltip_SetDefaultAnchor(GameTooltip, self.button)
-  self:UpdateTooltip()
-end
-
-function ReActionButton.prototype:ClearTooltip()
-  tooltipTime = nil
-  GameTooltip:Hide()
-end
-
-
-
--- colorize the hotkey
-function ReActionButton.prototype:ColorHotKey()
-  local action = self:GetActionID()
-  local c = hotKeyDefaultColor
-
-  if action and HasAction(action) then
-    if IsActionInRange(action) == 0 then
-      c = hotKeyOutOfRangeColor
-    elseif self.config.keyBindColorCode then
-      local modKey = string.match( self.frames.hotkey:GetText() or "", "([ACS])%-")
-      c = modKey and hotKeyModifierColors[modKey] or c
-    end
-  else
-    c = hotKeyDisabledColor
-  end
-
-  self.frames.hotkey:SetTextColor(c.r, c.g, c.b)
-end
-
-
-
-
--- display update functions
-function ReActionButton.prototype:UpdateDisplay()
-  self:UpdateIcon()
-  self:UpdateHotkey()
-  self:UpdateCount()
-  self:UpdateMacroText()
-  self:UpdateUsable()
-  self:UpdateCooldown()
-  self:UpdateFlash()
-  self:UpdateEvents()
-  self:UpdateVisibility()
-  self:UpdateTooltip()
-end
-
-function ReActionButton.prototype:UpdateIcon()
-  local f = self.frames
-  local b = self.button
-
-  local action = self:GetActionID()
-  local texture = action and GetActionTexture(action)
-
-  if action and texture then
-    f.icon:SetTexture(texture)
-    f.icon:Show()
-    self.rangeTimer = -1
-    b:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
-  else
-    f.icon:Hide()
-    f.cooldown:Hide()
-    self.rangeTimer = nil
-    b:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
-  end
-
-  self:UpdateCheckedState()
-
-  -- Add a green border if action is an equipped item
-  if action and IsEquippedAction(action) then
-    local c = equippedActionBorderColor
-    f.border:SetVertexColor(c.r, c.g, c.b, c.a or 1)
-    f.border:Show()
-  else
-    f.border:Hide()
-  end
-end
-
-function ReActionButton.prototype:UpdateCheckedState()
-  local action = self:GetActionID()
-	if action and (IsCurrentAction(action) or IsAutoRepeatAction(action)) then
-		self.button:SetChecked(1)
-	else
-		self.button:SetChecked(0)
-	end
-end
-
-
-function ReActionButton.prototype:UpdateHotkey()
-  local action = self:GetActionID()
-  local b = self.button
-  local f = self.frames
-  local key = self:GetKeyBinding()
-  local txt = GetBindingText(key, "KEY_",1)
-
-  -- abbreviate long key names
-  for pat, rep in pairs(keybindAbbreviations) do
-    txt = string.gsub(txt,pat,rep)
-  end
-   
-  if txt then
-    f.hotkey:SetText(string.upper(txt))
-    self:ColorHotKey()
-  else
-    f.hotkey:SetText("")
-  end
-end
-
-function ReActionButton.prototype:UpdateCount()
-  local action = self:GetActionID()
-	if action and (IsConsumableAction(action) or IsStackableAction(action)) then
-		self.frames.count:SetText(GetActionCount(action))
-	else
-		self.frames.count:SetText("")
-	end
-end
-
-function ReActionButton.prototype:UpdateMacroText()
-  local action = self:GetActionID()
-	self.frames.macro:SetText(action and GetActionText(action) or "")
-end
-
-function ReActionButton.prototype:UpdateUsable()
-  local f = self.frames
-  local action = self:GetActionID()
-	local isUsable, notEnoughMana
-  if action then
-    isUsable, notEnoughMana = IsUsableAction(action)
-  end
-	if isUsable then
-    local c = actionUsableColor
-    if IsActionInRange(action) == 0 then
-      c = actionOutOfRangeColor
-    else
-  		f.normalTexture:SetVertexColor(c.r, c.g, c.b, c.a)
-    end
-		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
-	elseif notEnoughMana then
-    local c = actionNotEnoughManaColor
-		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
-		f.normalTexture:SetVertexColor(c.r, c.g, c.b, c.a)
-  else
-    local c = actionNotUsableColor
-		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
-		f.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
-	end
-end
-
-function ReActionButton.prototype:UpdateCooldown()
-  local action = self:GetActionID()
-  if action then
-  	local start, duration, enable = GetActionCooldown(self:GetActionID())
-  	CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enable)
-    -- do numeric cooldown stuff here
-  end
-end
-
-function ReActionButton.prototype:UpdateFlash()
-  local b = self.button
-  local action = self:GetActionID()
-	if action and ((IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action)) then
-    self:StartFlash()
-	else
-    self:StopFlash()
-	end
-end
-
-function ReActionButton.prototype:UpdateVisibility()
-  local action = self:GetActionID()
-  local b = self.button
-
-  if b:GetAttribute("statehidden") then
-    b:Hide()
-  elseif action and HasAction(action) then
-    b:GetNormalTexture():SetAlpha(1.0)
-    b:Show()
-  elseif self.showGridTmp_ > 0 or self.config.showGrid then
-    b:GetNormalTexture():SetAlpha(0.5)
-    self.frames.cooldown:Hide()
-    b:Show()
-  else
-    b:Hide()
-  end
-end
-
-function ReActionButton.prototype:UpdateEvents()
-  local action = self:GetActionID()
-	if action and HasAction(action) then
-    self:RegisterActionEvents()
-  elseif self.actionEventsRegistered then
-    self:UnregisterActionEvents()
-	end
-end
-
-function ReActionButton.prototype:UpdateTooltip()
-  local action = self:GetActionID()
-	if GameTooltip:IsOwned(self.button) and action and GameTooltip:SetAction(action) then
-		self.tooltipTime = TOOLTIP_UPDATE_TIME
-	else
-		self.tooltipTime = nil
-	end
-end
-
-
-
--- a/ReAction.lua	Tue Mar 20 21:11:15 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
--- ReAction.lua
--- 
--- Top-level file for the ReAction Action Bar add-on
---
--- ReAction is implemented in terms of the Ace 2 library: http://www.wowace.com
---
-
--- key binding label constants
-BINDING_HEADER_REACTION                 = "ReAction"
-BINDING_NAME_REACTION_TOGGLELOCK        = "Lock/Unlock ReAction Bars"
-BINDING_NAME_REBINDER_TOGGLEBINDINGMODE = "Toggle ReAction keybinding mode"
-
--- ReAction addon setup via Ace 2
-ReAction = AceLibrary("AceAddon-2.0"):new(
-  "AceConsole-2.0",
-  "AceEvent-2.0",
-  "AceDB-2.0",
-  "FuBarPlugin-2.0"
-)
-
-local function tcopy(t)
-  local r = { }
-  for k, v in pairs(t) do
-    r[k] = (type(v) == "table" and tcopy(v) or v)
-  end
-  return r
-end
-
--- FuBar plugin setup
-ReAction.hasIcon = false
-ReAction.hasNoColor = true
-ReAction.hideMenuTitle = true
-ReAction.defaultPosition = "RIGHT"
-ReAction.defaultMinimapPosition = 240 -- degrees
-ReAction.OnMenuRequest = tcopy(ReActionGlobalMenuOptions)
-
--- initial non-persistent state
-ReAction.locked = true
-
--- localization
--- local L = AceLibrary("AceLocale-2.0"):new("ReAction")
-
-
-
--- Event handling
-function ReAction:OnInitialize()
-  self:RegisterChatCommand( {"/reaction", "/rxn"}, ReActionConsoleOptions, "REACTION" )
-
-  self:RegisterDB("ReActionDB","ReActionDBPC")
-  self:RegisterDefaults("profile", ReActionProfileDefaults)
-  self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown")
-  self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars")
-end
-
-function ReAction:OnEnable()
-  if self.db.profile.firstRunDone ~= true then
-    -- Do some "first-run" setup
-    self.db.profile.firstRunDone = true
-  elseif self.db.profile.disabled == true then
-    -- print some kind of a warning
-  end
-  self:SetupBars()
-end
-
-function ReAction:OnDisable()
-  self:Lock()
-end
-
-function ReAction:OnProfileEnable()
-  -- handle profile switching
-  self:Lock()
-  self:SetupBars()
-end
-
-function ReAction:CombatLockdown()
-  if not self:IsLocked() then
-    self:Lock()
-    UIErrorsFrame:AddMessage("ReAction bars locked when in combat")
-  end
-end
-
-
--- lock/unlock ReAction
-function ReAction:SetLocked( lock )
-  if lock ~= self.locked then
-    if not lock then
-      self:Print("Buttons disabled while unlocked")
-    end
-    if not lock and InCombatLockdown() then
-      UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
-    else
-      self.locked = lock and true or false -- force data integrity
-      for _, bar in pairs(self.bars) do
-        if self.locked then bar:HideControls() else bar:ShowControls() end
-      end
-    end
-  end
-end
-
-function ReAction:IsLocked()
-  return self.locked
-end
-
-function ReAction:Lock()
-  self:SetLocked(true)
-end
-
-function ReAction:Unlock()
-  self:SetLocked(false)
-end
-
-function ReAction:ToggleLocked()
-  ReAction:SetLocked( not(self.locked) )
-end
-
-
-
--- Hide the default Blizzard main bar artwork
-function ReAction:HideArt()
-  if self.db.profile.hideArt then
-    MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons.
-  else
-    MainMenuBar:Show()
-  end
-end
-
-function ReAction:IsArtHidden()
-  return self.db.profile.hideArt
-end
-
-function ReAction:SetHideArt( hide )
-  if InCombatLockdown() then
-    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
-  else
-    self.db.profile.hideArt = hide and true or false -- force data integrity
-    self:HideArt()
-  end
-end
-
-function ReAction:ToggleHideArt()
-  self:SetHideArt( not self:IsArtHidden() )
-end
-
-
-
--- Keybinding color coding
-function ReAction:SetKeyColorCoding( cc )
-  self.db.profile.keyColorCode = cc
-end
-
-function ReAction:IsKeyColorCodeEnabled()
-  return self.db.profile.keyColorCode
-end
-
-function ReAction:ToggleKeyColorCoding()
-  self:SetKeyColorCoding(not self.db.profile.keyColorCode)
-end
-
-
-
--- Hide default Blizzard bars
-local blizzDefaultBars = {
-  ActionButton1,
-  ActionButton2,
-  ActionButton3,
-  ActionButton4,
-  ActionButton5,
-  ActionButton6,
-  ActionButton7,
-  ActionButton8,
-  ActionButton9,
-  ActionButton10,
-  ActionButton11,
-  ActionButton12,
-  BonusActionBarFrame,
-  MultiBarLeft,
-  MultiBarRight,
-  MultiBarBottomLeft,
-  MultiBarBottomRight
-}
-
-function ReAction:HideDefaultBars()
-  for _, f in pairs(blizzDefaultBars) do
-    f:UnregisterAllEvents()
-    f:Hide()
-    f:SetParent(ReActionButtonRecycler) -- I mean it!
-    f:ClearAllPoints()                  -- no, I really mean it!
-  end
-end
-
-
--- Reset bars to defaults
-function ReAction:ResetBars()
-  if InCombatLockdown() then
-    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
-  else
-    self.db.profile.bars = ReActionProfileDefaults.bars
-    self:SetupBars()
-  end
-end
-
-
--- re-sync action IDs
-function ReAction:ResyncActionIDs()
-  -- TODO
-end
-
-
-
--- Bar manipulation
-ReAction.bars    = { }
-
-function ReAction:SetupBars()
-  -- hide the default Blizzard art, if configued
-  self:HideArt()
-  -- hide the default Blizzard bars
-  self:HideDefaultBars()
-
-  -- set up the bars from the profile
-  -- note the use of table.maxn rather than # or ipairs: 
-  -- our array of bars can in fact contain holes
-  for id = 1, table.maxn(self.db.profile.bars) do
-    local config = self.db.profile.bars[id]
-    if self.bars[id] then 
-      self.bars[id]:Destroy() -- remove old version of bar if switching profiles 
-    end
-    if config then
-      self.bars[id] = ReBar:new(config, id)
-    end
-  end
-  
-  -- remove excess bars
-  for id = table.maxn(self.db.profile.bars) + 1, table.maxn(self.bars) do
-    if self.bars[id] then
-      self.bars[id]:Destroy()
-      self.bars[id] = nil
-    end
-  end
-  
-  -- anchor the bars, have to do this in a second pass because
-  -- they might be anchored to each other in a non-ordered way
-  for _, bar in pairs(self.bars) do
-    bar:ApplyAnchor()
-  end
-end
-
-
-function ReAction:NewBar()
-  if InCombatLockdown() then
-    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
-  else
-    local c = tcopy(ReActionBarConfigDefaults)
-    local bar = ReBar:new(c, #self.bars+1)
-    table.insert(self.bars, bar)
-    table.insert(self.db.profile.bars, c) 
-    if not self.locked then
-      bar:ShowControls()
-    end
-  end
-end
-
-
-function ReAction:DeleteBar(id)
-  if InCombatLockdown() then
-    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
-  else
-    if self.bars[id] then
-      -- we can't do tremove because each bar ID is encoded into the
-      -- frame names as they're created. Need a nil entry in the table.
-      -- The nice thing is that table.insert in NewBar() will automatically
-      -- find the first nil slot.
-      self.bars[id]:Destroy()
-      self.bars[id] = nil
-      self.db.profile.bars[id] = nil
-    end
-  end
-end
-
-function ReAction:ToggleActionID()
-  if self.showActionIDs then
-    ReActionButton:HideAllActionIDs()
-  else
-    ReActionButton:ShowAllActionIDs()
-  end
-  self.showActionIDs = not self.showActionIDs
-end
-
-function ReAction:IsActionIDVisible()
-  return self.showActionIDs
-end
-
-
-
--- FuBar plugin methods
-local tablet = AceLibrary("Tablet-2.0")
-
-function ReAction:OnTooltipUpdate()
-	local c = tablet:AddCategory("columns", 2)
-	c:AddLine("text", "Bar lock", "text2", self.locked and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
-  c:AddLine("text", "Button lock", "text2", LOCK_ACTIONBAR == "1" and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
-  c:AddLine("text", "Kebinding mode", "text2", ReBinder:IsEnabled() and "|cff33ff33On|r" or "|cffffcc00Off|r")
-	tablet:SetHint("|cffffcc00Shift-Click|r for bar lock|n"..
-                 "|cff33ff33Alt-Click|r for keybindings|n"..
-                 "Right-click for menu")
-end
-
-function ReAction:OnClick(button)
-	if IsShiftKeyDown() then
-	  self:ToggleLocked()
-    self:UpdateDisplay()
-	elseif IsAltKeyDown() then
-    ReBinder:ToggleEnabled()
-  end
-end
--- a/ReBar.lua	Tue Mar 20 21:11:15 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,527 +0,0 @@
-
--- private constants
-local insideFrame  = 1
-local outsideFrame = 2
-
-local pointFindTable = {
-  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,
-}
-
-local oppositePointTable = {
-  BOTTOMLEFT  = "TOPRIGHT",
-  BOTTOM      = "TOP",
-  BOTTOMRIGHT = "TOPLEFT",
-  RIGHT       = "LEFT",
-  TOPRIGHT    = "BOTTOMLEFT",
-  TOP         = "BOTTOM",
-  TOPLEFT     = "BOTTOMRIGHT",
-  LEFT        = "RIGHT"
-}
-
-local anchoredLabelColor = { r =0.6, g = 0.2, b = 1.0 }
-local nonAnchoredLabelColor = { r = 1.0, g = 0.82, b = 0.0 }
-
--- private variables
-local stickyTargets = {
-  [UIParent] = insideFrame,
-  [WorldFrame] = insideFrame
-}
-
--- ReBar is an Ace 2 class prototype object.
-ReBar = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
-
-local dewdrop = AceLibrary("Dewdrop-2.0")
-
-function ReBar.prototype:init( config, id )
-  ReBar.super.prototype.init(self)
-
-  local buttonClass = config and config.btnConfig and config.btnConfig.type and getglobal(config.btnConfig.type)
-  self.config  = config
-  self.barID   = id
-  self.class   = { button = buttonClass }
-  self.buttons = { }
-
-  -- create the bar and control widgets
-  self.barFrame     = CreateFrame("Frame", "ReBar_"..self.barID, UIParent, "ReBarTemplate")
-  self.controlFrame = getglobal(self.barFrame:GetName().."Controls")
-  self.controlFrame.reBar = self
-  self.barFrame:SetClampedToScreen(true)
-
-  -- set the text label on the control widget
-  self.labelString = getglobal(self.controlFrame:GetName().."LabelString")
-  self.labelString:SetText(id)
-
-  -- initialize the bar layout
-  self:ApplySize()
-  self:ApplyAnchor()
-  self:LayoutButtons()
-  self:ApplyVisibility()
-
-  -- add bar to stickyTargets list
-  stickyTargets[self.barFrame] = outsideFrame
-  
-  -- initialize dewdrop menu
-	dewdrop:Register(self.controlFrame, 'children', function()
-	    dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions)
-	    dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(self))
-	    dewdrop:FeedAceOptionsTable(GenerateReActionButtonOptions(self))
-	  end,
-	  'cursorX', true, 
-	  'cursorY', true
-	)
-end
-
-
-function ReBar.prototype:Destroy()
-  if self.barFrame == dewdrop:GetOpenedParent() then
-    dewdrop:Close()
-    dewdrop:Unregister(self.barFrame)
-  end
-
-  self:HideControls()
-  self.barFrame:Hide()
-  self.barFrame:ClearAllPoints()
-  self.barFrame:SetParent(nil)
-  self.barFrame:SetPoint("BOTTOMRIGHT", UIParent, "TOPLEFT", 0, 0)
-  
-  -- need to keep around self.config for dewdrop menus in the process of deleting self 
-
-  while #self.buttons > 0 do
-    self.class.button:release(table.remove(self.buttons))
-  end
-
-  -- remove from sticky targets table
-  stickyTargets[self.barFrame] = nil
-  
-  -- remove from global table
-  -- for some reason after a destroy/recreate the globals still reference
-  -- the old frames
-  setglobal(self.barFrame:GetName(), nil)
-  setglobal(self.barFrame:GetName().."Controls", nil)
-  setglobal(self.controlFrame:GetName().."LabelString", nil)
-end
-
-
--- show/hide the control frame
-function ReBar.prototype:ShowControls()
-  self.controlFrame:Show()
-  for _, b in ipairs(self.buttons) do
-    b:BarUnlocked()
-  end
-end
-
-function ReBar.prototype:HideControls()
-  local b = self.barFrame
-  if b.isMoving or b.resizing then
-    b:StopMovingOrSizing()
-    b:SetScript("OnUpdate",nil)
-  end
-  -- close any dewdrop menu owned by us
-  if self.barFrame == dewdrop:GetOpenedParent() then
-    dewdrop:Close()
-  end
-  for _, b in ipairs(self.buttons) do
-    b:BarLocked()
-  end
-  self.controlFrame:Hide()
-end
-
-
-
-
--- accessors
-function ReBar.prototype:GetVisibility()
-  return self.config.visible
-end
-
-function ReBar.prototype:ToggleVisibility()
-  self.config.visible = not self.config.visible
-  self:ApplyVisibility()
-end
-
-function ReBar.prototype:GetOpacity()
-  return self.config.opacity or 100
-end
-
-function ReBar.prototype:SetOpacity( o )
-  self.config.opacity = tonumber(o)
-  self:ApplyVisibility()
-  return self.config.opacity
-end
-
-
--- layout methods
-function ReBar.prototype:ApplySize()
-  local buttonSz = self.config.size or 36
-  local spacing  = self.config.spacing or 4
-  local rows     = self.config.rows or 1
-  local columns  = self.config.columns or 12
-  local w = buttonSz * columns + spacing * (columns + 1)
-  local h = buttonSz * rows + spacing * (rows + 1)
-  local f = self.barFrame
-
-  -- +1: avoid resizing oddities caused by fractional UI scale setting
-  f:SetMinResize(buttonSz + spacing*2 + 1, buttonSz + spacing*2 + 1)
-  f:SetWidth(w + 1)
-  f:SetHeight(h + 1)
-end
-
-function ReBar.prototype:ApplyAnchor()
-  local a = self.config.anchor
-  local f = self.barFrame
-  if a then
-    f:ClearAllPoints()
-    f:SetPoint(a.point,getglobal(a.to),a.relPoint,a.x,a.y)
-    local color = anchoredLabelColor
-    if a.to == "UIParent" or a.to == "WorldFrame" then
-      color = nonAnchoredLabelColor
-    end
-    self.labelString:SetTextColor(color.r, color.g, color.b)
-  end
-end
-
-function ReBar.prototype:ApplyVisibility()
-  local v = self.config.visibility
-  if type(v) == "table" then
-    if v.class then
-      local _, c = UnitClass("player")
-      v = v.class[c]
-    end
-  elseif type(v) == "string" then
-    local value = getglobal(v)
-    v = value
-  end
-  
-  if self.config.opacity then
-    self.barFrame:SetAlpha(self.config.opacity / 100)
-  end
-
-  if v then
-    self.barFrame:Show()
-  else
-    self.barFrame:Hide()
-  end
-end
-
-function ReBar.prototype:LayoutButtons()
-  local r = self.config.rows
-  local c = self.config.columns
-  local n = r * c
-  local sp = self.config.spacing
-  local sz = self.config.size
-  local gSize = sp + sz
-  
-  for i = 1, n do
-    if self.buttons[i] == nil then
-      table.insert(self.buttons, self.class.button:acquire(self.barFrame, self.config.btnConfig, i))
-    end
-    local b = self.buttons[i]
-    if b == nil then
-      break -- handling for button types that support limited numbers
-    end
-    b:PlaceButton("TOPLEFT", sp + gSize * math.fmod(i-1,c), - (sp + gSize * math.floor((i-1)/c)), sz)
-  end
-
-  -- b == nil, above, should always be the case if and only if i == n. ReBar never monkeys
-  -- with buttons in the middle of the sequence: it always adds or removes on the array end
-  while #self.buttons > n do
-    self.class.button:release(table.remove(self.buttons))
-  end
-  
-end
-
-
-function ReBar.prototype:StoreAnchor(f, p, rp, x, y)
-  local name = f:GetName()
-  -- no point if we can't store the name or the offsets are incomplete
-  if name and x and y then
-    self.config.anchor = { 
-      to = name,
-      point = p,
-      relPoint = rp or p,
-      x = x,
-      y = y
-    }
-  end
-end  
-
-
-
--- mouse event handlers (clicking/dragging/resizing the bar)
-function ReBar.prototype:BeginDrag()
-  local f = self.barFrame
-  f:StartMoving()
-  f.isMoving = true
-  f:SetScript("OnUpdate", function() self:StickyIndicatorUpdate() end)
-end
-
-function ReBar.prototype:FinishDrag()
-  local f, p, rp, x, y 
-  local bf = self.barFrame
-
-  bf:StopMovingOrSizing()
-  bf.isMoving = false
-
-  bf:SetScript("OnUpdate",nil)
-  if IsShiftKeyDown() then
-    f, p, rp, x, y = self:GetStickyAnchor()
-    ReBarStickyIndicator1:Hide()
-    ReBarStickyIndicator2:Hide()
-  end
-  
-  if f == nil then
-    f = UIParent
-    local _
-    _, p,rp,x,y = self:GetClosestPointTo(f)
-  end
-
-  if f then
-    self:StoreAnchor(f,p,rp,x,y)
-    self:ApplyAnchor()
-  end
-end
-
-function ReBar.prototype:BeginBarResize( sizingPoint )
-  local f = self.barFrame
-  f:StartSizing(sizingPoint)
-  f.resizing = true
-  f:SetScript("OnUpdate",function() self:ReflowButtons() end)
-end
-
-function ReBar.prototype:BeginButtonResize( sizingPoint, mouseBtn )
-  local f = self.barFrame
-  f:StartSizing(sizingPoint)
-  f.resizing = true
-  local r = self.config.rows
-  local c = self.config.columns
-  local s = self.config.spacing
-  local sz = self.config.size
-  if mouseBtn == "LeftButton" then
-    f:SetMinResize(c*(12 + 2*s) +1, r*(12 + 2*s) +1)
-    f:SetScript("OnUpdate",function() self:DragSizeButtons() end)
-  elseif mouseBtn == "RightButton" then
-    f:SetMinResize(c*sz+1, r*sz+1)
-    f:SetScript("OnUpdate",function() self:DragSizeSpacing() end)
-  end
-end
-
-function ReBar.prototype:FinishResize()
-  local f = self.barFrame
-  f:StopMovingOrSizing()
-  f.resizing = false
-  f:SetScript("OnUpdate",nil)
-  self:ApplySize()
-end
-
-
-
-
--- sticky anchoring functions
-function ReBar.prototype:StickyIndicatorUpdate()
-  local si1 = ReBarStickyIndicator1
-  local si2 = ReBarStickyIndicator2
-  if IsShiftKeyDown() then
-    local f, p, rp, x, y = self:GetStickyAnchor()
-    if f then
-      si1:ClearAllPoints()
-      si2:ClearAllPoints()
-      si1:SetPoint("CENTER",self.barFrame,p,0,0)
-      si2:SetPoint("CENTER",f,rp,x,y)
-      si1:Show()
-      si2:Show()
-      return nil
-    end
-  end
-  si1:Hide()
-  si2:Hide()
-  si1:ClearAllPoints()
-  si2:ClearAllPoints()
-end
-
-function ReBar.prototype:CheckAnchorable(f)
-  -- can't anchor to self or to a hidden frame
-  if f == self.barFrame or not(f:IsShown()) then return false end
-
-  -- also can't anchor to frames that are anchored to self
-  for i = 1, f:GetNumPoints() do
-    local _, f2 = f:GetPoint(i)
-    if f2 == self.barFrame then return false end
-  end
-
-  return true
-end
-
-
-function ReBar.prototype:GetStickyAnchor()
-  local snapRange = (self.config.size + self.config.spacing)
-  local r2, f, p, rp, x, y = self:GetClosestAnchor()
-
-  if f and p then
-    local xx, yy = pointFindTable[p](f) 
-    if r2 and r2 < (snapRange*snapRange) then
-      if xx or math.abs(x) < snapRange then x = 0 end
-      if yy or math.abs(y) < snapRange then y = 0 end
-    elseif not(yy) and math.abs(x) < snapRange then
-      x = 0
-    elseif not(xx) and math.abs(y) < snapRange then
-      y = 0
-    else
-      f = nil -- nothing in range
-    end
-  end
-  return f, p, rp, x, y
-end
-
-function ReBar.prototype:GetClosestAnchor()
-  -- choose the closest anchor point on the list of target frames
-  local range2, frame, point, relPoint, offsetX, offsetY
-
-  for f, tgtRegion in pairs(stickyTargets) do
-    if self:CheckAnchorable(f) then
-      local r2 ,p, rp, x, y = self:GetClosestPointTo(f,tgtRegion)
-      if r2 then
-        if not(range2 and range2 < r2) then
-          range2, frame, point, relPoint, offsetX, offsetY = r2, f, p, rp, x, y
-        end
-      end
-    end
-  end
-
-  return range2, frame, point, relPoint, offsetX, offsetY
-end
-
-function ReBar.prototype:GetClosestPointTo(f,inside)
-  local range2, point, relPoint, offsetX, offsetY
-  local pft = pointFindTable
-  local cx, cy = self.barFrame:GetCenter()
-  local fcx, fcy = f:GetCenter()
-  local fh = f:GetHeight()
-  local fw = f:GetWidth()
-
-  -- compute whether edge bisector intersects target edge
-  local dcx = math.abs(cx-fcx) < fw/2 and (cx-fcx)
-  local dcy = math.abs(cy-fcy) < fh/2 and (cy-fcy)
-  
-  for p, func in pairs(pft) do
-    local rp, x, y
-    if inside == outsideFrame then
-      rp = oppositePointTable[p]
-      x, y = self:GetOffsetToPoint(f, func, pft[rp])
-    else
-      rp = p
-      x, y = self:GetOffsetToPoint(f, func, func)
-    end
-
-    -- if anchoring to an edge, only anchor if the center point overlaps the other edge
-    if (x or dcx) and (y or dcy) then
-      local r2 = (x or 0)^2 + (y or 0)^2
-      if range2 == nil or r2 < range2 then
-        range2, point, relPoint, offsetX, offsetY = r2, p, rp, x or dcx, y or dcy
-      end
-    end
-  end
-  return range2, point, relPoint, offsetX, offsetY
-end
-
-function ReBar.prototype:GetOffsetToPoint(f,func,ffunc)
-  local x, y = func(self.barFrame)  -- coordinates of the point on this frame
-  local fx, fy = ffunc(f)  -- coordinates of the point on the target frame
-  -- guarantees: if x then fx, if y then fy
-  return x and (x-fx), y and (y-fy)
-end
-
-
-
-
-
-
--- utility function to get the height, width, and button size attributes
-function ReBar.prototype:GetLayout()
-  local c = self.config
-  local f = self.barFrame
-  return f:GetWidth(), f:GetHeight(), c.size, c.rows, c.columns, c.spacing
-end
-
--- add and remove buttons dynamically as the bar is resized
-function ReBar.prototype:ReflowButtons()
-  local w, h, sz, r, c, sp = self:GetLayout()
-
-  self.config.rows = math.floor( (h - sp) / (sz + sp) )
-  self.config.columns = math.floor( (w - sp) / (sz + sp) )
-
-  if self.config.rows ~= r or self.config.columns ~= c then
-    self:LayoutButtons()
-  end
-end
-
-
--- change the size of buttons as the bar is resized
-function ReBar.prototype:DragSizeButtons()
-  local w, h, sz, r, c, sp = self:GetLayout()
-
-  local newSzW = math.floor((w - (c+1)*sp)/c)
-  local newSzH = math.floor((h - (r+1)*sp)/r)
-  
-  self.config.size = math.max(12, math.min(newSzW, newSzH))
-
-  if self.config.size ~= sz then
-    self:LayoutButtons()
-    self:UpdateResizeTooltip()
-  end
-end
-
-
--- change the spacing of buttons as the bar is resized
-function ReBar.prototype:DragSizeSpacing()
-  local w, h, sz, r, c, sp = self:GetLayout()
-
-  local newSpW = math.floor((w - c*sz)/(c+1))
-  local newSpH = math.floor((h - r*sz)/(r+1))
-
-  self.config.spacing = math.max(0, math.min(newSpW, newSpH))
-
-  if self.config.spacing ~= sp then
-    self:LayoutButtons()
-    self:UpdateResizeTooltip()
-  end
-end
-
-
--- update the drag tooltip to indicate current sizes
-function ReBar.prototype:UpdateResizeTooltip()
-  GameTooltipTextRight4:SetText(self.config.size)
-  GameTooltipTextRight5:SetText(self.config.spacing)
-  GameTooltip:Show()
-end
-
-function ReBar.prototype:ShowTooltip()
-  GameTooltip:SetOwner(self.barFrame, "ANCHOR_TOPRIGHT")
-  GameTooltip:AddLine("Bar "..self.barID)
-  GameTooltip:AddLine("Drag to move")
-  GameTooltip:AddLine("Shift-drag for sticky mode")
-  GameTooltip:AddLine("Right-click for options")
-  GameTooltip:Show()
-end
-
-function ReBar.prototype:ShowButtonResizeTooltip(point)
-  GameTooltip:SetOwner(self.barFrame, "ANCHOR_"..point)
-  GameTooltip:AddLine("Drag to resize buttons")
-  GameTooltip:AddLine("Right-click-drag")
-  GameTooltip:AddLine("to change spacing")
-  GameTooltip:AddDoubleLine("Size: ", "0")
-  GameTooltip:AddDoubleLine("Spacing: ", "0")
-  self:UpdateResizeTooltip()
-end
-
-function ReBar.prototype:ShowBarResizeTooltip(point)
-  GameTooltip:SetOwner(self.barFrame, "ANCHOR_"..point)
-  GameTooltip:AddLine("Drag to add/remove buttons")
-  GameTooltip:Show()
-end
--- a/ReBar.xml	Tue Mar 20 21:11:15 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,318 +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">
-
-
-  <Frame name="ReBarControlEdgeTemplate" virtual="true">
-    <Size>
-      <AbsDimension x="8" y="8"/>
-    </Size>
-    <Layers>
-      <Layer level="HIGHLIGHT" alphaMode="ADD">
-        <Texture>
-          <Color r="1.0" g="0.82" b="0" a="0.7"/>
-        </Texture>
-      </Layer>
-    </Layers>
-    <Scripts>
-      <OnLoad>
-        this:RegisterForDrag("LeftButton")
-      </OnLoad>
-      <OnMouseDown>
-        this:GetParent().reBar:BeginBarResize(this.sizingPoint)
-      </OnMouseDown>
-      <OnMouseUp>
-        this:GetParent().reBar:FinishResize()
-      </OnMouseUp>
-      <OnEnter>
-        this:GetParent().reBar:ShowBarResizeTooltip(this.sizingPoint)
-      </OnEnter>
-      <OnLeave>
-        GameTooltip:Hide()
-      </OnLeave>
-    </Scripts>
-  </Frame>
-
-
-  <Frame name="ReBarControlCornerTemplate" virtual="true">
-    <Size>
-      <AbsDimension x="12" y="12"/>
-    </Size>
-    <Layers>
-      <Layer level="HIGHLIGHT" alphaMode="ADD">
-        <Texture>
-          <Color r="1.0" g="0.82" b="0" a="0.7"/>
-        </Texture>
-      </Layer>
-    </Layers>
-    <Scripts>
-      <OnLoad>
-        this:RegisterForDrag("LeftButton","RightButton")
-      </OnLoad>
-      <OnMouseDown>
-        this:GetParent():GetParent().reBar:BeginButtonResize(this.sizingPoint, arg1)
-      </OnMouseDown>
-      <OnMouseUp>
-        this:GetParent():GetParent().reBar:FinishResize()
-      </OnMouseUp>
-      <OnEnter>
-        this:GetParent():GetParent().reBar:ShowButtonResizeTooltip(this.sizingPoint)
-      </OnEnter>
-      <OnLeave>
-        GameTooltip:Hide()
-      </OnLeave>
-    </Scripts>
-  </Frame>
-
-
-
-  <Frame name="ReBarStickyIndicatorTemplate" virtual="true" frameStrata="HIGH" enableMouse="false" hidden="true" parent="UIParent">
-    <Size>
-      <AbsDimension x="8" y="8"/>
-    </Size>
-    <Layers>
-      <Layer level="OVERLAY">
-        <Texture alphaMode="ADD">
-          <Color r="1.0" g="0.82" b="0" a="0.8"/>
-        </Texture>
-      </Layer>
-    </Layers>
-  </Frame>
-
-  <Frame name="ReBarStickyIndicator1" inherits="ReBarStickyIndicatorTemplate"/>
-  <Frame name="ReBarStickyIndicator2" inherits="ReBarStickyIndicatorTemplate"/>
-
-
-  <!-- A ReAction bar is a container for buttons. The bar container itself is invisible and non-responsive to
-       mouse input, but when unlocked a normally invisible child control frame becomes visible and
-       consumes mouse events to move, resize, and set bar options. -->
-  <Frame name="ReBarTemplate" virtual="true" toplevel="true" enableMouse="true" movable="true" resizable="true">
-    <Layers>
-      <Layer level="BACKGROUND"/>
-    </Layers>
-    <Frames>
-      <Frame name="$parentControl" setAllPoints="true">
-        <!-- this nesting is to ensure the control frame is on top of the buttons, which will 
-             live at this level -->
-        <Frames>
-          <!-- name: e.g. $parentControls (with an s) - yes I know, goofy naming structure -->
-          <Button name="$parents" hidden="true" enableMouse="true" setAllPoints="true">
-            <Anchors>
-              <Anchor point="TOPLEFT">
-                <Offset>
-                  <AbsDimension x="-4" y="4"/>
-                </Offset>
-              </Anchor>
-              <Anchor point="BOTTOMRIGHT">
-                <Offset>
-                  <AbsDimension x="4" y="-4"/>
-                </Offset>
-              </Anchor>
-            </Anchors>
-            <Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
-              <EdgeSize>
-                <AbsValue val="16"/>
-              </EdgeSize>
-              <TileSize>
-                <AbsValue val="16"/>
-              </TileSize>
-              <BackgroundInsets>
-                <AbsInset left="0" right="0" top="0" bottom="0"/>
-              </BackgroundInsets>
-            </Backdrop>
-            <Layers>
-              <Layer level="BACKGROUND">
-                <Texture>
-                  <!-- offsets so that the highlight layer plays nice with the edge border -->
-                  <Anchors>
-                    <Anchor point="TOPLEFT">
-                      <Offset>
-                        <AbsDimension x="4" y="-4"/>
-                      </Offset>
-                    </Anchor>
-                    <Anchor point="BOTTOMRIGHT">
-                      <Offset>
-                        <AbsDimension x="-4" y="4"/>
-                      </Offset>
-                    </Anchor>
-                  </Anchors>
-                  <Color r="0.7" g="0.7" b="1.0" a="0.2"/>
-                </Texture>
-              </Layer>
-              <Layer level="HIGHLIGHT">
-                <Texture alphaMode="ADD">
-                  <Anchors>
-                    <Anchor point="TOPLEFT">
-                      <Offset>
-                        <AbsDimension x="4" y="-4"/>
-                      </Offset>
-                    </Anchor>
-                    <Anchor point="BOTTOMRIGHT">
-                      <Offset>
-                        <AbsDimension x="-4" y="4"/>
-                      </Offset>
-                    </Anchor>
-                  </Anchors>
-                  <Color r="0.7" g="0.7" b="1.0" a="0.2"/>
-                </Texture>
-              </Layer>
-            </Layers>
-            <Frames>
-              <!-- edge drag handles -->
-              <Frame inherits="ReBarControlEdgeTemplate">
-                <Anchors>
-                  <Anchor point="TOPLEFT"/>
-                  <Anchor point="TOPRIGHT"/>
-                </Anchors>
-                <Scripts>
-                  <OnLoad> this.sizingPoint = "TOP" </OnLoad>
-                </Scripts>
-              </Frame>
-
-              <Frame inherits="ReBarControlEdgeTemplate">
-                <Anchors>
-                  <Anchor point="TOPLEFT"/>
-                  <Anchor point="BOTTOMLEFT"/>
-                </Anchors>
-                <Scripts>
-                  <OnLoad> this.sizingPoint = "LEFT" </OnLoad>
-                </Scripts>
-              </Frame>
-
-              <Frame inherits="ReBarControlEdgeTemplate">
-                <Anchors>
-                  <Anchor point="TOPRIGHT"/>
-                  <Anchor point="BOTTOMRIGHT"/>
-                </Anchors>
-                <Scripts>
-                  <OnLoad> this.sizingPoint = "RIGHT" </OnLoad>
-                </Scripts>
-              </Frame>
-
-              <Frame inherits="ReBarControlEdgeTemplate">
-                <Anchors>
-                  <Anchor point="BOTTOMLEFT"/>
-                  <Anchor point="BOTTOMRIGHT"/>
-                </Anchors>
-                <Scripts>
-                  <OnLoad> this.sizingPoint = "BOTTOM" </OnLoad>
-                </Scripts>
-              </Frame>
-
-              <!-- corner drag handles -->
-              <Frame setAllPoints="true">
-                <!-- nesting to ensure they're on top -->
-                <Frames>
-                  <Frame inherits="ReBarControlCornerTemplate">
-                    <Anchors>
-                      <Anchor point="TOPLEFT"/>
-                    </Anchors>
-                    <Scripts>
-                      <OnLoad> this.sizingPoint = "TOPLEFT" </OnLoad>
-                    </Scripts>
-                  </Frame>
-
-                  <Frame inherits="ReBarControlCornerTemplate">
-                    <Anchors>
-                      <Anchor point="TOPRIGHT"/>
-                    </Anchors>
-                    <Scripts>
-                      <OnLoad> this.sizingPoint = "TOPRIGHT" </OnLoad>
-                    </Scripts>
-                  </Frame>
-
-                  <Frame inherits="ReBarControlCornerTemplate">
-                    <Anchors>
-                      <Anchor point="BOTTOMLEFT"/>
-                    </Anchors>
-                    <Scripts>
-                      <OnLoad> this.sizingPoint = "BOTTOMLEFT" </OnLoad>
-                    </Scripts>
-                  </Frame>
-
-                  <Frame inherits="ReBarControlCornerTemplate">
-                    <Anchors>
-                      <Anchor point="BOTTOMRIGHT"/>
-                    </Anchors>
-                    <Scripts>
-                      <OnLoad> this.sizingPoint = "BOTTOMRIGHT" </OnLoad>
-                    </Scripts>
-                  </Frame>
-                </Frames>
-              </Frame>
-
-              <Frame name="$parentLabel">
-                <Size>
-                  <AbsDimension x="32" y="24"/>
-                </Size>
-                <Anchors>
-                  <Anchor point="CENTER"/>
-                </Anchors>
-                <Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
-                  <EdgeSize>
-                    <AbsValue val="16"/>
-                  </EdgeSize>
-                  <TileSize>
-                    <AbsValue val="16"/>
-                  </TileSize>
-                  <BackgroundInsets>
-                    <AbsInset left="0" right="0" top="0" bottom="0"/>
-                  </BackgroundInsets>
-                </Backdrop>
-                <Layers>
-                  <Layer level="BACKGROUND">
-                    <Texture>
-                      <Anchors>
-                        <Anchor point="TOPLEFT">
-                          <Offset>
-                            <AbsDimension x="4" y="-4"/>
-                          </Offset>
-                        </Anchor>
-                        <Anchor point="BOTTOMRIGHT">
-                          <Offset>
-                            <AbsDimension x="-4" y="4"/>
-                          </Offset>
-                        </Anchor>
-                      </Anchors>
-                      <Color r="0.0" g="0.0" b="0.0"/>
-                    </Texture>
-                  </Layer>
-                  <Layer level="ARTWORK">
-                    <FontString name="$parentString" inherits="GameFontNormalLarge" justifyH="CENTER" text="(barID)">
-                      <Size>
-                        <AbsDimension x="24" y="18"/>
-                      </Size>
-                      <Anchors>
-                        <Anchor point="CENTER"/>
-                      </Anchors>
-                    </FontString>
-                  </Layer>
-                </Layers>
-              </Frame>
-            </Frames>
-            <Scripts>
-              <OnLoad>
-                this:RegisterForDrag("LeftButton")
-                this:RegisterForClicks("AnyUp")
-              </OnLoad>
-              <OnDragStart>
-                this.reBar:BeginDrag()
-              </OnDragStart>
-              <OnDragStop>
-                this.reBar:FinishDrag()
-              </OnDragStop>
-              <OnEnter>
-                this.reBar:ShowTooltip()
-              </OnEnter>
-              <OnLeave>
-                GameTooltip:Hide()
-              </OnLeave>
-            </Scripts>
-          </Button>
-        </Frames>
-      </Frame>
-    </Frames>
-  </Frame>
-
-
-</Ui>
--- a/ReBinder.lua	Tue Mar 20 21:11:15 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
--- ReBinder.lua
--- 
-
-ReBinder = { }
-
--- initial values
-ReBinder.active = false
-
-ReBinder.targets = { }
-
-function ReBinder:AddKeybindTarget( t )
-  if t then
-    self.targets[t] = CreateFrame("Button", nil, t, "ReBinderClickBindingTemplate")
-    self.targets[t].keybindTarget = t:GetName()
-  end
-end
-
-function ReBinder:RemoveKeybindTarget( t )
-  if t then
-    self.targets[t] = nil
-  end
-end
-
-function ReBinder:ShowClickBindingButtons()
-  for _, clickFrame in pairs(self.targets) do
-    clickFrame:Show()
-  end    
-end
-
-function ReBinder:HideClickBindingButtons()
-  for _, clickFrame in pairs(self.targets) do
-    clickFrame:Hide()
-  end    
-end
-
-function ReBinder:ClearSelectedKey()
-  self.selectedKey = nil
-end
-
-function ReBinder:ToggleEnabled()
-  if self:IsEnabled() then
-    self:Disable()
-  else
-    self:Enable()
-  end
-end
-
-function ReBinder:IsEnabled()
-  return ReBinderFrame:IsVisible()
-end
-
-function ReBinder:Enable()
-  ReBinderFrame:Show()
-end
-
-function ReBinder:Disable()
-  ReBinderFrame:Hide()
-end
-
-
-function ReBinder:HandleKeyPressed( key )
-  if key == nil or key == "UNKNOWN" or key == "SHIFT" or key == "CTRL" or key == "ALT" then 
-    return
-  end
-  if IsShiftKeyDown() then 
-    key = "SHIFT-"..key
-  end
-  if IsControlKeyDown() then
-    key = "CTRL-"..key
-  end
-  if IsAltKeyDown() then
-    key = "ALT-"..key
-  end
-  if key == "ESCAPE" or GetBindingAction(key) == "REBINDER_TOGGLEBINDINGMODE" then
-    ReBinderFrame:Hide()
-    return nil, nil
-  end
-
-  self.selectedKey = key
-
-  local keyTxt = GetBindingText(key, "KEY_")
-  local cmd    = GetBindingAction(key)
-  local cmdTxt
-  
-  if cmd then
-    cmdTxt = GetBindingText(cmd, "BINDING_NAME_")
-  end
-  
-  -- make click-bindings look prettier
-  local btnName
-  if cmdTxt then
-    btnName = string.match(cmdTxt,"CLICK (.+)\:LeftButton")
-    btnName = btnName or string.match(cmdTxt,"CLICK (.+)\:RightButton")
-  end
-  
-  return keyTxt, btnName or cmdTxt
-end
-
--- TODO: move to override-binding model and store data in profile
-function ReBinder:BindSelectedKeyTo( btnName )
-  if self.selectedKey and btnName then
-    self:ClearBinding(btnName)
-    SetBindingClick(self.selectedKey, btnName, "LeftButton")
-    SaveBindings(2) -- 2 = character-specific
-    ReBinderFrame.statusMsg:SetText(GetBindingText(self.selectedKey, "KEY_") .. " is now bound to " .. btnName)
-    ReBinderFrame.selectedKey:SetText("(none)")
-    ReBinderFrame.currentAction:SetText("(none)")
-    self.selectedKey = nil
-  end
-end
-
-
-function ReBinder:ClearBinding( btnName )
-  if btnName then
-    local current = GetBindingKey("CLICK "..btnName..":LeftButton")
-    if current then
-      SetBinding(current, nil)
-      ReBinderFrame.statusMsg:SetText("|cFFFF3333"..btnName .. " is now unbound|r")
-    end
-  end
-end
-
-
-function ReBinder:UpdateCurrentTarget( btnName )
-  local msg = ""
-  if btnName then
-    msg = btnName.." is currently "
-    local current = GetBindingKey("CLICK "..btnName..":LeftButton")
-    if current then
-      msg = msg .. "bound to " .. GetBindingText(current, "KEY_")
-    else
-      msg = msg .. " not bound"
-    end
-  end
-  ReBinderFrame.statusMsg:SetText(msg)
-end
--- a/ReBinder.xml	Tue Mar 20 21:11:15 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +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">
-
-
-  <Button name="ReBinderClickBindingTemplate" virtual="true" hidden="true" toplevel="true" setAllPoints="true">
-		<HighlightTexture alphaMode="ADD" file="Interface\Buttons\ButtonHilight-Square"/>
-    <Layers>
-      <Layer level="BACKGROUND">
-        <Texture>
-          <Color r="0" g="0" b="0" a="0"/>
-        </Texture>
-      </Layer>
-    </Layers>
-    <Scripts>
-      <OnLoad>
-        this:RegisterForClicks("LeftButtonUp","RightButtonUp")
-      </OnLoad>
-      <OnClick>
-        local mouseBtn = arg1
-        if mouseBtn == "LeftButton" then
-          ReBinder:BindSelectedKeyTo(this.keybindTarget)
-        elseif mouseBtn == "RightButton" then
-          ReBinder:ClearBinding(this.keybindTarget)
-        end
-      </OnClick>
-      <PostClick>
-        this:SetButtonState("NORMAL")
-      </PostClick>
-      <OnEnter>
-        ReBinder:UpdateCurrentTarget(this.keybindTarget)
-      </OnEnter>
-      <OnLeave>
-        ReBinder:UpdateCurrentTarget(nil)
-      </OnLeave>
-    </Scripts>
-  </Button>
-
-
-  <!-- this frame covers the entire UIParent. It is visible but empty and in the background, so all it does is consume key presses and unhandled mouse clicks -->
-  <Button name="ReBinderFrame" frameStrata="BACKGROUND" movable="false" enableMouse="true" enableKeyboard="true" parent="UIParent" hidden="true" setAllPoints="true">
-    <Frames>
-      <!-- this is a dialog frame that appears to provide user feedback for the outer frame -->
-      <Button name="$parentDialog" frameStrata="DIALOG" movable="true" enableMouse="true">
-        <Size>
-          <AbsDimension x="330" y="350"/>
-        </Size>
-        <Anchors>
-          <Anchor point="CENTER"/>
-        </Anchors>
-        <TitleRegion>
-          <Size>
-            <AbsDimension x="350" y="30"/>
-          </Size>
-          <Anchors>
-            <Anchor point="TOP">
-              <Offset>
-                <AbsDimension x="0" y="-10"/>
-              </Offset>
-            </Anchor>
-          </Anchors>
-        </TitleRegion>
-        <Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
-          <EdgeSize>
-            <AbsValue val="16"/>
-          </EdgeSize>
-          <TileSize>
-            <AbsValue val="16"/>
-          </TileSize>
-          <BackgroundInsets>
-            <AbsInset left="4" right="4" top="4" bottom="4"/>
-          </BackgroundInsets>
-        </Backdrop>
-        <Layers>
-          <Layer level="BACKGROUND">
-            <Texture>
-              <Color r="0" g="0" b="0" a="0.7"/>
-            </Texture>
-          </Layer>
-          <Layer level="ARTWORK">
-            <FontString inherits="GameFontNormalLarge" text="Key Binding Setup" justifyH="CENTER">
-              <Size>
-                <AbsDimension x="200" y="30"/>
-              </Size>
-              <Anchors>
-                <Anchor point="TOP">
-                  <Offset>
-                    <AbsDimension x="0" y="-10"/>
-                  </Offset>
-                </Anchor>
-              </Anchors>
-            </FontString>
-            <FontString inherits="GameFontNormal" text="Press a key to ready it for assignment, then click a button to assign the key.|nRight-click a button to clear its binding." justifyH="CENTER">
-              <Size>
-                <AbsDimension x="240" y="70"/>
-              </Size>
-              <Anchors>
-                <Anchor point="TOP">
-                  <Offset>
-                    <AbsDimension x="0" y="-55"/>
-                  </Offset>
-                </Anchor>
-              </Anchors>
-              <Color r="1.0" g="1.0" b="1.0"/>
-            </FontString>
-            <FontString inherits="GameFontNormal" text="Selected Key:" justifyH="RIGHT">
-              <Size>
-                <AbsDimension x="175" y="25"/>
-              </Size>
-              <Anchors>
-                <Anchor point="RIGHT" relativePoint="TOP">
-                  <Offset>
-                    <AbsDimension x="-25" y="-160"/>
-                  </Offset>
-                </Anchor>
-              </Anchors>
-            </FontString>
-            <FontString inherits="GameFontNormal" text="Current Binding:" justifyH="RIGHT">
-              <Size>
-                <AbsDimension x="175" y="25"/>
-              </Size>
-              <Anchors>
-                <Anchor point="RIGHT" relativePoint="TOP">
-                  <Offset>
-                    <AbsDimension x="-25" y="-205"/>
-                  </Offset>
-                </Anchor>
-              </Anchors>
-            </FontString>
-            <FontString name="$parentCurrentActionText" inherits="GameFontNormal" text="(none)" justifyH="CENTER">
-              <Size>
-                <AbsDimension x="140" y="50"/>
-              </Size>
-              <Anchors>
-                <Anchor point="CENTER" relativePoint="TOP">
-                  <Offset>
-                    <AbsDimension x="75" y="-205"/>
-                  </Offset>
-                </Anchor>
-              </Anchors>
-              <Color r="0" g="1" b="0" a="1"/>
-            </FontString>
-            <FontString name="$parentStatusMsg" inherits="GameFontNormal" text="" justifyH="CENTER">
-              <Size>
-                <AbsDimension x="200" y="50"/>
-              </Size>
-              <Anchors>
-                <Anchor point="TOP">
-                  <Offset>
-                    <AbsDimension x="0" y="-230"/>
-                  </Offset>
-                </Anchor>
-              </Anchors>
-              <Color r="0.1" g="1.0" b="0.1"/>
-            </FontString>
-          </Layer>
-        </Layers>
-        <Frames>
-          <Button name="$parentSelectedKey" inherits="UIPanelButtonTemplate2" text="(none)">
-            <Size>
-              <AbsDimension x="140" y="28"/>
-            </Size>
-            <Anchors>
-              <Anchor point="CENTER" relativePoint="TOP">
-                <Offset>
-                  <AbsDimension x="75" y="-160"/>
-                </Offset>
-              </Anchor>
-            </Anchors>
-          </Button>
-          <Button inherits="GameMenuButtonTemplate" text="Done">
-            <Size>
-              <AbsDimension x="112" y="28"/>
-            </Size>
-            <Anchors>
-              <Anchor point="BOTTOM">
-                <Offset>
-                  <AbsDimension x="0" y="10"/>
-                </Offset>
-              </Anchor>
-            </Anchors>
-            <Scripts>
-              <OnClick>
-                this:GetParent():GetParent():Hide()
-              </OnClick>
-            </Scripts>
-          </Button>
-        </Frames>
-        <Scripts>
-          <!-- the dialog frame needs to handle clicks (close button, drag title) so we have to
-            re-implement the behavior of capturing alternate mouse buttons -->
-          <OnLoad>
-            this.selectedKey   = getglobal(this:GetName().."SelectedKeyText")
-            this.currentAction = getglobal(this:GetName().."CurrentActionText")
-            this:RegisterForClicks("MiddleButtonUp","Button4Up","Button5Up")
-          </OnLoad>
-          <OnClick>
-            local k, a = ReBinder:HandleKeyPressed(arg1)
-            if k then
-              this.selectedKey:SetText(k)
-              this.currentAction:SetText(a or "(none)")
-            end
-          </OnClick>
-        </Scripts>
-      </Button>
-    </Frames>
-    <Scripts>
-      <OnLoad>
-        this.selectedKey   = getglobal(this:GetName().."DialogSelectedKeyText")
-        this.currentAction = getglobal(this:GetName().."DialogCurrentActionText")
-        this.statusMsg     = getglobal(this:GetName().."DialogStatusMsg")
-        tinsert(UISpecialFrames,this:GetName())
-        this:RegisterForClicks("MiddleButtonUp","Button4Up","Button5Up")
-      </OnLoad>
-      <OnShow>
-        this.selectedKey:SetText("(none)")
-        this.currentAction:SetText("(none)")
-        this.statusMsg:SetText("")
-        ReBinder:ShowClickBindingButtons()
-      </OnShow>
-      <OnHide>
-        ReBinder:HideClickBindingButtons()
-        ReBinder:ClearSelectedKey()
-      </OnHide>
-      <OnKeyDown>
-        local k, a = ReBinder:HandleKeyPressed(arg1)
-        if k then
-          this.selectedKey:SetText(k)
-          this.currentAction:SetText(a or "(none)")
-        end
-      </OnKeyDown>
-      <OnClick>
-        local k, a = ReBinder:HandleKeyPressed(arg1)
-        if k then
-          this.selectedKey:SetText(k)
-          this.currentAction:SetText(a or "(none)")
-        end
-      </OnClick>
-    </Scripts>
-  </Button>
-
-</Ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/ReAction.lua	Tue Mar 20 21:19:34 2007 +0000
@@ -0,0 +1,773 @@
+-- private constants
+local namePrefix = "ReActionButton"
+local _G = getfenv(0)
+local ACTION_FREE = { }
+local MAX_ACTIONS = 120
+
+local hotKeyDefaultColor    = { r=1.0, g=1.0, b=1.0, a=1.0 }
+local hotKeyDisabledColor   = { r=0.6, g=0.6, b=0.6, a=1.0 }
+local hotKeyOutOfRangeColor = { r=1.0, g=0.2, b=0.2, a=1.0 }
+
+local hotKeyModifierColors = {
+  S = { r=0.6, g=0.6, b=1.0, a=1.0 },  -- shift
+  C = { r=1.0, g=0.82, b=0, a=1.0 },  -- ctrl
+  A = { r=0.1, g=1.0, b=0.1, a=1.0 },  -- alt
+}
+
+-- TODO: localize these key names with GetBindingText(KEY_)
+local keybindAbbreviations = {
+  ["Mouse Button "] = "M-",
+  ["Spacebar"] = "Sp",
+  ["Num Pad "] = "Num-",
+  ["Page Up"]  = "PgUp",
+  ["Page Down"] = "PgDn",
+  [" Arrow"] = "",
+}
+
+local equippedActionBorderColor = { r=0, g=1.0, b=0, a=0.35 }
+
+local actionUsableColor        = { r=1.0, g=1.0, b=1.0, a=1.0 }
+local actionNotUsableColor     = { r=0.4, g=0.4, b=0.4, a=1.0 }
+local actionNotEnoughManaColor = { r=0.2, g=0.2, b=0.7, a=1.0 }
+local actionOutOfRangeColor    = { r=1.0, g=0.2, b=0.2, a=1.0 }
+
+-- private variables
+local kbValidate = AceLibrary("AceConsole-2.0").keybindingValidateFunc
+local actionButtonTbl = { }
+
+
+
+-- ReActionButton is a class prototype object.
+ReActionButton = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
+
+-------------------
+-- Class methods
+-------------------
+
+-- In addition to supporting the 'new' creation method (in which case an action ID must be specified directly),
+-- ReActionButton supports the 'acquire'/'release' creation method, which recycles objects and manages actionID assignment.
+
+function ReActionButton:acquire(parent, config, barIdx)
+  local id = nil
+  for i = 1, MAX_ACTIONS do
+    if actionButtonTbl[i] == nil or actionButtonTbl[i].inUse == false then
+      id = i
+      break
+    end
+  end
+
+  if id == nil then return nil end  -- all buttons and action ids are in use
+
+  local hint = config.actionIDs[barIdx]
+  if hint and (actionButtonTbl[hint] == nil or actionButtonTbl[hint].inUse == false) then
+    id = hint
+  end
+
+  if actionButtonTbl[id] == nil then 
+    actionButtonTbl[id] = { }
+  end
+  local t = actionButtonTbl[id]
+
+  t.inUse = true
+  if t.button then
+    t.button:Configure(parent,config,barIdx)
+  else
+    t.button = self:new(parent,config,barIdx,id)
+  end
+
+  -- fix screwy config with overlapping IDs
+  config.actionIDs[barIdx] = id
+  return t.button
+end
+
+function ReActionButton:release( b )
+  if b then
+    actionButtonTbl[b:GetActionID()].inUse = false
+    b:Recycle()
+  end
+end
+
+
+
+function ReActionButton:ShowAllActionIDs()
+  for _, b in ipairs(actionButtonTbl) do
+    b:ShowActionID()
+  end
+end
+
+function ReActionButton:HideAllActionIDs()
+  for _, b in ipairs(actionButtonTbl) do
+    b:HideActionID()
+  end
+end
+
+
+----------------------
+-- Instance methods
+----------------------
+function ReActionButton.prototype:init( parentFrame, config, barIdx, id )
+  ReActionButton.super.prototype.init(self)
+
+  -- create the button widget
+  self.name = namePrefix..id
+  self.button = CreateFrame("CheckButton", self.name, parentFrame, "ReActionButtonTemplate")
+  
+  -- store references to the various sub-frames so we don't have to look it up all the time
+  self.frames      = {
+    hotkey         = _G[self.name.."HotKey"],
+    count          = _G[self.name.."Count"],
+    cooldown       = _G[self.name.."Cooldown"],
+--    nCooldown      = _G[self.name.."CooldownNumeric"],
+    macro          = _G[self.name.."Name"],
+    icon           = _G[self.name.."Icon"],
+    border         = _G[self.name.."Border"],
+    normalTexture  = _G[self.name.."NormalTexture"],
+    flash          = _G[self.name.."Flash"],
+    actionID       = _G[self.name.."ActionID"],
+  }
+
+  -- provide a reference back to this object for the frame to use in event handlers
+  self.button.rxnBtn = self
+
+  -- set the action ID
+  self:SetActionID(id)
+
+  -- register button with ReBinder for keybinding
+  ReBinder:AddKeybindTarget(self.button)
+
+  -- initialize
+  self:Configure(parentFrame, config, barIdx)
+end
+
+local function tcopy(t)
+  local r = { }
+  for k, v in pairs(t) do
+    r[k] = (type(v) == "table" and tcopy(v) or v)
+  end
+  return r
+end
+
+function ReActionButton.prototype:Recycle()
+  local b = self.button
+
+  self:SetKeyBinding(nil)
+  self:UpdateDisplay()
+  b:UnregisterAllEvents()
+  b:SetParent(ReActionButtonRecycleFrame)
+  b:ClearAllPoints()
+  b:SetPoint("TOPLEFT",0,0)
+  b:Hide()
+  self.config = tcopy(self.config) -- ew, but necessary
+end
+
+function ReActionButton.prototype:BarUnlocked()
+  self:ShowGridTmp()
+end
+
+function ReActionButton.prototype:BarLocked()
+  self:HideGridTmp()
+end
+
+
+-- set the button location
+function ReActionButton.prototype:PlaceButton(point, x, y, sz)
+  local b = self.button
+  local scale = sz / 36
+  b:ClearAllPoints()
+  b:SetScale( scale )
+  b:SetPoint(point,x/scale,y/scale)
+end
+
+
+function ReActionButton.prototype:ShowActionID()
+  self.frames.actionID:Show()
+end
+
+function ReActionButton.prototype:HideActionID()
+  self.frames.actionID:Hide()
+end
+
+
+
+-- configuration and setup
+function ReActionButton.prototype:Configure( parentFrame, config, barIdx )
+  self.config   = config
+  self.barIdx   = barIdx
+  self.showGridTmp_ = 0
+
+  self.button:ClearAllPoints()
+  self.button:SetParent(parentFrame)
+
+  self:SetupAttributes()
+  self:RegisterStaticEvents()
+
+  self:ApplyLayout()
+  self:ApplyStyle()
+
+  self:UpdateDisplay()
+end
+
+function ReActionButton.prototype:SetupAttributes()
+  local b = self.button
+  b:SetAttribute("type", "action")
+	b:SetAttribute("shift-type*", ATTRIBUTE_NOOP)
+	b:SetAttribute("checkselfcast", true)
+	b:SetAttribute("useparent-unit", true)
+end
+
+function ReActionButton.prototype:RegisterStaticEvents()
+	self:RegisterEvent("PLAYER_ENTERING_WORLD")
+	self:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
+	self:RegisterEvent("UPDATE_BINDINGS")
+  self:RegisterEvent("ACTIONBAR_SHOWGRID")
+  self:RegisterEvent("ACTIONBAR_HIDEGRID")
+end
+
+function ReActionButton.prototype:RegisterActionEvents()
+  self:RegisterEvent("ACTIONBAR_UPDATE_STATE")
+  self:RegisterEvent("ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("UPDATE_INVENTORY_ALERTS", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("PLAYER_AURAS_CHANGED", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("PLAYER_TARGET_CHANGED", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("UNIT_INVENTORY_CHANGED")
+  self:RegisterEvent("CRAFT_SHOW")
+  self:RegisterEvent("CRAFT_CLOSE", "CRAFT_SHOW")
+  self:RegisterEvent("TRADE_SKILL_SHOW", "CRAFT_SHOW")
+  self:RegisterEvent("TRADE_SKILL_CLOSE", "CRAFT_SHOW")
+  self:RegisterEvent("PLAYER_ENTER_COMBAT", "CRAFT_SHOW")
+  self:RegisterEvent("PLAYER_LEAVE_COMBAT")
+  self:RegisterEvent("START_AUTOREPEAT_SPELL")
+  self:RegisterEvent("STOP_AUTOREPEAT_SPELL")
+
+  self.button:SetScript("OnUpdate", function() self:OnUpdate(arg1) end)
+  self.actionEventsRegistered = true
+end
+
+function ReActionButton.prototype:UnregisterActionEvents()
+  self:UnregisterEvent("ACTIONBAR_UPDATE_STATE")
+  self:UnregisterEvent("ACTIONBAR_UPDATE_USABLE")
+  self:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN")
+  self:UnregisterEvent("UPDATE_INVENTORY_ALERTS")
+  self:UnregisterEvent("PLAYER_AURAS_CHANGED")
+  self:UnregisterEvent("PLAYER_TARGET_CHANGED")
+  self:UnregisterEvent("UNIT_INVENTORY_CHANGED")
+  self:UnregisterEvent("CRAFT_SHOW")
+  self:UnregisterEvent("CRAFT_CLOSE")
+  self:UnregisterEvent("TRADE_SKILL_SHOW")
+  self:UnregisterEvent("TRADE_SKILL_CLOSE")
+  self:UnregisterEvent("PLAYER_ENTER_COMBAT")
+  self:UnregisterEvent("PLAYER_LEAVE_COMBAT")
+  self:UnregisterEvent("START_AUTOREPEAT_SPELL")
+  self:UnregisterEvent("STOP_AUTOREPEAT_SPELL")
+
+  self.button:SetScript("OnUpdate", nil)
+  self.actionEventsRegistered = false
+end
+
+
+-- event handlers
+function ReActionButton.prototype:ACTIONBAR_SLOT_CHANGED()
+  if arg1 == 0 or arg1 == self:GetActionID() then
+    self:UpdateDisplay()
+  end
+end
+
+function ReActionButton.prototype:PLAYER_ENTERING_WORLD()
+  self:UpdateDisplay()
+end
+
+function ReActionButton.prototype:UPDATE_BINDINGS()
+  self:UpdateDisplay()
+end
+
+function ReActionButton.prototype:ACTIONBAR_SHOWGRID()
+  self:ShowGridTmp()
+end
+
+function ReActionButton.prototype:ACTIONBAR_HIDEGRID()
+  self:HideGridTmp()
+end
+
+function ReActionButton.prototype:ACTIONBAR_UPDATE_STATE()
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:ACTIONBAR_UPDATE_USABLE()
+  self:UpdateUsable()
+  self:UpdateCooldown()
+  self:ColorHotKey()
+end
+
+function ReActionButton.prototype:UNIT_INVENTORY_CHANGED()
+  if arg1 == "player" then
+    self:UpdateDisplay()
+  end
+end
+
+function ReActionButton.prototype:CRAFT_SHOW()
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:PLAYER_ENTER_COMBAT()
+  if IsAttackAction(self:GetActionID()) then
+    self:StartFlash()
+  end
+end
+
+function ReActionButton.prototype:PLAYER_LEAVE_COMBAT()
+  if IsAttackAction(self:GetActionID()) then
+    self:StopFlash()
+  end
+end
+
+function ReActionButton.prototype:START_AUTOREPEAT_SPELL()
+  if IsAutoRepeatAction(self:GetActionID()) then
+    self:StartFlash()
+  end
+end
+
+function ReActionButton.prototype:STOP_AUTOREPEAT_SPELL()
+  if self:IsFlashing() and not IsAttackAction(self:GetActionID()) then
+    self:StopFlash()
+  end
+end
+
+
+-- OnUpdate handler
+function ReActionButton.prototype:OnUpdate(elapsed)
+  local action = self:GetActionID()
+  local f = self.frames
+
+  -- handle flashing
+	if self:IsFlashing() then
+		self.flashtime = self.flashtime - elapsed
+		if self.flashtime <= 0 then
+			local overtime = -self.flashtime
+			if overtime >= ATTACK_BUTTON_FLASH_TIME then
+				overtime = 0
+			end
+			self.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
+
+			if f.flash:IsVisible() then
+        f.flash:Hide()
+      else
+        f.flash:Show()
+			end
+		end
+	end
+	
+	-- Handle range indicator
+	if self.rangeTimer then
+		self.rangeTimer = self.rangeTimer - elapsed
+		if self.rangeTimer <= 0 then
+      self:ColorHotKey()
+      self:UpdateUsable()
+			self.rangeTimer = TOOLTIP_UPDATE_TIME
+		end
+	end
+
+  -- handle toltip update
+  if self.tooltipTime then
+    self.tooltipTime = self.tooltipTime - elapsed
+    if self.tooltipTime <= 0 then
+      if GameTooltip:IsOwned(self.button) then
+        self:UpdateTooltip()
+      else
+        self.tooltipTime = nil
+      end
+    end
+  end
+end
+
+
+
+
+-- keybinding functions
+function ReActionButton.prototype:SetKeyBinding( k )
+  if k == nil or kbValidate(k) then
+    local current = self:GetKeyBinding()
+  	ClearOverrideBindings(self.button)
+    if current then
+      SetBinding(current,nil)
+    end
+    if k then
+      SetBindingClick(k, self.name, "LeftButton")
+    end
+  end
+end
+
+function ReActionButton.prototype:GetKeyBinding()
+  return GetBindingKey("CLICK "..self.name..":LeftButton")
+end
+
+-- action ID functions
+function ReActionButton.prototype:SetActionID( id )
+  self.actionID = tonumber(id) -- force data integrity
+  self:ApplyActionID()
+end
+
+function ReActionButton.prototype:GetActionID()
+  return self.actionID
+end
+
+function ReActionButton.prototype:ApplyActionID()
+  local action = tonumber(self:GetActionID())
+  self.button:SetAttribute("action",action)
+  self.frames.actionID:SetText(action or "")
+end
+
+function ReActionButton.prototype:ShowActionID()
+  self.frames.actionID:Show()
+end
+
+function ReActionButton.prototype:HideActionID()
+  self.frames.actionID:Hide()
+end
+
+function ReActionButton:ShowAllActionIDs() -- class-wide function
+  for _, tbl in pairs(actionButtonTbl) do
+    if tbl.button then tbl.button:ShowActionID() end
+  end
+end
+
+function ReActionButton:HideAllActionIDs() -- class-wide function
+  for _, tbl in pairs(actionButtonTbl) do
+    if tbl.button then tbl.button:HideActionID() end
+  end
+end
+
+
+-- action transfer functions
+function ReActionButton.prototype:ShouldPickupAction(mouseButton)
+	return IsShiftKeyDown() and not SecureButton_GetModifiedAttribute(self.button, "type", mouseButton)
+end
+
+function ReActionButton.prototype:ShowGridTmp()
+  self.showGridTmp_ = self.showGridTmp_ + 1
+  self:UpdateVisibility()
+end
+
+function ReActionButton.prototype:HideGridTmp()
+  self.showGridTmp_ = self.showGridTmp_ - 1
+  self:UpdateVisibility()
+end
+
+function ReActionButton.prototype:ShowGrid()
+  self.config.showGrid = true
+  self:UpdateVisibility()
+end
+
+function ReActionButton.prototype:HideGrid()
+  self.config.showGrid = false
+  self:UpdateVisibility()
+end
+
+
+
+-- layout & style functions
+function ReActionButton.prototype:ApplyLayout()
+  local f = self.frames
+
+  if self.config.keyBindLoc then
+    local h = f.hotkey
+    local loc = self.config.keyBindLoc
+    local top = string.match(loc,"TOP")
+    local bottom = string.match(loc, "BOTTOM")
+    h:ClearAllPoints()
+    h:SetWidth(40)
+    h:SetPoint(top or bottom,0,top and 2 or -2)
+    local j
+    if string.match(loc,"LEFT") then
+      j = "LEFT"
+    elseif string.match(loc,"RIGHT") then
+      j = "RIGHT"
+    else
+      j = "CENTER"
+    end
+    h:SetJustifyH(j)
+  end
+
+  if self.config.stackCountLoc then
+    local c = f.count
+    local loc = self.config.stackCountLoc
+    local top = string.match(loc,"TOP")
+    local bottom = string.match(loc, "BOTTOM")
+    c:ClearAllPoints()
+    c:SetWidth(40)
+    c:SetPoint(top or bottom,0,top and 2 or -2)
+    local j
+    if string.match(loc,"LEFT") then
+      j = "LEFT"
+    elseif string.match(loc,"RIGHT") then
+      j = "RIGHT"
+    else
+      j = "CENTER"
+    end
+    c:SetJustifyH(j)
+  end
+
+  if self.config.showKeyBind then
+    f.hotkey:Show()
+  else
+    f.hotkey:Hide()
+  end
+    
+  if self.config.showStackCount then
+    f.count:Show()
+  else
+    f.count:Hide()
+  end
+
+--[[
+  if self.config.showNumericCooldown then
+    f.nCooldown:Show()
+  else
+    f.nCooldown:Hide()
+  end
+]]
+
+  if self.config.showMacroName then
+    f.macro:Show()
+  else
+    f.macro:Hide()
+  end
+end
+
+function ReActionButton.prototype:ApplyStyle()
+  local f = self.frames
+  -- for now, just a static style
+  f.hotkey:SetFontObject(NumberFontNormal)
+  f.count:SetFontObject(NumberFontNormalYellow)
+end
+
+
+
+-- start/stop flashing
+function ReActionButton.prototype:StartFlash()
+  self.flashing = true
+  self.flashtime = 0
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:StopFlash()
+  self.flashing = false
+  self.frames.flash:Hide()
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:IsFlashing()
+  return self.flashing
+end
+
+
+
+
+
+-- set the tooltip
+function ReActionButton.prototype:SetTooltip()
+  GameTooltip_SetDefaultAnchor(GameTooltip, self.button)
+  self:UpdateTooltip()
+end
+
+function ReActionButton.prototype:ClearTooltip()
+  tooltipTime = nil
+  GameTooltip:Hide()
+end
+
+
+
+-- colorize the hotkey
+function ReActionButton.prototype:ColorHotKey()
+  local action = self:GetActionID()
+  local c = hotKeyDefaultColor
+
+  if action and HasAction(action) then
+    if IsActionInRange(action) == 0 then
+      c = hotKeyOutOfRangeColor
+    elseif self.config.keyBindColorCode then
+      local modKey = string.match( self.frames.hotkey:GetText() or "", "([ACS])%-")
+      c = modKey and hotKeyModifierColors[modKey] or c
+    end
+  else
+    c = hotKeyDisabledColor
+  end
+
+  self.frames.hotkey:SetTextColor(c.r, c.g, c.b)
+end
+
+
+
+
+-- display update functions
+function ReActionButton.prototype:UpdateDisplay()
+  self:UpdateIcon()
+  self:UpdateHotkey()
+  self:UpdateCount()
+  self:UpdateMacroText()
+  self:UpdateUsable()
+  self:UpdateCooldown()
+  self:UpdateFlash()
+  self:UpdateEvents()
+  self:UpdateVisibility()
+  self:UpdateTooltip()
+end
+
+function ReActionButton.prototype:UpdateIcon()
+  local f = self.frames
+  local b = self.button
+
+  local action = self:GetActionID()
+  local texture = action and GetActionTexture(action)
+
+  if action and texture then
+    f.icon:SetTexture(texture)
+    f.icon:Show()
+    self.rangeTimer = -1
+    b:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+  else
+    f.icon:Hide()
+    f.cooldown:Hide()
+    self.rangeTimer = nil
+    b:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+  end
+
+  self:UpdateCheckedState()
+
+  -- Add a green border if action is an equipped item
+  if action and IsEquippedAction(action) then
+    local c = equippedActionBorderColor
+    f.border:SetVertexColor(c.r, c.g, c.b, c.a or 1)
+    f.border:Show()
+  else
+    f.border:Hide()
+  end
+end
+
+function ReActionButton.prototype:UpdateCheckedState()
+  local action = self:GetActionID()
+	if action and (IsCurrentAction(action) or IsAutoRepeatAction(action)) then
+		self.button:SetChecked(1)
+	else
+		self.button:SetChecked(0)
+	end
+end
+
+
+function ReActionButton.prototype:UpdateHotkey()
+  local action = self:GetActionID()
+  local b = self.button
+  local f = self.frames
+  local key = self:GetKeyBinding()
+  local txt = GetBindingText(key, "KEY_",1)
+
+  -- abbreviate long key names
+  for pat, rep in pairs(keybindAbbreviations) do
+    txt = string.gsub(txt,pat,rep)
+  end
+   
+  if txt then
+    f.hotkey:SetText(string.upper(txt))
+    self:ColorHotKey()
+  else
+    f.hotkey:SetText("")
+  end
+end
+
+function ReActionButton.prototype:UpdateCount()
+  local action = self:GetActionID()
+	if action and (IsConsumableAction(action) or IsStackableAction(action)) then
+		self.frames.count:SetText(GetActionCount(action))
+	else
+		self.frames.count:SetText("")
+	end
+end
+
+function ReActionButton.prototype:UpdateMacroText()
+  local action = self:GetActionID()
+	self.frames.macro:SetText(action and GetActionText(action) or "")
+end
+
+function ReActionButton.prototype:UpdateUsable()
+  local f = self.frames
+  local action = self:GetActionID()
+	local isUsable, notEnoughMana
+  if action then
+    isUsable, notEnoughMana = IsUsableAction(action)
+  end
+	if isUsable then
+    local c = actionUsableColor
+    if IsActionInRange(action) == 0 then
+      c = actionOutOfRangeColor
+    else
+  		f.normalTexture:SetVertexColor(c.r, c.g, c.b, c.a)
+    end
+		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
+	elseif notEnoughMana then
+    local c = actionNotEnoughManaColor
+		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
+		f.normalTexture:SetVertexColor(c.r, c.g, c.b, c.a)
+  else
+    local c = actionNotUsableColor
+		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
+		f.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+	end
+end
+
+function ReActionButton.prototype:UpdateCooldown()
+  local action = self:GetActionID()
+  if action then
+  	local start, duration, enable = GetActionCooldown(self:GetActionID())
+  	CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enable)
+    -- do numeric cooldown stuff here
+  end
+end
+
+function ReActionButton.prototype:UpdateFlash()
+  local b = self.button
+  local action = self:GetActionID()
+	if action and ((IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action)) then
+    self:StartFlash()
+	else
+    self:StopFlash()
+	end
+end
+
+function ReActionButton.prototype:UpdateVisibility()
+  local action = self:GetActionID()
+  local b = self.button
+
+  if b:GetAttribute("statehidden") then
+    b:Hide()
+  elseif action and HasAction(action) then
+    b:GetNormalTexture():SetAlpha(1.0)
+    b:Show()
+  elseif self.showGridTmp_ > 0 or self.config.showGrid then
+    b:GetNormalTexture():SetAlpha(0.5)
+    self.frames.cooldown:Hide()
+    b:Show()
+  else
+    b:Hide()
+  end
+end
+
+function ReActionButton.prototype:UpdateEvents()
+  local action = self:GetActionID()
+	if action and HasAction(action) then
+    self:RegisterActionEvents()
+  elseif self.actionEventsRegistered then
+    self:UnregisterActionEvents()
+	end
+end
+
+function ReActionButton.prototype:UpdateTooltip()
+  local action = self:GetActionID()
+	if GameTooltip:IsOwned(self.button) and action and GameTooltip:SetAction(action) then
+		self.tooltipTime = TOOLTIP_UPDATE_TIME
+	else
+		self.tooltipTime = nil
+	end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/ReBar.lua	Tue Mar 20 21:19:34 2007 +0000
@@ -0,0 +1,527 @@
+
+-- private constants
+local insideFrame  = 1
+local outsideFrame = 2
+
+local pointFindTable = {
+  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,
+}
+
+local oppositePointTable = {
+  BOTTOMLEFT  = "TOPRIGHT",
+  BOTTOM      = "TOP",
+  BOTTOMRIGHT = "TOPLEFT",
+  RIGHT       = "LEFT",
+  TOPRIGHT    = "BOTTOMLEFT",
+  TOP         = "BOTTOM",
+  TOPLEFT     = "BOTTOMRIGHT",
+  LEFT        = "RIGHT"
+}
+
+local anchoredLabelColor = { r =0.6, g = 0.2, b = 1.0 }
+local nonAnchoredLabelColor = { r = 1.0, g = 0.82, b = 0.0 }
+
+-- private variables
+local stickyTargets = {
+  [UIParent] = insideFrame,
+  [WorldFrame] = insideFrame
+}
+
+-- ReBar is an Ace 2 class prototype object.
+ReBar = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
+
+local dewdrop = AceLibrary("Dewdrop-2.0")
+
+function ReBar.prototype:init( config, id )
+  ReBar.super.prototype.init(self)
+
+  local buttonClass = config and config.btnConfig and config.btnConfig.type and getglobal(config.btnConfig.type)
+  self.config  = config
+  self.barID   = id
+  self.class   = { button = buttonClass }
+  self.buttons = { }
+
+  -- create the bar and control widgets
+  self.barFrame     = CreateFrame("Frame", "ReBar_"..self.barID, UIParent, "ReBarTemplate")
+  self.controlFrame = getglobal(self.barFrame:GetName().."Controls")
+  self.controlFrame.reBar = self
+  self.barFrame:SetClampedToScreen(true)
+
+  -- set the text label on the control widget
+  self.labelString = getglobal(self.controlFrame:GetName().."LabelString")
+  self.labelString:SetText(id)
+
+  -- initialize the bar layout
+  self:ApplySize()
+  self:ApplyAnchor()
+  self:LayoutButtons()
+  self:ApplyVisibility()
+
+  -- add bar to stickyTargets list
+  stickyTargets[self.barFrame] = outsideFrame
+  
+  -- initialize dewdrop menu
+	dewdrop:Register(self.controlFrame, 'children', function()
+	    dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions)
+	    dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(self))
+	    dewdrop:FeedAceOptionsTable(GenerateReActionButtonOptions(self))
+	  end,
+	  'cursorX', true, 
+	  'cursorY', true
+	)
+end
+
+
+function ReBar.prototype:Destroy()
+  if self.barFrame == dewdrop:GetOpenedParent() then
+    dewdrop:Close()
+    dewdrop:Unregister(self.barFrame)
+  end
+
+  self:HideControls()
+  self.barFrame:Hide()
+  self.barFrame:ClearAllPoints()
+  self.barFrame:SetParent(nil)
+  self.barFrame:SetPoint("BOTTOMRIGHT", UIParent, "TOPLEFT", 0, 0)
+  
+  -- need to keep around self.config for dewdrop menus in the process of deleting self 
+
+  while #self.buttons > 0 do
+    self.class.button:release(table.remove(self.buttons))
+  end
+
+  -- remove from sticky targets table
+  stickyTargets[self.barFrame] = nil
+  
+  -- remove from global table
+  -- for some reason after a destroy/recreate the globals still reference
+  -- the old frames
+  setglobal(self.barFrame:GetName(), nil)
+  setglobal(self.barFrame:GetName().."Controls", nil)
+  setglobal(self.controlFrame:GetName().."LabelString", nil)
+end
+
+
+-- show/hide the control frame
+function ReBar.prototype:ShowControls()
+  self.controlFrame:Show()
+  for _, b in ipairs(self.buttons) do
+    b:BarUnlocked()
+  end
+end
+
+function ReBar.prototype:HideControls()
+  local b = self.barFrame
+  if b.isMoving or b.resizing then
+    b:StopMovingOrSizing()
+    b:SetScript("OnUpdate",nil)
+  end
+  -- close any dewdrop menu owned by us
+  if self.barFrame == dewdrop:GetOpenedParent() then
+    dewdrop:Close()
+  end
+  for _, b in ipairs(self.buttons) do
+    b:BarLocked()
+  end
+  self.controlFrame:Hide()
+end
+
+
+
+
+-- accessors
+function ReBar.prototype:GetVisibility()
+  return self.config.visible
+end
+
+function ReBar.prototype:ToggleVisibility()
+  self.config.visible = not self.config.visible
+  self:ApplyVisibility()
+end
+
+function ReBar.prototype:GetOpacity()
+  return self.config.opacity or 100
+end
+
+function ReBar.prototype:SetOpacity( o )
+  self.config.opacity = tonumber(o)
+  self:ApplyVisibility()
+  return self.config.opacity
+end
+
+
+-- layout methods
+function ReBar.prototype:ApplySize()
+  local buttonSz = self.config.size or 36
+  local spacing  = self.config.spacing or 4
+  local rows     = self.config.rows or 1
+  local columns  = self.config.columns or 12
+  local w = buttonSz * columns + spacing * (columns + 1)
+  local h = buttonSz * rows + spacing * (rows + 1)
+  local f = self.barFrame
+
+  -- +1: avoid resizing oddities caused by fractional UI scale setting
+  f:SetMinResize(buttonSz + spacing*2 + 1, buttonSz + spacing*2 + 1)
+  f:SetWidth(w + 1)
+  f:SetHeight(h + 1)
+end
+
+function ReBar.prototype:ApplyAnchor()
+  local a = self.config.anchor
+  local f = self.barFrame
+  if a then
+    f:ClearAllPoints()
+    f:SetPoint(a.point,getglobal(a.to),a.relPoint,a.x,a.y)
+    local color = anchoredLabelColor
+    if a.to == "UIParent" or a.to == "WorldFrame" then
+      color = nonAnchoredLabelColor
+    end
+    self.labelString:SetTextColor(color.r, color.g, color.b)
+  end
+end
+
+function ReBar.prototype:ApplyVisibility()
+  local v = self.config.visibility
+  if type(v) == "table" then
+    if v.class then
+      local _, c = UnitClass("player")
+      v = v.class[c]
+    end
+  elseif type(v) == "string" then
+    local value = getglobal(v)
+    v = value
+  end
+  
+  if self.config.opacity then
+    self.barFrame:SetAlpha(self.config.opacity / 100)
+  end
+
+  if v then
+    self.barFrame:Show()
+  else
+    self.barFrame:Hide()
+  end
+end
+
+function ReBar.prototype:LayoutButtons()
+  local r = self.config.rows
+  local c = self.config.columns
+  local n = r * c
+  local sp = self.config.spacing
+  local sz = self.config.size
+  local gSize = sp + sz
+  
+  for i = 1, n do
+    if self.buttons[i] == nil then
+      table.insert(self.buttons, self.class.button:acquire(self.barFrame, self.config.btnConfig, i))
+    end
+    local b = self.buttons[i]
+    if b == nil then
+      break -- handling for button types that support limited numbers
+    end
+    b:PlaceButton("TOPLEFT", sp + gSize * math.fmod(i-1,c), - (sp + gSize * math.floor((i-1)/c)), sz)
+  end
+
+  -- b == nil, above, should always be the case if and only if i == n. ReBar never monkeys
+  -- with buttons in the middle of the sequence: it always adds or removes on the array end
+  while #self.buttons > n do
+    self.class.button:release(table.remove(self.buttons))
+  end
+  
+end
+
+
+function ReBar.prototype:StoreAnchor(f, p, rp, x, y)
+  local name = f:GetName()
+  -- no point if we can't store the name or the offsets are incomplete
+  if name and x and y then
+    self.config.anchor = { 
+      to = name,
+      point = p,
+      relPoint = rp or p,
+      x = x,
+      y = y
+    }
+  end
+end  
+
+
+
+-- mouse event handlers (clicking/dragging/resizing the bar)
+function ReBar.prototype:BeginDrag()
+  local f = self.barFrame
+  f:StartMoving()
+  f.isMoving = true
+  f:SetScript("OnUpdate", function() self:StickyIndicatorUpdate() end)
+end
+
+function ReBar.prototype:FinishDrag()
+  local f, p, rp, x, y 
+  local bf = self.barFrame
+
+  bf:StopMovingOrSizing()
+  bf.isMoving = false
+
+  bf:SetScript("OnUpdate",nil)
+  if IsShiftKeyDown() then
+    f, p, rp, x, y = self:GetStickyAnchor()
+    ReBarStickyIndicator1:Hide()
+    ReBarStickyIndicator2:Hide()
+  end
+  
+  if f == nil then
+    f = UIParent
+    local _
+    _, p,rp,x,y = self:GetClosestPointTo(f)
+  end
+
+  if f then
+    self:StoreAnchor(f,p,rp,x,y)
+    self:ApplyAnchor()
+  end
+end
+
+function ReBar.prototype:BeginBarResize( sizingPoint )
+  local f = self.barFrame
+  f:StartSizing(sizingPoint)
+  f.resizing = true
+  f:SetScript("OnUpdate",function() self:ReflowButtons() end)
+end
+
+function ReBar.prototype:BeginButtonResize( sizingPoint, mouseBtn )
+  local f = self.barFrame
+  f:StartSizing(sizingPoint)
+  f.resizing = true
+  local r = self.config.rows
+  local c = self.config.columns
+  local s = self.config.spacing
+  local sz = self.config.size
+  if mouseBtn == "LeftButton" then
+    f:SetMinResize(c*(12 + 2*s) +1, r*(12 + 2*s) +1)
+    f:SetScript("OnUpdate",function() self:DragSizeButtons() end)
+  elseif mouseBtn == "RightButton" then
+    f:SetMinResize(c*sz+1, r*sz+1)
+    f:SetScript("OnUpdate",function() self:DragSizeSpacing() end)
+  end
+end
+
+function ReBar.prototype:FinishResize()
+  local f = self.barFrame
+  f:StopMovingOrSizing()
+  f.resizing = false
+  f:SetScript("OnUpdate",nil)
+  self:ApplySize()
+end
+
+
+
+
+-- sticky anchoring functions
+function ReBar.prototype:StickyIndicatorUpdate()
+  local si1 = ReBarStickyIndicator1
+  local si2 = ReBarStickyIndicator2
+  if IsShiftKeyDown() then
+    local f, p, rp, x, y = self:GetStickyAnchor()
+    if f then
+      si1:ClearAllPoints()
+      si2:ClearAllPoints()
+      si1:SetPoint("CENTER",self.barFrame,p,0,0)
+      si2:SetPoint("CENTER",f,rp,x,y)
+      si1:Show()
+      si2:Show()
+      return nil
+    end
+  end
+  si1:Hide()
+  si2:Hide()
+  si1:ClearAllPoints()
+  si2:ClearAllPoints()
+end
+
+function ReBar.prototype:CheckAnchorable(f)
+  -- can't anchor to self or to a hidden frame
+  if f == self.barFrame or not(f:IsShown()) then return false end
+
+  -- also can't anchor to frames that are anchored to self
+  for i = 1, f:GetNumPoints() do
+    local _, f2 = f:GetPoint(i)
+    if f2 == self.barFrame then return false end
+  end
+
+  return true
+end
+
+
+function ReBar.prototype:GetStickyAnchor()
+  local snapRange = (self.config.size + self.config.spacing)
+  local r2, f, p, rp, x, y = self:GetClosestAnchor()
+
+  if f and p then
+    local xx, yy = pointFindTable[p](f) 
+    if r2 and r2 < (snapRange*snapRange) then
+      if xx or math.abs(x) < snapRange then x = 0 end
+      if yy or math.abs(y) < snapRange then y = 0 end
+    elseif not(yy) and math.abs(x) < snapRange then
+      x = 0
+    elseif not(xx) and math.abs(y) < snapRange then
+      y = 0
+    else
+      f = nil -- nothing in range
+    end
+  end
+  return f, p, rp, x, y
+end
+
+function ReBar.prototype:GetClosestAnchor()
+  -- choose the closest anchor point on the list of target frames
+  local range2, frame, point, relPoint, offsetX, offsetY
+
+  for f, tgtRegion in pairs(stickyTargets) do
+    if self:CheckAnchorable(f) then
+      local r2 ,p, rp, x, y = self:GetClosestPointTo(f,tgtRegion)
+      if r2 then
+        if not(range2 and range2 < r2) then
+          range2, frame, point, relPoint, offsetX, offsetY = r2, f, p, rp, x, y
+        end
+      end
+    end
+  end
+
+  return range2, frame, point, relPoint, offsetX, offsetY
+end
+
+function ReBar.prototype:GetClosestPointTo(f,inside)
+  local range2, point, relPoint, offsetX, offsetY
+  local pft = pointFindTable
+  local cx, cy = self.barFrame:GetCenter()
+  local fcx, fcy = f:GetCenter()
+  local fh = f:GetHeight()
+  local fw = f:GetWidth()
+
+  -- compute whether edge bisector intersects target edge
+  local dcx = math.abs(cx-fcx) < fw/2 and (cx-fcx)
+  local dcy = math.abs(cy-fcy) < fh/2 and (cy-fcy)
+  
+  for p, func in pairs(pft) do
+    local rp, x, y
+    if inside == outsideFrame then
+      rp = oppositePointTable[p]
+      x, y = self:GetOffsetToPoint(f, func, pft[rp])
+    else
+      rp = p
+      x, y = self:GetOffsetToPoint(f, func, func)
+    end
+
+    -- if anchoring to an edge, only anchor if the center point overlaps the other edge
+    if (x or dcx) and (y or dcy) then
+      local r2 = (x or 0)^2 + (y or 0)^2
+      if range2 == nil or r2 < range2 then
+        range2, point, relPoint, offsetX, offsetY = r2, p, rp, x or dcx, y or dcy
+      end
+    end
+  end
+  return range2, point, relPoint, offsetX, offsetY
+end
+
+function ReBar.prototype:GetOffsetToPoint(f,func,ffunc)
+  local x, y = func(self.barFrame)  -- coordinates of the point on this frame
+  local fx, fy = ffunc(f)  -- coordinates of the point on the target frame
+  -- guarantees: if x then fx, if y then fy
+  return x and (x-fx), y and (y-fy)
+end
+
+
+
+
+
+
+-- utility function to get the height, width, and button size attributes
+function ReBar.prototype:GetLayout()
+  local c = self.config
+  local f = self.barFrame
+  return f:GetWidth(), f:GetHeight(), c.size, c.rows, c.columns, c.spacing
+end
+
+-- add and remove buttons dynamically as the bar is resized
+function ReBar.prototype:ReflowButtons()
+  local w, h, sz, r, c, sp = self:GetLayout()
+
+  self.config.rows = math.floor( (h - sp) / (sz + sp) )
+  self.config.columns = math.floor( (w - sp) / (sz + sp) )
+
+  if self.config.rows ~= r or self.config.columns ~= c then
+    self:LayoutButtons()
+  end
+end
+
+
+-- change the size of buttons as the bar is resized
+function ReBar.prototype:DragSizeButtons()
+  local w, h, sz, r, c, sp = self:GetLayout()
+
+  local newSzW = math.floor((w - (c+1)*sp)/c)
+  local newSzH = math.floor((h - (r+1)*sp)/r)
+  
+  self.config.size = math.max(12, math.min(newSzW, newSzH))
+
+  if self.config.size ~= sz then
+    self:LayoutButtons()
+    self:UpdateResizeTooltip()
+  end
+end
+
+
+-- change the spacing of buttons as the bar is resized
+function ReBar.prototype:DragSizeSpacing()
+  local w, h, sz, r, c, sp = self:GetLayout()
+
+  local newSpW = math.floor((w - c*sz)/(c+1))
+  local newSpH = math.floor((h - r*sz)/(r+1))
+
+  self.config.spacing = math.max(0, math.min(newSpW, newSpH))
+
+  if self.config.spacing ~= sp then
+    self:LayoutButtons()
+    self:UpdateResizeTooltip()
+  end
+end
+
+
+-- update the drag tooltip to indicate current sizes
+function ReBar.prototype:UpdateResizeTooltip()
+  GameTooltipTextRight4:SetText(self.config.size)
+  GameTooltipTextRight5:SetText(self.config.spacing)
+  GameTooltip:Show()
+end
+
+function ReBar.prototype:ShowTooltip()
+  GameTooltip:SetOwner(self.barFrame, "ANCHOR_TOPRIGHT")
+  GameTooltip:AddLine("Bar "..self.barID)
+  GameTooltip:AddLine("Drag to move")
+  GameTooltip:AddLine("Shift-drag for sticky mode")
+  GameTooltip:AddLine("Right-click for options")
+  GameTooltip:Show()
+end
+
+function ReBar.prototype:ShowButtonResizeTooltip(point)
+  GameTooltip:SetOwner(self.barFrame, "ANCHOR_"..point)
+  GameTooltip:AddLine("Drag to resize buttons")
+  GameTooltip:AddLine("Right-click-drag")
+  GameTooltip:AddLine("to change spacing")
+  GameTooltip:AddDoubleLine("Size: ", "0")
+  GameTooltip:AddDoubleLine("Spacing: ", "0")
+  self:UpdateResizeTooltip()
+end
+
+function ReBar.prototype:ShowBarResizeTooltip(point)
+  GameTooltip:SetOwner(self.barFrame, "ANCHOR_"..point)
+  GameTooltip:AddLine("Drag to add/remove buttons")
+  GameTooltip:Show()
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/ReBar.xml	Tue Mar 20 21:19:34 2007 +0000
@@ -0,0 +1,318 @@
+<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">
+
+
+  <Frame name="ReBarControlEdgeTemplate" virtual="true">
+    <Size>
+      <AbsDimension x="8" y="8"/>
+    </Size>
+    <Layers>
+      <Layer level="HIGHLIGHT" alphaMode="ADD">
+        <Texture>
+          <Color r="1.0" g="0.82" b="0" a="0.7"/>
+        </Texture>
+      </Layer>
+    </Layers>
+    <Scripts>
+      <OnLoad>
+        this:RegisterForDrag("LeftButton")
+      </OnLoad>
+      <OnMouseDown>
+        this:GetParent().reBar:BeginBarResize(this.sizingPoint)
+      </OnMouseDown>
+      <OnMouseUp>
+        this:GetParent().reBar:FinishResize()
+      </OnMouseUp>
+      <OnEnter>
+        this:GetParent().reBar:ShowBarResizeTooltip(this.sizingPoint)
+      </OnEnter>
+      <OnLeave>
+        GameTooltip:Hide()
+      </OnLeave>
+    </Scripts>
+  </Frame>
+
+
+  <Frame name="ReBarControlCornerTemplate" virtual="true">
+    <Size>
+      <AbsDimension x="12" y="12"/>
+    </Size>
+    <Layers>
+      <Layer level="HIGHLIGHT" alphaMode="ADD">
+        <Texture>
+          <Color r="1.0" g="0.82" b="0" a="0.7"/>
+        </Texture>
+      </Layer>
+    </Layers>
+    <Scripts>
+      <OnLoad>
+        this:RegisterForDrag("LeftButton","RightButton")
+      </OnLoad>
+      <OnMouseDown>
+        this:GetParent():GetParent().reBar:BeginButtonResize(this.sizingPoint, arg1)
+      </OnMouseDown>
+      <OnMouseUp>
+        this:GetParent():GetParent().reBar:FinishResize()
+      </OnMouseUp>
+      <OnEnter>
+        this:GetParent():GetParent().reBar:ShowButtonResizeTooltip(this.sizingPoint)
+      </OnEnter>
+      <OnLeave>
+        GameTooltip:Hide()
+      </OnLeave>
+    </Scripts>
+  </Frame>
+
+
+
+  <Frame name="ReBarStickyIndicatorTemplate" virtual="true" frameStrata="HIGH" enableMouse="false" hidden="true" parent="UIParent">
+    <Size>
+      <AbsDimension x="8" y="8"/>
+    </Size>
+    <Layers>
+      <Layer level="OVERLAY">
+        <Texture alphaMode="ADD">
+          <Color r="1.0" g="0.82" b="0" a="0.8"/>
+        </Texture>
+      </Layer>
+    </Layers>
+  </Frame>
+
+  <Frame name="ReBarStickyIndicator1" inherits="ReBarStickyIndicatorTemplate"/>
+  <Frame name="ReBarStickyIndicator2" inherits="ReBarStickyIndicatorTemplate"/>
+
+
+  <!-- A ReAction bar is a container for buttons. The bar container itself is invisible and non-responsive to
+       mouse input, but when unlocked a normally invisible child control frame becomes visible and
+       consumes mouse events to move, resize, and set bar options. -->
+  <Frame name="ReBarTemplate" virtual="true" toplevel="true" enableMouse="true" movable="true" resizable="true">
+    <Layers>
+      <Layer level="BACKGROUND"/>
+    </Layers>
+    <Frames>
+      <Frame name="$parentControl" setAllPoints="true">
+        <!-- this nesting is to ensure the control frame is on top of the buttons, which will 
+             live at this level -->
+        <Frames>
+          <!-- name: e.g. $parentControls (with an s) - yes I know, goofy naming structure -->
+          <Button name="$parents" hidden="true" enableMouse="true" setAllPoints="true">
+            <Anchors>
+              <Anchor point="TOPLEFT">
+                <Offset>
+                  <AbsDimension x="-4" y="4"/>
+                </Offset>
+              </Anchor>
+              <Anchor point="BOTTOMRIGHT">
+                <Offset>
+                  <AbsDimension x="4" y="-4"/>
+                </Offset>
+              </Anchor>
+            </Anchors>
+            <Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
+              <EdgeSize>
+                <AbsValue val="16"/>
+              </EdgeSize>
+              <TileSize>
+                <AbsValue val="16"/>
+              </TileSize>
+              <BackgroundInsets>
+                <AbsInset left="0" right="0" top="0" bottom="0"/>
+              </BackgroundInsets>
+            </Backdrop>
+            <Layers>
+              <Layer level="BACKGROUND">
+                <Texture>
+                  <!-- offsets so that the highlight layer plays nice with the edge border -->
+                  <Anchors>
+                    <Anchor point="TOPLEFT">
+                      <Offset>
+                        <AbsDimension x="4" y="-4"/>
+                      </Offset>
+                    </Anchor>
+                    <Anchor point="BOTTOMRIGHT">
+                      <Offset>
+                        <AbsDimension x="-4" y="4"/>
+                      </Offset>
+                    </Anchor>
+                  </Anchors>
+                  <Color r="0.7" g="0.7" b="1.0" a="0.2"/>
+                </Texture>
+              </Layer>
+              <Layer level="HIGHLIGHT">
+                <Texture alphaMode="ADD">
+                  <Anchors>
+                    <Anchor point="TOPLEFT">
+                      <Offset>
+                        <AbsDimension x="4" y="-4"/>
+                      </Offset>
+                    </Anchor>
+                    <Anchor point="BOTTOMRIGHT">
+                      <Offset>
+                        <AbsDimension x="-4" y="4"/>
+                      </Offset>
+                    </Anchor>
+                  </Anchors>
+                  <Color r="0.7" g="0.7" b="1.0" a="0.2"/>
+                </Texture>
+              </Layer>
+            </Layers>
+            <Frames>
+              <!-- edge drag handles -->
+              <Frame inherits="ReBarControlEdgeTemplate">
+                <Anchors>
+                  <Anchor point="TOPLEFT"/>
+                  <Anchor point="TOPRIGHT"/>
+                </Anchors>
+                <Scripts>
+                  <OnLoad> this.sizingPoint = "TOP" </OnLoad>
+                </Scripts>
+              </Frame>
+
+              <Frame inherits="ReBarControlEdgeTemplate">
+                <Anchors>
+                  <Anchor point="TOPLEFT"/>
+                  <Anchor point="BOTTOMLEFT"/>
+                </Anchors>
+                <Scripts>
+                  <OnLoad> this.sizingPoint = "LEFT" </OnLoad>
+                </Scripts>
+              </Frame>
+
+              <Frame inherits="ReBarControlEdgeTemplate">
+                <Anchors>
+                  <Anchor point="TOPRIGHT"/>
+                  <Anchor point="BOTTOMRIGHT"/>
+                </Anchors>
+                <Scripts>
+                  <OnLoad> this.sizingPoint = "RIGHT" </OnLoad>
+                </Scripts>
+              </Frame>
+
+              <Frame inherits="ReBarControlEdgeTemplate">
+                <Anchors>
+                  <Anchor point="BOTTOMLEFT"/>
+                  <Anchor point="BOTTOMRIGHT"/>
+                </Anchors>
+                <Scripts>
+                  <OnLoad> this.sizingPoint = "BOTTOM" </OnLoad>
+                </Scripts>
+              </Frame>
+
+              <!-- corner drag handles -->
+              <Frame setAllPoints="true">
+                <!-- nesting to ensure they're on top -->
+                <Frames>
+                  <Frame inherits="ReBarControlCornerTemplate">
+                    <Anchors>
+                      <Anchor point="TOPLEFT"/>
+                    </Anchors>
+                    <Scripts>
+                      <OnLoad> this.sizingPoint = "TOPLEFT" </OnLoad>
+                    </Scripts>
+                  </Frame>
+
+                  <Frame inherits="ReBarControlCornerTemplate">
+                    <Anchors>
+                      <Anchor point="TOPRIGHT"/>
+                    </Anchors>
+                    <Scripts>
+                      <OnLoad> this.sizingPoint = "TOPRIGHT" </OnLoad>
+                    </Scripts>
+                  </Frame>
+
+                  <Frame inherits="ReBarControlCornerTemplate">
+                    <Anchors>
+                      <Anchor point="BOTTOMLEFT"/>
+                    </Anchors>
+                    <Scripts>
+                      <OnLoad> this.sizingPoint = "BOTTOMLEFT" </OnLoad>
+                    </Scripts>
+                  </Frame>
+
+                  <Frame inherits="ReBarControlCornerTemplate">
+                    <Anchors>
+                      <Anchor point="BOTTOMRIGHT"/>
+                    </Anchors>
+                    <Scripts>
+                      <OnLoad> this.sizingPoint = "BOTTOMRIGHT" </OnLoad>
+                    </Scripts>
+                  </Frame>
+                </Frames>
+              </Frame>
+
+              <Frame name="$parentLabel">
+                <Size>
+                  <AbsDimension x="32" y="24"/>
+                </Size>
+                <Anchors>
+                  <Anchor point="CENTER"/>
+                </Anchors>
+                <Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
+                  <EdgeSize>
+                    <AbsValue val="16"/>
+                  </EdgeSize>
+                  <TileSize>
+                    <AbsValue val="16"/>
+                  </TileSize>
+                  <BackgroundInsets>
+                    <AbsInset left="0" right="0" top="0" bottom="0"/>
+                  </BackgroundInsets>
+                </Backdrop>
+                <Layers>
+                  <Layer level="BACKGROUND">
+                    <Texture>
+                      <Anchors>
+                        <Anchor point="TOPLEFT">
+                          <Offset>
+                            <AbsDimension x="4" y="-4"/>
+                          </Offset>
+                        </Anchor>
+                        <Anchor point="BOTTOMRIGHT">
+                          <Offset>
+                            <AbsDimension x="-4" y="4"/>
+                          </Offset>
+                        </Anchor>
+                      </Anchors>
+                      <Color r="0.0" g="0.0" b="0.0"/>
+                    </Texture>
+                  </Layer>
+                  <Layer level="ARTWORK">
+                    <FontString name="$parentString" inherits="GameFontNormalLarge" justifyH="CENTER" text="(barID)">
+                      <Size>
+                        <AbsDimension x="24" y="18"/>
+                      </Size>
+                      <Anchors>
+                        <Anchor point="CENTER"/>
+                      </Anchors>
+                    </FontString>
+                  </Layer>
+                </Layers>
+              </Frame>
+            </Frames>
+            <Scripts>
+              <OnLoad>
+                this:RegisterForDrag("LeftButton")
+                this:RegisterForClicks("AnyUp")
+              </OnLoad>
+              <OnDragStart>
+                this.reBar:BeginDrag()
+              </OnDragStart>
+              <OnDragStop>
+                this.reBar:FinishDrag()
+              </OnDragStop>
+              <OnEnter>
+                this.reBar:ShowTooltip()
+              </OnEnter>
+              <OnLeave>
+                GameTooltip:Hide()
+              </OnLeave>
+            </Scripts>
+          </Button>
+        </Frames>
+      </Frame>
+    </Frames>
+  </Frame>
+
+
+</Ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/ReBinder.lua	Tue Mar 20 21:19:34 2007 +0000
@@ -0,0 +1,136 @@
+-- ReBinder.lua
+-- 
+
+ReBinder = { }
+
+-- initial values
+ReBinder.active = false
+
+ReBinder.targets = { }
+
+function ReBinder:AddKeybindTarget( t )
+  if t then
+    self.targets[t] = CreateFrame("Button", nil, t, "ReBinderClickBindingTemplate")
+    self.targets[t].keybindTarget = t:GetName()
+  end
+end
+
+function ReBinder:RemoveKeybindTarget( t )
+  if t then
+    self.targets[t] = nil
+  end
+end
+
+function ReBinder:ShowClickBindingButtons()
+  for _, clickFrame in pairs(self.targets) do
+    clickFrame:Show()
+  end    
+end
+
+function ReBinder:HideClickBindingButtons()
+  for _, clickFrame in pairs(self.targets) do
+    clickFrame:Hide()
+  end    
+end
+
+function ReBinder:ClearSelectedKey()
+  self.selectedKey = nil
+end
+
+function ReBinder:ToggleEnabled()
+  if self:IsEnabled() then
+    self:Disable()
+  else
+    self:Enable()
+  end
+end
+
+function ReBinder:IsEnabled()
+  return ReBinderFrame:IsVisible()
+end
+
+function ReBinder:Enable()
+  ReBinderFrame:Show()
+end
+
+function ReBinder:Disable()
+  ReBinderFrame:Hide()
+end
+
+
+function ReBinder:HandleKeyPressed( key )
+  if key == nil or key == "UNKNOWN" or key == "SHIFT" or key == "CTRL" or key == "ALT" then 
+    return
+  end
+  if IsShiftKeyDown() then 
+    key = "SHIFT-"..key
+  end
+  if IsControlKeyDown() then
+    key = "CTRL-"..key
+  end
+  if IsAltKeyDown() then
+    key = "ALT-"..key
+  end
+  if key == "ESCAPE" or GetBindingAction(key) == "REBINDER_TOGGLEBINDINGMODE" then
+    ReBinderFrame:Hide()
+    return nil, nil
+  end
+
+  self.selectedKey = key
+
+  local keyTxt = GetBindingText(key, "KEY_")
+  local cmd    = GetBindingAction(key)
+  local cmdTxt
+  
+  if cmd then
+    cmdTxt = GetBindingText(cmd, "BINDING_NAME_")
+  end
+  
+  -- make click-bindings look prettier
+  local btnName
+  if cmdTxt then
+    btnName = string.match(cmdTxt,"CLICK (.+)\:LeftButton")
+    btnName = btnName or string.match(cmdTxt,"CLICK (.+)\:RightButton")
+  end
+  
+  return keyTxt, btnName or cmdTxt
+end
+
+-- TODO: move to override-binding model and store data in profile
+function ReBinder:BindSelectedKeyTo( btnName )
+  if self.selectedKey and btnName then
+    self:ClearBinding(btnName)
+    SetBindingClick(self.selectedKey, btnName, "LeftButton")
+    SaveBindings(2) -- 2 = character-specific
+    ReBinderFrame.statusMsg:SetText(GetBindingText(self.selectedKey, "KEY_") .. " is now bound to " .. btnName)
+    ReBinderFrame.selectedKey:SetText("(none)")
+    ReBinderFrame.currentAction:SetText("(none)")
+    self.selectedKey = nil
+  end
+end
+
+
+function ReBinder:ClearBinding( btnName )
+  if btnName then
+    local current = GetBindingKey("CLICK "..btnName..":LeftButton")
+    if current then
+      SetBinding(current, nil)
+      ReBinderFrame.statusMsg:SetText("|cFFFF3333"..btnName .. " is now unbound|r")
+    end
+  end
+end
+
+
+function ReBinder:UpdateCurrentTarget( btnName )
+  local msg = ""
+  if btnName then
+    msg = btnName.." is currently "
+    local current = GetBindingKey("CLICK "..btnName..":LeftButton")
+    if current then
+      msg = msg .. "bound to " .. GetBindingText(current, "KEY_")
+    else
+      msg = msg .. " not bound"
+    end
+  end
+  ReBinderFrame.statusMsg:SetText(msg)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes/ReBinder.xml	Tue Mar 20 21:19:34 2007 +0000
@@ -0,0 +1,242 @@
+<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">
+
+
+  <Button name="ReBinderClickBindingTemplate" virtual="true" hidden="true" toplevel="true" setAllPoints="true">
+		<HighlightTexture alphaMode="ADD" file="Interface\Buttons\ButtonHilight-Square"/>
+    <Layers>
+      <Layer level="BACKGROUND">
+        <Texture>
+          <Color r="0" g="0" b="0" a="0"/>
+        </Texture>
+      </Layer>
+    </Layers>
+    <Scripts>
+      <OnLoad>
+        this:RegisterForClicks("LeftButtonUp","RightButtonUp")
+      </OnLoad>
+      <OnClick>
+        local mouseBtn = arg1
+        if mouseBtn == "LeftButton" then
+          ReBinder:BindSelectedKeyTo(this.keybindTarget)
+        elseif mouseBtn == "RightButton" then
+          ReBinder:ClearBinding(this.keybindTarget)
+        end
+      </OnClick>
+      <PostClick>
+        this:SetButtonState("NORMAL")
+      </PostClick>
+      <OnEnter>
+        ReBinder:UpdateCurrentTarget(this.keybindTarget)
+      </OnEnter>
+      <OnLeave>
+        ReBinder:UpdateCurrentTarget(nil)
+      </OnLeave>
+    </Scripts>
+  </Button>
+
+
+  <!-- this frame covers the entire UIParent. It is visible but empty and in the background, so all it does is consume key presses and unhandled mouse clicks -->
+  <Button name="ReBinderFrame" frameStrata="BACKGROUND" movable="false" enableMouse="true" enableKeyboard="true" parent="UIParent" hidden="true" setAllPoints="true">
+    <Frames>
+      <!-- this is a dialog frame that appears to provide user feedback for the outer frame -->
+      <Button name="$parentDialog" frameStrata="DIALOG" movable="true" enableMouse="true">
+        <Size>
+          <AbsDimension x="330" y="350"/>
+        </Size>
+        <Anchors>
+          <Anchor point="CENTER"/>
+        </Anchors>
+        <TitleRegion>
+          <Size>
+            <AbsDimension x="350" y="30"/>
+          </Size>
+          <Anchors>
+            <Anchor point="TOP">
+              <Offset>
+                <AbsDimension x="0" y="-10"/>
+              </Offset>
+            </Anchor>
+          </Anchors>
+        </TitleRegion>
+        <Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
+          <EdgeSize>
+            <AbsValue val="16"/>
+          </EdgeSize>
+          <TileSize>
+            <AbsValue val="16"/>
+          </TileSize>
+          <BackgroundInsets>
+            <AbsInset left="4" right="4" top="4" bottom="4"/>
+          </BackgroundInsets>
+        </Backdrop>
+        <Layers>
+          <Layer level="BACKGROUND">
+            <Texture>
+              <Color r="0" g="0" b="0" a="0.7"/>
+            </Texture>
+          </Layer>
+          <Layer level="ARTWORK">
+            <FontString inherits="GameFontNormalLarge" text="Key Binding Setup" justifyH="CENTER">
+              <Size>
+                <AbsDimension x="200" y="30"/>
+              </Size>
+              <Anchors>
+                <Anchor point="TOP">
+                  <Offset>
+                    <AbsDimension x="0" y="-10"/>
+                  </Offset>
+                </Anchor>
+              </Anchors>
+            </FontString>
+            <FontString inherits="GameFontNormal" text="Press a key to ready it for assignment, then click a button to assign the key.|nRight-click a button to clear its binding." justifyH="CENTER">
+              <Size>
+                <AbsDimension x="240" y="70"/>
+              </Size>
+              <Anchors>
+                <Anchor point="TOP">
+                  <Offset>
+                    <AbsDimension x="0" y="-55"/>
+                  </Offset>
+                </Anchor>
+              </Anchors>
+              <Color r="1.0" g="1.0" b="1.0"/>
+            </FontString>
+            <FontString inherits="GameFontNormal" text="Selected Key:" justifyH="RIGHT">
+              <Size>
+                <AbsDimension x="175" y="25"/>
+              </Size>
+              <Anchors>
+                <Anchor point="RIGHT" relativePoint="TOP">
+                  <Offset>
+                    <AbsDimension x="-25" y="-160"/>
+                  </Offset>
+                </Anchor>
+              </Anchors>
+            </FontString>
+            <FontString inherits="GameFontNormal" text="Current Binding:" justifyH="RIGHT">
+              <Size>
+                <AbsDimension x="175" y="25"/>
+              </Size>
+              <Anchors>
+                <Anchor point="RIGHT" relativePoint="TOP">
+                  <Offset>
+                    <AbsDimension x="-25" y="-205"/>
+                  </Offset>
+                </Anchor>
+              </Anchors>
+            </FontString>
+            <FontString name="$parentCurrentActionText" inherits="GameFontNormal" text="(none)" justifyH="CENTER">
+              <Size>
+                <AbsDimension x="140" y="50"/>
+              </Size>
+              <Anchors>
+                <Anchor point="CENTER" relativePoint="TOP">
+                  <Offset>
+                    <AbsDimension x="75" y="-205"/>
+                  </Offset>
+                </Anchor>
+              </Anchors>
+              <Color r="0" g="1" b="0" a="1"/>
+            </FontString>
+            <FontString name="$parentStatusMsg" inherits="GameFontNormal" text="" justifyH="CENTER">
+              <Size>
+                <AbsDimension x="200" y="50"/>
+              </Size>
+              <Anchors>
+                <Anchor point="TOP">
+                  <Offset>
+                    <AbsDimension x="0" y="-230"/>
+                  </Offset>
+                </Anchor>
+              </Anchors>
+              <Color r="0.1" g="1.0" b="0.1"/>
+            </FontString>
+          </Layer>
+        </Layers>
+        <Frames>
+          <Button name="$parentSelectedKey" inherits="UIPanelButtonTemplate2" text="(none)">
+            <Size>
+              <AbsDimension x="140" y="28"/>
+            </Size>
+            <Anchors>
+              <Anchor point="CENTER" relativePoint="TOP">
+                <Offset>
+                  <AbsDimension x="75" y="-160"/>
+                </Offset>
+              </Anchor>
+            </Anchors>
+          </Button>
+          <Button inherits="GameMenuButtonTemplate" text="Done">
+            <Size>
+              <AbsDimension x="112" y="28"/>
+            </Size>
+            <Anchors>
+              <Anchor point="BOTTOM">
+                <Offset>
+                  <AbsDimension x="0" y="10"/>
+                </Offset>
+              </Anchor>
+            </Anchors>
+            <Scripts>
+              <OnClick>
+                this:GetParent():GetParent():Hide()
+              </OnClick>
+            </Scripts>
+          </Button>
+        </Frames>
+        <Scripts>
+          <!-- the dialog frame needs to handle clicks (close button, drag title) so we have to
+            re-implement the behavior of capturing alternate mouse buttons -->
+          <OnLoad>
+            this.selectedKey   = getglobal(this:GetName().."SelectedKeyText")
+            this.currentAction = getglobal(this:GetName().."CurrentActionText")
+            this:RegisterForClicks("MiddleButtonUp","Button4Up","Button5Up")
+          </OnLoad>
+          <OnClick>
+            local k, a = ReBinder:HandleKeyPressed(arg1)
+            if k then
+              this.selectedKey:SetText(k)
+              this.currentAction:SetText(a or "(none)")
+            end
+          </OnClick>
+        </Scripts>
+      </Button>
+    </Frames>
+    <Scripts>
+      <OnLoad>
+        this.selectedKey   = getglobal(this:GetName().."DialogSelectedKeyText")
+        this.currentAction = getglobal(this:GetName().."DialogCurrentActionText")
+        this.statusMsg     = getglobal(this:GetName().."DialogStatusMsg")
+        tinsert(UISpecialFrames,this:GetName())
+        this:RegisterForClicks("MiddleButtonUp","Button4Up","Button5Up")
+      </OnLoad>
+      <OnShow>
+        this.selectedKey:SetText("(none)")
+        this.currentAction:SetText("(none)")
+        this.statusMsg:SetText("")
+        ReBinder:ShowClickBindingButtons()
+      </OnShow>
+      <OnHide>
+        ReBinder:HideClickBindingButtons()
+        ReBinder:ClearSelectedKey()
+      </OnHide>
+      <OnKeyDown>
+        local k, a = ReBinder:HandleKeyPressed(arg1)
+        if k then
+          this.selectedKey:SetText(k)
+          this.currentAction:SetText(a or "(none)")
+        end
+      </OnKeyDown>
+      <OnClick>
+        local k, a = ReBinder:HandleKeyPressed(arg1)
+        if k then
+          this.selectedKey:SetText(k)
+          this.currentAction:SetText(a or "(none)")
+        end
+      </OnClick>
+    </Scripts>
+  </Button>
+
+</Ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.lua	Tue Mar 20 21:19:34 2007 +0000
@@ -0,0 +1,314 @@
+-- ReAction.lua
+-- 
+-- Top-level file for the ReAction Action Bar add-on
+--
+-- ReAction is implemented in terms of the Ace 2 library: http://www.wowace.com
+--
+
+-- key binding label constants
+BINDING_HEADER_REACTION                 = "ReAction"
+BINDING_NAME_REACTION_TOGGLELOCK        = "Lock/Unlock ReAction Bars"
+BINDING_NAME_REBINDER_TOGGLEBINDINGMODE = "Toggle ReAction keybinding mode"
+
+-- ReAction addon setup via Ace 2
+ReAction = AceLibrary("AceAddon-2.0"):new(
+  "AceConsole-2.0",
+  "AceEvent-2.0",
+  "AceDB-2.0",
+  "FuBarPlugin-2.0"
+)
+
+local function tcopy(t)
+  local r = { }
+  for k, v in pairs(t) do
+    r[k] = (type(v) == "table" and tcopy(v) or v)
+  end
+  return r
+end
+
+-- FuBar plugin setup
+ReAction.hasIcon = false
+ReAction.hasNoColor = true
+ReAction.hideMenuTitle = true
+ReAction.defaultPosition = "RIGHT"
+ReAction.defaultMinimapPosition = 240 -- degrees
+ReAction.OnMenuRequest = tcopy(ReActionGlobalMenuOptions)
+
+-- initial non-persistent state
+ReAction.locked = true
+
+-- localization
+-- local L = AceLibrary("AceLocale-2.0"):new("ReAction")
+
+
+
+-- Event handling
+function ReAction:OnInitialize()
+  self:RegisterChatCommand( {"/reaction", "/rxn"}, ReActionConsoleOptions, "REACTION" )
+
+  self:RegisterDB("ReActionDB","ReActionDBPC")
+  self:RegisterDefaults("profile", ReActionProfileDefaults)
+  self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown")
+  self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars")
+end
+
+function ReAction:OnEnable()
+  if self.db.profile.firstRunDone ~= true then
+    -- Do some "first-run" setup
+    self.db.profile.firstRunDone = true
+  elseif self.db.profile.disabled == true then
+    -- print some kind of a warning
+  end
+  self:SetupBars()
+end
+
+function ReAction:OnDisable()
+  self:Lock()
+end
+
+function ReAction:OnProfileEnable()
+  -- handle profile switching
+  self:Lock()
+  self:SetupBars()
+end
+
+function ReAction:CombatLockdown()
+  if not self:IsLocked() then
+    self:Lock()
+    UIErrorsFrame:AddMessage("ReAction bars locked when in combat")
+  end
+end
+
+
+-- lock/unlock ReAction
+function ReAction:SetLocked( lock )
+  if lock ~= self.locked then
+    if not lock then
+      self:Print("Buttons disabled while unlocked")
+    end
+    if not lock and InCombatLockdown() then
+      UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+    else
+      self.locked = lock and true or false -- force data integrity
+      for _, bar in pairs(self.bars) do
+        if self.locked then bar:HideControls() else bar:ShowControls() end
+      end
+    end
+  end
+end
+
+function ReAction:IsLocked()
+  return self.locked
+end
+
+function ReAction:Lock()
+  self:SetLocked(true)
+end
+
+function ReAction:Unlock()
+  self:SetLocked(false)
+end
+
+function ReAction:ToggleLocked()
+  ReAction:SetLocked( not(self.locked) )
+end
+
+
+
+-- Hide the default Blizzard main bar artwork
+function ReAction:HideArt()
+  if self.db.profile.hideArt then
+    MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons.
+  else
+    MainMenuBar:Show()
+  end
+end
+
+function ReAction:IsArtHidden()
+  return self.db.profile.hideArt
+end
+
+function ReAction:SetHideArt( hide )
+  if InCombatLockdown() then
+    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+  else
+    self.db.profile.hideArt = hide and true or false -- force data integrity
+    self:HideArt()
+  end
+end
+
+function ReAction:ToggleHideArt()
+  self:SetHideArt( not self:IsArtHidden() )
+end
+
+
+
+-- Keybinding color coding
+function ReAction:SetKeyColorCoding( cc )
+  self.db.profile.keyColorCode = cc
+end
+
+function ReAction:IsKeyColorCodeEnabled()
+  return self.db.profile.keyColorCode
+end
+
+function ReAction:ToggleKeyColorCoding()
+  self:SetKeyColorCoding(not self.db.profile.keyColorCode)
+end
+
+
+
+-- Hide default Blizzard bars
+local blizzDefaultBars = {
+  ActionButton1,
+  ActionButton2,
+  ActionButton3,
+  ActionButton4,
+  ActionButton5,
+  ActionButton6,
+  ActionButton7,
+  ActionButton8,
+  ActionButton9,
+  ActionButton10,
+  ActionButton11,
+  ActionButton12,
+  BonusActionBarFrame,
+  MultiBarLeft,
+  MultiBarRight,
+  MultiBarBottomLeft,
+  MultiBarBottomRight
+}
+
+function ReAction:HideDefaultBars()
+  for _, f in pairs(blizzDefaultBars) do
+    f:UnregisterAllEvents()
+    f:Hide()
+    f:SetParent(ReActionButtonRecycler) -- I mean it!
+    f:ClearAllPoints()                  -- no, I really mean it!
+  end
+end
+
+
+-- Reset bars to defaults
+function ReAction:ResetBars()
+  if InCombatLockdown() then
+    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+  else
+    self.db.profile.bars = ReActionProfileDefaults.bars
+    self:SetupBars()
+  end
+end
+
+
+-- re-sync action IDs
+function ReAction:ResyncActionIDs()
+  -- TODO
+end
+
+
+
+-- Bar manipulation
+ReAction.bars    = { }
+
+function ReAction:SetupBars()
+  -- hide the default Blizzard art, if configued
+  self:HideArt()
+  -- hide the default Blizzard bars
+  self:HideDefaultBars()
+
+  -- set up the bars from the profile
+  -- note the use of table.maxn rather than # or ipairs: 
+  -- our array of bars can in fact contain holes
+  for id = 1, table.maxn(self.db.profile.bars) do
+    local config = self.db.profile.bars[id]
+    if self.bars[id] then 
+      self.bars[id]:Destroy() -- remove old version of bar if switching profiles 
+    end
+    if config then
+      self.bars[id] = ReBar:new(config, id)
+    end
+  end
+  
+  -- remove excess bars
+  for id = table.maxn(self.db.profile.bars) + 1, table.maxn(self.bars) do
+    if self.bars[id] then
+      self.bars[id]:Destroy()
+      self.bars[id] = nil
+    end
+  end
+  
+  -- anchor the bars, have to do this in a second pass because
+  -- they might be anchored to each other in a non-ordered way
+  for _, bar in pairs(self.bars) do
+    bar:ApplyAnchor()
+  end
+end
+
+
+function ReAction:NewBar()
+  if InCombatLockdown() then
+    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+  else
+    local c = tcopy(ReActionBarConfigDefaults)
+    local bar = ReBar:new(c, #self.bars+1)
+    table.insert(self.bars, bar)
+    table.insert(self.db.profile.bars, c) 
+    if not self.locked then
+      bar:ShowControls()
+    end
+  end
+end
+
+
+function ReAction:DeleteBar(id)
+  if InCombatLockdown() then
+    UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT)
+  else
+    if self.bars[id] then
+      -- we can't do tremove because each bar ID is encoded into the
+      -- frame names as they're created. Need a nil entry in the table.
+      -- The nice thing is that table.insert in NewBar() will automatically
+      -- find the first nil slot.
+      self.bars[id]:Destroy()
+      self.bars[id] = nil
+      self.db.profile.bars[id] = nil
+    end
+  end
+end
+
+function ReAction:ToggleActionID()
+  if self.showActionIDs then
+    ReActionButton:HideAllActionIDs()
+  else
+    ReActionButton:ShowAllActionIDs()
+  end
+  self.showActionIDs = not self.showActionIDs
+end
+
+function ReAction:IsActionIDVisible()
+  return self.showActionIDs
+end
+
+
+
+-- FuBar plugin methods
+local tablet = AceLibrary("Tablet-2.0")
+
+function ReAction:OnTooltipUpdate()
+	local c = tablet:AddCategory("columns", 2)
+	c:AddLine("text", "Bar lock", "text2", self.locked and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
+  c:AddLine("text", "Button lock", "text2", LOCK_ACTIONBAR == "1" and "|cffcc0000Locked|r" or "|cff00cc00Unlocked|r")
+  c:AddLine("text", "Kebinding mode", "text2", ReBinder:IsEnabled() and "|cff33ff33On|r" or "|cffffcc00Off|r")
+	tablet:SetHint("|cffffcc00Shift-Click|r for bar lock|n"..
+                 "|cff33ff33Alt-Click|r for keybindings|n"..
+                 "Right-click for menu")
+end
+
+function ReAction:OnClick(button)
+	if IsShiftKeyDown() then
+	  self:ToggleLocked()
+    self:UpdateDisplay()
+	elseif IsAltKeyDown() then
+    ReBinder:ToggleEnabled()
+  end
+end